diff --git a/batch_picking_create_one_bill/__init__.py b/batch_picking_create_one_bill/__init__.py index 862180d..408a600 100644 --- a/batch_picking_create_one_bill/__init__.py +++ b/batch_picking_create_one_bill/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- from . import models -from . import wizards +from . import wizard diff --git a/batch_picking_create_one_bill/__manifest__.py b/batch_picking_create_one_bill/__manifest__.py index 44e921a..43c0f29 100644 --- a/batch_picking_create_one_bill/__manifest__.py +++ b/batch_picking_create_one_bill/__manifest__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- { - 'name': 'Batch Picking - Create One Bill', - 'version': '18.0.1.0.0', - 'category': 'Inventory/Purchase', - 'summary': 'Créer une seule facture fournisseur pour tous les bons de commande d\'un batch picking', - 'description': """ + "name": "Batch Picking - Create One Bill", + "version": "18.0.1.0.0", + "category": "Inventory/Purchase", + "summary": "Créer une seule facture fournisseur pour tous les bons de commande d'un batch picking", + "description": """ Ce module permet de générer une seule facture fournisseur pour tous les bons de commande associés à un batch picking. @@ -14,23 +14,24 @@ - Validation que tous les bons de commande proviennent du même fournisseur - Suivi des factures créées directement depuis le batch """, - 'author': 'Pneumac', - 'website': 'https://www.pneumac.ca', - 'depends': [ - 'stock_picking_batch', - 'purchase', - 'purchase_stock', - 'account', - 'account_reports', + "author": "Pneumac", + "website": "https://www.pneumac.ca", + "depends": [ + "stock_picking_batch", + "purchase", + "purchase_stock", + "account", + "account_reports", ], - 'data': [ - 'security/ir.model.access.csv', - 'wizards/create_bill_wizard_views.xml', - 'wizards/merge_bill_wizard_views.xml', - 'views/stock_picking_batch_views.xml', + "data": [ + "security/ir.model.access.csv", + "wizard/create_bill_wizard_views.xml", + "wizard/merge_bill_wizard_views.xml", + "wizard/stock_picking_to_batch_views.xml", + "views/stock_picking_batch_views.xml", ], - 'installable': True, - 'application': False, - 'auto_install': False, - 'license': 'LGPL-3', + "installable": True, + "application": False, + "auto_install": False, + "license": "LGPL-3", } diff --git a/batch_picking_create_one_bill/models/stock_picking_batch.py b/batch_picking_create_one_bill/models/stock_picking_batch.py index eb46d5a..829da5d 100644 --- a/batch_picking_create_one_bill/models/stock_picking_batch.py +++ b/batch_picking_create_one_bill/models/stock_picking_batch.py @@ -2,61 +2,81 @@ from odoo import models, fields, api from odoo.exceptions import ValidationError + class StockPickingBatch(models.Model): - _inherit = 'stock.picking.batch' + _inherit = "stock.picking.batch" + + @api.model_create_multi + def create(self, vals_list): + # Handle zero_quantity_default from context if not explicitly set in vals + for vals in vals_list: + if ( + "zero_quantity_default" not in vals + and self.env.context.get("default_zero_quantity_default") is not None + ): + vals["zero_quantity_default"] = self.env.context.get( + "default_zero_quantity_default" + ) + return super().create(vals_list) zero_quantity_default = fields.Boolean( - string='Quantités à zéro par défaut', + string="Quantités à zéro par défaut", default=True, - help='Initialiser les quantités à zéro lors de la création du batch' + help="Initialiser les quantités à zéro lors de la création du batch", ) invoice_ids = fields.Many2many( - 'account.move', - string='Factures associées', - compute='_compute_invoice_ids', - store=True + "account.move", + string="Factures associées", + compute="_compute_invoice_ids", + store=True, ) invoice_count = fields.Integer( - string='Nombre de factures', - compute='_compute_invoice_count', + string="Nombre de factures", + compute="_compute_invoice_count", store=True, - compute_sudo=True + compute_sudo=True, ) def _prepare_move_line_vals(self, **kwargs): vals = super()._prepare_move_line_vals(**kwargs) if self.zero_quantity_default: - vals['quantity'] = 0.0 + vals["quantity"] = 0.0 return vals - @api.depends('picking_ids.move_ids.purchase_line_id.order_id.invoice_ids') + @api.depends("picking_ids.move_ids.purchase_line_id.order_id.invoice_ids") def _compute_invoice_ids(self): for batch in self: purchase_orders = batch.picking_ids.move_ids.purchase_line_id.order_id batch.invoice_ids = purchase_orders.invoice_ids - @api.depends('invoice_ids') + @api.depends("invoice_ids") def _compute_invoice_count(self): for batch in self: batch.invoice_count = len(batch.invoice_ids) def action_view_invoices(self): self.ensure_one() - action = self.env['ir.actions.act_window']._for_xml_id( - 'account.action_move_in_invoice_type' + action = self.env["ir.actions.act_window"]._for_xml_id( + "account.action_move_in_invoice_type" ) if self.invoice_count == 1: - action['views'] = [(False, 'form')] - action['res_id'] = self.invoice_ids.id + action["views"] = [(False, "form")] + action["res_id"] = self.invoice_ids.id else: - action['domain'] = [('id', 'in', self.invoice_ids.ids)] + action["domain"] = [("id", "in", self.invoice_ids.ids)] return action - @api.constrains('picking_ids') + @api.constrains("picking_ids") def _check_purchase_orders(self): for batch in self: partners = batch.picking_ids.purchase_id.partner_id if len(partners) > 1: raise ValidationError( - 'Tous les bons de commande du batch doivent provenir du même fournisseur.' + "Tous les bons de commande du batch doivent provenir du même fournisseur." ) + + def action_confirm(self): + """Override to set zero quantity on move lines at confirmation of the batch""" + res = super().action_confirm() + self.filtered("zero_quantity_default").move_line_ids.write({"quantity": 0}) + return res diff --git a/batch_picking_create_one_bill/tests/test_batch_picking_bill.py b/batch_picking_create_one_bill/tests/test_batch_picking_bill.py index 2e5c6cc..1627f7b 100644 --- a/batch_picking_create_one_bill/tests/test_batch_picking_bill.py +++ b/batch_picking_create_one_bill/tests/test_batch_picking_bill.py @@ -251,3 +251,68 @@ class TestBatchPickingBill(TransactionCase): ], } ) + + def test_zero_quantity_default_from_wizard(self): + """Test that zero_quantity_default is properly set when creating a batch from wizard""" + # Switch to warehouse user like in the parent test + self.env = self.env(user=self.warehouse_user) + + pickings = (self.po1 + self.po2).picking_ids + self.assertTrue(pickings, "Purchase orders should have created pickings") + + # Create batch through wizard + wizard = ( + self.env["stock.picking.to.batch"] + .with_context(active_ids=pickings.ids, active_model="stock.picking") + .create( + { + "mode": "new", + "zero_quantity_default": True, + } + ) + ) + + result = wizard.attach_pickings() + batch = self.env["stock.picking.batch"].browse(result["res_id"]) + + # Check that zero_quantity_default was properly set on the batch + self.assertTrue( + batch.zero_quantity_default, + "zero_quantity_default should be True on the created batch", + ) + + # Check that all move lines have quantity 0 + for move_line in batch.move_line_ids: + self.assertEqual( + move_line.quantity, + 0.0, + f"Move line for {move_line.product_id.name} should have quantity 0", + ) + + def test_zero_quantity_default_from_picking(self): + """Test that zero_quantity_default works when adding picking to existing batch""" + # Switch to warehouse user like in the parent test + self.env = self.env(user=self.warehouse_user) + + pickings = (self.po1 + self.po2).picking_ids + + # Create batch directly + batch = self.env["stock.picking.batch"].create( + { + "zero_quantity_default": True, + } + ) + + # Add pickings to batch + pickings.write({"batch_id": batch.id}) + + # Confirm the batch to get the move lines set up + batch.action_confirm() + + # Check that all move lines have quantity 0 + for move_line in batch.move_line_ids: + self.assertEqual( + move_line.quantity, + 0.0, + f"Move line for {move_line.product_id.name} should have quantity 0", + ) diff --git a/batch_picking_create_one_bill/views/stock_picking_batch_views.xml b/batch_picking_create_one_bill/views/stock_picking_batch_views.xml index bea2f0c..c1953aa 100644 --- a/batch_picking_create_one_bill/views/stock_picking_batch_views.xml +++ b/batch_picking_create_one_bill/views/stock_picking_batch_views.xml @@ -7,18 +7,10 @@ - @@ -27,4 +19,19 @@ + + + + stock.move.line.tree.picked.inherit + stock.move.line + + + + + + + picked + + + diff --git a/batch_picking_create_one_bill/wizards/__init__.py b/batch_picking_create_one_bill/wizard/__init__.py similarity index 70% rename from batch_picking_create_one_bill/wizards/__init__.py rename to batch_picking_create_one_bill/wizard/__init__.py index 7306402..cb92c49 100644 --- a/batch_picking_create_one_bill/wizards/__init__.py +++ b/batch_picking_create_one_bill/wizard/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import create_bill_wizard from . import merge_bill_wizard +from . import stock_picking_to_batch diff --git a/batch_picking_create_one_bill/wizards/create_bill_wizard.py b/batch_picking_create_one_bill/wizard/create_bill_wizard.py similarity index 100% rename from batch_picking_create_one_bill/wizards/create_bill_wizard.py rename to batch_picking_create_one_bill/wizard/create_bill_wizard.py diff --git a/batch_picking_create_one_bill/wizards/create_bill_wizard_views.xml b/batch_picking_create_one_bill/wizard/create_bill_wizard_views.xml similarity index 100% rename from batch_picking_create_one_bill/wizards/create_bill_wizard_views.xml rename to batch_picking_create_one_bill/wizard/create_bill_wizard_views.xml diff --git a/batch_picking_create_one_bill/wizards/merge_bill_wizard.py b/batch_picking_create_one_bill/wizard/merge_bill_wizard.py similarity index 100% rename from batch_picking_create_one_bill/wizards/merge_bill_wizard.py rename to batch_picking_create_one_bill/wizard/merge_bill_wizard.py diff --git a/batch_picking_create_one_bill/wizards/merge_bill_wizard_views.xml b/batch_picking_create_one_bill/wizard/merge_bill_wizard_views.xml similarity index 100% rename from batch_picking_create_one_bill/wizards/merge_bill_wizard_views.xml rename to batch_picking_create_one_bill/wizard/merge_bill_wizard_views.xml diff --git a/batch_picking_create_one_bill/wizard/stock_picking_to_batch.py b/batch_picking_create_one_bill/wizard/stock_picking_to_batch.py new file mode 100644 index 0000000..9dae773 --- /dev/null +++ b/batch_picking_create_one_bill/wizard/stock_picking_to_batch.py @@ -0,0 +1,20 @@ +from odoo import _, fields, models +from odoo.exceptions import UserError + + +class StockPickingToBatch(models.TransientModel): + _inherit = "stock.picking.to.batch" + + zero_quantity_default = fields.Boolean( + string="Zero Quantity by Default", + default=False, + help="If checked, the default quantity for new move lines will be 0 instead of the computed quantity.", + ) + + def attach_pickings(self): + self.ensure_one() + # Pass zero_quantity_default through context to be handled in batch create + return super( + StockPickingToBatch, + self.with_context(default_zero_quantity_default=self.zero_quantity_default), + ).attach_pickings() diff --git a/batch_picking_create_one_bill/wizard/stock_picking_to_batch_views.xml b/batch_picking_create_one_bill/wizard/stock_picking_to_batch_views.xml new file mode 100644 index 0000000..ac145a7 --- /dev/null +++ b/batch_picking_create_one_bill/wizard/stock_picking_to_batch_views.xml @@ -0,0 +1,13 @@ + + + + stock.picking.to.batch.form.inherit + stock.picking.to.batch + + + + + + + +