diff --git a/service_line_qty_update_purchase/models/purchase_order.py b/service_line_qty_update_purchase/models/purchase_order.py
index 89b09be..9cb17cd 100644
--- a/service_line_qty_update_purchase/models/purchase_order.py
+++ b/service_line_qty_update_purchase/models/purchase_order.py
@@ -2,7 +2,7 @@
# @author Alexis de Lattre
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-from odoo import fields, models
+from odoo import api, fields, models
class PurchaseOrder(models.Model):
@@ -10,6 +10,7 @@ class PurchaseOrder(models.Model):
has_service = fields.Boolean(compute='_compute_has_service')
+ @api.depends('order_line.product_id.type')
def _compute_has_service(self):
for order in self:
has_service = False
diff --git a/service_line_qty_update_sale/__init__.py b/service_line_qty_update_sale/__init__.py
new file mode 100644
index 0000000..9b42961
--- /dev/null
+++ b/service_line_qty_update_sale/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import wizard
diff --git a/service_line_qty_update_sale/__manifest__.py b/service_line_qty_update_sale/__manifest__.py
new file mode 100644
index 0000000..45c850d
--- /dev/null
+++ b/service_line_qty_update_sale/__manifest__.py
@@ -0,0 +1,22 @@
+# 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 Sale',
+ 'version': '12.0.1.0.0',
+ 'category': 'Tools',
+ 'license': 'AGPL-3',
+ 'summary': 'Update delivery qty on service lines - Sale module',
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com',
+ 'depends': [
+ 'sale',
+ 'service_line_qty_update_base',
+ # 'purchase_reception_status',
+ ],
+ 'data': [
+ 'views/sale_order.xml',
+ ],
+ 'installable': True,
+}
diff --git a/service_line_qty_update_sale/models/__init__.py b/service_line_qty_update_sale/models/__init__.py
new file mode 100644
index 0000000..6aacb75
--- /dev/null
+++ b/service_line_qty_update_sale/models/__init__.py
@@ -0,0 +1 @@
+from . import sale_order
diff --git a/service_line_qty_update_sale/models/sale_order.py b/service_line_qty_update_sale/models/sale_order.py
new file mode 100644
index 0000000..802625f
--- /dev/null
+++ b/service_line_qty_update_sale/models/sale_order.py
@@ -0,0 +1,21 @@
+# 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
+
+
+class SaleOrder(models.Model):
+ _inherit = 'sale.order'
+
+ has_service = fields.Boolean(compute='_compute_has_service')
+
+ @api.depends('order_line.product_id.type')
+ 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_sale/views/sale_order.xml b/service_line_qty_update_sale/views/sale_order.xml
new file mode 100644
index 0000000..04ebf16
--- /dev/null
+++ b/service_line_qty_update_sale/views/sale_order.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ sale.order
+
+
+
+
+ 1
+
+
+
+
+
+
diff --git a/service_line_qty_update_sale/wizard/__init__.py b/service_line_qty_update_sale/wizard/__init__.py
new file mode 100644
index 0000000..c0ac3f4
--- /dev/null
+++ b/service_line_qty_update_sale/wizard/__init__.py
@@ -0,0 +1 @@
+from . import service_qty_update
diff --git a/service_line_qty_update_sale/wizard/service_qty_update.py b/service_line_qty_update_sale/wizard/service_qty_update.py
new file mode 100644
index 0000000..8be21ec
--- /dev/null
+++ b/service_line_qty_update_sale/wizard/service_qty_update.py
@@ -0,0 +1,62 @@
+# 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') == 'sale.order' and self._context.get('active_id'):
+ lines = []
+ order = self.env['sale.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_delivered, precision_digits=prec) > 0:
+ lines.append((0, 0, {
+ 'sale_line_id': l.id,
+ 'product_id': l.product_id.id,
+ 'name': l.name,
+ 'name_readonly': l.name,
+ 'order_qty': l.product_uom_qty,
+ 'order_qty_readonly': l.product_uom_qty,
+ 'pre_delivered_qty': l.qty_delivered,
+ 'pre_delivered_qty_readonly': l.qty_delivered,
+ 'uom_id': l.product_uom.id,
+ }))
+ if lines:
+ res['line_ids'] = lines
+ else:
+ raise UserError(_(
+ "All service lines are fully delivered."))
+ return res
+
+
+class ServiceQtyUpdateLine(models.TransientModel):
+ _inherit = 'service.qty.update.line'
+
+ sale_line_id = fields.Many2one('sale.order.line', string='Sale Line', readonly=True)
+
+ def process_line(self):
+ so_line = self.sale_line_id
+ if so_line:
+ new_qty = so_line.qty_delivered + self.added_delivered_qty
+ so_line.write({'qty_delivered': new_qty})
+ body = """
+ Delivered qty updated on service line %s:
+
+ - Added delivered qty: %s
+ - Total delivered qty: %s
+
+ """ % (self.name, self.added_delivered_qty, new_qty)
+ if self.comment:
+ body += 'Comment: %s
' % self.comment
+ so_line.order_id.message_post(body=body)
+ return super().process_line()