Skip to content

Commit

Permalink
[UPD] l10n_it_delivery_note_base: aggiornata PR OCA#4293
Browse files Browse the repository at this point in the history
  • Loading branch information
Borruso committed Aug 1, 2024
1 parent bfe7344 commit 0afb5dd
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 43 deletions.
57 changes: 41 additions & 16 deletions l10n_it_delivery_note/models/account_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ def goto_invoice(self, **kwargs):
}

def _prepare_note_dn_value(self, sequence, delivery_note_id):
delivery_note_line_sequence = self.invoice_line_ids.filtered(
lambda x: x.delivery_note_id == delivery_note_id
).mapped("sequence")
if delivery_note_line_sequence:
sequence = min(delivery_note_line_sequence) - 1
return {
"sequence": sequence,
"display_type": "line_note",
Expand Down Expand Up @@ -124,23 +129,43 @@ def update_delivery_note_lines(self):
)
)
else:
for line in invoice.invoice_line_ids:
sequence = line.sequence - 1
delivery_note_line = invoice.mapped(
"delivery_note_ids.line_ids"
) & line.mapped("sale_line_ids.delivery_note_line_ids")
for delivery_note_id in delivery_note_line.filtered(
lambda l: l.invoice_status # noqa: E741
== DOMAIN_INVOICE_STATUSES[2]
).mapped("delivery_note_id"):
line.delivery_note_id = delivery_note_id.id
new_lines.append(
(
0,
False,
self._prepare_note_dn_value(sequence, delivery_note_id),
)
sequence = 1
done_invoice_lines = self.env["account.move.line"]
delivery_notes = invoice.mapped(
"invoice_line_ids.sale_line_ids.delivery_note_line_ids."
"delivery_note_id"
).sorted(key="name")
for dn in delivery_notes:
dn_invoice_lines = invoice.invoice_line_ids.filtered(
lambda x, dn=dn, done_invoice_lines=done_invoice_lines: x
not in done_invoice_lines
and dn
in x.mapped(
"sale_line_ids.delivery_note_line_ids.delivery_note_id"
)
# fixme test invoice from 2 sale lines
)
done_invoice_lines |= dn_invoice_lines
for note_line in dn.line_ids.filtered(
lambda line: line.invoice_status == DOMAIN_INVOICE_STATUSES[2]
):
for invoice_line in dn_invoice_lines.filtered(
lambda x: not x.delivery_note_id
):
if (
note_line
in invoice_line.sale_line_ids.delivery_note_line_ids
):
invoice_line.delivery_note_id = (
note_line.delivery_note_id.id
)
new_lines.append(
(
0,
False,
self._prepare_note_dn_value(sequence, dn),
)
)

invoice.write({"line_ids": new_lines})

Expand Down
3 changes: 3 additions & 0 deletions l10n_it_delivery_note/models/res_config_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ def _default_virtual_locations_root(self):
related="company_id.display_delivery_method_dn_report",
readonly=False,
)
delivery_note_group_by_quantity = fields.Boolean(
string="Group Delivery note invoices by quantity"
)
149 changes: 144 additions & 5 deletions l10n_it_delivery_note/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Copyright (c) 2019, Link IT Europe Srl
# @author: Matteo Bilotta <[email protected]>
from itertools import groupby

from odoo import api, fields, models
from odoo.exceptions import AccessError, UserError
from odoo.fields import Command

from .stock_delivery_note import DOMAIN_DELIVERY_NOTE_STATES, DOMAIN_INVOICE_STATUSES

Expand Down Expand Up @@ -121,13 +124,14 @@ def _generate_delivery_note_lines(self, invoice_ids):
invoices = self.env["account.move"].browse(invoice_ids)
invoices.update_delivery_note_lines()

def _create_invoices(self, grouped=False, final=False, date=None):
invoice_ids = super()._create_invoices(grouped=grouped, final=final, date=date)
# def _create_invoices(self, grouped=False, final=False, date=None):
# invoice_ids = super()._create_invoices(grouped=grouped,
# final=final, date=date)

self._assign_delivery_notes_invoices(invoice_ids.ids)
self._generate_delivery_note_lines(invoice_ids.ids)
# self._assign_delivery_notes_invoices(invoice_ids.ids)
# self._generate_delivery_note_lines(invoice_ids.ids)

return invoice_ids
# return invoice_ids

def goto_delivery_notes(self, **kwargs):
delivery_notes = self.mapped("delivery_note_ids")
Expand All @@ -154,3 +158,138 @@ def goto_delivery_notes(self, **kwargs):
action = {"type": "ir.actions.act_window_close"}

return action

def _create_invoices(self, grouped=False, final=False, date=None): # noqa: C901
if (
not self.env["ir.config_parameter"]
.sudo()
.get_param("l10n_it_delivery_note.delivery_note_group_by_quantity")
):
invoice_ids = super()._create_invoices(grouped, final, date)
self._assign_delivery_notes_invoices(invoice_ids.ids)
self._generate_delivery_note_lines(invoice_ids.ids)
return invoice_ids
if not self.env["account.move"].check_access_rights("create", False):
try:
self.check_access_rights("write")
self.check_access_rule("write")
except AccessError:
return self.env["account.move"]

# 1) Create invoices.
invoice_vals_list = []
invoice_item_sequence = (
10 # Incremental sequencing to keep the lines order on the invoice.
)
for order in self:
order = order.with_company(order.company_id).with_context(
lang=order.partner_invoice_id.lang
)

invoice_vals = order._prepare_invoice()
invoiceable_lines = order._get_invoiceable_lines(final)

# if not any(not line.display_type for line in invoiceable_lines):
# continue

invoice_line_vals = []
down_payment_section_added = False
for line in invoiceable_lines.mapped("delivery_note_line_ids"):
if not down_payment_section_added and line.sale_line_id.is_downpayment:
# Create a dedicated section for the down payments
# (put at the end of the invoiceable_lines)
invoice_line_vals.append(
Command.create(
order._prepare_down_payment_section_line(
sequence=invoice_item_sequence
)
),
)
down_payment_section_added = True
invoice_item_sequence += 10
invoice_line_vals.append(
Command.create(
line._prepare_ddt_invoice_line(sequence=invoice_item_sequence)
),
)
invoice_item_sequence += 10

invoice_vals["invoice_line_ids"] += invoice_line_vals
invoice_vals_list.append(invoice_vals)

if not invoice_vals_list and self._context.get(
"raise_if_nothing_to_invoice", True
):
raise UserError(self._nothing_to_invoice_error_message())

# 2) Manage 'grouped' parameter: group by (partner_id, currency_id).
if not grouped:
new_invoice_vals_list = []
invoice_grouping_keys = self._get_invoice_grouping_keys()
invoice_vals_list = sorted(
invoice_vals_list,
key=lambda x: [
x.get(grouping_key) for grouping_key in invoice_grouping_keys
],
)
for _grouping_keys, invoices in groupby(
invoice_vals_list,
key=lambda x: [
x.get(grouping_key) for grouping_key in invoice_grouping_keys
],
):
origins = set()
payment_refs = set()
refs = set()
ref_invoice_vals = None
for invoice_vals in invoices:
if not ref_invoice_vals:
ref_invoice_vals = invoice_vals
else:
ref_invoice_vals["invoice_line_ids"] += invoice_vals[
"invoice_line_ids"
]
origins.add(invoice_vals["invoice_origin"])
payment_refs.add(invoice_vals["payment_reference"])
refs.add(invoice_vals["ref"])
ref_invoice_vals.update(
{
"ref": ", ".join(refs)[:2000],
"invoice_origin": ", ".join(origins),
"payment_reference": len(payment_refs) == 1
and payment_refs.pop()
or False,
}
)
new_invoice_vals_list.append(ref_invoice_vals)
invoice_vals_list = new_invoice_vals_list
if len(invoice_vals_list) < len(self):
SaleOrderLine = self.env["sale.order.line"]
for invoice in invoice_vals_list:
sequence = 1
for line in invoice["invoice_line_ids"]:
line[2]["sequence"] = SaleOrderLine._get_invoice_line_sequence(
new=sequence, old=line[2]["sequence"]
)
sequence += 1

moves = (
self.env["account.move"]
.sudo()
.with_context(default_move_type="out_invoice")
.create(invoice_vals_list)
)
if final:
moves.sudo().filtered(
lambda m: m.amount_total < 0
).action_switch_invoice_into_refund_credit_note()
for move in moves:
move.message_post_with_view(
"mail.message_origin_link",
values={"self": move, "origin": move.line_ids.sale_line_ids.order_id},
subtype_id=self.env["ir.model.data"]._xmlid_to_res_id("mail.mt_note"),
)
# return moves
self._assign_delivery_notes_invoices(moves.ids)
self._generate_delivery_note_lines(moves.ids)
return moves
54 changes: 36 additions & 18 deletions l10n_it_delivery_note/models/stock_delivery_note.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,9 @@ def _domain_weight_uom(self):
def _check_transport_reason_inconsistency(self):
for note in self:
if (
note.type_id
and note.type_id.transport_reason_inconsistency_ids
note.transport_reason_id
and note.transport_reason_id
and note.transport_reason_id.id
in note.type_id.transport_reason_inconsistency_ids.ids
in note.type_id.transport_reason_inconsistency_ids
):
raise UserError(
_(
Expand Down Expand Up @@ -673,19 +671,17 @@ def _check_delivery_notes_before_invoicing(self):
if line.product_id.invoice_policy == "order":
raise UserError(
_(
"In %(ddt_name)s there is %(product_name)s"
" with invoicing policy 'order'"
"In %(dn_name)s there is %(product_name)s "
"with invoicing policy 'order'",
dn_name=delivery_note_id.display_name,
product_name=line.product_id.name,
)
% {
"ddt_name": delivery_note_id.display_name,
"product_name": line.product_id.name,
}
)

def _fix_quantities_to_invoice(self, lines, invoice_method):
cache = {}

pickings_lines = lines.retrieve_pickings_lines(self.picking_ids)
pickings_lines = lines.retrieve_pickings_lines(self.mapped("picking_ids"))
other_lines = lines - pickings_lines

if not invoice_method or invoice_method == "dn":
Expand Down Expand Up @@ -716,16 +712,17 @@ def action_invoice(self, invoice_method=False):
]
for payment_term_id in payment_term_ids:
sale_ids = self.mapped("sale_ids").filtered(
lambda s, pay_term_id=payment_term_id: s.payment_term_id == pay_term_id
lambda s, payment_term_id=payment_term_id: s.payment_term_id
== payment_term_id
)
if not sale_ids:
continue
orders_lines = sale_ids.mapped("order_line").filtered(
lambda l: l.product_id # noqa: E741
lambda line: line.product_id
)

downpayment_lines = orders_lines.filtered(lambda l: l.is_downpayment) # noqa: E741
invoiceable_lines = orders_lines.filtered(lambda l: l.is_invoiceable) # noqa: E741
downpayment_lines = orders_lines.filtered(lambda line: line.is_downpayment)
invoiceable_lines = orders_lines.filtered(lambda line: line.is_invoiceable)

cache = self._fix_quantities_to_invoice(
invoiceable_lines - downpayment_lines, invoice_method
Expand All @@ -734,13 +731,13 @@ def action_invoice(self, invoice_method=False):
for downpayment in downpayment_lines:
order = downpayment.order_id
order_lines = order.order_line.filtered(
lambda l: l.product_id and not l.is_downpayment # noqa: E741
lambda line: line.product_id and not line.is_downpayment
)

if order_lines.filtered(lambda l: l.need_to_be_invoiced): # noqa: E741
if order_lines.filtered(lambda line: line.need_to_be_invoiced):
cache[downpayment] = downpayment.fix_qty_to_invoice()

invoice_ids = sale_ids.filtered(
invoice_ids = self.sale_ids.filtered(
lambda o: o.invoice_status == DOMAIN_INVOICE_STATUSES[1]
)._create_invoices(final=True)

Expand Down Expand Up @@ -768,6 +765,27 @@ def action_invoice(self, invoice_method=False):
invoices = self.env["account.move"].browse(invoice_ids.ids)
invoices.update_delivery_note_lines()

if all(
line.invoice_status == "invoiced" for line in self.mapped("line_ids")
):
for delivery_note in self:
ready_invoice_ids = [
invoice_id
for invoice_id in delivery_note.sale_ids.mapped(
"invoice_ids"
).ids
if invoice_id in invoices.ids
]
delivery_note.write(
{
"invoice_ids": [
(4, invoice_id) for invoice_id in ready_invoice_ids
]
}
)
self._compute_invoice_status()
invoices.update_delivery_note_lines()

def action_done(self):
self.write({"state": DOMAIN_DELIVERY_NOTE_STATES[3]})

Expand Down
25 changes: 25 additions & 0 deletions l10n_it_delivery_note/models/stock_delivery_note_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.fields import Command

DATE_FORMAT = "%d/%m/%Y"
DATETIME_FORMAT = "%d/%m/%Y %H:%M:%S"
Expand Down Expand Up @@ -197,3 +198,27 @@ def sync_invoice_status(self):
if invoice_status == "upselling"
else invoice_status
)

def _prepare_ddt_invoice_line(self, **optional_values):
self.ensure_one()
sequence = optional_values["sequence"] or self.sequence
res = {
"display_type": "product",
"sequence": sequence,
"name": self.name,
"product_id": self.product_id.id,
"product_uom_id": self.product_uom_id.id,
"quantity": self.product_qty,
"price_unit": self.price_unit,
"tax_ids": [Command.set(self.tax_ids.ids)],
"delivery_note_id": self.delivery_note_id.id,
}
if self.sale_line_id:
res.update(
{
"sale_line_ids": [Command.link(self.sale_line_id.id)],
"is_downpayment": self.sale_line_id.is_downpayment,
"discount": self.sale_line_id.discount,
}
)
return res
Loading

0 comments on commit 0afb5dd

Please sign in to comment.