bemade_fsm: Equipment to sale order line connection made. Fixes #71.

This commit is contained in:
Marc Durepos 2023-07-18 10:36:59 -04:00
parent f997215aca
commit 454656159c
6 changed files with 127 additions and 62 deletions

View file

@ -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 []

View file

@ -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:

View file

@ -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

View file

@ -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,

View file

@ -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()

View file

@ -15,7 +15,6 @@
<field name="location_notes"/>
</group>
<group name="right">
<field name="partner_id"/>
<field name="partner_location_id"
groups="sale.group_delivery_invoice_address"
context="{'default_type': 'delivery', 'show_address': 1}"
@ -23,19 +22,6 @@
<field name="tag_ids" widget="many2many_tags" options="{'no_open': False}"/>
</group>
</group>
<!-- <notebook>-->
<!-- <page string="Interventions">-->
<!-- <field name="intervention_ids" mode="tree">-->
<!-- <tree string="Interventions" create="0" edit="0">-->
<!-- <field name="name"/>-->
<!-- <field name="description"/>-->
<!-- <field name="date_planned"/>-->
<!-- <field name="state"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </page>-->
<!-- </notebook>-->
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
@ -60,26 +46,6 @@
</field>
</record>
<!-- BV: AN OTHER SEARCH VIEW TO BRING BACK
<record id="equipment_view_search" model="ir.ui.view">
<field name="name">bemade_fsm.equipment.search</field>
<field name="model">bemade_fsm.equipment</field>
<field name="arch" type="xml">
<search string="Equipments">
<field name="name"/>
<field name="partner_id"/>
<field name="pid_tag"/>
<field name="partner_location_id"/>
<group expand="0" string="Group By">
<filter string="Partner" context="{'group_by':'partner_id'}"/>
<filter string="Location" context="{'group_by':'partner_location_id'}"/>
</group>
</search>
</field>
</record>
-->
<record model="ir.actions.act_window" id="action_window_equipment">
<field name="name">Equipment</field>
<field name="res_model">bemade_fsm.equipment</field>