From 84514c49dea077fdb177f439744eaf6ecff46a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 26 Jan 2023 15:11:21 +0100 Subject: [PATCH] Add relates to sale and purchase lines from party and product --- modules/purchase/CHANGELOG | 1 + modules/purchase/purchase.py | 43 ++++++++++++- modules/purchase/purchase.xml | 68 ++++++++++++++++++++ modules/purchase/view/party_form.xml | 1 + modules/purchase/view/purchase_line_tree.xml | 7 +- modules/purchase/view/template_form.xml | 4 ++ modules/sale/CHANGELOG | 1 + modules/sale/sale.py | 42 +++++++++++- modules/sale/sale.xml | 68 ++++++++++++++++++++ modules/sale/view/party_form.xml | 1 + modules/sale/view/sale_line_tree.xml | 7 +- modules/sale/view/template_form.xml | 4 ++ 12 files changed, 239 insertions(+), 8 deletions(-) diff --git a/modules/purchase/CHANGELOG b/modules/purchase/CHANGELOG index 4987b9d68d..9df4f63cdc 100644 --- a/modules/purchase/CHANGELOG +++ b/modules/purchase/CHANGELOG @@ -1,3 +1,4 @@ +* Add relate to purchase lines from party and product * Simplify relate to purchases * Prevent creation of lines for non draft purchases * Allow searching reporting records by name diff --git a/modules/purchase/purchase.py b/modules/purchase/purchase.py index ad2b75c368..972b3690fe 100644 --- a/modules/purchase/purchase.py +++ b/modules/purchase/purchase.py @@ -1066,7 +1066,7 @@ class Line(sequence_ordered(), ModelSQL, ModelView): actual_quantity = fields.Float( "Actual Quantity", digits='unit', readonly=True, states={ - 'invisible': Eval('type') != 'line', + 'invisible': ((Eval('type') != 'line') | ~Eval('actual_quantity')), }) unit = fields.Many2One('product.uom', 'Unit', ondelete='RESTRICT', @@ -1205,10 +1205,20 @@ class Line(sequence_ordered(), ModelSQL, ModelView): }) purchase_state = fields.Function( fields.Selection('get_purchase_states', 'Purchase State'), - 'on_change_with_purchase_state') + 'on_change_with_purchase_state', searcher='search_purchase_state') company = fields.Function( fields.Many2One('company.company', "Company"), 'on_change_with_company') + supplier = fields.Function( + fields.Many2One( + 'party.party', "Supplier", + context={ + 'company': Eval('company', -1), + }), + 'on_change_with_supplier', searcher='search_supplier') + purchase_date = fields.Function( + fields.Date("Purchase Date"), + 'on_change_with_purchase_date', searcher='search_purchase_date') currency = fields.Function( fields.Many2One('currency.currency', 'Currency'), 'on_change_with_currency') @@ -1223,6 +1233,8 @@ class Line(sequence_ordered(), ModelSQL, ModelView): def __setup__(cls): super().__setup__() cls.__access__.add('purchase') + cls._order.insert(0, ('purchase.purchase_date', 'DESC NULLS FIRST')) + cls._order.insert(1, ('purchase.id', 'DESC')) @classmethod def __register__(cls, module_name): @@ -1517,11 +1529,38 @@ class Line(sequence_ordered(), ModelSQL, ModelView): if self.purchase: return self.purchase.state + @classmethod + def search_purchase_state(cls, name, clause): + return [('purchase.state', *clause[1:])] + @fields.depends('purchase', '_parent_purchase.company') def on_change_with_company(self, name=None): if self.purchase and self.purchase.company: return self.purchase.company.id + @fields.depends('purchase', '_parent_purchase.party') + def on_change_with_supplier(self, name=None): + if self.purchase and self.purchase.party: + return self.purchase.party.id + + @classmethod + def search_supplier(cls, name, clause): + return [('purchase.party' + clause[0][len(name):], *clause[1:])] + + @fields.depends('purchase', '_parent_purchase.purchase_date') + def on_change_with_purchase_date(self, name=None): + if self.purchase: + return self.purchase.purchase_date + + @classmethod + def search_purchase_date(cls, name, clause): + return [('purchase.purchase_date', *clause[1:])] + + @classmethod + def order_purchase_date(cls, tables): + return cls.purchase.convert_order( + 'purchase.purchase_date', tables, cls) + @fields.depends('purchase', '_parent_purchase.currency') def on_change_with_currency(self, name=None): if self.purchase and self.purchase.currency: diff --git a/modules/purchase/purchase.xml b/modules/purchase/purchase.xml index b8d3d949a8..63dd7f7331 100644 --- a/modules/purchase/purchase.xml +++ b/modules/purchase/purchase.xml @@ -435,6 +435,74 @@ this repository contains the full copyright notices and license terms. --> purchase_line_tree_sequence + + Purchase Lines + purchase.line + + + + + + + + + + + + + + Pending + + + + + + + Done + + + + + + + All + + + + + + form_relate + purchase.purchase,-1 + + + + form_relate + product.product,-1 + + + + form_relate + product.template,-1 + + + + form_relate + party.party,-1 + + + diff --git a/modules/purchase/view/party_form.xml b/modules/purchase/view/party_form.xml index 956587a63e..5baf42b7cd 100644 --- a/modules/purchase/view/party_form.xml +++ b/modules/purchase/view/party_form.xml @@ -4,6 +4,7 @@ this repository contains the full copyright notices and license terms. --> + diff --git a/modules/purchase/view/purchase_line_tree.xml b/modules/purchase/view/purchase_line_tree.xml index 2c4704a5ac..f7ebffaed6 100644 --- a/modules/purchase/view/purchase_line_tree.xml +++ b/modules/purchase/view/purchase_line_tree.xml @@ -3,12 +3,15 @@ this repository contains the full copyright notices and license terms. --> + + - + + - + diff --git a/modules/purchase/view/template_form.xml b/modules/purchase/view/template_form.xml index e7931d5cb4..88bee12213 100644 --- a/modules/purchase/view/template_form.xml +++ b/modules/purchase/view/template_form.xml @@ -16,6 +16,10 @@ this repository contains the full copyright notices and license terms. --> + + + + diff --git a/modules/sale/CHANGELOG b/modules/sale/CHANGELOG index 5a9c94b8ed..4423edf490 100644 --- a/modules/sale/CHANGELOG +++ b/modules/sale/CHANGELOG @@ -1,3 +1,4 @@ +* Add relate to sale lines from party and product * Simplify relate to sales * Prevent creation of lines for non draft sales * Allow searching reporting records by name diff --git a/modules/sale/sale.py b/modules/sale/sale.py index c5ecc179fd..00375e2d50 100644 --- a/modules/sale/sale.py +++ b/modules/sale/sale.py @@ -1153,7 +1153,7 @@ class SaleLine(TaxableMixin, sequence_ordered(), ModelSQL, ModelView): actual_quantity = fields.Float( "Actual Quantity", digits='unit', readonly=True, states={ - 'invisible': Eval('type') != 'line', + 'invisible': ((Eval('type') != 'line') | ~Eval('actual_quantity')), }) unit = fields.Many2One('product.uom', 'Unit', ondelete='RESTRICT', states={ @@ -1255,10 +1255,20 @@ class SaleLine(TaxableMixin, sequence_ordered(), ModelSQL, ModelView): 'on_change_with_shipping_date') sale_state = fields.Function( fields.Selection('get_sale_states', "Sale State"), - 'on_change_with_sale_state') + 'on_change_with_sale_state', searcher='search_sale_state') company = fields.Function( fields.Many2One('company.company', "Company"), 'on_change_with_company') + customer = fields.Function( + fields.Many2One( + 'party.party', "Customer", + context={ + 'company': Eval('company', -1), + }), + 'on_change_with_customer', searcher='search_customer') + sale_date = fields.Function( + fields.Date("Sale Date"), + 'on_change_with_sale_date', searcher='search_sale_date') @classmethod def get_move_product_types(cls): @@ -1270,6 +1280,8 @@ class SaleLine(TaxableMixin, sequence_ordered(), ModelSQL, ModelView): def __setup__(cls): super().__setup__() cls.__access__.add('sale') + cls._order.insert(0, ('sale.sale_date', 'DESC NULLS FIRST')) + cls._order.insert(1, ('sale.id', 'DESC')) @classmethod def __register__(cls, module_name): @@ -1536,11 +1548,37 @@ class SaleLine(TaxableMixin, sequence_ordered(), ModelSQL, ModelView): if self.sale: return self.sale.state + @classmethod + def search_sale_state(cls, name, clause): + return [('sale.state', *clause[1:])] + @fields.depends('sale', '_parent_sale.company') def on_change_with_company(self, name=None): if self.sale and self.sale.company: return self.sale.company.id + @fields.depends('sale', '_parent_sale.party') + def on_change_with_customer(self, name=None): + if self.sale and self.sale.party: + return self.sale.party.id + + @classmethod + def search_customer(cls, name, clause): + return [('sale.party' + clause[0][len(name):], *clause[1:])] + + @fields.depends('sale', '_parent_sale.sale_date') + def on_change_with_sale_date(self, name=None): + if self.sale: + return self.sale.sale_date + + @classmethod + def search_sale_date(cls, name, clause): + return [('sale.sale_date', *clause[1:])] + + @classmethod + def order_sale_date(cls, tables): + return cls.sale.convert_order('sale.sale_date', tables, cls) + def get_invoice_line(self): 'Return a list of invoice lines for sale line' pool = Pool() diff --git a/modules/sale/sale.xml b/modules/sale/sale.xml index 1bd77698dc..c5f362d657 100644 --- a/modules/sale/sale.xml +++ b/modules/sale/sale.xml @@ -419,6 +419,74 @@ this repository contains the full copyright notices and license terms. --> sale_line_tree_sequence + + Sale Lines + sale.line + + + + + + + + + + + + + + Pending + + + + + + + Done + + + + + + + All + + + + + + form_relate + sale.sale,-1 + + + + form_relate + product.product,-1 + + + + form_relate + product.template,-1 + + + + form_relate + party.party,-1 + + + sale.return_sale.start form diff --git a/modules/sale/view/party_form.xml b/modules/sale/view/party_form.xml index 23b5098291..ff63233c6d 100644 --- a/modules/sale/view/party_form.xml +++ b/modules/sale/view/party_form.xml @@ -4,6 +4,7 @@ this repository contains the full copyright notices and license terms. --> + diff --git a/modules/sale/view/sale_line_tree.xml b/modules/sale/view/sale_line_tree.xml index 2836c9272f..9907150946 100644 --- a/modules/sale/view/sale_line_tree.xml +++ b/modules/sale/view/sale_line_tree.xml @@ -3,11 +3,14 @@ this repository contains the full copyright notices and license terms. --> + + - + + - + diff --git a/modules/sale/view/template_form.xml b/modules/sale/view/template_form.xml index dbb109423d..a0f5c9130b 100644 --- a/modules/sale/view/template_form.xml +++ b/modules/sale/view/template_form.xml @@ -15,6 +15,10 @@ this repository contains the full copyright notices and license terms. -->