diff --git a/delivery_distribution_list/README.rst b/delivery_distribution_list/README.rst new file mode 100644 index 000000000..6c9c63711 --- /dev/null +++ b/delivery_distribution_list/README.rst @@ -0,0 +1,60 @@ +================================ +Delivery distribution Management +================================ + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-coopiteasy%2Faddons-lightgray.png?logo=github + :target: https://github.com/coopiteasy/addons/tree/14.0/delivery_distribution_list + :alt: coopiteasy/addons + +|badge1| |badge2| |badge3| + +This module manage the distribution of a product through all the sale/deposit +points, it manages the recurring order through the list of distribution. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Coop IT Easy SC + +Contributors +~~~~~~~~~~~~ + +* `Coop IT Easy SC `_: + + * Houssine Bakkali + +Maintainers +~~~~~~~~~~~ + +This module is part of the `coopiteasy/addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/delivery_distribution_list/__init__.py b/delivery_distribution_list/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/delivery_distribution_list/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/delivery_distribution_list/__manifest__.py b/delivery_distribution_list/__manifest__.py new file mode 100644 index 000000000..42da23651 --- /dev/null +++ b/delivery_distribution_list/__manifest__.py @@ -0,0 +1,25 @@ +{ + "name": "Delivery distribution Management", + "summary": """ + Manage the distribution of a product through all the deposit points. + """, + "author": "Coop IT Easy SC", + "license": "AGPL-3", + "version": "14.0.1.0.0", + "website": "https://coopiteasy.be", + "category": "Sales", + "depends": [ + "sale_management", + "account", + ], + "data": [ + "security/delivery_distribution_list_security.xml", + "security/ir.model.access.csv", + "data/ddl_data.xml", + "views/delivery_distribution_list_view.xml", + "views/partner_view.xml", + "views/sale_view.xml", + "views/product_view.xml", + "report/sale_order_report_template.xml", + ], +} diff --git a/delivery_distribution_list/data/ddl_data.xml b/delivery_distribution_list/data/ddl_data.xml new file mode 100644 index 000000000..714398863 --- /dev/null +++ b/delivery_distribution_list/data/ddl_data.xml @@ -0,0 +1,10 @@ + + + + + Delivery Distribution List + + DDL/%(year)s/ + + + diff --git a/delivery_distribution_list/models/__init__.py b/delivery_distribution_list/models/__init__.py new file mode 100644 index 000000000..69d95f8dd --- /dev/null +++ b/delivery_distribution_list/models/__init__.py @@ -0,0 +1,5 @@ +from . import invoice +from . import partner +from . import sale_order +from . import delivery_distribution_list +from . import product 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..72d2102f4 --- /dev/null +++ b/delivery_distribution_list/models/delivery_distribution_list.py @@ -0,0 +1,307 @@ +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class DeliveryDistributionList(models.Model): + _name = "delivery.distribution.list" + + name = fields.Char(string="Name", copy=False) + 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", + domain=[("sale_ok", "=", True)], + required=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + distribution_lines = fields.One2many( + "delivery.distribution.line", + "distribution_list_id", + string="Distribution lines", + copy=False, + ) + journal_id = fields.Many2one( + "account.journal", + string="Journal", + domain=[("type", "=", "sale")], + required=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"), + ("done", "Done"), + ("cancelled", "Cancelled"), + ], + string="State", + readonly=True, + copy=False, + default="draft", + ) + + def action_validate(self): + self.ensure_one() + self.distribution_lines.write({"state": "validated"}) + self.state = "validated" + + def action_draft(self): + self.ensure_one() + self.distribution_lines.write({"state": "draft"}) + self.state = "draft" + + def action_done(self): + self.ensure_one() + self.state = "done" + + def action_sale(self): + self.ensure_one() + self.distribution_lines.generate_sale_order() + self.state = "sale" + + def action_send_sale_order(self): + self.ensure_one() + self.distribution_lines.send_sale_order() + self.state = "sale_sent" + + def action_invoice(self): + self.ensure_one() + self.distribution_lines.invoice_sale_order() + self.state = "invoiced" + + def action_validate_invoice(self): + self.ensure_one() + self.distribution_lines.validate_invoice() + self.state = "invoice_validated" + + def action_send_invoice(self): + self.ensure_one() + self.distribution_lines.send_invoice() + self.state = "invoice_sent" + + def action_cancel(self): + self.ensure_one() + self.state = "cancelled" + + def generate_distribution_list(self): + self.ensure_one() + deposit_points = self.env["res.partner"].search([("deposit_point", "=", True)]) + + # delete existing lines if any + if self.state == "draft": + if not self.name: + ddl_seq = self.env.ref("delivery_distribution_list.sequence_ddl", False) + self.name = ddl_seq.next_by_id() + 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) + + 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 = "distribution_list_id desc, partner_id, date" + + 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)], + required=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="Product Unit of Measure", + required=True, + ) + delivered_qty = fields.Float( + string="Quantity Delivered", + digits="Product Unit of Measure", + default=0.0, + required=True, + ) + returned_qty = fields.Float( + string="Quantity Returned", + digits="Product Unit of Measure", + default=0.0, + required=True, + ) + sold_qty = fields.Float( + string="Quantity Sold", + digits="Product Unit of Measure", + compute="_compute_sold_qty", + ) + carrier_id = fields.Many2one( + "res.partner", + string="Assigned carrier", + domain=[("carrier_delivery", "=", True)], + readonly=True, + required=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) + + def unlink(self): + self.ensure_one() + if self.state != "draft": + raise UserError( + _( + "It is forbidden to modify a distribution list which is not in draft status" + ) + ) + super(DeliveryDistributionLine, self).unlink() + + def action_validate(self): + for line in self: + if line.state == "draft": + line.state = "validated" + + def action_draft(self): + for line in self: + if line.state == "validated": + line.state = "draft" + + 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, + "distribution_list_id": line.distribution_list_id.id, + "distribution_carrier_id": line.carrier_id.id, + "project_id": line.product_id.analytic_account_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" + + 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" + + def invoice_sale_order(self): + for line in self: + if line.state in ["sale", "sale_sent"]: + if line.sale_order.invoice_status == "to invoice": + line.sale_order.action_invoice_create() + line.sale_order.invoice_ids.journal_id = ( + line.distribution_list_id.journal_id + ) + line.state = "invoiced" + + 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" + + def send_invoice(self): + mail_template = self.env.ref("account.email_template_edi_invoice", False) + for line in self: + if line.state == "invoice_validated": + mail_template.send_mail(line.sale_order.invoice_ids.id, False) + line.state = "invoice_sent" + + @api.onchange("partner_id") + def onchage_partner_id(self): + self.delivered_qty = self.partner_id.quantity_to_deliver + self.ordered_qty = self.partner_id.quantity_to_deliver + self.carrier_id = self.partner_id.carrier_id.id + + @api.onchange("ordered_qty") + def onchage_orderer_qty(self): + self.delivered_qty = self.ordered_qty diff --git a/delivery_distribution_list/models/invoice.py b/delivery_distribution_list/models/invoice.py new file mode 100644 index 000000000..6d26a1aca --- /dev/null +++ b/delivery_distribution_list/models/invoice.py @@ -0,0 +1,7 @@ +from odoo import fields, models + + +class AccountMove(models.Model): + _inherit = "account.move" + + deposit_point = fields.Boolean(string="Deposit/Sale", readonly=True) diff --git a/delivery_distribution_list/models/partner.py b/delivery_distribution_list/models/partner.py new file mode 100644 index 000000000..9215a0d8c --- /dev/null +++ b/delivery_distribution_list/models/partner.py @@ -0,0 +1,14 @@ +from odoo import 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)], + ) diff --git a/delivery_distribution_list/models/product.py b/delivery_distribution_list/models/product.py new file mode 100644 index 000000000..df79b9e51 --- /dev/null +++ b/delivery_distribution_list/models/product.py @@ -0,0 +1,12 @@ +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + analytic_account_id = fields.Many2one( + "account.analytic.account", + string="Analytic Account", + company_dependent=True, + domain=[("account_type", "!=", "closed")], + ) diff --git a/delivery_distribution_list/models/sale_order.py b/delivery_distribution_list/models/sale_order.py new file mode 100644 index 000000000..18e86c743 --- /dev/null +++ b/delivery_distribution_list/models/sale_order.py @@ -0,0 +1,12 @@ +from odoo import fields, models + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + distribution_carrier_id = fields.Many2one( + "res.partner", string="Assigned carrier", readonly=True + ) + distribution_list_id = fields.Many2one( + "delivery.distribution.list", string="Distribution list", readonly=True + ) diff --git a/delivery_distribution_list/readme/CONTRIBUTORS.rst b/delivery_distribution_list/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..12553817c --- /dev/null +++ b/delivery_distribution_list/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Coop IT Easy SC `_: + + * Houssine Bakkali diff --git a/delivery_distribution_list/readme/DESCRIPTION.rst b/delivery_distribution_list/readme/DESCRIPTION.rst new file mode 100644 index 000000000..c34512848 --- /dev/null +++ b/delivery_distribution_list/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module manage the distribution of a product through all the sale/deposit +points, it manages the recurring order through the list of distribution. diff --git a/delivery_distribution_list/report/sale_order_report_template.xml b/delivery_distribution_list/report/sale_order_report_template.xml new file mode 100644 index 000000000..fdd89b7fa --- /dev/null +++ b/delivery_distribution_list/report/sale_order_report_template.xml @@ -0,0 +1,14 @@ + + + + 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..608810052 --- /dev/null +++ b/delivery_distribution_list/security/delivery_distribution_list_security.xml @@ -0,0 +1,26 @@ + + + + + Distribution List + + + + Distribution User + + + + + + Distribution Manager + + + + + 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..156fcbb86 --- /dev/null +++ b/delivery_distribution_list/security/ir.model.access.csv @@ -0,0 +1,15 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_partner_distribution_user,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 +access_account_move_user,account.move,account.model_account_move,group_distribution_user,1,1,0,0 +access_account_move_manager,account.move,account.model_account_move,group_distribution_manager,1,1,1,1 +access_account_move_line_user,account.move.line,account.model_account_move_line,group_distribution_user,1,1,0,0 +access_account_move_line_manager,account.move.line,account.model_account_move_line,group_distribution_manager,1,1,1,1 +access_account_partial_reconcile_user,account.partial.reconcile,account.model_account_partial_reconcile,group_distribution_user,1,1,0,0 +access_account_partial_reconcile_manager,account.partial.reconcile,account.model_account_partial_reconcile,group_distribution_manager,1,1,1,1 +access_account_account_type_user,account.account.type,account.model_account_account_type,group_distribution_user,1,1,0,0 +access_account_account_type_manager,account.account.type,account.model_account_account_type,group_distribution_manager,1,1,1,1 diff --git a/delivery_distribution_list/static/description/index.html b/delivery_distribution_list/static/description/index.html new file mode 100644 index 000000000..c0c8a2acc --- /dev/null +++ b/delivery_distribution_list/static/description/index.html @@ -0,0 +1,418 @@ + + + + + + +Delivery distribution Management + + + +
+

Delivery distribution Management

+ + +

Beta License: AGPL-3 coopiteasy/addons

+

This module manage the distribution of a product through all the sale/deposit +points, it manages the recurring order through the list of distribution.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Coop IT Easy SC
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the coopiteasy/addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + 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..0a5ede372 --- /dev/null +++ b/delivery_distribution_list/views/delivery_distribution_list_view.xml @@ -0,0 +1,436 @@ + + + + + + + delivery.distribution.list.form + delivery.distribution.list + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +