From cc28c814250cc022ede7f001ef76c4af188735bf Mon Sep 17 00:00:00 2001 From: houssine Date: Fri, 28 Jul 2017 18:42:18 +0200 Subject: [PATCH 01/39] [ADD] manage the product distribution through a delivery distribution list. still in WIP --- delivery_distribution_list/__init__.py | 1 + delivery_distribution_list/__openerp__.py | 42 ++++ delivery_distribution_list/models/__init__.py | 4 + .../models/delivery_distribution_list.py | 200 ++++++++++++++++++ delivery_distribution_list/models/invoice.py | 9 + delivery_distribution_list/models/partner.py | 13 ++ .../models/sale_order.py | 14 ++ .../delivery_distribution_list_security.xml | 14 ++ .../security/ir.model.access.csv | 7 + .../views/delivery_distribution_list_view.xml | 126 +++++++++++ .../views/invoice_view.xml | 28 +++ .../views/partner_view.xml | 35 +++ .../views/sale_view.xml | 16 ++ 13 files changed, 509 insertions(+) create mode 100644 delivery_distribution_list/__init__.py create mode 100644 delivery_distribution_list/__openerp__.py create mode 100644 delivery_distribution_list/models/__init__.py create mode 100644 delivery_distribution_list/models/delivery_distribution_list.py create mode 100644 delivery_distribution_list/models/invoice.py create mode 100644 delivery_distribution_list/models/partner.py create mode 100644 delivery_distribution_list/models/sale_order.py create mode 100644 delivery_distribution_list/security/delivery_distribution_list_security.xml create mode 100644 delivery_distribution_list/security/ir.model.access.csv create mode 100644 delivery_distribution_list/views/delivery_distribution_list_view.xml create mode 100644 delivery_distribution_list/views/invoice_view.xml create mode 100644 delivery_distribution_list/views/partner_view.xml create mode 100644 delivery_distribution_list/views/sale_view.xml diff --git a/delivery_distribution_list/__init__.py b/delivery_distribution_list/__init__.py new file mode 100644 index 000000000..9a7e03ede --- /dev/null +++ b/delivery_distribution_list/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/delivery_distribution_list/__openerp__.py b/delivery_distribution_list/__openerp__.py new file mode 100644 index 000000000..fcf11c265 --- /dev/null +++ b/delivery_distribution_list/__openerp__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Business Open Source Solution +# Copyright (C) 2013-2016 Coop IT Easy SPRL. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + "name": "Delivery distribution Management", + "version": "1.0", + "depends": [ + "sale", + "account", + ], + "author": "Houssine BAKKALI ", + "category": "Sales", + "description": """ + This module manage the distribution of a product on a through all the sale/deposit + points, it manages the recurring order through the list of distribution. + """, + 'data': [ + 'security/delivery_distribution_list_security.xml', + 'security/ir.model.access.csv', + 'views/partner_view.xml', + 'views/sale_view.xml', + 'views/delivery_distribution_list_view.xml', + ], + 'installable': True, +} \ No newline at end of file diff --git a/delivery_distribution_list/models/__init__.py b/delivery_distribution_list/models/__init__.py new file mode 100644 index 000000000..3c9b9dd85 --- /dev/null +++ b/delivery_distribution_list/models/__init__.py @@ -0,0 +1,4 @@ +from . import invoice +from . import partner +from . import sale_order +from . import delivery_distribution_list \ No newline at end of file diff --git a/delivery_distribution_list/models/delivery_distribution_list.py b/delivery_distribution_list/models/delivery_distribution_list.py new file mode 100644 index 000000000..1316f0999 --- /dev/null +++ b/delivery_distribution_list/models/delivery_distribution_list.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- + +from openerp import api, fields, models, _ +import openerp.addons.decimal_precision as dp + +from openerp.exceptions import UserError + +class DeliveryDistributionList(models.Model): + _name = 'delivery.distribution.list' + + name = fields.Char(string="Name") + distribution_date = fields.Date(string='Distribution Date', readonly=True, required=True, index=True, states={'draft': [('readonly', False)]}) + create_date = fields.Date(string='Creation Date', readonly=True, help="Date on which distribution list is created.", copy=False, default=fields.Datetime.now) + + user_id = fields.Many2one('res.users', string='Distribution responsible', index=True, copy=False, default=lambda self: self.env.user) + product_id = fields.Many2one('product.template', string='Product', required=True, readonly=True, states={'draft': [('readonly', False)]}) + distribution_lines = fields.One2many('delivery.distribution.line','distribution_list_id', string="Distribution lines", copy=False) + + state = fields.Selection([ + ('draft', 'Draft'), + ('validated', 'Validated'), + ('sale', 'Sale Order'), + ('sale_sent', 'Sale order sent'), + ('invoiced', 'Invoiced'), + ('invoice_validated', 'Invoice validated'), + ('invoice_sent', 'Invoice sent'), + ('cancelled', 'Cancelled'), + ], string='State', readonly=True, copy=False, default='draft') + + @api.one + def action_validate(self): + self.distribution_lines.write({'state':'validated'}) + self.state = 'validated' + + @api.one + def action_draft(self): + self.distribution_lines.write({'state':'draft'}) + self.state = 'draft' + + @api.one + def action_sale(self): + self.distribution_lines.generate_sale_order() + self.state = 'sale' + + @api.one + def action_send_sale_order(self): + self.distribution_lines.send_sale_order() + self.state = 'sale_sent' + + @api.one + def action_invoice(self): + self.distribution_lines.invoice_sale_order() + self.state = 'invoiced' + + @api.one + def action_validate_invoice(self): + self.distribution_lines.validate_invoice() + self.state = 'invoice_validated' + + @api.one + def action_send_invoice(self): + self.distribution_lines.send_invoice() + self.state = 'invoice_sent' + + @api.one + def action_cancel(self): + self.state = 'cancelled' + + @api.one + def generate_distribution_list(self): + deposit_points = self.env['res.partner'].search([('deposit_point','=',True)]) + + #delete existing lines if any + if self.state == 'draft': + self.distribution_lines.unlink() + + vals = {'distribution_list_id':self.id, 'product_id':self.product_id.id} + + for deposit_point in deposit_points: + if deposit_point.quantity_to_deliver > 0.0: + vals['partner_id'] = deposit_point.id + vals['carrier_id'] = deposit_point.carrier_id.id + vals['ordered_qty'] = deposit_point.quantity_to_deliver + vals['delivered_qty'] = deposit_point.quantity_to_deliver + self.env['delivery.distribution.line'].create(vals) + + @api.multi + def unlink(self): + for distri_list in self: + if distri_list.state != 'draft': + raise UserError(_('It is forbidden to modify a distribution list which is not in draft status')) + super(DeliveryDistributionList,self).unlink() + +class DeliveryDistributionLine(models.Model): + _name = 'delivery.distribution.line' + + _order = 'partner_id, date' + + @api.multi + def _compute_sold_qty(self): + for line in self: + line.sold_qty = line.delivered_qty - line.returned_qty + + distribution_list_id = fields.Many2one('delivery.distribution.list', string="Distribution list", required=True) + partner_id = fields.Many2one('res.partner', string="Customer", domain=[('deposit_point','=',True)]) + product_id = fields.Many2one('product.template', string='Product', required=True) + date = fields.Date(string='Creation Date', readonly=True, help="Date on which distribution line is created.", default=fields.Datetime.now) + product_uom = fields.Many2one(related='product_id.uom_id', string='Unit of Measure', readonly=True) + ordered_qty = fields.Float(string="Quantity Ordered", digits=dp.get_precision('Product Unit of Measure'), required=True) + delivered_qty = fields.Float(string="Quantity Delivered", digits=dp.get_precision('Product Unit of Measure'), default=0.0, required=True) + returned_qty = fields.Float(string="Quantity Returned", digits=dp.get_precision('Product Unit of Measure'), default=0.0, required=True) + sold_qty = fields.Float(string="Quantity Sold", digits=dp.get_precision('Product Unit of Measure'), compute='_compute_sold_qty') + carrier_id = fields.Many2one('res.partner', string="Assigned carrier", readonly=True) + + state = fields.Selection([ + ('draft', 'Draft'), + ('validated', 'Validated'), + ('sale', 'Sale Order'), + ('sale_sent', 'Sale order sent'), + ('invoiced', 'Invoiced'), + ('invoice_validated', 'Invoice validated'), + ('invoice_sent', 'Invoice sent'), + ('cancelled', 'Cancelled'), + ], string='State', readonly=True, copy=False, index=True, default='draft') + + sale_order = fields.Many2one('sale.order', string="Sale Order", readonly=True) +# invoices = fields.One2many('account.invoice','distribution_line_id', string="Invoice", readonly=True) + + @api.one + def unlink(self): + if self.state != 'draft': + raise UserError(_('It is forbidden to modify a distribution list which is not in draft status')) + super(DeliveryDistributionLine,self).unlink() + + @api.multi + def generate_sale_order(self): + sale_order_obj = self.env['sale.order'] + order_line_obj = self.env['sale.order.line'] + for line in self: + vals = { + 'partner_id':line.partner_id.id, + } + order_id = sale_order_obj.create(vals) + vals_line = { + 'product_id':line.product_id.id, + 'product_uom_qty':line.delivered_qty, + 'product_uom':line.product_uom.id, + 'order_id':order_id.id + } + order_line_obj.create(vals_line) + line.sale_order = order_id + order_id.action_confirm() + line.state = 'sale' + + @api.multi + def send_sale_order(self): + ir_model_data = self.env['ir.model.data'] + mail_template_obj = self.env['mail.template'] + mail_template_id = ir_model_data.get_object_reference('sale', 'email_template_edi_sale')[1] + mail_template = mail_template_obj.browse(mail_template_id) + for line in self: + mail_template.send_mail(line.sale_order.id, False) + line.state = 'sale_sent' + + @api.multi + def invoice_sale_order(self): + for line in self: + if line.state in ['sale','sale_sent']: + picking_ids = line.sale_order.picking_ids.ids + pickings = self.env['stock.picking'].search([('id','in',picking_ids), + ('origin','=',line.sale_order.name)]) + for picking in pickings: + if picking.state not in ['cancel','done']: + if picking.state != 'assigned': + picking.recheck_availability() + for pack_operation in picking.pack_operation_ids: + if pack_operation.product_id.id == line.product_id.product_variant_ids.id: + pack_operation.qty_done = line.sold_qty + if line.sold_qty < line.delivered_qty: + pack_operation.product_qty = line.sold_qty + picking.do_transfer() + if line.sold_qty < line.delivered_qty: + backorder_pick = self.env['stock.picking'].search([('backorder_id', '=', picking.id)]) + backorder_pick.action_cancel() + picking.message_post(body=_("Back order %s cancelled.") % (backorder_pick.name)) + line.sale_order.action_invoice_create() + line.state = 'invoiced' + + @api.multi + def validate_invoice(self): + for line in self: + if line.state == 'invoiced': + line.sale_order.invoice_ids.signal_workflow('invoice_open') + line.state = 'invoice_validated' + @api.multi + def send_invoice(self): + mail_template = self.env.ref('account.email_template_edi_invoice', False) + for line in self: + mail_template.send_mail(line.sale_order.invoice_ids.id, False) + line.state = 'sale_sent' \ No newline at end of file diff --git a/delivery_distribution_list/models/invoice.py b/delivery_distribution_list/models/invoice.py new file mode 100644 index 000000000..5284901cc --- /dev/null +++ b/delivery_distribution_list/models/invoice.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +from openerp import api, fields, models, _ + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + deposit_point = fields.Boolean(string="Deposit/Sale", readonly=True) + \ No newline at end of file diff --git a/delivery_distribution_list/models/partner.py b/delivery_distribution_list/models/partner.py new file mode 100644 index 000000000..f29a8dd10 --- /dev/null +++ b/delivery_distribution_list/models/partner.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +from openerp import api, fields, models, _ + +class ResPartner(models.Model): + _inherit = 'res.partner' + + quantity_to_deliver = fields.Float(string="Default quantity to deliver") + deposit_point = fields.Boolean(string="Deposit/Sale") + carrier_delivery = fields.Boolean(string="Carrier delivery") + carrier_id = fields.Many2one('res.partner', string="Assigned carrier", domain=[('carrier_delivery','=',True)]) + + \ No newline at end of file diff --git a/delivery_distribution_list/models/sale_order.py b/delivery_distribution_list/models/sale_order.py new file mode 100644 index 000000000..42ad1c021 --- /dev/null +++ b/delivery_distribution_list/models/sale_order.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +from openerp import api, fields, models, _ + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + carrier_id = fields.Many2one('res.partner', string="Assigned carrier", readonly=True) + distribution_list_id = fields.Many2one('delivery.distribution.list', string="Distribution list", readonly=True) + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + carrier_id = fields.Many2one('res.partner', string="Assigned carrier", readonly=True) \ No newline at end of file diff --git a/delivery_distribution_list/security/delivery_distribution_list_security.xml b/delivery_distribution_list/security/delivery_distribution_list_security.xml new file mode 100644 index 000000000..5062d3a2e --- /dev/null +++ b/delivery_distribution_list/security/delivery_distribution_list_security.xml @@ -0,0 +1,14 @@ + + + + + Distribution User + + + + Distribution Manager + + + + + \ No newline at end of file diff --git a/delivery_distribution_list/security/ir.model.access.csv b/delivery_distribution_list/security/ir.model.access.csv new file mode 100644 index 000000000..e2b522751 --- /dev/null +++ b/delivery_distribution_list/security/ir.model.access.csv @@ -0,0 +1,7 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_partner_distribution_manager,res.partner,model_res_partner,group_distribution_user,1,0,0,0 +access_res_partner_distribution_manager,res.partner,model_res_partner,group_distribution_manager,1,1,1,0 +access_delivery_distribution_list_user,delivery.distribution.list,model_delivery_distribution_list,group_distribution_user,1,1,0,0 +access_delivery_distribution_list_manager,delivery.distribution.list,model_delivery_distribution_list,group_distribution_manager,1,1,1,1 +access_delivery_distribution_line_user,delivery.distribution.line,model_delivery_distribution_line,group_distribution_user,1,1,0,0 +access_delivery_distribution_line_manager,delivery.distribution.line,model_delivery_distribution_line,group_distribution_manager,1,1,1,1 diff --git a/delivery_distribution_list/views/delivery_distribution_list_view.xml b/delivery_distribution_list/views/delivery_distribution_list_view.xml new file mode 100644 index 000000000..f8561ef4a --- /dev/null +++ b/delivery_distribution_list/views/delivery_distribution_list_view.xml @@ -0,0 +1,126 @@ + + + + + delivery.distribution.list.form + delivery.distribution.list + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+
+ + + delivery.distribution.list.tree + delivery.distribution.list + + + + + + + + + + + + delivery.distribution.list.select + delivery.distribution.list + + + + + + + + + + + + + + + + + + + + + + + Delivery Distribution List + ir.actions.act_window + delivery.distribution.list + form + tree,form + + + + +
+
\ No newline at end of file diff --git a/delivery_distribution_list/views/invoice_view.xml b/delivery_distribution_list/views/invoice_view.xml new file mode 100644 index 000000000..d3ab35304 --- /dev/null +++ b/delivery_distribution_list/views/invoice_view.xml @@ -0,0 +1,28 @@ + + + + + account.invoice.tree + account.invoice + + + + + + + + account.invoice.form + account.invoice + + + + + + + \ No newline at end of file diff --git a/delivery_distribution_list/views/partner_view.xml b/delivery_distribution_list/views/partner_view.xml new file mode 100644 index 000000000..9db1dfd39 --- /dev/null +++ b/delivery_distribution_list/views/partner_view.xml @@ -0,0 +1,35 @@ + + + + + + + res.partner.form.ddl + res.partner + + + + + + + + + + + + + + + + + Carriers + res.partner + form + {"default_customer":0,"default_supplier":1,"default_carrier_delivery":1} + [('carrier_delivery','=',True)] + + + + + + \ No newline at end of file diff --git a/delivery_distribution_list/views/sale_view.xml b/delivery_distribution_list/views/sale_view.xml new file mode 100644 index 000000000..0ce92eb97 --- /dev/null +++ b/delivery_distribution_list/views/sale_view.xml @@ -0,0 +1,16 @@ + + + + + sale.order.form.ddl + sale.order + + + + + + + + + + \ No newline at end of file From 8b73db9d9b1d141b8f9c64f4481b2630e1ba96ea Mon Sep 17 00:00:00 2001 From: houssine Date: Fri, 28 Jul 2017 19:17:40 +0200 Subject: [PATCH 02/39] [IMP]adding state done to distribution list and corresponding state function --- .../models/delivery_distribution_list.py | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/delivery_distribution_list/models/delivery_distribution_list.py b/delivery_distribution_list/models/delivery_distribution_list.py index 1316f0999..6934f25c0 100644 --- a/delivery_distribution_list/models/delivery_distribution_list.py +++ b/delivery_distribution_list/models/delivery_distribution_list.py @@ -24,6 +24,7 @@ class DeliveryDistributionList(models.Model): ('invoiced', 'Invoiced'), ('invoice_validated', 'Invoice validated'), ('invoice_sent', 'Invoice sent'), + ('done', 'Done'), ('cancelled', 'Cancelled'), ], string='State', readonly=True, copy=False, default='draft') @@ -37,6 +38,10 @@ def action_draft(self): self.distribution_lines.write({'state':'draft'}) self.state = 'draft' + @api.one + def action_done(self): + self.state = 'done' + @api.one def action_sale(self): self.distribution_lines.generate_sale_order() @@ -131,7 +136,19 @@ def unlink(self): if self.state != 'draft': raise UserError(_('It is forbidden to modify a distribution list which is not in draft status')) super(DeliveryDistributionLine,self).unlink() + + @api.multi + def action_validate(self): + for line in self: + if line == 'draft': + line.state = 'validated' + @api.multi + def action_draft(self): + for line in self: + if line == 'validated': + line.state = 'draft' + @api.multi def generate_sale_order(self): sale_order_obj = self.env['sale.order'] @@ -192,9 +209,11 @@ def validate_invoice(self): if line.state == 'invoiced': line.sale_order.invoice_ids.signal_workflow('invoice_open') line.state = 'invoice_validated' + @api.multi def send_invoice(self): mail_template = self.env.ref('account.email_template_edi_invoice', False) for line in self: - mail_template.send_mail(line.sale_order.invoice_ids.id, False) - line.state = 'sale_sent' \ No newline at end of file + if line.state == 'invoice_validated': + mail_template.send_mail(line.sale_order.invoice_ids.id, False) + line.state = 'sale_sent' \ No newline at end of file From 39b2708ce261aadf20aab09a71be127da93eeb5f Mon Sep 17 00:00:00 2001 From: houssine Date: Fri, 28 Jul 2017 19:18:29 +0200 Subject: [PATCH 03/39] [IMP] adding action button at line level. Still in WIP --- .../views/delivery_distribution_list_view.xml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/delivery_distribution_list/views/delivery_distribution_list_view.xml b/delivery_distribution_list/views/delivery_distribution_list_view.xml index f8561ef4a..9d1987d75 100644 --- a/delivery_distribution_list/views/delivery_distribution_list_view.xml +++ b/delivery_distribution_list/views/delivery_distribution_list_view.xml @@ -9,12 +9,13 @@
@@ -30,7 +31,8 @@ - + @@ -42,6 +44,14 @@ +