Skip to content

Commit

Permalink
[13.0][MIG] purchase_stock_picking_return_invoicing
Browse files Browse the repository at this point in the history
  • Loading branch information
kittiu authored and mariadforgeflow committed Aug 24, 2021
1 parent fe95f2b commit aaa9008
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 146 deletions.
8 changes: 4 additions & 4 deletions purchase_stock_picking_return_invoicing/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Purchase Stock Picking Return Invoicing
:target: https://runbot.odoo-community.org/runbot/95/12.0
:alt: Try me on Runbot

|badge1| |badge2| |badge3| |badge4| |badge5|
|badge1| |badge2| |badge3| |badge4| |badge5|

This module extends the functionality of purchase orders to better manage
supplier returns and refunds.
Expand Down Expand Up @@ -75,7 +75,7 @@ received a bill from the supplier.
#. Go back to the purchase order. Press the button *Create Bill* to create
the vendor bill.
#. The proposed vendor bill will be proposed for the quantity received. The
*Billing Status* is now 'No Bill to Receive'
*Billing Status* is now 'Fully Billed'
#. Go to the original incoming shipment
#. Press the button *Return*.
#. In the wizard *Reverse Transfer* set *Quantity* to the quantity to be
Expand All @@ -89,7 +89,7 @@ received a bill from the supplier.
#. The proposed vendor refund bill will be proposed for the quantity that is
to be refunded.
#. If you back to the purchase order, you will notice that *Billing Status*
is now 'No Bill to Receive', even when the quantity ordered does not match
is now 'Fully Billed', even when the quantity ordered does not match
with the quantity invoiced, because you did return some products.

Remark: If you accept that you will not claim for a refund for the quantity
Expand Down Expand Up @@ -145,7 +145,7 @@ promote its widespread use.

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-pedrobaeza|
|maintainer-pedrobaeza|

This module is part of the `OCA/account-invoicing <https://github.com/OCA/account-invoicing/tree/12.0/purchase_stock_picking_return_invoicing>`_ project on GitHub.

Expand Down
40 changes: 7 additions & 33 deletions purchase_stock_picking_return_invoicing/models/account_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,17 @@
from odoo.tools import float_is_zero


class AccountInvoice(models.Model):
_inherit = "account.invoice"
class AccountMove(models.Model):
_inherit = "account.move"

@api.onchange("purchase_id")
def purchase_order_change(self):
@api.onchange("purchase_vendor_bill_id", "purchase_id")
def _onchange_purchase_auto_complete(self):
"""Remove lines with qty=0 when making refunds."""
res = super().purchase_order_change()
res = super()._onchange_purchase_auto_complete()
if self.type == "in_refund":
self.invoice_line_ids -= self.invoice_line_ids.filtered(
self.line_ids -= self.invoice_line_ids.filtered(
lambda x: float_is_zero(
x.quantity, precision_rounding=x.uom_id.rounding
x.quantity, precision_rounding=x.product_uom_id.rounding
)
)
return res

def _prepare_invoice_line_from_po_line(self, line):
data = super()._prepare_invoice_line_from_po_line(line)
if line.product_id.purchase_method == "receive":
# This formula proceeds from the simplification of full expression:
# qty_received + qty_returned - (qty_invoiced + qty_refunded) -
# (qty_returned - qty_refunded)
qty = line.qty_received - line.qty_invoiced
data["quantity"] = qty
if self.type == "in_refund":
invoice_line = self.env["account.invoice.line"]
data["quantity"] *= -1.0
data["account_id"] = (
invoice_line.with_context(
{"journal_id": self.journal_id.id, "type": "in_invoice"}
)._default_account(),
)
account = invoice_line.get_invoice_line_account(
"in_invoice",
line.product_id,
self.purchase_id.fiscal_position_id,
self.env.user.company_id,
)
if account:
data["account_id"] = account.id
return data
47 changes: 28 additions & 19 deletions purchase_stock_picking_return_invoicing/models/purchase_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ def _get_invoiced(self):
if order._check_invoice_status_to_invoice():
order.invoice_status = "to invoice"

@api.depends("order_line.invoice_lines.invoice_id.state")
@api.depends("order_line.invoice_lines.move_id.state")
def _compute_invoice_refund_count(self):
for order in self:
invoices = order.mapped("order_line.invoice_lines.invoice_id").filtered(
invoices = order.mapped("order_line.invoice_lines.move_id").filtered(
lambda x: x.type == "in_refund"
)
order.invoice_refund_count = len(invoices)
Expand All @@ -60,38 +60,34 @@ def _compute_invoice(self):
for order in self:
order.invoice_count -= order.invoice_refund_count

@api.multi
def action_view_invoice_refund(self):
"""This function returns an action that display existing vendor refund
bills of given purchase order id.
When only one found, show the vendor bill immediately.
"""
action = self.env.ref("account.action_vendor_bill_template")
action = self.env.ref("account.action_move_in_refund_type")
result = action.read()[0]
create_refund = self.env.context.get("create_refund", False)
refunds = self.invoice_ids.filtered(lambda x: x.type == "in_refund")
# override the context to get rid of the default filtering
result["context"] = {
"type": "in_refund",
"default_purchase_id": self.id,
"default_currency_id": self.currency_id.id,
"default_type": "in_refund",
"default_company_id": self.company_id.id,
"company_id": self.company_id.id,
"default_purchase_id": self.id,
}
# choose the view_mode accordingly
if len(refunds) > 1 and not create_refund:
result["domain"] = "[('id', 'in', " + str(refunds.ids) + ")]"
else:
res = self.env.ref("account.invoice_supplier_form", False)
result["views"] = [(res and res.id or False, "form")]
# Do not set an invoice_id if we want to create a new refund.
# Do not set an move_id if we want to create a new refund.
if not create_refund:
result["res_id"] = refunds.id or False
result["context"]["default_origin"] = self.name
result["context"]["default_reference"] = self.partner_ref
return result

@api.multi
def action_view_invoice(self):
"""Change super action for displaying only normal invoices."""
result = super(PurchaseOrder, self).action_view_invoice()
Expand All @@ -100,7 +96,7 @@ def action_view_invoice(self):
if len(invoices) != 1:
result["domain"] = [("id", "in", invoices.ids)]
elif len(invoices) == 1:
res = self.env.ref("account.invoice_supplier_form", False)
res = self.env.ref("account.view_move_form", False)
result["views"] = [(res and res.id or False, "form")]
result["res_id"] = invoices.id
return result
Expand All @@ -117,18 +113,20 @@ class PurchaseOrderLine(models.Model):
store=True,
)

@api.depends("invoice_lines.invoice_id.state", "invoice_lines.quantity")
@api.depends("invoice_lines.move_id.state", "invoice_lines.quantity")
def _compute_qty_refunded(self):
for line in self:
inv_lines = line.invoice_lines.filtered(
lambda x: (
(x.invoice_id.type == "in_invoice" and x.quantity < 0.0)
or (x.invoice_id.type == "in_refund" and x.quantity > 0.0)
(x.move_id.type == "in_invoice" and x.quantity < 0.0)
or (x.move_id.type == "in_refund" and x.quantity > 0.0)
)
)
line.qty_refunded = sum(
inv_lines.mapped(
lambda x: (x.uom_id._compute_quantity(x.quantity, line.product_uom))
lambda x: (
x.product_uom_id._compute_quantity(x.quantity, line.product_uom)
)
)
)

Expand All @@ -147,18 +145,29 @@ def _compute_qty_returned(self):
["purchase_line_id", "product_uom"],
lazy=False,
)
p = self._prefetch
# load all UoM records at once on first access
uom_ids = {g["product_uom"][0] for g in groups}
ProductUom.browse(list(uom_ids), prefetch=p)
ProductUom.browse(list(uom_ids)) # Prefetching
line_qtys = collections.defaultdict(lambda: 0)
for g in groups:
uom = ProductUom.browse(g["product_uom"][0], prefetch=p)
line = self.browse(g["purchase_line_id"][0], prefetch=p)
uom = ProductUom.browse(g["product_uom"][0])
line = self.browse(g["purchase_line_id"][0])
if uom == line.product_uom:
qty = g["product_uom_qty"]
else:
qty = uom._compute_quantity(g["product_uom_qty"], line.product_uom)
line_qtys[line.id] += qty
for line in self:
line.qty_returned = line_qtys.get(line.id, 0)

def _prepare_account_move_line(self, move):
data = super()._prepare_account_move_line(move)
if self.product_id.purchase_method == "receive":
# This formula proceeds from the simplification of full expression:
# qty_received + qty_returned - (qty_invoiced + qty_refunded) -
# (qty_returned - qty_refunded)
qty = self.qty_received - self.qty_invoiced
data["quantity"] = qty
if move.type == "in_refund":
data["quantity"] *= -1.0
return data
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
* Tecnativa <https://www.tecnativa.com>

* Pedro M. Baeza

* Ecosoft <https://ecosoft.co.th>

* Kitti Upariphutthiphong
4 changes: 2 additions & 2 deletions purchase_stock_picking_return_invoicing/readme/USAGE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ received a bill from the supplier.
#. Go back to the purchase order. Press the button *Create Bill* to create
the vendor bill.
#. The proposed vendor bill will be proposed for the quantity received. The
*Billing Status* is now 'No Bill to Receive'
*Billing Status* is now 'Fully Billed'
#. Go to the original incoming shipment
#. Press the button *Return*.
#. In the wizard *Reverse Transfer* set *Quantity* to the quantity to be
Expand All @@ -42,7 +42,7 @@ received a bill from the supplier.
#. The proposed vendor refund bill will be proposed for the quantity that is
to be refunded.
#. If you back to the purchase order, you will notice that *Billing Status*
is now 'No Bill to Receive', even when the quantity ordered does not match
is now 'Fully Billed', even when the quantity ordered does not match
with the quantity invoiced, because you did return some products.

Remark: If you accept that you will not claim for a refund for the quantity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ <h1><a class="toc-backref" href="#id1">Usage</a></h1>
<li>Go back to the purchase order. Press the button <em>Create Bill</em> to create
the vendor bill.</li>
<li>The proposed vendor bill will be proposed for the quantity received. The
<em>Billing Status</em> is now ‘No Bill to Receive</li>
<em>Billing Status</em> is now ‘Fully Billed</li>
<li>Go to the original incoming shipment</li>
<li>Press the button <em>Return</em>.</li>
<li>In the wizard <em>Reverse Transfer</em> set <em>Quantity</em> to the quantity to be
Expand All @@ -436,7 +436,7 @@ <h1><a class="toc-backref" href="#id1">Usage</a></h1>
<li>The proposed vendor refund bill will be proposed for the quantity that is
to be refunded.</li>
<li>If you back to the purchase order, you will notice that <em>Billing Status</em>
is now ‘No Bill to Receive’, even when the quantity ordered does not match
is now ‘Fully Billed’, even when the quantity ordered does not match
with the quantity invoiced, because you did return some products.</li>
</ol>
<p>Remark: If you accept that you will not claim for a refund for the quantity
Expand Down
Loading

0 comments on commit aaa9008

Please sign in to comment.