diff --git a/bemade_fsm/models/equipment.py b/bemade_fsm/models/equipment.py index a4b5275..4997fed 100644 --- a/bemade_fsm/models/equipment.py +++ b/bemade_fsm/models/equipment.py @@ -37,10 +37,6 @@ class Equipment(models.Model): string='Application', help="Classify and analyze your equipment categories like: Boiler, Laboratory, " "Waste water, Pure water") - partner_id = fields.Many2one('res.partner', - string="Owner", - compute="_compute_partner", - search="_search_partner", ) description = fields.Text(string="Description", tracking=True) @@ -63,15 +59,6 @@ class Equipment(models.Model): for rec in self: rec.partner_id = rec.partner_location_id and rec.partner_location_id.root_ancestor - @api.model - def _search_partner(self, operator, value): - return [('partner_location_id.root_ancestor', operator, value)] - - @api.depends('pid_tag', 'name') - def _compute_complete_name(self): - for rec in self: - rec.complete_name = "[%s] %s" % (rec.pid_tag or ' ', rec.name) - @api.model def name_search(self, name='', args=None, operator='ilike', limit=100): args = args or [] diff --git a/bemade_fsm/models/res_partner.py b/bemade_fsm/models/res_partner.py index f5dba22..4754cb1 100644 --- a/bemade_fsm/models/res_partner.py +++ b/bemade_fsm/models/res_partner.py @@ -1,5 +1,6 @@ from odoo import api, fields, models, Command + class Partner(models.Model): _inherit = 'res.partner' @@ -7,17 +8,16 @@ class Partner(models.Model): string='Equipment Count') owned_equipment_ids = fields.One2many(comodel_name="bemade_fsm.equipment", - inverse_name="partner_id", + compute="_compute_owned_equipment_ids", string="Owned Equipments") - equipment_ids = fields.One2many(comodel_name='bemade_fsm.equipment', inverse_name='partner_location_id', string='Site Equipment') is_site_contact = fields.Boolean(string='Is a site contact', compute="_compute_is_site_contact", - search="_search_is_site_contact",) + search="_search_is_site_contact", ) site_ids = fields.Many2many(string='Work Sites', comodel_name='res.partner', @@ -42,6 +42,13 @@ class Partner(models.Model): domain=[('is_company', '=', False)], tracking=True) + @api.depends('equipment_ids', 'child_ids.company_type', 'child_ids.equipment_ids') + def _compute_owned_equipment_ids(self): + for rec in self: + ids = rec.equipment_ids | rec.child_ids.filtered(lambda l: l.company_type == 'company').mapped( + 'equipment_ids') + rec.owned_equipment_ids = ids or False + @api.depends('site_ids') def _compute_is_site_contact(self): for rec in self: diff --git a/bemade_fsm/models/sale_order.py b/bemade_fsm/models/sale_order.py index 6356d27..3c12223 100644 --- a/bemade_fsm/models/sale_order.py +++ b/bemade_fsm/models/sale_order.py @@ -55,10 +55,13 @@ class SaleOrder(models.Model): def _inverse_default_contacts(self): pass - @api.depends('partner_shipping_id') + @api.depends('partner_id', 'partner_shipping_id', 'partner_shipping_id.equipment_ids', 'partner_id.owned_equipment_ids') def _compute_default_equipment(self): - ids = self.partner_shipping_id.equipment_ids for rec in self: + if rec.partner_shipping_id.equipment_ids: + ids = rec.partner_shipping_id.equipment_ids + else: + ids = rec.partner_id.owned_equipment_ids rec.default_equipment_ids = ids if len(ids) < 4 else False def _inverse_default_equipment(self): @@ -86,6 +89,14 @@ class SaleOrderLine(models.Model): column1="sale_order_line_id", column2="equipment_id") + @api.model_create_multi + def create(self, vals): + recs = super().create(vals) + for rec in recs: + if rec.order_id.default_equipment_ids and not rec.equipment_ids: + rec.equipment_ids = rec.order_id.default_equipment_ids + return recs + def _timesheet_create_task(self, project): """ Generate task for the given so line, and link it. :param project: record of project.project in which the task should be created @@ -132,7 +143,7 @@ class SaleOrderLine(models.Model): vals['tag_ids'] = template.tags.ids vals['planned_hours'] = template.planned_hours if template.equipment_ids: - vals['equipment_ids'] = [Command.set(template.equipment_ids.ids)] + vals['equipment_ids'] = template.equipment_ids.ids return vals tmpl = self.product_id.task_template_id @@ -147,7 +158,7 @@ class SaleOrderLine(models.Model): self.order_id.id, self.order_id.name, self.product_id.name) task.message_post(body=task_msg) if not task.equipment_ids and self.equipment_ids: - task.write({'equipment_ids': [Command.set([self.equipment_ids.ids])]}) + task.equipment_ids = self.equipment_ids.ids task.name = _generate_task_name(tmpl) return task diff --git a/bemade_fsm/tests/test_bemade_fsm_common.py b/bemade_fsm/tests/test_bemade_fsm_common.py index a9f7e12..2abc0e9 100644 --- a/bemade_fsm/tests/test_bemade_fsm_common.py +++ b/bemade_fsm/tests/test_bemade_fsm_common.py @@ -67,16 +67,20 @@ class BemadeFSMBaseTest(TransactionCase): }) @classmethod - def _generate_sale_order(cls, partner=None, client_order_ref='Test Order', equipment=None): + def _generate_sale_order(cls, partner=None, client_order_ref='Test Order', equipment=None, shipping_location=None): partner = partner or cls._generate_partner() - return cls.env['sale.order'].create({ - 'partner_id': partner.id, - 'client_order_ref': client_order_ref, - 'equipment_id': equipment and equipment.id or False, - }) + vals = {'partner_id': partner.id, + 'client_order_ref': client_order_ref} + if equipment: + vals.update({'default_equipment_ids': [Command.set([equipment.id])]}) + if shipping_location: + vals.update({'partner_shipping_id': shipping_location.id}) + return cls.env['sale.order'].create(vals) @classmethod - def _generate_sale_order_line(cls, sale_order, product, qty=1.0, uom=None, price=100.0, tax_id=False): + def _generate_sale_order_line(cls, sale_order, product=None, qty=1.0, uom=None, price=100.0, tax_id=False): + if not product: + product = cls._generate_product() return cls.env['sale.order.line'].create({ 'order_id': sale_order.id, 'product_id': product.id, diff --git a/bemade_fsm/tests/test_sale_order.py b/bemade_fsm/tests/test_sale_order.py index 9cba450..e1202d1 100644 --- a/bemade_fsm/tests/test_sale_order.py +++ b/bemade_fsm/tests/test_sale_order.py @@ -42,7 +42,7 @@ class TestSalesOrder(BemadeFSMBaseTest): self.assertTrue(sol.task_id.child_ids[0].child_ids and len(sol.task_id.child_ids[0].child_ids) == 1) self.assertTrue(grandchild_task.name in sol.task_id.child_ids.child_ids[0].name) - def test_order_confirmation_equipment(self): + def test_order_confirmation_single_equipment(self): """ The equipment selected on the SO should transfer to the task.""" partner = self._generate_partner() equipment = self._generate_equipment(partner=partner) @@ -60,6 +60,23 @@ class TestSalesOrder(BemadeFSMBaseTest): self.assertEqual(task1.equipment_ids[0], equipment) self.assertEqual(task2.equipment_ids[0], equipment) + def test_order_confirmation_multiple_equipment(self): + """ All equipment items should flow from the sale order line to the final task """ + partner = self._generate_partner() + for i in range(5): + self._generate_equipment(partner=partner) + sale_order = self._generate_sale_order(partner=partner) # No default equipment since more than 3 on partner + sol1, sol2, sol3 = [self._generate_sale_order_line(sale_order=sale_order) for i in range(3)] + sol1.equipment_ids = [Command.set([partner.equipment_ids[i].id for i in range(2)])] + sol3.equipment_ids = [Command.set([partner.equipment_ids[i].id for i in range(2, 5)])] + + sale_order.action_confirm() + + self.assertEqual(sol1.equipment_ids, sol1.task_id.equipment_ids) + self.assertEqual(sol2.equipment_ids, sol2.task_id.equipment_ids) + self.assertEqual(sol3.equipment_ids, sol3.task_id.equipment_ids) + + def test_task_template_with_equipment_flow(self): """ The equipment selected on a task template should flow down to the task created on SO confirmation.""" partner = self._generate_partner() @@ -73,6 +90,79 @@ class TestSalesOrder(BemadeFSMBaseTest): self.assertEqual(sol.task_id.equipment_ids[0], equipment) + def test_sale_order_line_gets_default_equipment(self): + """ Sale order lines created on an SO with default equipment set should inherit that default equipment. """ + partner = self._generate_partner() + self._generate_equipment(partner=partner) + sale_order = self._generate_sale_order(partner=partner) + + sol = self._generate_sale_order_line(sale_order=sale_order) + + self.assertEqual(sol.equipment_ids, partner.equipment_ids) + + def test_sale_order_gets_correct_default_equipment_from_partner(self): + """ Should pick up equipment from the partner.""" + partner = self._generate_partner() + self._generate_equipment(partner=partner) + + sale_order = self._generate_sale_order(partner=partner) + + self.assertEqual(sale_order.default_equipment_ids, partner.owned_equipment_ids) + + def test_sale_order_default_equipment_maximum_number(self): + parent = self._generate_partner() + child = self._generate_partner(parent=parent) + for i in range(3): + self._generate_equipment(child) + + sale_order = self._generate_sale_order(partner=parent) + + self.assertEqual(sale_order.default_equipment_ids, parent.owned_equipment_ids) + + def test_sale_order_no_default_equipment_with_more_than_three_owned_on_partner(self): + parent = self._generate_partner() + child = self._generate_partner(parent=parent) + for i in range(4): + self._generate_equipment(child) + + sale_order = self._generate_sale_order(partner=parent) + + self.assertEqual(sale_order.default_equipment_ids, parent.owned_equipment_ids) + + def test_sale_order_resets_default_equipment_on_partner_change(self): + partner_1 = self._generate_partner() + partner_2 = self._generate_partner() + self._generate_equipment(partner=partner_1) + sale_order = self._generate_sale_order(partner_1) + form = Form(sale_order) + + form.partner_id = partner_2 + form.save() + + self.assertFalse(sale_order.default_equipment_ids) + + def test_sale_order_prioritize_shipping_location_equipments(self): + parent = self._generate_partner() + child = self._generate_partner(parent=parent, location_type='delivery') + self._generate_equipment(partner=parent) + self._generate_equipment(partner=child) + + sale_order = self._generate_sale_order(partner=parent, shipping_location=child) + + self.assertEqual(sale_order.default_equipment_ids, child.equipment_ids) + + def test_default_equipment_transfers_to_sale_order_line(self): + partner = self._generate_partner() + for i in range(3): + self._generate_equipment(partner=partner) + sale_order = self._generate_sale_order(partner=partner) + + for i in range(3): + self._generate_sale_order_line(sale_order=sale_order) + + for line in sale_order.order_line: + self.assertEqual(line.equipment_ids, partner.equipment_ids) + def test_task_mark_done(self): """ Marking the task linked to an SO line should mark the line delivered. Marking sub-tasks done should not.""" partner = self._generate_partner() diff --git a/bemade_fsm/views/equipment.xml b/bemade_fsm/views/equipment.xml index 5bf4d41..da1042d 100644 --- a/bemade_fsm/views/equipment.xml +++ b/bemade_fsm/views/equipment.xml @@ -15,7 +15,6 @@ - - - - - - - - - - - - - -
@@ -60,26 +46,6 @@ - - Equipment bemade_fsm.equipment