[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. TT40443pull/999/head
parent
ec6c4043b1
commit
7bf9cd6b20
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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",
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<group>
|
||||
<field name="stock_move_non_billed_threshold" />
|
||||
<field name="date_check" />
|
||||
<field name="interval_restrict_invoices" />
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
|
|
Loading…
Reference in New Issue