diff --git a/sale_line_change/__init__.py b/sale_line_change/__init__.py new file mode 100644 index 00000000..40272379 --- /dev/null +++ b/sale_line_change/__init__.py @@ -0,0 +1 @@ +from . import wizard diff --git a/sale_line_change/__manifest__.py b/sale_line_change/__manifest__.py new file mode 100644 index 00000000..3e58d8d9 --- /dev/null +++ b/sale_line_change/__manifest__.py @@ -0,0 +1,24 @@ +{ + 'name': 'Sale Line Change', + 'summary': 'Change Confirmed Sale Lines Routes or Warehouses.', + 'version': '11.0.1.0.0', + 'author': "Hibou Corp.", + 'category': 'Sale', + 'license': 'AGPL-3', + 'complexity': 'expert', + 'images': [], + 'website': "https://hibou.io", + 'description': """ +""", + 'depends': [ + 'sale_sourced_by_line', + 'sale_stock', + ], + 'demo': [], + 'data': [ + 'wizard/sale_line_change_views.xml', + 'views/sale_views.xml', + ], + 'auto_install': False, + 'installable': True, +} diff --git a/sale_line_change/views/sale_views.xml b/sale_line_change/views/sale_views.xml new file mode 100644 index 00000000..829d4f75 --- /dev/null +++ b/sale_line_change/views/sale_views.xml @@ -0,0 +1,19 @@ + + + + sale.order.form.inherit + sale.order + + + + + + + + + \ No newline at end of file diff --git a/sale_line_change/wizard/__init__.py b/sale_line_change/wizard/__init__.py new file mode 100644 index 00000000..1307b5ec --- /dev/null +++ b/sale_line_change/wizard/__init__.py @@ -0,0 +1 @@ +from . import sale_line_change diff --git a/sale_line_change/wizard/sale_line_change.py b/sale_line_change/wizard/sale_line_change.py new file mode 100644 index 00000000..6e922a43 --- /dev/null +++ b/sale_line_change/wizard/sale_line_change.py @@ -0,0 +1,79 @@ +from odoo import api, fields, models + + +class SaleLineChangeOrder(models.TransientModel): + _name = 'sale.line.change.order' + _description = 'Sale Line Change Order' + + order_id = fields.Many2one('sale.order', string='Sale Order') + line_ids = fields.One2many('sale.line.change.order.line', 'change_order_id', string='Change Lines') + + @api.model + def default_get(self, fields): + rec = super(SaleLineChangeOrder, self).default_get(fields) + if 'order_id' in rec: + order = self.env['sale.order'].browse(rec['order_id']) + if not order: + return rec + + line_model = self.env['sale.line.change.order.line'] + rec['line_ids'] = [(0, 0, line_model.values_from_so_line(l)) for l in order.order_line] + return rec + + @api.multi + def apply(self): + self.ensure_one() + self.line_ids.apply() + return True + + +class SaleLineChangeOrderLine(models.TransientModel): + _name = 'sale.line.change.order.line' + + change_order_id = fields.Many2one('sale.line.change.order') + sale_line_id = fields.Many2one('sale.order.line', string='Sale Line') + line_ordered_qty = fields.Float(string='Ordered Qty') + line_delivered_qty = fields.Float(string='Delivered Qty') + line_reserved_qty = fields.Float(string='Reserved Qty') + line_date_planned = fields.Datetime(string='Planned Date') + line_warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse') + line_route_id = fields.Many2one('stock.location.route', string='Route') + + def values_from_so_line(self, so_line): + move_ids = so_line.move_ids + reserved_qty = sum(move_ids.mapped('reserved_availability')) + return { + 'sale_line_id': so_line.id, + 'line_ordered_qty': so_line.product_uom_qty, + 'line_delivered_qty': so_line.qty_delivered, + 'line_reserved_qty': reserved_qty, + 'line_date_planned': so_line.date_planned, + 'line_warehouse_id': so_line.warehouse_id.id, + 'line_route_id': so_line.route_id.id, + } + + def _apply(self): + self._apply_clean_existing_moves() + self._apply_new_values() + self._apply_procurement() + + def _apply_clean_existing_moves(self): + moves = self.mapped('sale_line_id.move_ids').filtered(lambda m: m.state != 'done') + moves._action_cancel() + + def _apply_new_values(self): + for line in self: + line.sale_line_id.write({ + 'date_planned': line.line_date_planned, + 'warehouse_id': line.line_warehouse_id.id, + 'route_id': line.line_route_id.id, + }) + + def _apply_procurement(self): + self.mapped('sale_line_id')._action_launch_procurement_rule() + + def apply(self): + changed_lines = self.filtered(lambda l: ( + l.sale_line_id.warehouse_id != l.line_warehouse_id + or l.sale_line_id.route_id != l.line_route_id)) + changed_lines._apply() diff --git a/sale_line_change/wizard/sale_line_change_views.xml b/sale_line_change/wizard/sale_line_change_views.xml new file mode 100644 index 00000000..bca33ca4 --- /dev/null +++ b/sale_line_change/wizard/sale_line_change_views.xml @@ -0,0 +1,40 @@ + + + + sale.line.change.order.form + sale.line.change.order + form + + + Changing Date Planned alone should be done on any existing Pickings or POs. + + + + + + + + + + + + + + + + + + Sale Line Change Order + sale.line.change.order + form + form + + new + + \ No newline at end of file
Changing Date Planned alone should be done on any existing Pickings or POs.