Skip to content

Commit

Permalink
Merge PR #3299 into 14.0
Browse files Browse the repository at this point in the history
Signed-off-by rvalyi
  • Loading branch information
OCA-git-bot committed Aug 25, 2024
2 parents ae5adae + 5afbaac commit dd38cbd
Show file tree
Hide file tree
Showing 4 changed files with 268 additions and 24 deletions.
1 change: 1 addition & 0 deletions l10n_br_purchase_stock/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"license": "AGPL-3",
"category": "Localisation",
"author": "Akretion, Odoo Community Association (OCA)",
"maintainers": ["renatonlima", "mbcosta"],
"website": "https://github.com/OCA/l10n-brazil",
"version": "14.0.2.0.1",
"depends": [
Expand Down
80 changes: 80 additions & 0 deletions l10n_br_purchase_stock/demo/purchase_order.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,46 @@
<value eval="[ref('main_pl_only_products_1_2')]" />
</function>

<!-- Section -->
<record id="main_pl_only_products_1_3" model="purchase.order.line">
<field name="order_id" ref="main_po_only_products_1" />
<field name="name">TEST SECTION 1</field>
<field name="display_type">line_section</field>
<field name="product_qty">0</field>
</record>

<!-- Note -->
<record id="main_pl_only_products_1_4" model="purchase.order.line">
<field name="order_id" ref="main_po_only_products_1" />
<field name="name">TEST NOTE 1</field>
<field name="display_type">line_note</field>
<field name="product_qty">0</field>
</record>

<record id="main_pl_only_products_1_5" model="purchase.order.line">
<field name="order_id" ref="main_po_only_products_1" />
<field name="product_id" ref="product.product_product_8" />
<field name="product_qty">2</field>
<field name="product_uom" ref="uom.product_uom_unit" />
<field name="price_unit">500</field>
<field name="fiscal_operation_id" ref="l10n_br_fiscal.fo_compras" />
<field
name="fiscal_operation_line_id"
ref="l10n_br_fiscal.fo_compras_compras"
/>
<field name="date_planned" eval="time.strftime('%Y-%m-%d')" />
<field name="partner_order">999999</field>
<field name="partner_order_line">003</field>
<field name="manual_additional_data">Teste - Additional Data</field>
<field name="insurance_value">10</field>
<field name="other_value">10</field>
<field name="freight_value">10</field>
</record>

<function model="purchase.order.line" name="_onchange_product_id_fiscal">
<value eval="[ref('main_pl_only_products_1_5')]" />
</function>

<!-- Purchase Order with only products test 2 - Teste Agrupamento -->
<record id="main_po_only_products_2" model="purchase.order">
<field name="name">Main l10n_br_purchase_stock - teste agrupamento</field>
Expand Down Expand Up @@ -170,6 +210,46 @@
<value eval="[ref('main_pl_only_products_2_2')]" />
</function>

<!-- Section -->
<record id="main_pl_only_products_2_3" model="purchase.order.line">
<field name="order_id" ref="main_po_only_products_2" />
<field name="name">TEST SECTION 2</field>
<field name="display_type">line_section</field>
<field name="product_qty">0</field>
</record>

<!-- Note -->
<record id="main_pl_only_products_2_4" model="purchase.order.line">
<field name="order_id" ref="main_po_only_products_2" />
<field name="name">TEST NOTE 2</field>
<field name="display_type">line_note</field>
<field name="product_qty">0</field>
</record>

<record id="main_pl_only_products_2_5" model="purchase.order.line">
<field name="order_id" ref="main_po_only_products_2" />
<field name="product_id" ref="product.product_product_8" />
<field name="product_qty">2</field>
<field name="product_uom" ref="uom.product_uom_unit" />
<field name="price_unit">500</field>
<field name="fiscal_operation_id" ref="l10n_br_fiscal.fo_compras" />
<field
name="fiscal_operation_line_id"
ref="l10n_br_fiscal.fo_compras_compras"
/>
<field name="date_planned" eval="time.strftime('%Y-%m-%d')" />
<field name="partner_order">999999</field>
<field name="partner_order_line">003</field>
<field name="manual_additional_data">Teste - Additional Data</field>
<field name="insurance_value">10</field>
<field name="other_value">10</field>
<field name="freight_value">10</field>
</record>

<function model="purchase.order.line" name="_onchange_product_id_fiscal">
<value eval="[ref('main_pl_only_products_2_5')]" />
</function>

<!-- Lucro Presumido -->
<!-- Purchase Order with only products test -->
<record id="lucro_presumido_po_only_products_1" model="purchase.order">
Expand Down
15 changes: 13 additions & 2 deletions l10n_br_purchase_stock/tests/test_l10n_br_purchase_stock.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def test_grouping_pickings(self):
self.assertIn(picking_2, invoice.picking_ids)

# Validar o price_unit usado
for inv_line in invoice.invoice_line_ids:
for inv_line in invoice.invoice_line_ids.filtered(lambda ln: ln.product_id):
# TODO: A forma de instalação dos modulos feita no CI
# falha o browse aqui
# l10n_br_stock_account/models/stock_invoice_onshipping.py:105
Expand All @@ -72,6 +72,17 @@ def test_grouping_pickings(self):
inv_line.fiscal_operation_line_id, "Missing Fiscal Operation Line."
)

# Section Lines
section_lines = invoice.invoice_line_ids.filtered(
lambda ln: ln.display_type == "line_section"
)
self.assertEqual(len(section_lines), 2)
# Note Lines
note_lines = invoice.invoice_line_ids.filtered(
lambda ln: ln.display_type == "line_note"
)
self.assertEqual(len(note_lines), 2)

if hasattr(invoice, "document_serie"):
invoice.document_serie = "1"
invoice.document_number = "123"
Expand Down Expand Up @@ -150,7 +161,7 @@ def test_purchase_order_lucro_presumido(self):
invoice = self.create_invoice_wizard(picking)

# Validar o price_unit usado
for inv_line in invoice.invoice_line_ids:
for inv_line in invoice.invoice_line_ids.filtered(lambda ln: ln.product_id):
# TODO: A forma de instalação dos modulos feita no CI
# falha o browse aqui
# l10n_br_stock_account/models/stock_invoice_onshipping.py:105
Expand Down
196 changes: 174 additions & 22 deletions l10n_br_purchase_stock/wizards/stock_invocing_onshipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Magno Costa <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import fields, models
from odoo import models

from odoo.addons.l10n_br_fiscal.constants.fiscal import DOCUMENT_ISSUER_PARTNER

Expand All @@ -18,16 +18,76 @@ def _build_invoice_values_from_pickings(self, pickings):
"""
invoice, values = super()._build_invoice_values_from_pickings(pickings)

pick = fields.first(pickings)
if pick.purchase_id:
values["purchase_id"] = pick.purchase_id.id
values["issuer"] = DOCUMENT_ISSUER_PARTNER
purchase_pickings = pickings.filtered(lambda pk: pk.purchase_id)
if purchase_pickings and self._get_invoice_type() != "in_refund":
# Case more than one Purchase Order the fields below will be join
# the others will be overwritting, as done in purchase module,
# one more field include here Note
payment_refs = set()
refs = set()
# Include Note/Narration
narration = set()
for picking in purchase_pickings:
# Campos informados em qualquer caso
purchase = picking.purchase_id

if pick.purchase_id.payment_term_id.id != values.get(
"invoice_payment_term_id"
):
# Campo purchase_id store=false
# values["purchase_id"] = purchase.id
if picking.fiscal_operation_id:
values["issuer"] = DOCUMENT_ISSUER_PARTNER

# Refund case don't get values from Purchase Dict
# TODO: Should get any value?
purchase_values = purchase._prepare_invoice()

# Fields to Join
# origins.add(purchase_values["invoice_origin"])
payment_refs.add(purchase_values["payment_reference"])
refs.add(purchase_values["ref"])
narration.add(purchase_values["narration"])

# Original dict from purchase module.

# Fields to get from original dict:
# - "ref": self.partner_ref or "",
# - "narration": self.notes,
# - "currency_id": self.currency_id.id,
# - "invoice_user_id": self.user_id and self.user_id.id
# or self.env.user.id,
# - "payment_reference": self.partner_ref or "",
# - "partner_bank_id": partner_bank_id.id,
# - "invoice_payment_term_id": self.payment_term_id.id,

# Fields to remove from Original Dict
vals_to_remove = {
"move_type",
"partner_id",
"fiscal_position_id",
"invoice_origin",
"invoice_line_ids",
"company_id",
# Another fields
"__last_update",
"display_name",
}

purchase_values_rm = {
k: purchase_values[k] for k in set(purchase_values) - vals_to_remove
}
values.update(purchase_values_rm)

# Fields to join
if len(purchase_pickings) > 1:
values.update(
{"invoice_payment_term_id": pick.purchase_id.payment_term_id.id}
{
"ref": ", ".join(refs)[:2000],
# In this case Origin get Pickings Names
# "invoice_origin": ", ".join(origins),
"payment_reference": len(payment_refs) == 1
and payment_refs.pop()
or False,
"narration": ", ".join(narration),
}
)

return invoice, values
Expand All @@ -40,8 +100,7 @@ def _get_move_key(self, move):
"""
key = super()._get_move_key(move)
if move.purchase_line_id:
# TODO: deveria permitir agrupar as linhas ?
# Deveria permitir agrupar Pedidos de Compras ?
# Field purchase_line_id in account.move is Many2one
key = key + (move.purchase_line_id,)

return key
Expand All @@ -57,16 +116,109 @@ def _get_invoice_line_values(self, moves, invoice_values, invoice):
values = super()._get_invoice_line_values(moves, invoice_values, invoice)
# Devido ao KEY com purchase_line_id aqui
# vem somente um registro
if len(moves) == 1:
# Caso venha apenas uma linha porem sem
# purchase_line_id é preciso ignora-la
if moves.purchase_line_id:
values["purchase_line_id"] = moves.purchase_line_id.id
values[
"analytic_account_id"
] = moves.purchase_line_id.account_analytic_id.id
values["analytic_tag_ids"] = [
(6, 0, moves.purchase_line_id.analytic_tag_ids.ids)
]
purchase_moves = moves.filtered(lambda ln: ln.purchase_line_id)
if purchase_moves:
purchase_line = purchase_moves.purchase_line_id
# Campos informados em qualquer caso
values["purchase_line_id"] = purchase_line.id
values["analytic_account_id"] = purchase_line.account_analytic_id.id
values["analytic_tag_ids"] = [(6, 0, purchase_line.analytic_tag_ids.ids)]

# Refund case don't get values from Purchase Line Dict
# TODO: Should get any value?
if self._get_invoice_type() != "in_refund":
# Same make above, get fields informed in
# original of Purchase Line dict:
purchase_line_values = purchase_line._prepare_account_move_line()

# Fields to get:
# "display_type": self.display_type,
# "sequence": self.sequence,

# Fields to remove:
vals_to_remove = {
"name",
"product_id",
"product_uom_id",
"quantity",
"price_unit",
"tax_ids",
"analytic_account_id",
"analytic_tag_ids",
"purchase_line_id",
# another fields
"__last_update",
"display_name",
}

purchase_line_values_rm = {
k: purchase_line_values[k]
for k in set(purchase_line_values) - vals_to_remove
}
values.update(purchase_line_values_rm)

return values

def _create_invoice(self, invoice_values):
"""Override this method if you need to change any values of the
invoice and the lines before the invoice creation
:param invoice_values: dict with the invoice and its lines
:return: invoice
"""
purchase = self.env["purchase.order"].browse(invoice_values.get("purchase_id"))
pickings = self._load_pickings()
purchase_pickings = pickings.filtered(lambda pk: pk.purchase_id)
if not purchase_pickings or self._get_invoice_type() == "in_refund":
return super()._create_invoice(invoice_values)

# Check Other Purchase Lines
section_note_lines = self.env["purchase.order.line"]
# Resequencing
invoice_item_sequence = 10
invoice_item_seq_dict = {}
for picking in purchase_pickings.sorted(key=lambda p: p.name):
purchase = picking.purchase_id
# Resequencing
for line in purchase.order_line:
invoice_item_seq_dict[line.id] = invoice_item_sequence
invoice_item_sequence += 1

# Section and Note Lines
section_note_lines |= purchase.order_line.filtered(
lambda ln: ln.display_type in ("line_section", "line_note")
)

for line in section_note_lines:
line_vals = line._prepare_account_move_line()
invoice_values["invoice_line_ids"].append((0, 0, line_vals))

# Resequence
for ln in invoice_values["invoice_line_ids"]:
if ln[0] != 5:
if ln[2] and ln[2].get("purchase_line_id"):
ln[2].update(
{
"sequence": invoice_item_seq_dict.get(
ln[2].get("purchase_line_id")
)
}
)

# 3) Create invoices.
moves = self.env["account.move"]
AccountMove = self.env["account.move"].with_context(
default_move_type="in_invoice"
)
# for vals in invoice_vals_list:
moves |= AccountMove.with_company(self.env.company).create(invoice_values)

# 4) Some moves might actually be refunds: convert them if the
# total amount is negative
# We do this after the moves have been created since we need taxes,
# etc. to know if the total
# is actually negative or not
moves.filtered(
lambda m: m.currency_id.round(m.amount_total) < 0
).action_switch_invoice_into_refund_credit_note()

return moves

0 comments on commit dd38cbd

Please sign in to comment.