Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][IMP] stock_picking_invoice_link #1010

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 5 additions & 26 deletions stock_picking_invoice_link/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,16 @@ class SaleOrderLine(models.Model):
_inherit = "sale.order.line"

def get_stock_moves_link_invoice(self):
skip_check_invoice_state = self.env.context.get(
"skip_check_invoice_state", False
)
return self.mapped("move_ids").filtered(
lambda mv: (
mv.state == "done"
and not (
not skip_check_invoice_state
and any(
inv.state != "cancel"
for inv in mv.invoice_line_ids.mapped("move_id")
)
)
and not mv.scrapped
and (
mv.location_dest_id.usage == "customer"
or (mv.location_id.usage == "customer" and mv.to_refund)
)
)
)
return self.mapped("move_ids")._filter_for_invoice_link()

def _prepare_invoice_line(self, **optional_values):
vals = super()._prepare_invoice_line(**optional_values)
stock_moves = self.get_stock_moves_link_invoice()
# Invoice returned moves marked as to_refund
if (
float_compare(
self.qty_to_invoice, 0.0, precision_rounding=self.currency_id.rounding
)
< 0
):
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
if float_compare(self.product_uom_qty, 0.0, precision_digits=precision) < 0:
stock_moves = stock_moves.filtered(
lambda m: m.to_refund and not m.invoice_line_ids
)
Expand Down
41 changes: 41 additions & 0 deletions stock_picking_invoice_link/models/stock_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from odoo import _, fields, models
from odoo.exceptions import UserError
from odoo.tools import float_compare


class StockMove(models.Model):
Expand Down Expand Up @@ -34,3 +35,43 @@ def write(self, vals):
if move.state == "done" and move.invoice_line_ids:
raise UserError(_("You can not modify an invoiced stock move"))
return super().write(vals)

def _filter_for_invoice_link(self):
return self.filtered(
lambda x: (
x.state == "done"
and not (
any(
inv.state != "cancel"
for inv in x.invoice_line_ids.mapped("move_id")
)
)
and not x.scrapped
and (
x.location_dest_id.usage == "customer"
or (x.location_id.usage == "customer" and x.to_refund)
)
)
)

def _action_done(self, cancel_backorder=False):
res = super()._action_done(cancel_backorder)
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
moves = self._filter_for_invoice_link()
# Add extra filtering on products with invoice_policy = delivery as
# the link was already set at invoice creation
for move in moves.filtered(lambda m: m.product_id.invoice_policy != "delivery"):
if float_compare(
move.sale_line_id.qty_to_invoice, 0.0, precision_digits=precision
) < 0 and (not move.to_refund or move.invoice_line_ids):
continue
move.write(
{
"invoice_line_ids": [
(4, inv_line.id) for inv_line in move.sale_line_id.invoice_lines
]
}
)
return res
5 changes: 4 additions & 1 deletion stock_picking_invoice_link/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ class StockPicking(models.Model):
_inherit = "stock.picking"

invoice_ids = fields.Many2many(
comodel_name="account.move", copy=False, string="Invoices", readonly=True
comodel_name="account.move",
copy=False,
string="Invoices",
readonly=True,
)

def action_view_invoice(self):
Expand Down
3 changes: 0 additions & 3 deletions stock_picking_invoice_link/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,3 @@ invoices relate to. You only have the quantity.

This module is also useful if you want to present data on the invoice report
grouped by deliveries.

Note that the links are only for products with an invoicing policy set on
delivery.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def setUpClass(cls, chart_template_ref=None):
def test_00_sale_stock_invoice_link(self):
pick_obj = self.env["stock.picking"]
# invoice on order
self.so._create_invoices()
inv_0 = self.so._create_invoices()
# deliver partially
self.assertEqual(
self.so.invoice_status,
Expand Down Expand Up @@ -143,6 +143,20 @@ def test_00_sale_stock_invoice_link(self):
"invoicing",
)
# Check links
self.assertEqual(
inv_0.picking_ids,
pick_1 | pick_2,
"Invoice 0 must be linked to all the deliveries",
)
self.assertEqual(
inv_0.invoice_line_ids.mapped("move_line_ids"),
pick_1.move_lines.filtered(lambda x: x.product_id.invoice_policy == "order")
| pick_2.move_lines.filtered(
lambda x: x.product_id.invoice_policy == "order"
),
"Invoice 0 lines must be link to all delivery lines for "
"ordered quantities",
)
self.assertEqual(
inv_1.picking_ids,
pick_1,
Expand All @@ -167,8 +181,8 @@ def test_00_sale_stock_invoice_link(self):
)
# Invoice view
result = pick_1.action_view_invoice()
self.assertEqual(result["views"][0][1], "form")
self.assertEqual(result["res_id"], inv_1.id)
self.assertEqual(result["views"][0][1], "tree")
self.assertEqual(pick_1.invoice_ids.ids, (inv_0 | inv_1).ids)
# Mock multiple invoices linked to a picking
inv_3 = inv_1.copy()
inv_3.picking_ids |= pick_1
Expand Down
4 changes: 2 additions & 2 deletions stock_picking_invoice_link/views/account_invoice_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<odoo>
<!-- Copyright 2013-2014 Alexis de Lattre <[email protected]>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<record id="invoice_form" model="ir.ui.view">
<field name="name">related.pickings.account.invoice.form</field>
<record id="view_move_form_inherit" model="ir.ui.view">
<field name="name">related.pickings.account.move.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form" />
<field name="arch" type="xml">
Expand Down