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

[16.0][IMP] l10n_it_delivery_note: create invoice from delivery notes with 1:1 lines correspondence #4385

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from
Open
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
9 changes: 9 additions & 0 deletions l10n_it_delivery_note/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ permessi dell'utente.
Le fatture generate dai DDT contengono i riferimenti al DDT stesso nelle
righe nota.

Fatturazione da DN
------------------

E' possibile creare una fattura selezionando una o più DN dello stesso
partner dalla tree view tramite il wizard "crea fattura". Si può
scegliere se includere anche i servizi non ancora fatturati dell'ordine
di vendita correlato o considerare solo le righe nei DN. In maniera
predefinita vengono dedotti gli eventuali anticipi fatturati.

Accesso da portale
------------------

Expand Down
11 changes: 5 additions & 6 deletions l10n_it_delivery_note/models/account_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# @author: Gianmarco Conte <[email protected]>
# Copyright (c) 2019, Link IT Europe Srl
# @author: Matteo Bilotta <[email protected]>
# Copyright (c) 2024, Nextev Srl <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import _, fields, models
Expand Down Expand Up @@ -148,13 +149,11 @@ def unlink(self):
# Ripristino il valore delle delivery note
# per poterle rifatturare
inv_lines = self.mapped("invoice_line_ids")
all_dnls = inv_lines.mapped("sale_line_ids").mapped("delivery_note_line_ids")
inv_dnls = self.mapped("delivery_note_ids").mapped("line_ids")
dnls_to_unlink = all_dnls & inv_dnls
inv_dnls = inv_lines.mapped("delivery_note_line_id")
res = super().unlink()
dnls_to_unlink.sync_invoice_status()
dnls_to_unlink.mapped("delivery_note_id")._compute_invoice_status()
for dn in dnls_to_unlink.mapped("delivery_note_id"):
inv_dnls.sync_invoice_status()
inv_dnls.mapped("delivery_note_id")._compute_invoice_status()
for dn in inv_dnls.mapped("delivery_note_id"):
dn.state = "confirm"
return res

Expand Down
6 changes: 6 additions & 0 deletions l10n_it_delivery_note/models/account_invoice_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ class AccountInvoiceLine(models.Model):
delivery_note_id = fields.Many2one(
"stock.delivery.note", string="Delivery Note", readonly=True, copy=False
)
delivery_note_line_id = fields.Many2one(
"stock.delivery.note.line",
string="Delivery Note Line",
readonly=True,
copy=False,
)
note_dn = fields.Boolean(string="Note DN")
95 changes: 47 additions & 48 deletions l10n_it_delivery_note/models/stock_delivery_note.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Copyright (c) 2019, Link IT Europe Srl
# @author: Matteo Bilotta <[email protected]>
# Copyright (c) 2024, Nextev Srl <[email protected]>

import datetime

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

from ..mixins.picking_checker import (
Expand Down Expand Up @@ -657,30 +658,6 @@ def _check_delivery_notes_before_invoicing(self):
}
)

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

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

if not invoice_method or invoice_method == "dn":
for line in other_lines:
cache[line] = line.fix_qty_to_invoice()
elif invoice_method == "service":
for line in other_lines:
if line.product_id.type != "service":
cache[line] = line.fix_qty_to_invoice()

pickings_move_ids = self.mapped("picking_ids.move_ids")
for line in pickings_lines.filtered(lambda line: len(line.move_ids) > 1):
move_ids = line.move_ids & pickings_move_ids
qty_to_invoice = sum(move_ids.mapped("quantity_done"))

if qty_to_invoice < line.qty_to_invoice:
cache[line] = line.fix_qty_to_invoice(qty_to_invoice)

return cache

def action_invoice(self, invoice_method=False):
self._check_delivery_notes_before_invoicing()

Expand All @@ -695,34 +672,58 @@ def action_invoice(self, invoice_method=False):
)
if not sale_ids:
continue
orders_lines = sale_ids.mapped("order_line").filtered(
lambda l: l.product_id # noqa: E741
downpayment_lines_to_invoice = sale_ids.mapped("order_line").filtered(
lambda l: l.product_id and l.is_downpayment and l.qty_to_invoice < 0 # noqa: E741
)

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

cache = self._fix_quantities_to_invoice(
invoiceable_lines - downpayment_lines, invoice_method
)

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
)

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

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

for line, vals in cache.items():
line.write(vals)
invoice_line_ids = invoice_ids.invoice_line_ids
if invoice_method == "service":
invoice_line_ids = invoice_line_ids.filtered(
lambda il: il.product_id.type != "service"
)

invoice_line_ids.unlink()

vals_list = []
sequence = 1
account_move = self.env["account.move"]
for dn in self:
vals_list.append(
Command.create(account_move._prepare_note_dn_value(sequence, dn))
)
sequence += 1
for delivery_note_line in dn.line_ids:
vals_list.append(
Command.create(
delivery_note_line._prepare_invoice_line(sequence=sequence)
)
)
sequence += 1

if downpayment_lines_to_invoice:
vals_list.append(
Command.create(
{
"sequence": sequence,
"display_type": "line_section",
"name": _("Down Payments"),
"note_dn": True,
"quantity": 0,
}
)
)
sequence += 1
for line in downpayment_lines_to_invoice:
vals_list.append(
Command.create(line._prepare_invoice_line(sequence=sequence))
)
sequence += 1

orders_lines._compute_qty_to_invoice()
invoice_ids.line_ids = vals_list

for line in self.mapped("line_ids"):
line.write({"invoice_status": "invoiced"})
Expand All @@ -740,8 +741,6 @@ def action_invoice(self, invoice_method=False):
}
)
self._compute_invoice_status()
invoices = self.env["account.move"].browse(invoice_ids.ids)
invoices.update_delivery_note_lines()

def action_done(self):
self.write({"state": DOMAIN_DELIVERY_NOTE_STATES[3]})
Expand Down
45 changes: 44 additions & 1 deletion l10n_it_delivery_note/models/stock_delivery_note_line.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Copyright 2022 Dinamiche Aziendali srl
# (http://www.dinamicheaziendali.it/)
# @author: Giuseppe Borruso <[email protected]>
# Copyright 2024 Nextev srl <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

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

DATE_FORMAT = "%d/%m/%Y"
Expand Down Expand Up @@ -197,3 +198,45 @@
if invoice_status == "upselling"
else invoice_status
)

def _prepare_invoice_line(self, **optional_values):
"""Prepare the values to create the new invoice line for a DN line.

:param optional_values: any parameter that should be added to the
returned invoice line
:rtype: dict
"""
self.ensure_one()
res = {
"display_type": "product",
"name": self.name,
"product_id": self.product_id.id,
"product_uom_id": self.product_uom_id.id,
"quantity": self.product_qty,
"discount": self.discount,
"price_unit": self.price_unit,
"tax_ids": [Command.set(self.tax_ids.ids)],
"sale_line_ids": [Command.link(self.sale_line_id.id)],
"delivery_note_line_id": self.id,
}
if optional_values.get("sequence"):
res["sequence"] = optional_values["sequence"]
analytic_account_id = self.sale_line_id.order_id.analytic_account_id.id
if (
self.sale_line_id.analytic_distribution
and not self.sale_line_id.display_type
):
res["analytic_distribution"] = self.sale_line_id.analytic_distribution

Check warning on line 229 in l10n_it_delivery_note/models/stock_delivery_note_line.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_delivery_note/models/stock_delivery_note_line.py#L229

Added line #L229 was not covered by tests
if analytic_account_id and not self.sale_line_id.display_type:
analytic_account_id = str(analytic_account_id)
if "analytic_distribution" in res:
res["analytic_distribution"][analytic_account_id] = (

Check warning on line 233 in l10n_it_delivery_note/models/stock_delivery_note_line.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_delivery_note/models/stock_delivery_note_line.py#L233

Added line #L233 was not covered by tests
res["analytic_distribution"].get(analytic_account_id, 0) + 100
)
else:
res["analytic_distribution"] = {analytic_account_id: 100}
if optional_values:
res.update(optional_values)
if self.display_type:
res["account_id"] = False

Check warning on line 241 in l10n_it_delivery_note/models/stock_delivery_note_line.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_delivery_note/models/stock_delivery_note_line.py#L241

Added line #L241 was not covered by tests
return res
8 changes: 8 additions & 0 deletions l10n_it_delivery_note/readme/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ permessi dell'utente.
Le fatture generate dai DDT contengono i riferimenti al DDT stesso nelle
righe nota.

## Fatturazione da DN

E' possibile creare una fattura selezionando una o più DN dello stesso partner
dalla tree view tramite il wizard "crea fattura".
Si può scegliere se includere anche i servizi non ancora fatturati dell'ordine
di vendita correlato o considerare solo le righe nei DN.
In maniera predefinita vengono dedotti gli eventuali anticipi fatturati.

## Accesso da portale

Gli utenti portal hanno la possibilità di scaricare i report dei DDT di cui loro o la loro azienda padre sono impostati come destinatari o indirizzo di spedizione.
44 changes: 25 additions & 19 deletions l10n_it_delivery_note/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@

/*
:Author: David Goodger ([email protected])
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.

See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
Expand Down Expand Up @@ -275,7 +274,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: gray; } /* line numbers */
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -301,7 +300,7 @@
span.pre {
white-space: pre }

span.problematic, pre.problematic {
span.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -404,14 +403,15 @@ <h1 class="title">ITA - Documento di trasporto</h1>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a><ul>
<li><a class="reference internal" href="#funzionalita-base" id="toc-entry-3">Funzionalità base</a></li>
<li><a class="reference internal" href="#funzionalita-avanzata" id="toc-entry-4">Funzionalità avanzata</a></li>
<li><a class="reference internal" href="#accesso-da-portale" id="toc-entry-5">Accesso da portale</a></li>
<li><a class="reference internal" href="#fatturazione-da-dn" id="toc-entry-5">Fatturazione da DN</a></li>
<li><a class="reference internal" href="#accesso-da-portale" id="toc-entry-6">Accesso da portale</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-6">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-7">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-8">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-9">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-10">Maintainers</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-7">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-8">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-9">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-10">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-11">Maintainers</a></li>
</ul>
</li>
</ul>
Expand Down Expand Up @@ -488,33 +488,41 @@ <h2><a class="toc-backref" href="#toc-entry-4">Funzionalità avanzata</a></h2>
<p>Le fatture generate dai DDT contengono i riferimenti al DDT stesso nelle
righe nota.</p>
</div>
<div class="section" id="fatturazione-da-dn">
<h2><a class="toc-backref" href="#toc-entry-5">Fatturazione da DN</a></h2>
<p>E’ possibile creare una fattura selezionando una o più DN dello stesso
partner dalla tree view tramite il wizard “crea fattura”. Si può
scegliere se includere anche i servizi non ancora fatturati dell’ordine
di vendita correlato o considerare solo le righe nei DN. In maniera
predefinita vengono dedotti gli eventuali anticipi fatturati.</p>
</div>
<div class="section" id="accesso-da-portale">
<h2><a class="toc-backref" href="#toc-entry-5">Accesso da portale</a></h2>
<h2><a class="toc-backref" href="#toc-entry-6">Accesso da portale</a></h2>
<p>Gli utenti portal hanno la possibilità di scaricare i report dei DDT di
cui loro o la loro azienda padre sono impostati come destinatari o
indirizzo di spedizione.</p>
</div>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-6">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#toc-entry-7">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/l10n-italy/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/l10n-italy/issues/new?body=module:%20l10n_it_delivery_note%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-7">Credits</a></h1>
<h1><a class="toc-backref" href="#toc-entry-8">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-8">Authors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-9">Authors</a></h2>
<ul class="simple">
<li>Marco Calcagni</li>
<li>Gianmarco Conte</li>
<li>Link IT Europe Srl</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-9">Contributors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-10">Contributors</a></h2>
<ul>
<li><p class="first">Riccardo Bellanova &lt;<a class="reference external" href="mailto:r.bellanova&#64;apuliasoftware.it">r.bellanova&#64;apuliasoftware.it</a>&gt;</p>
</li>
Expand Down Expand Up @@ -555,11 +563,9 @@ <h2><a class="toc-backref" href="#toc-entry-9">Contributors</a></h2>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h2>
<h2><a class="toc-backref" href="#toc-entry-11">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
Expand Down
Loading
Loading