[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 ""
"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"

View File

@ -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 <sergio.teruel@tecnativa.com>\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"

View File

@ -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
)

View File

@ -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",
)

View File

@ -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

View File

@ -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)

View File

@ -19,6 +19,14 @@
<field name="stock_move_non_billed_threshold" />
</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>
</field>
</record>

View File

@ -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

View File

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