Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ivess/addons
1 result
Show changes
Commits on Source (2)
Showing
with 575 additions and 37 deletions
# -*- coding: utf-8 -*-
from . import models
\ No newline at end of file
from . import models
from . import wizard
\ No newline at end of file
......@@ -21,6 +21,8 @@
'views/no_purchase_reason.xml',
'views/res_partner.xml',
'views/role.xml',
'views/template_delivery_route.xml',
'wizard/delivery_route_mass_create_wizard.xml',
'views/menuitems.xml',
],
'assets': {
......
......@@ -15,6 +15,17 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route__message_needaction
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_fleet_truck__message_needaction
msgid "Action Needed"
msgstr "Se necesita acción"
#. module: logistic_custom_ivess
#: model:ir.ui.menu,name:logistic_custom_ivess.menu_delivery_actions_root
msgid "Actions"
msgstr "Acciones"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_fleet_truck__brand
msgid "Brand"
......@@ -62,6 +73,52 @@ msgstr "Creado el"
msgid "Customer Code"
msgstr "Código de cliente"
#. module: logistic_custom_ivess
#: model_terms:ir.ui.view,arch_db:logistic_custom_ivess.view_delivery_route_mass_create_wizard_form
msgid "Cancel"
msgstr "Cancelar"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route__create_from_wizard
msgid "Create from wizard"
msgstr "Creado desde wizard"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_mass_create_wizard__date_from
msgid "Date from"
msgstr "Fecha desde"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_mass_create_wizard__date_to
msgid "Date to"
msgstr "Fecha hasta"
#. module: logistic_custom_ivess
#: model_terms:ir.ui.view,arch_db:logistic_custom_ivess.view_delivery_route_mass_create_wizard_form
msgid "Generate"
msgstr "Generar"
#. module: logistic_custom_ivess
#: model:ir.actions.act_window,name:logistic_custom_ivess.action_delivery_route_mass_create_wizard
#: model:ir.ui.menu,name:logistic_custom_ivess.menu_delivery_route_mass_create
#: model_terms:ir.ui.view,arch_db:logistic_custom_ivess.view_delivery_route_mass_create_wizard_form
msgid "Generate Delivery Routes"
msgstr "Generar Rutas de reparto"
#. module: logistic_custom_ivess
#. odoo-python
#: code:addons/logistic_custom_ivess/wizard/delivery_route_mass_create_wizard.py:0
#, python-format
msgid "Generated Delivery Routes"
msgstr "Rutas de reparto generadas"
#. module: logistic_custom_ivess
#. odoo-python
#: code:addons/logistic_custom_ivess/wizard/delivery_route_mass_create_wizard.py:0
#, python-format
msgid "Invalid day of the week in the Delivery Assignment."
msgstr "Día de la semana no válido en la asignación de entrega."
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route__delivery_date
msgid "Delivery Date"
......@@ -82,9 +139,25 @@ msgstr "Común"
msgid "Universal"
msgstr "Universal"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_user_assigned_lines__user_id
msgid "User"
msgstr "Usuario"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_fleet_truck__user_assigned_ids
msgid "User Assigned"
msgstr "Usuarios Asignados"
#. module: logistic_custom_ivess
#: model:ir.model,name:logistic_custom_ivess.model_user_assigned_lines
msgid "User Assigned Lines"
msgstr "Líneas de usuarios asignados"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_res_partner__visit_day
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_res_users__visit_day
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_template_delivery_route__day
msgid "Visit Day"
msgstr "Día de visita"
......@@ -101,39 +174,58 @@ msgstr "Viernes"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__monday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__monday
msgid "Monday"
msgstr "Lunes"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__tuesday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__tuesday
msgid "Tuesday"
msgstr "Martes"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__wednesday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__wednesday
msgid "Wednesday"
msgstr "Miércoles"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__thursday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__thursday
msgid "Thursday"
msgstr "Jueves"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__friday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__friday
msgid "Friday"
msgstr "Viernes"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__saturday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__saturday
msgid "Saturday"
msgstr "Sábado"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__visit_day__sunday
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__template_delivery_route__day__sunday
msgid "Sunday"
msgstr "Domingo"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_line__template_route_id
msgid "Template Delivery Route"
msgstr "Reparto"
#. module: logistic_custom_ivess
#: model:ir.model,name:logistic_custom_ivess.model_template_delivery_route
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route__template_delivery_route_id
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_user_assigned_lines__template_delivery_route_id
msgid "Template delivery route"
msgstr "Reparto"
#. module: logistic_custom_ivess
#: model:ir.model.fields.selection,name:logistic_custom_ivess.selection__res_partner__frequency__weekly
msgid "Weekly"
......@@ -154,6 +246,18 @@ msgstr "Quincenal"
msgid "Delivery Person"
msgstr "Repartidor"
#. module: logistic_custom_ivess
#: model:ir.model,name:logistic_custom_ivess.model_role
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_user_assigned_lines__role_id
#: model_terms:ir.ui.view,arch_db:logistic_custom_ivess.view_roles_form
msgid "Role"
msgstr "Rol"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_role__name
msgid "Role Name"
msgstr "Nombre"
#. module: logistic_custom_ivess
#: model:ir.model,name:logistic_custom_ivess.model_delivery_route
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_line__route_id
......@@ -187,6 +291,32 @@ msgstr "Nombre para Mostrar"
msgid "No Purchase Reasons"
msgstr "Motivo de no compra"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_mass_create_wizard__template_delivery_route_id
msgid "Template route"
msgstr "Reparto"
#. module: logistic_custom_ivess
#. odoo-python
#: code:addons/logistic_custom_ivess/wizard/delivery_route_mass_create_wizard.py:0
#, python-format
msgid "The Start Date must be less than or equal to the End Date."
msgstr "La fecha de inicio debe ser menor o igual que la fecha de finalización."
#. module: logistic_custom_ivess
#. odoo-python
#: code:addons/logistic_custom_ivess/models/delivery_route.py:0
#, python-format
msgid "The delivery driver is not among the users assigned to this truck."
msgstr "El conductor de reparto no está entre los usuarios asignados a este camión."
#. module: logistic_custom_ivess
#. odoo-python
#: code:addons/logistic_custom_ivess/wizard/delivery_route_mass_create_wizard.py:0
#, python-format
msgid "No customers to visit in the selected Delivery Assignment."
msgstr "No hay clientes para visitar en la asignación de entrega seleccionada."
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_line__no_purchase_reason_id
msgid "No purchase reason"
......@@ -231,6 +361,11 @@ msgstr "ID"
msgid "In Progress"
msgstr "En Curso"
#. module: logistic_custom_ivess
#: model:ir.model,name:logistic_custom_ivess.model_delivery_route_mass_create_wizard
msgid "Wizard to mass create delivery routes"
msgstr "Asistente para crear rutas de entrega en masa"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route__write_uid
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route_line__write_uid
......@@ -264,6 +399,7 @@ msgstr "Modelo"
#. module: logistic_custom_ivess
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_delivery_route__name
#: model:ir.model.fields,field_description:logistic_custom_ivess.field_template_delivery_route__name
msgid "Name"
msgstr "Nombre"
......
......@@ -4,4 +4,5 @@ from . import visit_status
from . import delivery_route
from . import no_purchase_reason
from . import res_partner
from . import template_delivery_route
from . import role
\ No newline at end of file
......@@ -8,12 +8,15 @@ class DeliveryRoute(models.Model):
_description = 'Delivery Route'
_rec_name = 'name'
@api.model
def get_delivery_person_id(self):
allowed_partner = self.env['res.partner'].search(
[('user_id', '!=', False)]
).mapped('user_id.partner_id')
return [('id', 'in', allowed_partner.ids)]
@api.onchange('delivery_person_id', 'truck_id')
def _onchange_delivery_person_id(self):
if self.delivery_person_id and self.truck_id:
if self.delivery_person_id not in self.truck_id.user_assigned_ids:
self.delivery_person_id = False
raise ValidationError(_("The delivery driver is not among the users assigned to this truck."))
if self.delivery_route_line_ids and not self.create_from_wizard:
self.delivery_route_line_ids.unlink()
name = fields.Char(
string="Name"
......@@ -21,13 +24,21 @@ class DeliveryRoute(models.Model):
truck_id = fields.Many2one(
'fleet.truck',
string='Truck License Plate',
required=True
# required=True
)
template_delivery_route_id = fields.Many2one(
'template.delivery.route',
string="Template delivery route",
)
delivery_person_id = fields.Many2one(
'res.partner',
'res.users',
string='Delivery Person',
domain=lambda self: self.get_delivery_person_id(),
required=True
# required=True
)
allowed_person_ids = fields.Many2many(
comodel_name='res.users',
string="Allowed Person",
compute='_compute_allowed_person',
)
delivery_date = fields.Date(
string='Delivery Date',
......@@ -53,11 +64,49 @@ class DeliveryRoute(models.Model):
default='draft',
tracking=True
)
create_from_wizard = fields.Boolean(
string='Create from wizard',
)
@api.onchange('delivery_person_id')
def _onchange_delivery_person_id(self):
if self.delivery_route_line_ids:
self.delivery_route_line_ids.unlink()
@api.depends('truck_id')
def _compute_allowed_person(self):
all_users = self.env['res.users'].search([]) # Obtiene todos los usuarios
for rec in self:
if rec.truck_id:
rec.allowed_person_ids = rec.truck_id.user_assigned_ids
else:
rec.allowed_person_ids = all_users
def _prepare_route_lines_from_template(self, template):
"""Prepara las líneas de la ruta copiándolas desde el template."""
return [(0, 0, {
'route_id': self.id,
'client_id': line.client_id.id,
}) for line in template.delivery_route_line_ids]
@api.model
def create(self, vals):
context = self.env.context
if vals.get('template_delivery_route_id') and not context.get('create_from_wizard'):
template = self.env['template.delivery.route'].browse(vals['template_delivery_route_id'])
vals['delivery_route_line_ids'] = self._prepare_route_lines_from_template(template)
return super().create(vals)
def write(self, vals):
for record in self:
if 'template_delivery_route_id' in vals:
if vals['template_delivery_route_id']:
template = self.env['template.delivery.route'].browse(vals['template_delivery_route_id'])
vals['delivery_route_line_ids'] = [(5, 0, 0)] + self._prepare_route_lines_from_template(template)
else:
vals['delivery_route_line_ids'] = [(5, 0, 0)] # Borra las líneas si se borra el template
return super().write(vals)
def check_delivery_person(self):
if self.delivery_person_id and self.truck_id:
user = self.delivery_person_id
return user not in self.truck_id.user_assigned_ids
return False
def action_set_in_progress(self):
# if not self.delivery_route_line_ids:
......@@ -84,8 +133,16 @@ class DeliveryRouteLine(models.Model):
route_id = fields.Many2one(
'delivery.route',
string='Delivery Route',
required=True,
ondelete='cascade'
# required=True,
ondelete='cascade',
copy=False,
)
template_route_id = fields.Many2one(
'template.delivery.route',
string='Template Delivery Route',
# required=True,
ondelete='cascade',
copy=False,
)
client_id = fields.Many2one(
'res.partner',
......@@ -121,7 +178,7 @@ class DeliveryRouteLine(models.Model):
readonly=1
)
parent_delivery_person = fields.Many2one(
comodel_name='res.partner',
comodel_name='res.users',
related='route_id.delivery_person_id',
store=True,
readonly=1,
......@@ -157,17 +214,22 @@ class DeliveryRouteLine(models.Model):
record.client_address = ''
@api.depends(
'route_id',
'template_route_id',
'template_route_id.day',
'parent_delivery_type',
'parent_delivery_person',
)
def _compute_allowed_client(self):
for rec in self:
partnerObj = self.env['res.partner']
rec.allowed_client = partnerObj.search([])
partner_delivery = rec.parent_delivery_person
if rec.parent_delivery_type == 'common' and partner_delivery:
users = self.env['res.users'].search([('partner_id', '=', partner_delivery.id)])
rec.allowed_client = partnerObj.search([('user_id', 'in', users.ids)])
partner_obj = self.env['res.partner']
for rec in self:
rec.allowed_client = partner_obj.browse()
if rec.route_id and rec.parent_delivery_type == 'common' and rec.parent_delivery_person:
# users = self.env['res.users'].search([('partner_id', '=', rec.parent_delivery_person.id)])
rec.allowed_client = partner_obj.search([('user_id', '=', rec.parent_delivery_person.id)], limit=None)
elif rec.template_route_id:
rec.allowed_client = partner_obj.search([('visit_day', '=', rec.template_route_id.day)], limit=None)
@api.depends(
'visit_status_id',
......
......@@ -4,6 +4,7 @@ from odoo.exceptions import ValidationError
class FleetTruck(models.Model):
_name = 'fleet.truck'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = 'Truck Model'
_rec_name = 'license_plate'
......@@ -26,6 +27,11 @@ class FleetTruck(models.Model):
string='Year',
required=True
)
user_assigned_ids = fields.Many2many(
'res.users',
string='User Assigned',
tracking=True
)
@api.constrains('year')
def _check_year(self):
......
......@@ -14,9 +14,8 @@ class ResPartner(models.Model):
('saturday', 'Saturday'),
('sunday', 'Sunday')
],
default='monday',
default=False,
string='Visit Day',
required=True,
tracking=True,
)
frequency = fields.Selection(
......@@ -25,8 +24,7 @@ class ResPartner(models.Model):
('biweekly', 'Biweekly'),
('monthly', 'Monthly')
],
default='weekly',
default=False,
string='Frequency',
required=True,
tracking=True,
)
\ No newline at end of file
from odoo import models, fields, api
class TemplateDeliveryRoute(models.Model):
_name = 'template.delivery.route'
_description = 'Template delivery route'
name = fields.Char(string="Name")
day = fields.Selection(
selection=[
('monday', 'Monday'),
('tuesday', 'Tuesday'),
('wednesday', 'Wednesday'),
('thursday', 'Thursday'),
('friday', 'Friday'),
('saturday', 'Saturday'),
('sunday', 'Sunday')
],
default='monday',
string='Visit Day',
required=True,
)
user_assigned_ids = fields.One2many(
'user.assigned.lines',
'template_delivery_route_id',
string='Users Assigned'
)
delivery_route_line_ids = fields.One2many(
'delivery.route.line',
'template_route_id',
string='Clients to Visit'
)
@api.onchange('day')
def _onchange_day(self):
for rec in self:
rec.delivery_route_line_ids.filtered(lambda x: x.client_id.visit_day != rec.day).unlink()
class UserAssignedLines(models.Model):
_name = 'user.assigned.lines'
_description = 'User Assigned Lines'
template_delivery_route_id = fields.Many2one(
'template.delivery.route',
string="Template delivery route",
ondelete='cascade',
)
user_id = fields.Many2one(
'res.users',
string="User"
)
role_id = fields.Many2one(
'role',
string="Role"
)
......@@ -5,3 +5,7 @@ access_fleet_truck_id,fleet.truck.name,model_fleet_truck,sales_team.group_sale_s
access_visit_status_id,visit.status.name,model_visit_status,sales_team.group_sale_salesman_all_leads,1,1,1,1
access_no_purchase_reason,no.purchase.reason.name,model_no_purchase_reason,sales_team.group_sale_salesman_all_leads,1,1,1,1
access_role,access.role,model_role,base.group_system,1,1,1,1
access_delivery_route_template,access.delivery.route.template,model_template_delivery_route,sales_team.group_sale_salesman_all_leads,1,1,1,1
access_assigned_user,access.duser.assigned.lines,model_user_assigned_lines,sales_team.group_sale_salesman_all_leads,1,1,1,1
access_wizard_massive_assigned_user,access.wizard.massive.user.assigned.lines,model_delivery_route_mass_create_wizard,sales_team.group_sale_salesman_all_leads,1,1,1,1
......@@ -17,9 +17,12 @@
</h1>
</div>
<group>
<group>
<field name="truck_id" readonly="state not in ('draft', 'in_progress')"/>
<field name="delivery_person_id" readonly="state not in ('draft', 'in_progress')"/>
<group>
<field name="create_from_wizard" invisible="1"/>
<field name="template_delivery_route_id" required="True" readonly="state not in ('draft', 'in_progress')"/>
<field name="truck_id" required="True" readonly="state not in ('draft', 'in_progress')"/>
<field name="allowed_person_ids" invisible="1"/>
<field name="delivery_person_id" required="True" readonly="state not in ('draft', 'in_progress')" domain="[('id', 'in', allowed_person_ids)]"/>
<field name="delivery_date" readonly="state not in ('draft', 'in_progress')"/>
<field name="delivery_type" readonly="state not in ('draft', 'in_progress')"/>
</group>
......@@ -58,6 +61,7 @@
<field name="model">delivery.route</field>
<field name="arch" type="xml">
<tree string="Delivery Routes">
<field name="name"/>
<field name="truck_id"/>
<field name="delivery_person_id"/>
<field name="delivery_date"/>
......
......@@ -5,14 +5,26 @@
<field name="model">fleet.truck</field>
<field name="arch" type="xml">
<form string="Truck">
<header>
</header>
<sheet>
<group>
<field name="license_plate"/>
<field name="brand"/>
<field name="model"/>
<field name="year" widget="char"/>
<group>
<field name="license_plate"/>
<field name="brand"/>
<field name="model"/>
<field name="year" widget="char"/>
</group>
<group>
<field name="user_assigned_ids" widget="many2many_tags"/>
</group>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
......
......@@ -11,8 +11,12 @@
parent="sale.menu_sale_config" sequence="22"
action="action_visit_status"/>
<menuitem id="menu_roles" name="Roles"
<menuitem id="menu_tempalte_delivery_route" name="Repartos"
parent="sale.menu_sale_config" sequence="23"
action="action_template_delivery_route"/>
<menuitem id="menu_roles" name="Roles"
parent="sale.menu_sale_config" sequence="24"
action="action_roles"
groups="base.group_system"/>
......
<odoo>
<record id="view_template_delivery_route_form" model="ir.ui.view">
<field name="name">template.delivery.route.form</field>
<field name="model">template.delivery.route</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="name"/>
<field name="day"/>
</group>
</group>
<notebook>
<page string="Usuarios Asignados">
<field name="user_assigned_ids">
<tree editable="bottom">
<field name="user_id"/>
<field name="role_id"/>
</tree>
</field>
</page>
<page string="Clientes a Visitar">
<field name="delivery_route_line_ids">
<tree editable="bottom">
<field name="allowed_client" column_invisible="1" force_save="1"/>
<field name="client_id" widget="many2one_link" optional="show" domain="[('id', 'in', allowed_client)]"/>
<field name="customer_code"/>
<field name="client_address"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="view_template_delivery_route_tree" model="ir.ui.view">
<field name="name">template.delivery.route.tree</field>
<field name="model">template.delivery.route</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="day"/>
</tree>
</field>
</record>
<record id="action_template_delivery_route" model="ir.actions.act_window">
<field name="name">Repartos</field>
<field name="res_model">template.delivery.route</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>
\ No newline at end of file
# -*- coding: utf-8 -*-
from . import delivery_route_mass_create_wizard
\ No newline at end of file
# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from dateutil.rrule import rrule, WEEKLY
from datetime import datetime, timedelta
WEEKDAY_MAPPING = {
'monday': 0,
'tuesday': 1,
'wednesday': 2,
'thursday': 3,
'friday': 4,
'saturday': 5,
'sunday': 6
}
FREQUENCY_MAPPING = {
'weekly': 1,
'biweekly': 2,
'monthly': 4,
}
class DeliveryRouteMassCreateWizard(models.TransientModel):
_name = 'delivery.route.mass.create.wizard'
_description = 'Wizard to mass create delivery routes'
date_from = fields.Date(string="Date from", required=True)
date_to = fields.Date(string="Date to", required=True)
template_delivery_route_id = fields.Many2one('template.delivery.route', string="Template route", required=True)
def _validate_dates(self):
"""Valida que la fecha de inicio (date_from) no sea mayor que la fecha de fin (date_to).
Si la fecha de inicio es posterior a la fecha de fin, lanza un error de validación.
"""
for record in self:
if record.date_from and record.date_to and record.date_from > record.date_to:
raise ValidationError(_("The Start Date must be less than or equal to the End Date."))
@api.constrains('date_from', 'date_to')
def _check_dates(self):
"""Verifica que las fechas sean válidas cuando se guarde el registro."""
self._validate_dates()
@api.onchange('date_from', 'date_to')
def _onchange_dates(self):
self._validate_dates()
def prepare_vals_delivery_route(self, date):
"""Prepara los valores necesarios para crear una nueva ruta de entrega.
Args:
date (date): Fecha de la entrega.
Returns:
dict: Diccionario con los valores para la creación de la ruta.
"""
return {
'name': "{} {}".format(self.template_delivery_route_id.name, date),
'template_delivery_route_id': self.template_delivery_route_id.id,
'delivery_date': date,
'create_from_wizard': True,
}
def get_dates(self, assigned_weekday_index):
"""Genera una lista de fechas dentro del rango seleccionado, filtrando por el día de la semana asignado.
Args:
assigned_weekday_index (int): Índice del día de la semana (0=Lunes, 6=Domingo).
Returns:
list[datetime]: Lista de fechas en las que ocurren las entregas.
"""
return list(
rrule(
WEEKLY,
dtstart=self.date_from,
until=self.date_to,
byweekday=assigned_weekday_index
)
)
def action_generate_routes(self):
"""Genera rutas de reparto en función del período seleccionado y el día de la semana asignado.
- Verifica si hay clientes asignados al modelo de ruta de entrega.
- Obtiene todas las fechas dentro del rango que coincidan con el día de la semana especificado.
- Crea las rutas de entrega.
- Asigna los clientes a visitar en las rutas generadas.
Returns:
dict: Acción para abrir la vista de las rutas generadas.
"""
self.ensure_one()
template_route = self.template_delivery_route_id
assigned_weekday = template_route.day
customers_to_visit = template_route.delivery_route_line_ids
if not customers_to_visit:
raise ValidationError(_("No customers to visit in the selected Delivery Assignment."))
assigned_weekday_index = WEEKDAY_MAPPING.get(assigned_weekday)
if assigned_weekday_index is None:
raise ValidationError(_("Invalid day of the week in the Delivery Assignment."))
# Genera todas las fechas en el rango que coincidan con el día de la semana
dates = self.get_dates(assigned_weekday_index)
created_routes = self.env['delivery.route']
for current_date in dates:
data = self.prepare_vals_delivery_route(date=current_date.date()) # Convertimos a `date`
delivery_route = self.env['delivery.route'].with_context({'create_from_wizard': True}).create(data)
created_routes |= delivery_route
self.set_client_to_visit(created_routes)
return {
'type': 'ir.actions.act_window',
'name': _('Generated Delivery Routes'),
'res_model': 'delivery.route',
'view_mode': 'tree,form',
'domain': [('id', 'in', created_routes.ids)],
'target': 'current',
}
def set_client_to_visit(self, created_routes):
"""Asigna los clientes a las rutas generadas según la frecuencia de visita.
- Si la frecuencia del cliente es mensual, se asigna solo a la primera fecha disponible.
- Si la frecuencia es semanal o quincenal, se asignan fechas de acuerdo con el intervalo definido.
Args:
created_routes (recordset): Conjunto de rutas de entrega creadas.
"""
self.ensure_one()
if not created_routes:
return
route_dates = sorted(route.delivery_date for route in created_routes)
for line in self.template_delivery_route_id.delivery_route_line_ids:
client = line.client_id
interval = FREQUENCY_MAPPING.get(client.frequency, 1)
if client.frequency == 'monthly':
# Para mensual, solo asignar en la PRIMER fecha disponible
selected_dates = [route_dates[0]] if route_dates else []
else:
# Para semanal y quincenal, seleccionamos correctamente
selected_dates = route_dates[::interval]
selected_routes = created_routes.filtered(lambda r: r.delivery_date in selected_dates)
self.env['delivery.route.line'].create([
{'route_id': route.id, 'client_id': client.id}
for route in selected_routes
])
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_delivery_route_mass_create_wizard_form" model="ir.ui.view">
<field name="name">delivery.route.mass.create.wizard.form</field>
<field name="model">delivery.route.mass.create.wizard</field>
<field name="arch" type="xml">
<form string="Generate Delivery Routes">
<sheet>
<div class="text-center fw-bold mt-2 mb-3">
Se generarán rutas de reparto dentro del rango seleccionado para el reparto asignado.
</div>
<group>
<group>
<field name="date_from" required="1"/>
<field name="date_to" required="1"/>
<field name="template_delivery_route_id" required="1"/>
</group>
</group>
</sheet>
<footer>
<button name="action_generate_routes" type="object" string="Generate" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_delivery_route_mass_create_wizard" model="ir.actions.act_window">
<field name="name">Generate Delivery Routes</field>
<field name="res_model">delivery.route.mass.create.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_delivery_route_mass_create_wizard_form"/>
<field name="target">new</field>
</record>
<menuitem id="menu_delivery_actions_root"
parent="sale.sale_order_menu"
name="Actions"
sequence="25"
/>
<menuitem id="menu_delivery_route_mass_create"
name="Generate Delivery Routes"
parent="menu_delivery_actions_root"
action="action_delivery_route_mass_create_wizard"
sequence="1"/>
</odoo>
\ No newline at end of file