From 3cc5889ea4923ae39f9cb448110af684cbf16da8 Mon Sep 17 00:00:00 2001 From: Denis Durepos Date: Fri, 19 Sep 2025 13:45:28 -0400 Subject: [PATCH] Initial import pre-upgrade for bemade_quotation_alternative:18.0 --- bemade_quotation_alternative/__init__.py | 4 + bemade_quotation_alternative/__manifest__.py | 37 ++++++ .../models/__init__.py | 3 + .../models/sale_order.py | 19 ++++ .../security/ir.model.access.csv | 3 + .../views/sale_order_views.xml | 62 +++++++++++ .../wizard/__init__.py | 4 + .../sale_oder_line_duplication_wizard.py | 9 ++ .../wizard/sale_order_duplication_wizard.py | 105 ++++++++++++++++++ .../sale_order_duplication_wizard_view.xml | 39 +++++++ 10 files changed, 285 insertions(+) create mode 100644 bemade_quotation_alternative/__init__.py create mode 100644 bemade_quotation_alternative/__manifest__.py create mode 100644 bemade_quotation_alternative/models/__init__.py create mode 100644 bemade_quotation_alternative/models/sale_order.py create mode 100644 bemade_quotation_alternative/security/ir.model.access.csv create mode 100644 bemade_quotation_alternative/views/sale_order_views.xml create mode 100644 bemade_quotation_alternative/wizard/__init__.py create mode 100644 bemade_quotation_alternative/wizard/sale_oder_line_duplication_wizard.py create mode 100644 bemade_quotation_alternative/wizard/sale_order_duplication_wizard.py create mode 100644 bemade_quotation_alternative/wizard/sale_order_duplication_wizard_view.xml diff --git a/bemade_quotation_alternative/__init__.py b/bemade_quotation_alternative/__init__.py new file mode 100644 index 0000000..3c4e748 --- /dev/null +++ b/bemade_quotation_alternative/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import wizard +from . import models diff --git a/bemade_quotation_alternative/__manifest__.py b/bemade_quotation_alternative/__manifest__.py new file mode 100644 index 0000000..78e7504 --- /dev/null +++ b/bemade_quotation_alternative/__manifest__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Create Quotation Alternative", + + 'summary': """ + Short (1 phrase/line) summary of the module's purpose, used as + subtitle on modules listing or apps.openerp.com""", + + 'description': """ + Long description of module's purpose + """, + + 'author': "Bemade.org", + 'website': "https://odoo.bemade.org", + 'license': 'LGPL-3', + # Categories can be used to filter modules in modules listing + # Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml + # for the full list + 'category': 'Uncategorized', + 'version': '17.0.1.0.0', + + # any module necessary for this one to work correctly + 'depends': [ + 'sale_management' + ], + + # always loaded + 'data': [ + 'security/ir.model.access.csv', + 'views/sale_order_views.xml', + 'wizard/sale_order_duplication_wizard_view.xml', + ], + # only loaded in demonstration mode + 'demo': [ + # 'demo/demo.xml', + ], +} diff --git a/bemade_quotation_alternative/models/__init__.py b/bemade_quotation_alternative/models/__init__.py new file mode 100644 index 0000000..6064afe --- /dev/null +++ b/bemade_quotation_alternative/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import sale_order diff --git a/bemade_quotation_alternative/models/sale_order.py b/bemade_quotation_alternative/models/sale_order.py new file mode 100644 index 0000000..817beb4 --- /dev/null +++ b/bemade_quotation_alternative/models/sale_order.py @@ -0,0 +1,19 @@ +from odoo import models + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + def action_duplicate_order(self): + self.ensure_one() + action = ( + self.env.ref( + "bemade_quotation_alternative.sale_order_duplication_wizard_action" + ) + .sudo() + .read()[0] + ) + action["context"] = { + "default_original_order_id": self.id, + } + return action diff --git a/bemade_quotation_alternative/security/ir.model.access.csv b/bemade_quotation_alternative/security/ir.model.access.csv new file mode 100644 index 0000000..29adc9a --- /dev/null +++ b/bemade_quotation_alternative/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +bemade_quotation_alternative.access_sale_order_duplication_wizard,access_sale_order_duplication_wizard,bemade_quotation_alternative.model_sale_order_duplication_wizard,base.group_user,1,1,1,1 +bemade_quotation_alternative.access_sale_order_line_duplication_wizard,access_sale_order_line_duplication_wizard,bemade_quotation_alternative.model_sale_order_line_duplication_wizard,base.group_user,1,1,1,1 diff --git a/bemade_quotation_alternative/views/sale_order_views.xml b/bemade_quotation_alternative/views/sale_order_views.xml new file mode 100644 index 0000000..92af3f5 --- /dev/null +++ b/bemade_quotation_alternative/views/sale_order_views.xml @@ -0,0 +1,62 @@ + + + + + sale.order.form.inherit + sale.order + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/bemade_quotation_alternative/wizard/__init__.py b/bemade_quotation_alternative/wizard/__init__.py new file mode 100644 index 0000000..c8bd2b8 --- /dev/null +++ b/bemade_quotation_alternative/wizard/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import sale_order_duplication_wizard +from . import sale_oder_line_duplication_wizard diff --git a/bemade_quotation_alternative/wizard/sale_oder_line_duplication_wizard.py b/bemade_quotation_alternative/wizard/sale_oder_line_duplication_wizard.py new file mode 100644 index 0000000..c21a696 --- /dev/null +++ b/bemade_quotation_alternative/wizard/sale_oder_line_duplication_wizard.py @@ -0,0 +1,9 @@ +from odoo import models, fields + +class SaleOrderLineDuplicationWizard(models.TransientModel): + _name = 'sale.order.line.duplication.wizard' + _description = 'Wizard for selecting sale order lines to duplicate' + + wizard_id = fields.Many2one('sale.order.duplication.wizard', required=True, ondelete='cascade', string="Wizard") + sale_order_line_id = fields.Many2one('sale.order.line', string="Sale Order Line", required=True) + to_duplicate = fields.Boolean(string="Duplicate?", default=True) diff --git a/bemade_quotation_alternative/wizard/sale_order_duplication_wizard.py b/bemade_quotation_alternative/wizard/sale_order_duplication_wizard.py new file mode 100644 index 0000000..24eaf84 --- /dev/null +++ b/bemade_quotation_alternative/wizard/sale_order_duplication_wizard.py @@ -0,0 +1,105 @@ +from odoo import models, fields, api +from markupsafe import Markup + + +class SaleOrderDuplicationWizard(models.TransientModel): + _name = "sale.order.duplication.wizard" + _description = "Wizard for duplicating a sale order" + + original_order_id = fields.Many2one( + "sale.order", string="Original Order", required=True + ) + new_quot = fields.Char( + string="New Quotation Name", compute="_compute_new_quot", store=True + ) + + duplicate_all_lines = fields.Boolean(string="Duplicate All Lines?", default=True) + lines_to_duplicate = fields.One2many( + "sale.order.line.duplication.wizard", + "wizard_id", + string="Lines to Duplicate", + context={"default_original_order_id": original_order_id}, + ) + + purpose = fields.Text(string="Purpose") + note = fields.Html(string="Note") + + @api.model + def default_get(self, fields_list): + res = super(SaleOrderDuplicationWizard, self).default_get(fields_list) + if "default_original_order_id" in self.env.context: + original_order_id = self.env.context["default_original_order_id"] + original_order = self.env["sale.order"].browse(original_order_id) + lines_vals = [] + for line in original_order.order_line: + lines_vals.append((0, 0, {"sale_order_line_id": line.id})) + res.update( + { + "lines_to_duplicate": lines_vals, + "purpose": ( + original_order.purpose if "purpose" in fields_list else "" + ), + "note": original_order.note if "note" in fields_list else "", + } + ) + return res + + def action_duplicate_order(self): + self.ensure_one() + # Duplication de la commande de vente + new_order = self.original_order_id.copy( + { + "purpose": self.purpose, + "note": self.note, + # Assurez-vous que 'new_quot' est défini correctement dans votre modèle + "name": self.new_quot, + } + ) + if not self.duplicate_all_lines: + new_order.order_line.unlink() + for line_wiz in self.lines_to_duplicate.filtered("to_duplicate"): + line_wiz.sale_order_line_id.copy({"order_id": new_order.id}) + + # Préparation et envoi des messages de notification dans le chatter + user_name = self.env.user.name + now = fields.Datetime.now() + + # Message pour la commande originale + original_msg_body = Markup( + f"A new quotation #{new_order.name} " + f"created by {user_name} duplicating this Quotation." + ) + self.original_order_id.message_post(body=original_msg_body) + + # Message pour la nouvelle commande dupliquée + new_msg_body = Markup( + f"This quotation has been created by {user_name} duplicating the original " + f"Quotation #{self.original_order_id.name}" + f"." + ) + new_order.message_post(body=new_msg_body) + + return { + "type": "ir.actions.act_window", + "name": "Duplicated Order", + "res_model": "sale.order", + "res_id": new_order.id, + "view_mode": "form", + "target": "current", + } + + @api.depends("original_order_id") + def _compute_new_quot(self): + + for rec in self: + original_order_name = ( + rec.original_order_id.name.split("-")[0] + if "-" in rec.original_order_id.name + else rec.original_order_id.name + ) + other_quotes = self.env["sale.order"].search( + [("name", "like", original_order_name + "%")] + ) + rec.new_quot = original_order_name + "-REV" + str(len(other_quotes)) diff --git a/bemade_quotation_alternative/wizard/sale_order_duplication_wizard_view.xml b/bemade_quotation_alternative/wizard/sale_order_duplication_wizard_view.xml new file mode 100644 index 0000000..096cae0 --- /dev/null +++ b/bemade_quotation_alternative/wizard/sale_order_duplication_wizard_view.xml @@ -0,0 +1,39 @@ + + + + + sale.order.duplication.wizard.form + sale.order.duplication.wizard + +
+ + + + + + + + + + + + + + + + +
+
+
+
+ + Duplicate Sale Order + ir.actions.act_window + sale.order.duplication.wizard + form + new + +
+