[IMP] account_*_stock_report_non_billed: Allow use dates as a range

By doing this change we can use dates (threshold and check) as a range
to discart moves and invoices that are out of this range.

TT40443
pull/999/head
CarlosRoca13 2022-11-14 11:09:52 +01:00 committed by Stefan
parent ec6c4043b1
commit 7bf9cd6b20
9 changed files with 129 additions and 29 deletions

View File

@ -6,6 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 13.0\n" "Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \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" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -154,6 +156,12 @@ msgstr ""
msgid "Stock Moves Analysis" msgid "Stock Moves Analysis"
msgstr "" 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 #. 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 #: 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" msgid "Wizard to open stock moves that have not been invoiced at that time"

View File

@ -6,8 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 13.0\n" "Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-26 19:03+0000\n" "POT-Creation-Date: 2022-11-14 10:03+0000\n"
"PO-Revision-Date: 2022-09-26 21:04+0200\n" "PO-Revision-Date: 2022-11-14 11:04+0100\n"
"Last-Translator: Sergio Teruel <sergio.teruel@tecnativa.com>\n" "Last-Translator: Sergio Teruel <sergio.teruel@tecnativa.com>\n"
"Language-Team: \n" "Language-Team: \n"
"Language: es\n" "Language: es\n"
@ -15,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\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 #. 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 #: 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" msgid "Stock Moves Analysis"
msgstr "Análisis de movimientos de stock" 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 #. 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 #: 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" msgid "Wizard to open stock moves that have not been invoiced at that time"

View File

@ -7,8 +7,21 @@ from odoo import models
class StockMove(models.Model): class StockMove(models.Model):
_inherit = "account.move.line" _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() 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 ( return (
self.move_id.date or self.move_id.invoice_date or self.create_date.date() start
) <= date_check and (
self.move_id.date
or self.move_id.invoice_date
or self.create_date.date()
)
<= date_check
)

View File

@ -10,3 +10,7 @@ class ResConfigSettings(models.TransientModel):
stock_move_non_billed_threshold = fields.Date( stock_move_non_billed_threshold = fields.Date(
related="company_id.stock_move_non_billed_threshold", readonly=False 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",
)

View File

@ -77,6 +77,12 @@ class StockMove(models.Model):
) )
# Check when grouping different moves in an invoice line # Check when grouping different moves in an invoice line
moves = invoice_lines.mapped("move_line_ids") 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() total_qty = moves.get_total_devolution_moves()
if total_invoiced != total_qty: if total_invoiced != total_qty:
invoiced = 0.0 invoiced = 0.0
@ -109,23 +115,29 @@ class StockMove(models.Model):
move.quantity_not_invoiced = 0 move.quantity_not_invoiced = 0
move.price_not_invoiced = 0 move.price_not_invoiced = 0
continue continue
inv_lines = ( date_start = self.env.context.get("date_check_invoiced_moves_start", False)
move.invoice_line_ids.filtered(lambda l: l.move_id.state != "cancel") date_end = self.env.context.get("date_check_invoiced_moves", False)
.mapped("move_line_ids.invoice_line_ids") if date_start:
.filtered( date_start = fields.Date.from_string(date_start)
lambda l: l.check_invoice_line_in_date( if date_end:
fields.Date.from_string( date_end = fields.Date.from_string(date_start)
self.env.context["date_check_invoiced_moves"] 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 = ( qty_to_invoice = (
move.quantity_done move.quantity_done
if not move.check_is_return() if not move.check_is_return()
else -move.quantity_done 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) move._set_not_invoiced_values(qty_to_invoice, calculated_qty)
@api.model @api.model

View File

@ -1,5 +1,6 @@
# Copyright 2022 Tecnativa - Carlos Roca # Copyright 2022 Tecnativa - Carlos Roca
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from dateutil.relativedelta import relativedelta
from odoo import fields from odoo import fields
from odoo.tests import Form from odoo.tests import Form
@ -246,3 +247,21 @@ class TestAccountSaleStrockReportNonBilled(TestStockPickingInvoiceLink):
self.assertNotIn(move.id, domain_ids) self.assertNotIn(move.id, domain_ids)
for move in picking_return_return.move_lines: for move in picking_return_return.move_lines:
self.assertNotIn(move.id, domain_ids) 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)

View File

@ -19,6 +19,14 @@
<field name="stock_move_non_billed_threshold" /> <field name="stock_move_non_billed_threshold" />
</div> </div>
</div> </div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="default_interval_restrict_invoices" />
</div>
<div class="o_setting_right_pane">
<label for="default_interval_restrict_invoices" />
</div>
</div>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@ -16,9 +16,13 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel):
default=lambda self: self._default_stock_move_non_billed_threshold() default=lambda self: self._default_stock_move_non_billed_threshold()
) )
date_check = fields.Date(string="Date", default=fields.Date.today) 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): def _get_search_domain(self):
return [ return [
("date_done", ">=", self.stock_move_non_billed_threshold),
("date_done", "<=", self.date_check), ("date_done", "<=", self.date_check),
("sale_line_id", "!=", False), ("sale_line_id", "!=", False),
("state", "=", "done"), ("state", "=", "done"),
@ -46,6 +50,11 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel):
if move in neutralized_moves: if move in neutralized_moves:
continue continue
dp = self.env["decimal.precision"].precision_get("Product Unit of Measure") 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( if float_is_zero(
move.quantity_done move.quantity_done
- sum(move.returned_move_ids.mapped("quantity_done")), - sum(move.returned_move_ids.mapped("quantity_done")),
@ -54,7 +63,9 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel):
move.invoice_line_ids move.invoice_line_ids
+ move.returned_move_ids.mapped("invoice_line_ids") + move.returned_move_ids.mapped("invoice_line_ids")
).filtered( ).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 neutralized_moves |= move + move.returned_move_ids
return neutralized_moves return neutralized_moves
@ -62,26 +73,40 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel):
def open_at_date(self): def open_at_date(self):
dp = self.env["decimal.precision"].precision_get("Product Unit of Measure") dp = self.env["decimal.precision"].precision_get("Product Unit of Measure")
# Get the moves after the threshold # Get the moves after the threshold
stock_moves = self.env["stock.move"].search( domain = self._get_search_domain()
[("date_done", ">=", self.stock_move_non_billed_threshold)] stock_moves = self.env["stock.move"].search(domain)
)
# Filter the moves with the domain # Filter the moves with the domain
stock_moves = stock_moves.filtered_domain(self._get_search_domain()) stock_moves = stock_moves.filtered_domain(self._get_search_domain())
stock_moves = self.discart_kits_from_moves(stock_moves) stock_moves = self.discart_kits_from_moves(stock_moves)
stock_moves -= self._get_neutralized_moves(stock_moves) stock_moves -= self._get_neutralized_moves(stock_moves)
final_stock_move_ids = [] final_stock_move_ids = []
date_start = (
self.stock_move_non_billed_threshold
if self.interval_restrict_invoices
else False
)
for move in stock_moves: for move in stock_moves:
inv_lines = ( invoices_not_cancel = move.invoice_line_ids.filtered(
move.invoice_line_ids.filtered(lambda l: l.move_id.state != "cancel") 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)) 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 = ( qty_to_invoice = (
move.quantity_done move.quantity_done
if not move.check_is_return() if not move.check_is_return()
else -move.quantity_done 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): if not float_is_zero(qty_to_invoice - calculated_qty, precision_digits=dp):
final_stock_move_ids.append(move.id) final_stock_move_ids.append(move.id)
tree_view_id = self.env.ref( tree_view_id = self.env.ref(
@ -93,6 +118,12 @@ class AccountSaleStockReportNonBilledWiz(models.TransientModel):
search_view_id = self.env.ref( search_view_id = self.env.ref(
"account_sale_stock_report_non_billed.view_move_search" "account_sale_stock_report_non_billed.view_move_search"
).id ).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 = { action = {
"type": "ir.actions.act_window", "type": "ir.actions.act_window",
"views": [(tree_view_id, "tree"), (pivot_view_id, "pivot")], "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}, % {"from": self.stock_move_non_billed_threshold, "to": self.date_check},
"res_model": "stock.move", "res_model": "stock.move",
"domain": [("id", "in", final_stock_move_ids)], "domain": [("id", "in", final_stock_move_ids)],
"context": dict( "context": context,
self.env.context, date_check_invoiced_moves=self.date_check
),
} }
return action return action

View File

@ -10,6 +10,7 @@
<group> <group>
<field name="stock_move_non_billed_threshold" /> <field name="stock_move_non_billed_threshold" />
<field name="date_check" /> <field name="date_check" />
<field name="interval_restrict_invoices" />
</group> </group>
<footer> <footer>
<button <button