From 5c7985a15ccf2be950c4e27a907c68f85a30782a Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 29 May 2020 17:46:57 +0200 Subject: [PATCH] Add modules service_line_qty_update_base service_line_qty_update_purchase --- service_line_qty_update_base/__init__.py | 1 + service_line_qty_update_base/__manifest__.py | 18 +++++ .../wizard/__init__.py | 1 + .../wizard/service_qty_update.py | 70 +++++++++++++++++++ .../wizard/service_qty_update_view.xml | 45 ++++++++++++ service_line_qty_update_purchase/__init__.py | 2 + .../__manifest__.py | 18 +++++ .../models/__init__.py | 1 + .../models/purchase_order.py | 20 ++++++ .../views/purchase_order.xml | 27 +++++++ .../wizard/__init__.py | 1 + .../wizard/service_qty_update.py | 58 +++++++++++++++ 12 files changed, 262 insertions(+) create mode 100644 service_line_qty_update_base/__init__.py create mode 100644 service_line_qty_update_base/__manifest__.py create mode 100644 service_line_qty_update_base/wizard/__init__.py create mode 100644 service_line_qty_update_base/wizard/service_qty_update.py create mode 100644 service_line_qty_update_base/wizard/service_qty_update_view.xml create mode 100644 service_line_qty_update_purchase/__init__.py create mode 100644 service_line_qty_update_purchase/__manifest__.py create mode 100644 service_line_qty_update_purchase/models/__init__.py create mode 100644 service_line_qty_update_purchase/models/purchase_order.py create mode 100644 service_line_qty_update_purchase/views/purchase_order.xml create mode 100644 service_line_qty_update_purchase/wizard/__init__.py create mode 100644 service_line_qty_update_purchase/wizard/service_qty_update.py diff --git a/service_line_qty_update_base/__init__.py b/service_line_qty_update_base/__init__.py new file mode 100644 index 0000000..4027237 --- /dev/null +++ b/service_line_qty_update_base/__init__.py @@ -0,0 +1 @@ +from . import wizard diff --git a/service_line_qty_update_base/__manifest__.py b/service_line_qty_update_base/__manifest__.py new file mode 100644 index 0000000..e462e3a --- /dev/null +++ b/service_line_qty_update_base/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2020 Akretion France (http://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Service Line Qty Update Base', + 'version': '12.0.1.0.0', + 'category': 'Tools', + 'license': 'AGPL-3', + 'summary': 'Update delivery qty on service lines - Base module', + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['product'], + 'data': [ + 'wizard/service_qty_update_view.xml', + ], + 'installable': True, +} diff --git a/service_line_qty_update_base/wizard/__init__.py b/service_line_qty_update_base/wizard/__init__.py new file mode 100644 index 0000000..c0ac3f4 --- /dev/null +++ b/service_line_qty_update_base/wizard/__init__.py @@ -0,0 +1 @@ +from . import service_qty_update diff --git a/service_line_qty_update_base/wizard/service_qty_update.py b/service_line_qty_update_base/wizard/service_qty_update.py new file mode 100644 index 0000000..7358e47 --- /dev/null +++ b/service_line_qty_update_base/wizard/service_qty_update.py @@ -0,0 +1,70 @@ +# Copyright 2020 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import _, api, fields, models +from odoo.tools import float_compare, float_is_zero +import odoo.addons.decimal_precision as dp +from odoo.exceptions import UserError + + +class ServiceQtyUpdate(models.TransientModel): + _name = 'service.qty.update' + _description = 'Wizard to update delivery qty on service lines' + + line_ids = fields.One2many('service.qty.update.line', 'parent_id', string="Lines") + + def run(self): + self.ensure_one() + prec = self.env['decimal.precision'].precision_get('Product Unit of Measure') + for line in self: + if float_compare(line.post_delivered_qty, line.order_qty, precision_digits=prec) > 0: + raise UserError(_( + "On line '%s', the total delivered qty (%s) is superior to the ordered qty (%s).") % (line.name, line.post_delivered_qty, line.order_qty)) + fc_added = float_compare(line.added_delivered_qty, 0, precision_digits=prec) + if fc_added < 0: + raise UserError(_( + "On line '%s', the added quantity is negative.") % line.name) + if fc_added > 0: + line.process_line() + return True + + +class ServiceQtyUpdateLine(models.TransientModel): + _name = 'service.qty.update.line' + _description = 'Lines of the wizard that updates delivery qty on service lines' + + parent_id = fields.Many2one( + 'service.qty.update', string='Wizard', ondelete='cascade') + product_id = fields.Many2one('product.product', string='Product', readonly=True) + name = fields.Char(string='Description', readonly=True) + order_qty = fields.Float( + string='Order Qty', + digits=dp.get_precision('Product Unit of Measure'), + readonly=True) + pre_delivered_qty = fields.Float( + string='Current Delivered Qty', + digits=dp.get_precision('Product Unit of Measure'), + readonly=True) + added_delivered_qty = fields.Float( + string='Added Delivered Qty', + digits=dp.get_precision('Product Unit of Measure')) + post_delivered_qty = fields.Float( + compute='_compute_post_delivered_qty', + string='Total Delivered Qty', + digits=dp.get_precision('Product Unit of Measure')) + uom_id = fields.Many2one('uom.uom', string='UoM', readonly=True) + comment = fields.Char(string='Comment') + + @api.depends('pre_delivered_qty', 'added_delivered_qty') + def _compute_post_delivered_qty(self): + for line in self: + line.post_delivered_qty = line.pre_delivered_qty + line.added_delivered_qty + + def process_line(self): + # Write and message_post + return + + # sale : qty_delivered + # purchase : qty_received diff --git a/service_line_qty_update_base/wizard/service_qty_update_view.xml b/service_line_qty_update_base/wizard/service_qty_update_view.xml new file mode 100644 index 0000000..6965cee --- /dev/null +++ b/service_line_qty_update_base/wizard/service_qty_update_view.xml @@ -0,0 +1,45 @@ + + + + + + + + service.qty.update + +
+ + + + + + + + + + + + + + +
+
+
+
+
+ + + Service Order Lines - Update Delivered Qty + service.qty.update + form + new + + + +
diff --git a/service_line_qty_update_purchase/__init__.py b/service_line_qty_update_purchase/__init__.py new file mode 100644 index 0000000..9b42961 --- /dev/null +++ b/service_line_qty_update_purchase/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/service_line_qty_update_purchase/__manifest__.py b/service_line_qty_update_purchase/__manifest__.py new file mode 100644 index 0000000..554df7f --- /dev/null +++ b/service_line_qty_update_purchase/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2020 Akretion France (http://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Service Line Qty Update Purchase', + 'version': '12.0.1.0.0', + 'category': 'Tools', + 'license': 'AGPL-3', + 'summary': 'Update delivery qty on service lines - Purchase module', + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['purchase'], + 'data': [ + 'views/purchase_order.xml', + ], + 'installable': True, +} diff --git a/service_line_qty_update_purchase/models/__init__.py b/service_line_qty_update_purchase/models/__init__.py new file mode 100644 index 0000000..9f03530 --- /dev/null +++ b/service_line_qty_update_purchase/models/__init__.py @@ -0,0 +1 @@ +from . import purchase_order diff --git a/service_line_qty_update_purchase/models/purchase_order.py b/service_line_qty_update_purchase/models/purchase_order.py new file mode 100644 index 0000000..89b09be --- /dev/null +++ b/service_line_qty_update_purchase/models/purchase_order.py @@ -0,0 +1,20 @@ +# Copyright 2020 Akretion France (http://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class PurchaseOrder(models.Model): + _inherit = 'purchase.order' + + has_service = fields.Boolean(compute='_compute_has_service') + + def _compute_has_service(self): + for order in self: + has_service = False + for l in order.order_line: + if l.product_id.type == 'service': + has_service = True + break + order.has_service = has_service diff --git a/service_line_qty_update_purchase/views/purchase_order.xml b/service_line_qty_update_purchase/views/purchase_order.xml new file mode 100644 index 0000000..1937f8d --- /dev/null +++ b/service_line_qty_update_purchase/views/purchase_order.xml @@ -0,0 +1,27 @@ + + + + + + + + purchase.order.form + purchase.order + + + + + 1 + + + + + + diff --git a/service_line_qty_update_purchase/wizard/__init__.py b/service_line_qty_update_purchase/wizard/__init__.py new file mode 100644 index 0000000..c0ac3f4 --- /dev/null +++ b/service_line_qty_update_purchase/wizard/__init__.py @@ -0,0 +1 @@ +from . import service_qty_update diff --git a/service_line_qty_update_purchase/wizard/service_qty_update.py b/service_line_qty_update_purchase/wizard/service_qty_update.py new file mode 100644 index 0000000..e167f48 --- /dev/null +++ b/service_line_qty_update_purchase/wizard/service_qty_update.py @@ -0,0 +1,58 @@ +# Copyright 2020 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import _, api, fields, models +from odoo.tools import float_compare +from odoo.exceptions import UserError + + +class ServiceQtyUpdate(models.TransientModel): + _inherit = 'service.qty.update' + + @api.model + def default_get(self, fields_list): + res = super().default_get(fields_list) + prec = self.env['decimal.precision'].precision_get('Product Unit of Measure') + if self._context.get('active_model') == 'purchase.order' and self._context.get('active_id'): + lines = [] + order = self.env['purchase.order'].browse(self._context['active_id']) + for l in order.order_line.filtered(lambda x: x.product_id.type == 'service'): + if float_compare(l.product_qty, l.qty_received, precision_digits=prec) > 0: + lines.append((0, 0, { + 'purchase_line_id': l.id, + 'product_id': l.product_id.id, + 'name': l.name, + 'order_qty': l.product_qty, + 'pre_delivered_qty': l.qty_received, + 'uom_id': l.product_uom.id, + })) + if lines: + res['line_ids'] = lines + else: + raise UserError(_( + "All service lines are fully received.")) + return res + + +class ServiceQtyUpdateLine(models.TransientModel): + _inherit = 'service.qty.update.line' + + purchase_line_id = fields.Many2one('purchase.order.line', string='Purchase Line', readonly=True) + + def process_line(self): + po_line = self.purchase_line_id + if po_line: + po_line.write({'qty_received': self.post_delivered_qty}) + body = """ +

Received qty updated on service line %s: +

    +
  • Added received qty: %s
  • +
  • Total received qty: %s
  • +

+ """ % (self.added_delivered_qty, self.post_delivered_qty) + if self.comment: + body += '

Comment: %s

' % self.comment + po_line.order_id.message_post(body=body) + return super().process_line()