diff options
| author | Mitali Patel <mpa@odoo.com> | 2019-07-08 11:10:45 +0000 |
|---|---|---|
| committer | Simon Lejeune <sle@openerp.com> | 2020-03-05 14:31:13 +0000 |
| commit | 6f247d799a5e15ca0e6d3ea77f3cb378b1c92e8a (patch) | |
| tree | 841dbde12d9de7bd3cabb3b6b9cb17e03134f04d /addons | |
| parent | ffc6fe1704b748b03cdd66d81e54b202a4128c6f (diff) | |
[IMP] stock, sale_stock, mrp, purchase_stock: transfer the custom variant information
Allow to propagate custom information to upper document. It could be
usefull in many buisness that do custom stuff for people
(t-shirt with user defined text, poster with own pictures...)
The customes values are pass throught procurements'values and are
display on MO or purchase order line.
Task: 1970476
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/mrp/models/mrp_production.py | 1 | ||||
| -rw-r--r-- | addons/mrp/models/stock_rule.py | 1 | ||||
| -rw-r--r-- | addons/mrp/report/mrp_production_templates.xml | 4 | ||||
| -rw-r--r-- | addons/mrp/views/mrp_production_views.xml | 1 | ||||
| -rw-r--r-- | addons/purchase_stock/models/purchase.py | 18 | ||||
| -rw-r--r-- | addons/purchase_stock/models/stock_rule.py | 2 | ||||
| -rw-r--r-- | addons/purchase_stock/tests/common.py | 6 | ||||
| -rw-r--r-- | addons/purchase_stock/tests/test_purchase_lead_time.py | 51 | ||||
| -rw-r--r-- | addons/sale_stock/models/sale_order.py | 1 | ||||
| -rw-r--r-- | addons/stock/models/stock_move.py | 5 | ||||
| -rw-r--r-- | addons/stock/models/stock_rule.py | 5 |
11 files changed, 89 insertions, 6 deletions
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index ddd65b934f9..c62d7ac7657 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -205,6 +205,7 @@ class MrpProduction(models.Model): procurement_group_id = fields.Many2one( 'procurement.group', 'Procurement Group', copy=False) + product_description_variants = fields.Char('Custom Description') orderpoint_id = fields.Many2one('stock.warehouse.orderpoint', 'Orderpoint') propagate_cancel = fields.Boolean( 'Propagate cancel and split', diff --git a/addons/mrp/models/stock_rule.py b/addons/mrp/models/stock_rule.py index bb9c1deb738..c08e2ab2015 100644 --- a/addons/mrp/models/stock_rule.py +++ b/addons/mrp/models/stock_rule.py @@ -84,6 +84,7 @@ class StockRule(models.Model): return { 'origin': origin, 'product_id': product_id.id, + 'product_description_variants': values.get('product_description_variants'), 'product_qty': product_qty, 'product_uom_id': product_uom.id, 'location_src_id': self.location_src_id.id or self.picking_type_id.default_location_src_id.id or location_id.id, diff --git a/addons/mrp/report/mrp_production_templates.xml b/addons/mrp/report/mrp_production_templates.xml index 3b796e75bd1..fc41fae66dd 100644 --- a/addons/mrp/report/mrp_production_templates.xml +++ b/addons/mrp/report/mrp_production_templates.xml @@ -32,6 +32,10 @@ <strong>Finished Product:</strong><br/> <span t-field="o.product_id"/> </div> + <div class="col-3" t-if="o.product_description_variants"> + <strong>Description:</strong><br/> + <span t-field="o.product_description_variants"/> + </div> <div class="col-3"> <strong>Quantity to Produce:</strong><br/> <span t-field="o.product_qty"/> diff --git a/addons/mrp/views/mrp_production_views.xml b/addons/mrp/views/mrp_production_views.xml index 2fa32e3769b..3d5e9a2c4a3 100644 --- a/addons/mrp/views/mrp_production_views.xml +++ b/addons/mrp/views/mrp_production_views.xml @@ -115,6 +115,7 @@ <field name="id" invisible="1"/> <field name="product_id" attrs="{'readonly': [('state', '!=', 'draft')]}"/> <field name="product_tmpl_id" invisible="1"/> + <field name="product_description_variants" attrs="{'readonly': [('state', '!=', 'draft')]}"/> <label for="product_qty"/> <div class="o_row no-gutters d-flex"> <div class="col"> diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index c5a74770b80..d07893425ed 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -239,6 +239,7 @@ class PurchaseOrderLine(models.Model): orderpoint_id = fields.Many2one('stock.warehouse.orderpoint', 'Orderpoint') move_dest_ids = fields.One2many('stock.move', 'created_purchase_line_id', 'Downstream Moves') delay_alert = fields.Boolean(string='Delay alert') + product_description_variants = fields.Char('Custom Description') propagate_date = fields.Boolean(string="Propagate Rescheduling", help='The rescheduling is propagated to the next move.') propagate_date_minimum_delta = fields.Integer(string='Reschedule if Higher Than', help='The change must be higher than this value to be propagated') propagate_cancel = fields.Boolean('Propagate cancellation', default=True) @@ -381,12 +382,14 @@ class PurchaseOrderLine(models.Model): def _prepare_stock_move_vals(self, picking, price_unit, product_uom_qty, product_uom): self.ensure_one() + description_picking = self.product_id._get_description(self.order_id.picking_type_id) + if self.product_description_variants: + description_picking += self.product_description_variants return { # truncate to 2000 to avoid triggering index limit error # TODO: remove index in master? 'name': (self.name or '')[:2000], 'product_id': self.product_id.id, - 'product_uom': self.product_uom.id, 'date': self.order_id.date_order, 'date_expected': self.date_planned, 'location_id': self.order_id.partner_id.property_stock_supplier.id, @@ -403,7 +406,7 @@ class PurchaseOrderLine(models.Model): 'origin': self.order_id.name, 'propagate_date': self.propagate_date, 'propagate_date_minimum_delta': self.propagate_date_minimum_delta, - 'description_picking': self.product_id._get_description(self.order_id.picking_type_id), + 'description_picking': description_picking, 'propagate_cancel': self.propagate_cancel, 'delay_alert': self.delay_alert, 'route_ids': self.order_id.picking_type_id.warehouse_id and [(6, 0, [x.id for x in self.order_id.picking_type_id.warehouse_id.route_ids])] or [], @@ -414,14 +417,19 @@ class PurchaseOrderLine(models.Model): @api.model def _prepare_purchase_order_line_from_procurement(self, product_id, product_qty, product_uom, company_id, values, po): + line_description = product_id._get_description(po.picking_type_id) + if values.get('product_description_variants'): + line_description += values['product_description_variants'] supplier = values.get('supplier') res = self._prepare_purchase_order_line(product_id, product_qty, product_uom, company_id, supplier, po) + res['name'] = line_description res['move_dest_ids'] = [(4, x.id) for x in values.get('move_dest_ids', [])] res['orderpoint_id'] = values.get('orderpoint_id', False) and values.get('orderpoint_id').id res['propagate_cancel'] = values.get('propagate_cancel') res['delay_alert'] = values.get('delay_alert') res['propagate_date'] = values.get('propagate_date') res['propagate_date_minimum_delta'] = values.get('propagate_date_minimum_delta') + res['product_description_variants'] = values.get('product_description_variants') return res def _create_stock_moves(self, picking): @@ -442,9 +450,13 @@ class PurchaseOrderLine(models.Model): args can be merged. If it returns an empty record then a new line will be created. """ + description_picking = product_id._get_description(self.order_id.picking_type_id) or '' + if values.get('product_description_variants'): + description_picking += values['product_description_variants'] lines = self.filtered( lambda l: l.propagate_date == values['propagate_date'] and l.propagate_date_minimum_delta == values['propagate_date_minimum_delta'] and l.propagate_cancel == values['propagate_cancel'] and - ((values['orderpoint_id'] and not values['move_dest_ids']) and l.orderpoint_id == values['orderpoint_id'] or True)) + ((values['orderpoint_id'] and not values['move_dest_ids']) and l.orderpoint_id == values['orderpoint_id'] or True) and + (values.get('product_description_variants') and l.name == description_picking or True)) return lines and lines[0] or self.env['purchase.order.line'] diff --git a/addons/purchase_stock/models/stock_rule.py b/addons/purchase_stock/models/stock_rule.py index 0df54976cee..a102726dece 100644 --- a/addons/purchase_stock/models/stock_rule.py +++ b/addons/purchase_stock/models/stock_rule.py @@ -159,12 +159,14 @@ class StockRule(models.Model): # necessary anymore since those values are taken from destination moves. return procurement.product_id, procurement.product_uom, procurement.values['propagate_date'],\ procurement.values['propagate_date_minimum_delta'], procurement.values['propagate_cancel'],\ + procurement.values.get('product_description_variants'),\ (procurement.values.get('orderpoint_id') and not procurement.values.get('move_dest_ids')) and procurement.values['orderpoint_id'] @api.model def _get_procurements_to_merge_sorted(self, procurement): return procurement.product_id.id, procurement.product_uom.id, procurement.values['propagate_date'],\ procurement.values['propagate_date_minimum_delta'], procurement.values['propagate_cancel'],\ + procurement.values.get('product_description_variants'),\ (procurement.values.get('orderpoint_id') and not procurement.values.get('move_dest_ids')) and procurement.values['orderpoint_id'] @api.model diff --git a/addons/purchase_stock/tests/common.py b/addons/purchase_stock/tests/common.py index 99917378ff1..feada30badc 100644 --- a/addons/purchase_stock/tests/common.py +++ b/addons/purchase_stock/tests/common.py @@ -35,6 +35,12 @@ class PurchaseTestCommon(TestStockCommon): 'route_ids': [(6, 0, [cls.route_buy, cls.route_mto])], 'seller_ids': [(0, 0, {'name': cls.partner_1.id, 'delay': 5})]}) + cls.t_shirt = cls.env['product.product'].create({ + 'name': 'T-shirt', + 'route_ids': [(6, 0, [cls.route_buy, cls.route_mto])], + 'seller_ids': [(0, 0, {'name': cls.partner_1.id, 'delay': 5})] + }) + # Update product_2 with type, route and Delivery Lead Time cls.product_2.write({ 'type': 'product', diff --git a/addons/purchase_stock/tests/test_purchase_lead_time.py b/addons/purchase_stock/tests/test_purchase_lead_time.py index 45d29ce71f2..2706527dd78 100644 --- a/addons/purchase_stock/tests/test_purchase_lead_time.py +++ b/addons/purchase_stock/tests/test_purchase_lead_time.py @@ -242,6 +242,57 @@ class TestPurchaseLeadTime(PurchaseTestCommon): self.assertEqual(po_line[0].product_qty, 10, 'the purchase order line has a wrong quantity') self.assertEqual(po_line[1].product_qty, 5, 'the purchase order line has a wrong quantity') + def test_merge_po_line_3(self): + """Chage merging po line if same procurement is done depending on + propagate_date, propagate_date_minimum_delta and custom values. + """ + # Create procurement order of product_1 + ProcurementGroup = self.env['procurement.group'] + procurement_values = { + 'warehouse_id': self.warehouse_1, + 'rule_id': self.warehouse_1.buy_pull_id, + 'date_planned': fields.Datetime.to_string(fields.datetime.now() + timedelta(days=10)), + 'group_id': False, + 'route_ids': [], + } + + procurement_values['product_description_variants'] = '[{"color": "Red"}]' + procurement_values['description'] = "T-shirt (Red)" + order_1_values = procurement_values + ProcurementGroup.run([self.env['procurement.group'].Procurement( + self.t_shirt, 5, self.uom_unit, self.warehouse_1.lot_stock_id, + self.t_shirt.name, '/', self.env.company, order_1_values) + ]) + purchase_order = self.env['purchase.order.line'].search([('product_id', '=', self.t_shirt.id)], limit=1).order_id + self.assertEqual(len(purchase_order.order_line), 1, 'wrong number of order line is created') + + procurement_values['product_description_variants'] = '[{"color": "Red"}]' + order_2_values = procurement_values + ProcurementGroup.run([self.env['procurement.group'].Procurement( + self.t_shirt, 10, self.uom_unit, self.warehouse_1.lot_stock_id, + self.t_shirt.name, '/', self.env.company, order_2_values) + ]) + self.env['procurement.group'].run_scheduler() + self.assertEqual(len(purchase_order.order_line), 1, 'line with same custom value should be merged') + self.assertEqual(purchase_order.order_line[0].product_qty, 15, 'line with same custom value should be merged and qty should be update') + + procurement_values['product_description_variants'] = '[{"color": "Green"}]' + procurement_values['description'] = "T-shirt (Green)" + + order_3_values = procurement_values + ProcurementGroup.run([self.env['procurement.group'].Procurement( + self.t_shirt, 10, self.uom_unit, self.warehouse_1.lot_stock_id, + self.t_shirt.name, '/', self.env.company, order_3_values) + ]) + self.assertEqual(len(purchase_order.order_line), 2, 'line with different custom value should not be merged') + self.assertEqual(purchase_order.order_line.filtered(lambda x: x.product_qty == 15).name, "T-shirt (Red)", 'wrong description in po lines') + self.assertEqual(purchase_order.order_line.filtered(lambda x: x.product_qty == 10).name, "T-shirt (Green)", 'wrong description in po lines') + + purchase_order.button_confirm() + + self.assertEqual(purchase_order.picking_ids[0].move_ids_without_package.filtered(lambda x: x.product_uom_qty == 15).description_picking, "T-shirt (Red)", 'wrong description in picking') + self.assertEqual(purchase_order.picking_ids[0].move_ids_without_package.filtered(lambda x: x.product_uom_qty == 10).description_picking, "T-shirt (Green)", 'wrong description in picking') + def test_reordering_days_to_purchase(self): self.patcher = patch('odoo.addons.stock.models.stock_orderpoint.fields.Date', wraps=fields.Date) self.mock_date = self.patcher.start() diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index 12f2d445689..8833634c315 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -445,6 +445,7 @@ class SaleOrderLine(models.Model): 'route_ids': self.route_id, 'warehouse_id': self.order_id.warehouse_id or False, 'partner_id': self.order_id.partner_shipping_id.id, + 'product_description_variants': self._get_sale_order_line_multiline_description_variants(), 'company_id': self.order_id.company_id, }) for line in self.filtered("order_id.commitment_date"): diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index f322bb7ea6e..5540fdcaf51 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -691,7 +691,7 @@ class StockMove(models.Model): 'product_id', 'price_unit', 'procure_method', 'location_id', 'location_dest_id', 'product_uom', 'restrict_partner_id', 'scrapped', 'origin_returned_move_id', 'package_level_id', 'propagate_cancel', 'propagate_date', 'propagate_date_minimum_delta', - 'delay_alert', + 'delay_alert', 'description_picking' ] @api.model @@ -701,7 +701,7 @@ class StockMove(models.Model): move.product_id.id, move.price_unit, move.procure_method, move.location_id, move.location_dest_id, move.product_uom.id, move.restrict_partner_id.id, move.scrapped, move.origin_returned_move_id.id, move.package_level_id.id, move.propagate_cancel, move.propagate_date, move.propagate_date_minimum_delta, - move.delay_alert, + move.delay_alert, move.description_picking ] def _clean_merged(self): @@ -1040,6 +1040,7 @@ class StockMove(models.Model): elif self.rule_id.group_propagation_option == 'none': group_id = False return { + 'product_description_variants': self.description_picking and self.description_picking.replace(self.product_id._get_description(self.picking_type_id), ''), 'date_planned': self.date_expected, 'move_dest_ids': self, 'group_id': group_id, diff --git a/addons/stock/models/stock_rule.py b/addons/stock/models/stock_rule.py index 7570c0cbfb0..ddc37eccbcf 100644 --- a/addons/stock/models/stock_rule.py +++ b/addons/stock/models/stock_rule.py @@ -285,6 +285,9 @@ class StockRule(models.Model): date_expected = fields.Datetime.to_string( fields.Datetime.from_string(values['date_planned']) - relativedelta(days=self.delay or 0) ) + picking_description = product_id._get_description(self.picking_type_id) + if values.get('product_description_variants'): + picking_description += values['product_description_variants'] # it is possible that we've already got some move done, so check for the done qty and create # a new move with the correct qty qty_left = product_qty @@ -315,7 +318,7 @@ class StockRule(models.Model): 'propagate_cancel': self.propagate_cancel, 'propagate_date': self.propagate_date, 'propagate_date_minimum_delta': self.propagate_date_minimum_delta, - 'description_picking': product_id._get_description(self.picking_type_id), + 'description_picking': picking_description, 'priority': values.get('priority', "1"), 'delay_alert': self.delay_alert, 'orderpoint_id': values.get('orderpoint_id') and values['orderpoint_id'].id, |
