Skip to content
150 changes: 111 additions & 39 deletions l10n_it_delivery_note/README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

============================
ITA - Documento di trasporto
============================
Expand All @@ -17,7 +13,7 @@ ITA - Documento di trasporto
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--italy-lightgray.png?logo=github
Expand All @@ -37,8 +33,16 @@ ITA - Documento di trasporto
This module manage the Italian DDT (Delivery note).

From a picking is possible to generate a Delivery Note and group more
picking in one delivery note. It's also possible to invoice from the
delivery note form.
picking in one delivery note. It's also possible to invoice directly
from the delivery note form, with configurable options to use DN data
(product names, prices) instead of sale order data when generating
invoices.

This is particularly useful when:

- Products are substituted at delivery time
- Prices are negotiated during delivery
- Detailed descriptions need to be added in the DN

This module is alternative to ``l10n_it_ddt``, it follows the Odoo way
to process sale orders, pickings and invoices.
Expand All @@ -48,15 +52,24 @@ installed together.

There are two available settings:

- Base (default): one picking, one DN.
- Advanced: more picking in one DN.
- Base (default): one picking, one DN.
- Advanced: more picking in one DN.

**Italiano**

Questo modulo consente di gestire i DDT.

Da un prelievo è possibile generare un DDT e raggruppare più prelievi in
un DDT. È anche possibile fatturare dalla scheda del DDT.
un DDT. È anche possibile fatturare direttamente dalla scheda del DDT,
con opzioni configurabili per utilizzare i dati del DDT (nomi prodotti,
prezzi) invece dei dati dell'ordine di vendita nella generazione delle
fatture.

Questo è particolarmente utile quando:

- I prodotti vengono sostituiti al momento della consegna
- I prezzi vengono negoziati durante la consegna
- È necessario aggiungere descrizioni dettagliate nel DDT

Questo modulo è un alternativa al modulo ``l10n_it_ddt``, segue la
modalità Odoo di gestire ordini di vendita, prelievi e fatture.
Expand All @@ -66,8 +79,8 @@ Non è possibile avere installati contemporaneamente ``l10n_it_ddt`` e

Ci sono due impostazioni possibili.

- Base (predefinita): un prelievo, un DDT.
- Avanzata: più prelievi in un DDT.
- Base (predefinita): un prelievo, un DDT.
- Avanzata: più prelievi in un DDT.

**Table of contents**

Expand All @@ -94,17 +107,32 @@ To configure this module, go to:
Checking 'Display Delivery Method in Delivery Note Report' enables in
report field 'Delivery Method'.

**Invoice Generation from Delivery Notes:**

- Checking 'Use Delivery Note Product Name in Invoice' makes the
invoice use the product description from the delivery note instead
of the sale order. This is useful when you modify product
descriptions in the DN to reflect what was actually delivered.

- Checking 'Use Delivery Note Price Unit in Invoice' makes the
invoice use the unit price from the delivery note instead of the
sale order. This is useful for price negotiations at delivery time
or when substituting products with different prices.

2. *Inventory → Configuration → Warehouse Management → Delivery Note
Types*

In delivery note type you can specify if the product price have to be
printed in the delivery note report/slip.

- *Inventory → Configuration → Delivery Notes → Conditions of
Transport*
- *Inventory → Configuration → Delivery Notes → Appearances of Goods*
- *Inventory → Configuration → Delivery Notes → Reasons of Transport*
- *Inventory → Configuration → Delivery Notes → Methods of Transport*
- *Inventory → Configuration → Delivery Notes → Conditions of
Transport*
- *Inventory → Configuration → Delivery Notes → Appearances of
Goods*
- *Inventory → Configuration → Delivery Notes → Reasons of
Transport*
- *Inventory → Configuration → Delivery Notes → Methods of
Transport*

3. *Settings → User & Companies → Users*

Expand Down Expand Up @@ -142,10 +170,10 @@ Funzionalità avanzata

Vengono attivate varie funzionalità aggiuntive:

- più prelievi per un DDT
- selezione multipla di prelievi e generazione dei DDT
- aggiunta righe nota e righe sezione descrittive.
- lista dei DDT.
- più prelievi per un DDT
- selezione multipla di prelievi e generazione dei DDT
- aggiunta righe nota e righe sezione descrittive.
- lista dei DDT.

Il report DDT stampa in righe aggiuntive i lotti/seriali e le scadenze
del prodotto.
Expand All @@ -157,6 +185,50 @@ 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.

Utilizzo dei dati dal DDT nelle fatture
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Dalle impostazioni (*Inventario → Configurazione → Impostazioni -
Documenti di Trasporto*) è possibile configurare se la fattura deve
utilizzare i dati dal DDT anziché dall'ordine di vendita:

- **Usa Nome Prodotto da DDT nelle Fatture**: Quando attivo, la
descrizione del prodotto nella fattura viene presa dal DDT invece che
dall'ordine di vendita. Utile quando si modificano le descrizioni nel
DDT per riflettere ciò che è stato effettivamente consegnato.

- **Usa Prezzo Unitario da DDT nelle Fatture**: Quando attivo, il
prezzo unitario nella fattura viene preso dal DDT invece che
dall'ordine di vendita. Utile per negoziazioni di prezzo al momento
della consegna o quando si sostituiscono prodotti con prezzi diversi.

**Esempi pratici:**

1. **Prodotto sostituito**: Se ordini "Scrivania Modello A - €500" ma
consegni "Scrivania Modello B - €450", modificando DDT e attivando
entrambe le opzioni, la fattura rifletterà automaticamente il
prodotto e prezzo reale consegnato.

2. **Negoziazione alla consegna**: Se il cliente nota un difetto e
negoziate uno sconto, modificando il prezzo nel DDT con l'opzione
attiva, la fattura sarà corretta senza bisogno di note credito.

3. **Descrizioni dettagliate**: Se nel DDT specifichi "3 sacchi cemento
CEM II, 5 pannelli isolanti" invece di "Materiale edile vario", con
l'opzione attiva la fattura mostrerà i dettagli completi.

**Nota**: Queste opzioni sono disabilitate per default per mantenere la
retrocompatibilità. Attivarle solo se si desidera questo comportamento.

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

Expand Down Expand Up @@ -187,39 +259,39 @@ Authors
Contributors
------------

- Riccardo Bellanova <r.bellanova@apuliasoftware.it>
- Riccardo Bellanova <r.bellanova@apuliasoftware.it>

- Matteo Bilotta <mbilotta@linkeurope.it>
- Matteo Bilotta <mbilotta@linkeurope.it>

- Giuseppe Borruso <gborruso@dinamicheaziendali.it>
- Giuseppe Borruso <gborruso@dinamicheaziendali.it>

- Marco Calcagni <mcalcagni@dinamicheaziendali.it>
- Marco Calcagni <mcalcagni@dinamicheaziendali.it>

- Marco Colombo <marco.colombo@gmail.com>
- Marco Colombo <marco.colombo@gmail.com>

- Gianmarco Conte <gconte@dinamicheaziendali.it>
- Gianmarco Conte <gconte@dinamicheaziendali.it>

- Letizia Freda <letizia.freda@netfarm.it>
- Letizia Freda <letizia.freda@netfarm.it>

- Andrea Piovesana <andrea.m.piovesana@gmail.com>
- Andrea Piovesana <andrea.m.piovesana@gmail.com>

- Alex Comba <alex.comba@agilebg.com>
- Alex Comba <alex.comba@agilebg.com>

- `Ooops <https://www.ooops404.com>`__:
- `Ooops <https://www.ooops404.com>`__:

- Giovanni Serra <giovanni@gslab.it>
- Foresti Francesco <francesco.foresti@ooops404.com>
- Giovanni Serra <giovanni@gslab.it>
- Foresti Francesco <francesco.foresti@ooops404.com>

- Nextev Srl <odoo@nextev.it>
- Nextev Srl <odoo@nextev.it>

- `PyTech-SRL <https://www.pytech.it>`__:
- `PyTech-SRL <https://www.pytech.it>`__:

- Alessandro Uffreduzzi <alessandro.uffreduzzi@pytech.it>
- Sebastiano Picchi <sebastiano.picchi@pytech.it>
- Alessandro Uffreduzzi <alessandro.uffreduzzi@pytech.it>
- Sebastiano Picchi <sebastiano.picchi@pytech.it>

- `Aion Tech <https://aiontech.company/>`__:
- `Aion Tech <https://aiontech.company/>`__:

- Simone Rubino <simone.rubino@aion-tech.it>
- Simone Rubino <simone.rubino@aion-tech.it>

Maintainers
-----------
Expand Down
12 changes: 5 additions & 7 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 <gconte@dinamicheaziendali.it>
# Copyright (c) 2019, Link IT Europe Srl
# @author: Matteo Bilotta <mbilotta@linkeurope.it>
# Copyright (c) 2024, Nextev Srl <odoo@nextev.it>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import fields, models
Expand Down Expand Up @@ -147,14 +148,11 @@ def update_delivery_note_lines(self):
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 = self.invoice_line_ids.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.delivery_note_id._compute_invoice_status()
for dn in inv_dnls.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")
9 changes: 9 additions & 0 deletions l10n_it_delivery_note/models/res_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
class ResCompany(models.Model):
_inherit = "res.company"

use_dn_product_name_in_invoice = fields.Boolean(
string="Use Delivery Note Product Name in Invoice",
default=False,
)
use_dn_price_unit_in_invoice = fields.Boolean(
string="Use Delivery Note Price Unit in Invoice",
default=False,
)

display_ref_order_dn_report = fields.Boolean(
"Display Ref. Order in Delivery Note Report",
default=False,
Expand Down
11 changes: 11 additions & 0 deletions l10n_it_delivery_note/models/res_config_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ def _default_virtual_locations_root(self):
config_parameter="stock.location.virtual_root",
)

use_dn_product_name_in_invoice = fields.Boolean(
string="Use Delivery Note Product Name in Invoice",
related="company_id.use_dn_product_name_in_invoice",
readonly=False,
)
use_dn_price_unit_in_invoice = fields.Boolean(
string="Use Delivery Note Price Unit in Invoice",
related="company_id.use_dn_price_unit_in_invoice",
readonly=False,
)

display_ref_order_dn_report = fields.Boolean(
string="Display Ref. Order in Delivery Note Report",
related="company_id.display_ref_order_dn_report",
Expand Down
21 changes: 15 additions & 6 deletions l10n_it_delivery_note/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,21 @@ def _generate_delivery_note_lines(self, 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)

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

return invoice_ids
# TODO: Consider adding an 'invoice_policy' selection field on sale.order
# to allow choosing between 'delivered' (standard) and 'delivery_note' modes.
# In 'delivery_note' mode:
# - invoice_status should be computed based on delivery notes, not delivered qty
# - "Create Invoice" button should appear only when new delivery notes exist
# This would avoid bypassing standard invoicing when delivery notes exist
# but user wants to invoice directly (e.g., for multi-delivery orders).
if any(dn.invoice_status == "to invoice" for dn in self.delivery_note_ids):
self.delivery_note_ids.action_invoice(
invoice_method="service", final=final, sale_orders=self, grouped=grouped
)
# Assign delivery notes to invoices and update statuses
self._assign_delivery_notes_invoices(self.invoice_ids.ids)
return self.invoice_ids
return super()._create_invoices(grouped=grouped, final=final, date=date)

def goto_delivery_notes(self, **kwargs):
delivery_notes = self.mapped("delivery_note_ids")
Expand Down
Loading
Loading