diff --git a/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot b/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot index 3ed3f362..5f12808a 100644 --- a/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot +++ b/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot @@ -6,6 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-11-14 10:03+0000\n" +"PO-Revision-Date: 2022-11-14 10:03+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -154,6 +156,12 @@ msgstr "" msgid "Stock Moves Analysis" msgstr "" +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__interval_restrict_invoices +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_res_config_settings__default_interval_restrict_invoices +msgid "Restrict invoices using the date interval" +msgstr "" + #. module: account_sale_stock_report_non_billed #: model:ir.model,name:account_sale_stock_report_non_billed.model_account_sale_stock_report_non_billed_wiz msgid "Wizard to open stock moves that have not been invoiced at that time" diff --git a/account_sale_stock_report_non_billed/i18n/es.po b/account_sale_stock_report_non_billed/i18n/es.po index a36ee91c..8b4ff79a 100644 --- a/account_sale_stock_report_non_billed/i18n/es.po +++ b/account_sale_stock_report_non_billed/i18n/es.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-09-26 19:03+0000\n" -"PO-Revision-Date: 2022-09-26 21:04+0200\n" +"POT-Creation-Date: 2022-11-14 10:03+0000\n" +"PO-Revision-Date: 2022-11-14 11:04+0100\n" "Last-Translator: Sergio Teruel \n" "Language-Team: \n" "Language: es\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 2.3\n" #. module: account_sale_stock_report_non_billed #: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__price_not_invoiced @@ -160,6 +160,12 @@ msgstr "Fecha umbral movimientos no facturados" msgid "Stock Moves Analysis" msgstr "Análisis de movimientos de stock" +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__interval_restrict_invoices +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_res_config_settings__default_interval_restrict_invoices +msgid "Restrict invoices using the date interval" +msgstr "Aplicar intervalo de fechas también a las facturas vinculadas" + #. module: account_sale_stock_report_non_billed #: model:ir.model,name:account_sale_stock_report_non_billed.model_account_sale_stock_report_non_billed_wiz msgid "Wizard to open stock moves that have not been invoiced at that time" diff --git a/account_sale_stock_report_non_billed/models/account_move_line.py b/account_sale_stock_report_non_billed/models/account_move_line.py index fc26a138..0edda976 100644 --- a/account_sale_stock_report_non_billed/models/account_move_line.py +++ b/account_sale_stock_report_non_billed/models/account_move_line.py @@ -7,8 +7,21 @@ from odoo import models class StockMove(models.Model): _inherit = "account.move.line" - def check_invoice_line_in_date(self, date_check): + def check_invoice_line_in_date(self, date_check, date_start=False): self.ensure_one() + start = True + if date_start: + start = ( + self.move_id.date + or self.move_id.invoice_date + or self.create_date.date() + ) >= date_start return ( - self.move_id.date or self.move_id.invoice_date or self.create_date.date() - ) <= date_check + start + and ( + self.move_id.date + or self.move_id.invoice_date + or self.create_date.date() + ) + <= date_check + ) diff --git a/account_sale_stock_report_non_billed/models/res_config_settings.py b/account_sale_stock_report_non_billed/models/res_config_settings.py index 1e662c6e..32fbc531 100644 --- a/account_sale_stock_report_non_billed/models/res_config_settings.py +++ b/account_sale_stock_report_non_billed/models/res_config_settings.py @@ -10,3 +10,7 @@ class ResConfigSettings(models.TransientModel): stock_move_non_billed_threshold = fields.Date( related="company_id.stock_move_non_billed_threshold", readonly=False ) + default_interval_restrict_invoices = fields.Boolean( + string="Restrict invoices using the date interval", + default_model="account.sale.stock.report.non.billed.wiz", + ) diff --git a/account_sale_stock_report_non_billed/models/stock_move.py b/account_sale_stock_report_non_billed/models/stock_move.py index db742d2c..3a9fb0ec 100644 --- a/account_sale_stock_report_non_billed/models/stock_move.py +++ b/account_sale_stock_report_non_billed/models/stock_move.py @@ -77,6 +77,12 @@ class StockMove(models.Model): ) # Check when grouping different moves in an invoice line moves = invoice_lines.mapped("move_line_ids") + date_start = self.env.context.get("moves_date_start") + date_end = self.env.context.get("moves_date_end") + if date_start and date_end: + moves = moves.filtered( + lambda ml: ml.date_done >= date_start and ml.date_done <= date_end + ) total_qty = moves.get_total_devolution_moves() if total_invoiced != total_qty: invoiced = 0.0 @@ -109,23 +115,29 @@ class StockMove(models.Model): move.quantity_not_invoiced = 0 move.price_not_invoiced = 0 continue - inv_lines = ( - move.invoice_line_ids.filtered(lambda l: l.move_id.state != "cancel") - .mapped("move_line_ids.invoice_line_ids") - .filtered( - lambda l: l.check_invoice_line_in_date( - fields.Date.from_string( - self.env.context["date_check_invoiced_moves"] - ) - ) - ) + date_start = self.env.context.get("date_check_invoiced_moves_start", False) + date_end = self.env.context.get("date_check_invoiced_moves", False) + if date_start: + date_start = fields.Date.from_string(date_start) + if date_end: + date_end = fields.Date.from_string(date_start) + invoices_not_cancel = move.invoice_line_ids.filtered( + lambda l: l.move_id.state != "cancel" + ) + moves_in_date = invoices_not_cancel.mapped("move_line_ids").filtered( + lambda m: m.date_done >= date_start and m.date_done <= date_end + ) + inv_lines = moves_in_date.mapped("invoice_line_ids").filtered( + lambda l: l.check_invoice_line_in_date(date_end, date_start=date_start,) ) qty_to_invoice = ( move.quantity_done if not move.check_is_return() else -move.quantity_done ) - calculated_qty = move.get_quantity_invoiced(inv_lines) + calculated_qty = move.with_context( + moves_date_start=date_start, moves_date_end=date_end, + ).get_quantity_invoiced(inv_lines) move._set_not_invoiced_values(qty_to_invoice, calculated_qty) @api.model diff --git a/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py b/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py index ac04def8..643afe68 100644 --- a/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py +++ b/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py @@ -1,5 +1,6 @@ # Copyright 2022 Tecnativa - Carlos Roca # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from dateutil.relativedelta import relativedelta from odoo import fields from odoo.tests import Form @@ -246,3 +247,21 @@ class TestAccountSaleStrockReportNonBilled(TestStockPickingInvoiceLink): self.assertNotIn(move.id, domain_ids) for move in picking_return_return.move_lines: self.assertNotIn(move.id, domain_ids) + + def test_10_report_move_full_invoiced_out_of_date(self): + picking = self.so.picking_ids.filtered( + lambda x: x.picking_type_code == "outgoing" + and x.state in ("confirmed", "assigned", "partially_available") + ) + picking.move_line_ids.write({"qty_done": 2}) + picking.action_done() + # Emulate prepaying invoice + inv = self.so._create_invoices() + inv.date = fields.Date.today() - relativedelta(days=5) + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today(), "interval_restrict_invoices": True} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in picking.move_lines: + self.assertIn(move.id, domain_ids) diff --git a/account_sale_stock_report_non_billed/views/res_config_settings_views.xml b/account_sale_stock_report_non_billed/views/res_config_settings_views.xml index a934230c..7fb19ffa 100644 --- a/account_sale_stock_report_non_billed/views/res_config_settings_views.xml +++ b/account_sale_stock_report_non_billed/views/res_config_settings_views.xml @@ -19,6 +19,14 @@ +
+
+ +
+
+
+
diff --git a/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py b/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py index d5ca4f6a..0424a0c8 100644 --- a/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py +++ b/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py @@ -16,9 +16,13 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel): default=lambda self: self._default_stock_move_non_billed_threshold() ) date_check = fields.Date(string="Date", default=fields.Date.today) + interval_restrict_invoices = fields.Boolean( + string="Restrict invoices using the date interval" + ) def _get_search_domain(self): return [ + ("date_done", ">=", self.stock_move_non_billed_threshold), ("date_done", "<=", self.date_check), ("sale_line_id", "!=", False), ("state", "=", "done"), @@ -46,6 +50,11 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel): if move in neutralized_moves: continue dp = self.env["decimal.precision"].precision_get("Product Unit of Measure") + date_start = ( + self.stock_move_non_billed_threshold + if self.interval_restrict_invoices + else False + ) if float_is_zero( move.quantity_done - sum(move.returned_move_ids.mapped("quantity_done")), @@ -54,7 +63,9 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel): move.invoice_line_ids + move.returned_move_ids.mapped("invoice_line_ids") ).filtered( - lambda l: l.check_invoice_line_in_date(self.date_check) + lambda l: l.check_invoice_line_in_date( + self.date_check, date_start=date_start + ) ): neutralized_moves |= move + move.returned_move_ids return neutralized_moves @@ -62,26 +73,40 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel): def open_at_date(self): dp = self.env["decimal.precision"].precision_get("Product Unit of Measure") # Get the moves after the threshold - stock_moves = self.env["stock.move"].search( - [("date_done", ">=", self.stock_move_non_billed_threshold)] - ) + domain = self._get_search_domain() + stock_moves = self.env["stock.move"].search(domain) # Filter the moves with the domain stock_moves = stock_moves.filtered_domain(self._get_search_domain()) stock_moves = self.discart_kits_from_moves(stock_moves) stock_moves -= self._get_neutralized_moves(stock_moves) final_stock_move_ids = [] + date_start = ( + self.stock_move_non_billed_threshold + if self.interval_restrict_invoices + else False + ) for move in stock_moves: - inv_lines = ( - move.invoice_line_ids.filtered(lambda l: l.move_id.state != "cancel") - .mapped("move_line_ids.invoice_line_ids") - .filtered(lambda l: l.check_invoice_line_in_date(self.date_check)) + invoices_not_cancel = move.invoice_line_ids.filtered( + lambda l: l.move_id.state != "cancel" + ) + moves_in_date = invoices_not_cancel.mapped("move_line_ids").filtered( + lambda m: m.date_done >= self.stock_move_non_billed_threshold + and m.date_done <= self.date_check + ) + inv_lines = moves_in_date.mapped("invoice_line_ids").filtered( + lambda l: l.check_invoice_line_in_date( + self.date_check, date_start=date_start + ) ) qty_to_invoice = ( move.quantity_done if not move.check_is_return() else -move.quantity_done ) - calculated_qty = move.get_quantity_invoiced(inv_lines) + calculated_qty = move.with_context( + moves_date_start=self.stock_move_non_billed_threshold, + moves_date_end=self.date_check, + ).get_quantity_invoiced(inv_lines) if not float_is_zero(qty_to_invoice - calculated_qty, precision_digits=dp): final_stock_move_ids.append(move.id) tree_view_id = self.env.ref( @@ -93,6 +118,12 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel): search_view_id = self.env.ref( "account_sale_stock_report_non_billed.view_move_search" ).id + context = dict(self.env.context, date_check_invoiced_moves=self.date_check) + if self.interval_restrict_invoices: + context = dict( + context, + date_check_invoiced_moves_start=self.stock_move_non_billed_threshold, + ) action = { "type": "ir.actions.act_window", "views": [(tree_view_id, "tree"), (pivot_view_id, "pivot")], @@ -102,8 +133,6 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel): % {"from": self.stock_move_non_billed_threshold, "to": self.date_check}, "res_model": "stock.move", "domain": [("id", "in", final_stock_move_ids)], - "context": dict( - self.env.context, date_check_invoiced_moves=self.date_check - ), + "context": context, } return action diff --git a/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz_views.xml b/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz_views.xml index 5d882277..ba6438e3 100644 --- a/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz_views.xml +++ b/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz_views.xml @@ -10,6 +10,7 @@ +