Skip to content

Commit 4be1e2b

Browse files
committed
Merge PR #1975 into 16.0
Signed-off-by HviorForgeFlow
2 parents aa229e4 + 861560e commit 4be1e2b

29 files changed

+3546
-0
lines changed

purchase_return/README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
===============
2+
Purchase Return
3+
===============

purchase_return/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models

purchase_return/__manifest__.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright 2021 ForgeFlow, S.L. (https://www.forgeflow.com)
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
{
4+
"name": "Purchase Return",
5+
"summary": "Manage return orders.",
6+
"version": "16.0.1.0.0",
7+
"category": "Purchases",
8+
"website": "https://github.com/OCA/purchase-workflow",
9+
"author": "ForgeFlow, Odoo Community Association (OCA)",
10+
"license": "LGPL-3",
11+
"application": False,
12+
"installable": True,
13+
"depends": ["purchase", "mail"],
14+
"data": [
15+
"security/ir.model.access.csv",
16+
"security/purchase_security.xml",
17+
"data/purchase_data.xml",
18+
"views/product_template_views.xml",
19+
"views/product_category_views.xml",
20+
"views/purchase_views.xml",
21+
"views/account_move_views.xml",
22+
"views/purchase_return_template.xml",
23+
"report/purchase_reports.xml",
24+
"report/purchase_return_order_templates.xml",
25+
"data/mail_template_data.xml",
26+
],
27+
"maintainers": ["JordiBForgeFlow"],
28+
"development_status": "Alpha",
29+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo noupdate="1">
3+
<record id="email_template_edi_purchase_return" model="mail.template">
4+
<field name="name">Purchase Return Order: Send</field>
5+
<field name="model_id" ref="purchase_return.model_purchase_return_order" />
6+
<field
7+
name="subject"
8+
>{{ object.company_id.name }} Return Order (Ref {{ object.name or 'n/a' }})</field>
9+
<field name="partner_to">{{ object.partner_id.id }}</field>
10+
<field name="body_html" type="html">
11+
<div style="margin: 0px; padding: 0px;">
12+
<p style="margin: 0px; padding: 0px; font-size: 13px;">
13+
Dear <t t-out="object.partner_id.name or ''">Brandon Freeman</t>
14+
<t t-if="object.partner_id.parent_id">
15+
(<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>)
16+
</t>
17+
<br /><br />
18+
Here is in attachment Return Order <span
19+
style="font-weight:bold;"
20+
t-out="object.name or ''"
21+
>P00015</span>
22+
<t t-if="object.partner_ref">
23+
with reference: <t t-out="object.partner_ref or ''">REF_XXX</t>
24+
</t>
25+
from <t t-out="object.company_id.name or ''">YourCompany</t>.
26+
<br /><br />
27+
If you have any questions, please do not hesitate to contact us.
28+
<br /><br />
29+
Best regards,
30+
</p>
31+
</div></field>
32+
<field name="report_template" ref="report_purchase_return_order" />
33+
<field name="report_name">{{(object.name or '').replace('/','_')}}</field>
34+
<field name="lang">{{object.partner_id.lang}}</field>
35+
<field name="auto_delete" eval="True" />
36+
</record>
37+
</odoo>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo noupdate="1">
3+
<!-- Purchase-related subtypes for messaging / Chatter -->
4+
<record id="mt_return_confirmed" model="mail.message.subtype">
5+
<field name="name">Return Confirmed</field>
6+
<field name="default" eval="False" />
7+
<field name="res_model">purchase.return.order</field>
8+
</record>
9+
<record id="mt_return_approved" model="mail.message.subtype">
10+
<field name="name">Return Approved</field>
11+
<field name="default" eval="False" />
12+
<field name="res_model">purchase.return.order</field>
13+
</record>
14+
<record id="mt_return_done" model="mail.message.subtype">
15+
<field name="name">Return Done</field>
16+
<field name="default" eval="False" />
17+
<field name="res_model">purchase.return.order</field>
18+
</record>
19+
20+
<!-- Sequences for purchase.return.order -->
21+
<record id="seq_purchase_return_order" model="ir.sequence">
22+
<field name="name">Purchase Return Order</field>
23+
<field name="code">purchase.return.order</field>
24+
<field name="prefix">PRT</field>
25+
<field name="padding">5</field>
26+
<field name="company_id" eval="False" />
27+
</record>
28+
</odoo>

purchase_return/models/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from . import purchase_return_order
2+
from . import purchase_return_order_line
3+
from . import account_move
4+
from . import account_move_line
5+
from . import product_template
6+
from . import product_category
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Copyright 2021 ForgeFlow, S.L. (https://www.forgeflow.com)
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
4+
from odoo import _, api, fields, models
5+
6+
7+
class AccountMove(models.Model):
8+
_inherit = "account.move"
9+
10+
purchase_return_id = fields.Many2one(
11+
"purchase.return.order",
12+
store=False,
13+
readonly=True,
14+
states={"draft": [("readonly", False)]},
15+
string="Purchase Return Order",
16+
copy=False,
17+
help="Auto-complete from a past purchase return order.",
18+
)
19+
20+
def _get_invoice_reference(self):
21+
self.ensure_one()
22+
vendor_refs = [
23+
ref
24+
for ref in set(
25+
self.line_ids.mapped("purchase_return_line_id.order_id.name")
26+
)
27+
if ref
28+
]
29+
if self.ref:
30+
return [
31+
ref for ref in self.ref.split(", ") if ref and ref not in vendor_refs
32+
] + vendor_refs
33+
return vendor_refs
34+
35+
@api.onchange("purchase_return_id")
36+
def _onchange_purchase_return_auto_complete(self):
37+
38+
if not self.purchase_return_id:
39+
return
40+
41+
# Copy data from PO
42+
invoice_vals = self.purchase_return_id.with_company(
43+
self.purchase_return_id.company_id
44+
)._prepare_invoice()
45+
del invoice_vals["ref"]
46+
self.update(invoice_vals)
47+
48+
# Copy purchase return lines.
49+
po_lines = self.purchase_return_id.order_line - self.line_ids.mapped(
50+
"purchase_return_line_id"
51+
)
52+
new_lines = self.env["account.move.line"]
53+
for line in po_lines.filtered(lambda l: not l.display_type):
54+
new_line = new_lines.new(line._prepare_account_move_line(self))
55+
new_line.account_id = new_line._get_computed_account()
56+
new_line._onchange_price_subtotal()
57+
new_lines += new_line
58+
new_lines._onchange_mark_recompute_taxes()
59+
60+
# Compute invoice_origin.
61+
origins = set(self.line_ids.mapped("purchase_return_line_id.order_id.name"))
62+
self.invoice_origin = ",".join(list(origins))
63+
64+
# Compute ref.
65+
refs = self._get_invoice_reference()
66+
self.ref = ", ".join(refs)
67+
68+
# Compute payment_reference.
69+
if len(refs) == 1:
70+
self.payment_reference = refs[0]
71+
72+
self.purchase_return_id = False
73+
self._onchange_currency()
74+
self.partner_bank_id = (
75+
self.bank_partner_id.bank_ids and self.bank_partner_id.bank_ids[0]
76+
)
77+
78+
@api.model_create_multi
79+
def create(self, vals_list):
80+
# OVERRIDE
81+
moves = super(AccountMove, self).create(vals_list)
82+
for move in moves:
83+
if move.reversed_entry_id:
84+
continue
85+
purchase = move.line_ids.mapped("purchase_return_line_id.order_id")
86+
if not purchase:
87+
continue
88+
refs = [
89+
"<a href=# data-oe-model=purchase.order data-oe-id=%s>%s</a>"
90+
% tuple(name_get)
91+
for name_get in purchase.name_get()
92+
]
93+
message = _("This vendor bill has been created from: %s") % ",".join(refs)
94+
move.message_post(body=message)
95+
return moves
96+
97+
def write(self, vals):
98+
# OVERRIDE
99+
old_purchases = [
100+
move.mapped("line_ids.purchase_return_line_id.order_id") for move in self
101+
]
102+
res = super(AccountMove, self).write(vals)
103+
for i, move in enumerate(self):
104+
new_purchases = move.mapped("line_ids.purchase_return_line_id.order_id")
105+
if not new_purchases:
106+
continue
107+
diff_purchases = new_purchases - old_purchases[i]
108+
if diff_purchases:
109+
refs = [
110+
"<a href=# data-oe-model=purchase.order data-oe-id=%s>%s</a>"
111+
% tuple(name_get)
112+
for name_get in diff_purchases.name_get()
113+
]
114+
message = _("This vendor bill has been modified from: %s") % ",".join(
115+
refs
116+
)
117+
move.message_post(body=message)
118+
return res
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2021 ForgeFlow, S.L. (https://www.forgeflow.com)
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
4+
from odoo import fields, models
5+
6+
7+
class AccountMoveLine(models.Model):
8+
_inherit = "account.move.line"
9+
10+
purchase_return_line_id = fields.Many2one(
11+
"purchase.return.order.line",
12+
"Purchase Return Order Line",
13+
ondelete="set null",
14+
copy=False,
15+
index=True,
16+
)
17+
purchase_return_order_id = fields.Many2one(
18+
"purchase.return.order",
19+
"Purchase Return Order",
20+
related="purchase_return_line_id.order_id",
21+
copy=False,
22+
readonly=True,
23+
)
24+
25+
def _copy_data_extend_business_fields(self, values):
26+
# OVERRIDE to copy the 'purchase_line_id' field as well.
27+
super(AccountMoveLine, self)._copy_data_extend_business_fields(values)
28+
values["purchase_return_line_id"] = self.purchase_line_id.id
29+
return
30+
31+
def _get_computed_account(self):
32+
account = super(AccountMoveLine, self)._get_computed_account()
33+
if self.purchase_return_line_id:
34+
fiscal_position = self.move_id.fiscal_position_id
35+
accounts = self.product_id.product_tmpl_id.get_product_accounts(
36+
fiscal_pos=fiscal_position
37+
)
38+
return accounts["vendor_returns"]
39+
return account
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2021 ForgeFlow, S.L. (https://www.forgeflow.com)
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
4+
from odoo import fields, models
5+
6+
from odoo.addons.account.models.product import ACCOUNT_DOMAIN
7+
8+
9+
class ProductCategory(models.Model):
10+
_inherit = "product.category"
11+
12+
property_account_vendor_return_categ_id = fields.Many2one(
13+
"account.account",
14+
company_dependent=True,
15+
string="Purchase Returns Account",
16+
domain=ACCOUNT_DOMAIN,
17+
help="Keep this field empty to use the default value from the product category.",
18+
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright 2021 ForgeFlow, S.L. (https://www.forgeflow.com)
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
4+
from odoo import fields, models
5+
6+
from odoo.addons.account.models.product import ACCOUNT_DOMAIN
7+
8+
9+
class ProductTemplate(models.Model):
10+
_inherit = "product.template"
11+
12+
property_account_vendor_return_id = fields.Many2one(
13+
"account.account",
14+
company_dependent=True,
15+
string="Purchase Returns Account",
16+
domain=ACCOUNT_DOMAIN,
17+
help="Keep this field empty to use the default value from the product category.",
18+
)
19+
20+
def _get_product_accounts(self):
21+
accounts = super(ProductTemplate, self)._get_product_accounts()
22+
accounts["vendor_returns"] = (
23+
self.property_account_vendor_return_id
24+
or self.categ_id.property_account_vendor_return_categ_id
25+
)
26+
return accounts

0 commit comments

Comments
 (0)