Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

124
sale_delivery_state/README.rst Executable file
View File

@@ -0,0 +1,124 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
===================
Sale delivery State
===================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ab9d9ccdc1418a12be30fc3d05c0b5ae3b90ab4b409cffd9bbca2590661b3798
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github
:target: https://github.com/OCA/sale-workflow/tree/18.0/sale_delivery_state
:alt: OCA/sale-workflow
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_delivery_state
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This odoo module add delivery state on the sale order.
Delivery state is computed based on qty_delivered field on sale order
lines.
This is usefull for other modules to provide the state of delivery. The
state of the sale order can be forced to fully delivered in case some
quantities were cancelled by the customer and you consider you have
nothing more to deliver.
Sale order lines can have products or services, as long as the field
qty_delivered is set, it will trigger the computation of delivery state.
Sale order lines with the Skip Delivery State field set to True will be
ignored when computing the delivery state. This field is automatically
set depending on the field Sales > Configuration > Quotations & Orders >
Skip Service products for Sale Delivery State. If set to True, the field
Skip Delivery State in sale order lines containing service products will
be automatically set to True, but it can manually changed.
This module also works with delivery.carrier fees that are added as a
sale order line. Thoses line are special as they will never be
considered delivered. Delivery fees lines are ignored in the computation
of the delivery state.
When the 'sale_stock' module is installed, the glue module
'sale_stock_delivery_state' should also be installed; this module is
designed to override the compute method of the delivery status field
from 'sale_stock'.
**Table of contents**
.. contents::
:local:
Configuration
=============
#. Go to *Sales > Configuration > Quotations & Orders*. #. Check the
Skip Service products for Sale Delivery State checkbox to automatically
set the field Skip Delivery State in sale order lines to True when the
line contains a service product.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-workflow/issues>`_.
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
`feedback <https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_delivery_state%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* Akretion
Contributors
------------
- Pierrick BRUN <pierrick.brun@akretion.com>
- Benoît Guillot <benoit.guillot@akretion.com>
- Yannick Vaucher <yannick.vaucher@camptocamp.com>
- Daniel Reis <dreis@opensourceintegrators.com>, `Open Source
Integrators <https://opensourceintegrators.com>`__
- Carlos Lopez <celm1990@gmail.com>
- Virendrasinh Dabhi <veer.190.dabhi@gmail.com>
- Manuel Regidor manuel.regidor@sygel.es
- Simone Orsi simone.orsi@camptocamp.com
Maintainers
-----------
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
This module is part of the `OCA/sale-workflow <https://github.com/OCA/sale-workflow/tree/18.0/sale_delivery_state>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,2 @@
from . import models
from .hooks import pre_init_hook, post_init_hook

View File

@@ -0,0 +1,24 @@
# Copyright 2018 Akretion (http://www.akretion.com).
# @author Pierrick BRUN <pierrick.brun@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Sale delivery State",
"summary": "Show the delivery state on the sale order",
"version": "18.0.1.2.0",
"category": "Product",
"website": "https://github.com/OCA/sale-workflow",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"depends": ["sale"],
"data": [
"views/sale_order_views.xml",
"views/res_config_settings_views.xml",
],
"demo": [
"demo/sale_demo.xml",
],
"pre_init_hook": "pre_init_hook",
"post_init_hook": "post_init_hook",
}

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="sale_order_1" model="sale.order">
<field name="partner_id" ref="base.res_partner_2" />
<field name="partner_invoice_id" ref="base.res_partner_2" />
<field name="partner_shipping_id" ref="base.res_partner_2" />
<field name="user_id" ref="base.user_demo" />
<field name="team_id" ref="sales_team.team_sales_department" />
<field
name="date_order"
eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"
/>
</record>
<record id="sale_order_line_1" model="sale.order.line">
<field name="order_id" ref="sale_order_1" />
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25" />
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="uom.product_uom_unit" />
<field name="price_unit">2950.00</field>
</record>
<record id="sale_order_line_2" model="sale.order.line">
<field name="order_id" ref="sale_order_1" />
<field name="name">Pen drive, 16GB</field>
<field name="product_id" ref="product.product_delivery_02" />
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="uom.product_uom_unit" />
<field name="price_unit">145.00</field>
</record>
</odoo>

45
sale_delivery_state/hooks.py Executable file
View File

@@ -0,0 +1,45 @@
# Copyright 2023 Akretion (https://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# Copyright 2024 Manuel Regidor <manuel.regidor@sygel.es>
# Copyright 2025 Camptocamp SA
# @author: Simone Orsi <simahawk@gmail.com>
# @author: Sébastien Alix <sebastien.alix@camptocamp.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import logging
import math
from odoo.tools.misc import split_every
from odoo.tools.sql import column_exists, create_column
_logger = logging.getLogger(__name__)
def pre_init_hook(env):
_setup_new_columns(env.cr)
def _setup_new_columns(cr):
if not column_exists(cr, "sale_order", "delivery_status"):
_logger.info("Create sale_order column delivery_status")
create_column(cr, "sale_order", "delivery_status", "varchar")
if not column_exists(cr, "sale_order_line", "skip_sale_delivery_state"):
_logger.info("Create sale_order_line column skip_sale_delivery_state")
create_column(cr, "sale_order_line", "skip_sale_delivery_state", "boolean")
cr.execute("UPDATE sale_order_line SET skip_sale_delivery_state = False")
def post_init_hook(env):
# Recompute '<sale.order>.delivery_status' by chunk to keep a constant
# memory consumption
order_model = env["sale.order"].with_context(prefetch_fields=False)
rec_ids = order_model.search([]).ids
_logger.info("Recompute 'delivery_status' on %s sale orders...", len(rec_ids))
chunk_size = 2000
nb_chunks = math.ceil(len(rec_ids) / chunk_size)
for i, chunk_ids in enumerate(split_every(chunk_size, rec_ids), 1):
_logger.info("... %s / %s", i, nb_chunks)
records = order_model.browse(chunk_ids)
records._compute_oca_delivery_status()
env.cr.commit()
env.invalidate_all()

127
sale_delivery_state/i18n/es.po Executable file
View File

@@ -0,0 +1,127 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_delivery_state
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-09 20:57+0000\n"
"PO-Revision-Date: 2024-11-09 20:57+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__force_delivery_state
msgid ""
"Allow to enforce done state of delivery, for instance if some quantities "
"were cancelled"
msgstr ""
"Permitir forzar estado de entrega a hecho, por ejemplo si se han cancelado "
"algunas cantidades"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__delivery_status
msgid ""
"Blue: Not Delivered/Started\n"
" Orange: Partially Delivered\n"
" Green: Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_company
msgid "Companies"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__delivery_status
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Delivery Status"
msgstr "Estado de la Entrega"
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__force_delivery_state
msgid "Force Delivery State"
msgstr "Forzar estado de envío"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Force delivery done"
msgstr "Forzar envío realizado"
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__full
msgid "Fully Delivered"
msgstr "Totalmente Entregado"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_delivery_state_res_config_settings_view_form
msgid ""
"If active, sale order lines containing Service products will not be "
"evaluated by default when determining the Delivery State."
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__pending
msgid "Not Delivered"
msgstr "No Entregado"
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__partial
msgid "Partially Delivered"
msgstr "Entregado parcialmente"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Pending Deliveries"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order
msgid "Sales Order"
msgstr "Pedido de venta"
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order_line__skip_sale_delivery_state
msgid "Skip Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_company__skip_service_sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_config_settings__skip_service_sale_delivery_state
msgid "Skip Service products for Sale Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__started
msgid "Started"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Unforce delivery done"
msgstr "No forzar envío realizado"
#~ msgid ""
#~ "Red: Late\n"
#~ " Orange: To process today\n"
#~ " Green: On time"
#~ msgstr ""
#~ "Rojo: retrasado\n"
#~ " Naranja: a procesar hoy\n"
#~ " Verde: a tiempo"

133
sale_delivery_state/i18n/it.po Executable file
View File

@@ -0,0 +1,133 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_delivery_state
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-09 20:56+0000\n"
"PO-Revision-Date: 2025-09-26 16:14+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: \n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10.4\n"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__force_delivery_state
msgid ""
"Allow to enforce done state of delivery, for instance if some quantities "
"were cancelled"
msgstr ""
"Consente di forzare lo stato di consegna ad evasa, ad esempio se alcune "
"quantità sono state annullate"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__delivery_status
msgid ""
"Blue: Not Delivered/Started\n"
" Orange: Partially Delivered\n"
" Green: Fully Delivered"
msgstr ""
"Blue: non consegnato/avviato\n"
" Arancione: parzialmente consegnato\n"
" Verde: completamente consegnato"
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_company
msgid "Companies"
msgstr "Aziende"
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_config_settings
msgid "Config Settings"
msgstr "Impostazioni configurazione"
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__delivery_status
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Delivery Status"
msgstr "Stato della consegna"
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__force_delivery_state
msgid "Force Delivery State"
msgstr "Forza lo stato della consegna"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Force delivery done"
msgstr "Forza la consegna ad evasa"
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__full
msgid "Fully Delivered"
msgstr "Consegnata comletamente"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_delivery_state_res_config_settings_view_form
msgid ""
"If active, sale order lines containing Service products will not be "
"evaluated by default when determining the Delivery State."
msgstr ""
"Se attivo, le righe ordine di vendita che contengono prodotti servizio non "
"saranno prese in considerazione per determinare lo stato di consegna."
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__pending
msgid "Not Delivered"
msgstr "Non consegnata"
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__partial
msgid "Partially Delivered"
msgstr "Consegnata parzialmente"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Pending Deliveries"
msgstr "Consegne in attesa"
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order
msgid "Sales Order"
msgstr "Ordine di vendita"
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order_line
msgid "Sales Order Line"
msgstr "Riga ordine di vendita"
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order_line__skip_sale_delivery_state
msgid "Skip Delivery State"
msgstr "Ignora stato di consegna"
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_company__skip_service_sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_config_settings__skip_service_sale_delivery_state
msgid "Skip Service products for Sale Delivery State"
msgstr "Ignora i prodotti servizio per lo stato di consegna nelle vendite"
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__started
msgid "Started"
msgstr "Iniziata"
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Unforce delivery done"
msgstr "Annulla consegna evasa forzata"
#~ msgid ""
#~ "Red: Late\n"
#~ " Orange: To process today\n"
#~ " Green: On time"
#~ msgstr ""
#~ "Rosso: in ritardo\n"
#~ " Arancione: da elaborare oggi\n"
#~ " Verde: in tempo"

114
sale_delivery_state/i18n/pt.po Executable file
View File

@@ -0,0 +1,114 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_delivery_state
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__force_delivery_state
msgid ""
"Allow to enforce done state of delivery, for instance if some quantities "
"were cancelled"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__delivery_status
msgid ""
"Blue: Not Delivered/Started\n"
" Orange: Partially Delivered\n"
" Green: Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_company
msgid "Companies"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__delivery_status
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Delivery Status"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__force_delivery_state
msgid "Force Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Force delivery done"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__full
msgid "Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_delivery_state_res_config_settings_view_form
msgid ""
"If active, sale order lines containing Service products will not be "
"evaluated by default when determining the Delivery State."
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__pending
msgid "Not Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__partial
msgid "Partially Delivered"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Pending Deliveries"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order_line__skip_sale_delivery_state
msgid "Skip Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_company__skip_service_sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_config_settings__skip_service_sale_delivery_state
msgid "Skip Service products for Sale Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__started
msgid "Started"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Unforce delivery done"
msgstr ""

View File

@@ -0,0 +1,113 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_delivery_state
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__force_delivery_state
msgid ""
"Allow to enforce done state of delivery, for instance if some quantities "
"were cancelled"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__delivery_status
msgid ""
"Blue: Not Delivered/Started\n"
" Orange: Partially Delivered\n"
" Green: Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_company
msgid "Companies"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__delivery_status
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Delivery Status"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__force_delivery_state
msgid "Force Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Force delivery done"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__full
msgid "Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_delivery_state_res_config_settings_view_form
msgid ""
"If active, sale order lines containing Service products will not be "
"evaluated by default when determining the Delivery State."
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__pending
msgid "Not Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__partial
msgid "Partially Delivered"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Pending Deliveries"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order_line__skip_sale_delivery_state
msgid "Skip Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_company__skip_service_sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_config_settings__skip_service_sale_delivery_state
msgid "Skip Service products for Sale Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__started
msgid "Started"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Unforce delivery done"
msgstr ""

114
sale_delivery_state/i18n/tr.po Executable file
View File

@@ -0,0 +1,114 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_delivery_state
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__force_delivery_state
msgid ""
"Allow to enforce done state of delivery, for instance if some quantities "
"were cancelled"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,help:sale_delivery_state.field_sale_order__delivery_status
msgid ""
"Blue: Not Delivered/Started\n"
" Orange: Partially Delivered\n"
" Green: Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_company
msgid "Companies"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__delivery_status
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Delivery Status"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order__force_delivery_state
msgid "Force Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Force delivery done"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__full
msgid "Fully Delivered"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_delivery_state_res_config_settings_view_form
msgid ""
"If active, sale order lines containing Service products will not be "
"evaluated by default when determining the Delivery State."
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__pending
msgid "Not Delivered"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__partial
msgid "Partially Delivered"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.sale_order_view_search_inherit_sale_inherit_delivery_status
msgid "Pending Deliveries"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model,name:sale_delivery_state.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_sale_order_line__skip_sale_delivery_state
msgid "Skip Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_company__skip_service_sale_delivery_state
#: model:ir.model.fields,field_description:sale_delivery_state.field_res_config_settings__skip_service_sale_delivery_state
msgid "Skip Service products for Sale Delivery State"
msgstr ""
#. module: sale_delivery_state
#: model:ir.model.fields.selection,name:sale_delivery_state.selection__sale_order__delivery_status__started
msgid "Started"
msgstr ""
#. module: sale_delivery_state
#: model_terms:ir.ui.view,arch_db:sale_delivery_state.view_order_form_inherit_delivery_state
msgid "Unforce delivery done"
msgstr ""

View File

@@ -0,0 +1,9 @@
# Copyright 2025 Camptocamp SA
# @author: Simone Orsi <simahawk@gmail.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.addons.sale_delivery_state.hooks import _setup_new_columns
def migrate(cr, version):
_setup_new_columns(cr)

View File

@@ -0,0 +1,4 @@
from . import sale_order
from . import sale_order_line
from . import res_company
from . import res_config_settings

View File

@@ -0,0 +1,12 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = "res.company"
skip_service_sale_delivery_state = fields.Boolean(
string="Skip Service products for Sale Delivery State"
)

View File

@@ -0,0 +1,14 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
skip_service_sale_delivery_state = fields.Boolean(
string="Skip Service products for Sale Delivery State",
related="company_id.skip_service_sale_delivery_state",
readonly=False,
)

View File

@@ -0,0 +1,116 @@
# Copyright 2018 Akretion (http://www.akretion.com).
# @author Pierrick BRUN <pierrick.brun@akretion.com>
# Copyright 2018 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo.tools import float_compare, float_is_zero
class SaleOrder(models.Model):
_inherit = "sale.order"
delivery_status = fields.Selection(
# Compute method have a different name then the field because
# the method _compute_delivery_status already exist in odoo sale_stock
compute="_compute_oca_delivery_status",
store=True,
# Respect the same order as in sale_stock
# Including the 'started' state
# that is not used here but we compute it
# if pickings are available, to be compatible.
selection=[
("pending", "Not Delivered"),
("started", "Started"),
("partial", "Partially Delivered"),
("full", "Fully Delivered"),
],
)
force_delivery_state = fields.Boolean(
help=(
"Allow to enforce done state of delivery, for instance if some"
" quantities were cancelled"
),
)
def _all_qty_delivered(self):
"""
Returns True if all line have qty_delivered >= to ordered quantities
If `delivery` module is installed, ignores the lines with delivery costs
:returns: boolean
"""
self.ensure_one()
# Skip delivery costs lines
sale_lines = self.order_line.filtered(
lambda rec: not rec._is_delivery() and not rec.skip_sale_delivery_state
)
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
return all(
float_compare(
line.qty_delivered, line.product_uom_qty, precision_digits=precision
)
>= 0
for line in sale_lines
)
def _partially_delivered(self):
"""
Returns True if at least one line is delivered
:returns: boolean
"""
self.ensure_one()
# Skip delivery costs lines
sale_lines = self.order_line.filtered(
lambda rec: not rec._is_delivery() and not rec.skip_sale_delivery_state
)
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
return any(
not float_is_zero(line.qty_delivered, precision_digits=precision)
for line in sale_lines
)
@api.depends(
"order_line.qty_delivered",
"order_line.skip_sale_delivery_state",
"state",
"force_delivery_state",
)
def _compute_oca_delivery_status(self):
for order in self:
if order.state in ("draft", "cancel"):
order.delivery_status = None
elif order.force_delivery_state or order._all_qty_delivered():
order.delivery_status = "full"
elif order._partially_delivered():
order.delivery_status = "partial"
elif order._is_delivery_status_started():
order.delivery_status = "started"
else:
order.delivery_status = "pending"
def _is_delivery_status_started(self):
# Loose dep on sale_stock. Feel free to customize this method
# to add your own logic or to create sale_stock glue module.
# NOTE: as the delivery_status is stored the update of a picking
# won't have any effect here. Hence, if you really want to
# fully support the started state, you should trigger the update
# of the sale order when a picking is updated.
# For now, we don't care that much as this state was not used before.
has_pickings = "picking_ids" in self._fields
return has_pickings and any(p.state == "done" for p in self.picking_ids)
def action_force_delivery_state(self):
self.write({"force_delivery_state": True})
def action_unforce_delivery_state(self):
self.write({"force_delivery_state": False})

View File

@@ -0,0 +1,27 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
skip_sale_delivery_state = fields.Boolean(
string="Skip Delivery State",
compute="_compute_skip_sale_delivery_state",
store=True,
readonly=False,
)
@api.depends("company_id", "product_id")
def _compute_skip_sale_delivery_state(self):
for line in self:
skip_sale_delivery_state = False
if (
line.product_id
and line.product_id.type == "service"
and line.company_id.skip_service_sale_delivery_state
):
skip_sale_delivery_state = True
line.skip_sale_delivery_state = skip_sale_delivery_state

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,2 @@
#. Go to *Sales > Configuration > Quotations & Orders*.
#. Check the Skip Service products for Sale Delivery State checkbox to automatically set the field Skip Delivery State in sale order lines to True when the line contains a service product.

View File

@@ -0,0 +1,9 @@
- Pierrick BRUN \<<pierrick.brun@akretion.com>\>
- Benoît Guillot \<<benoit.guillot@akretion.com>\>
- Yannick Vaucher \<<yannick.vaucher@camptocamp.com>\>
- Daniel Reis \<<dreis@opensourceintegrators.com>\>, [Open Source
Integrators](https://opensourceintegrators.com)
- Carlos Lopez \<<celm1990@gmail.com>\>
- Virendrasinh Dabhi \<<veer.190.dabhi@gmail.com>\>
- Manuel Regidor <manuel.regidor@sygel.es>
- Simone Orsi <simone.orsi@camptocamp.com>

View File

@@ -0,0 +1,28 @@
This odoo module add delivery state on the sale order.
Delivery state is computed based on qty_delivered field on sale order
lines.
This is usefull for other modules to provide the state of delivery. The
state of the sale order can be forced to fully delivered in case some
quantities were cancelled by the customer and you consider you have
nothing more to deliver.
Sale order lines can have products or services, as long as the field
qty_delivered is set, it will trigger the computation of delivery state.
Sale order lines with the Skip Delivery State field set to True will be ignored when
computing the delivery state. This field is automatically set depending on the field
Sales > Configuration > Quotations & Orders > Skip Service products for Sale Delivery
State. If set to True, the field Skip Delivery State in sale order lines containing
service products will be automatically set to True, but it can manually changed.
This module also works with delivery.carrier fees that are added as a
sale order line. Thoses line are special as they will never be
considered delivered. Delivery fees lines are ignored in the computation
of the delivery state.
When the 'sale_stock' module is installed, the glue module
'sale_stock_delivery_state' should also be installed; this module is
designed to override the compute method of the delivery status field
from 'sale_stock'.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,467 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z 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.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* 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 }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="sale-delivery-state">
<h1>Sale delivery State</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ab9d9ccdc1418a12be30fc3d05c0b5ae3b90ab4b409cffd9bbca2590661b3798
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sale-workflow/tree/18.0/sale_delivery_state"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_delivery_state"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This odoo module add delivery state on the sale order.</p>
<p>Delivery state is computed based on qty_delivered field on sale order
lines.</p>
<p>This is usefull for other modules to provide the state of delivery. The
state of the sale order can be forced to fully delivered in case some
quantities were cancelled by the customer and you consider you have
nothing more to deliver.</p>
<p>Sale order lines can have products or services, as long as the field
qty_delivered is set, it will trigger the computation of delivery state.</p>
<p>Sale order lines with the Skip Delivery State field set to True will be
ignored when computing the delivery state. This field is automatically
set depending on the field Sales &gt; Configuration &gt; Quotations &amp; Orders &gt;
Skip Service products for Sale Delivery State. If set to True, the field
Skip Delivery State in sale order lines containing service products will
be automatically set to True, but it can manually changed.</p>
<p>This module also works with delivery.carrier fees that are added as a
sale order line. Thoses line are special as they will never be
considered delivered. Delivery fees lines are ignored in the computation
of the delivery state.</p>
<p>When the sale_stock module is installed, the glue module
sale_stock_delivery_state should also be installed; this module is
designed to override the compute method of the delivery status field
from sale_stock.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
<p>#. Go to <em>Sales &gt; Configuration &gt; Quotations &amp; Orders</em>. #. Check the
Skip Service products for Sale Delivery State checkbox to automatically
set the field Skip Delivery State in sale order lines to True when the
line contains a service product.</p>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/sale-workflow/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/sale-workflow/issues/new?body=module:%20sale_delivery_state%0Aversion:%2018.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">
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
<ul class="simple">
<li>Akretion</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
<ul class="simple">
<li>Pierrick BRUN &lt;<a class="reference external" href="mailto:pierrick.brun&#64;akretion.com">pierrick.brun&#64;akretion.com</a>&gt;</li>
<li>Benoît Guillot &lt;<a class="reference external" href="mailto:benoit.guillot&#64;akretion.com">benoit.guillot&#64;akretion.com</a>&gt;</li>
<li>Yannick Vaucher &lt;<a class="reference external" href="mailto:yannick.vaucher&#64;camptocamp.com">yannick.vaucher&#64;camptocamp.com</a>&gt;</li>
<li>Daniel Reis &lt;<a class="reference external" href="mailto:dreis&#64;opensourceintegrators.com">dreis&#64;opensourceintegrators.com</a>&gt;, <a class="reference external" href="https://opensourceintegrators.com">Open Source
Integrators</a></li>
<li>Carlos Lopez &lt;<a class="reference external" href="mailto:celm1990&#64;gmail.com">celm1990&#64;gmail.com</a>&gt;</li>
<li>Virendrasinh Dabhi &lt;<a class="reference external" href="mailto:veer.190.dabhi&#64;gmail.com">veer.190.dabhi&#64;gmail.com</a>&gt;</li>
<li>Manuel Regidor <a class="reference external" href="mailto:manuel.regidor&#64;sygel.es">manuel.regidor&#64;sygel.es</a></li>
<li>Simone Orsi <a class="reference external" href="mailto:simone.orsi&#64;camptocamp.com">simone.orsi&#64;camptocamp.com</a></li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
<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>
<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>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/sale-workflow/tree/18.0/sale_delivery_state">OCA/sale-workflow</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1 @@
from . import test_delivery_state

View File

@@ -0,0 +1,122 @@
# Copyright 2018 Akretion (http://www.akretion.com).
# @author Benoît GUILLOT <benoit.guillot@akretion.com>
# Copyright 2018 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from unittest import mock
from odoo.tests.common import TransactionCase
class TestDeliveryState(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.order = cls.env.ref("sale_delivery_state.sale_order_1")
cls.delivery_cost = cls.env["product.product"].create(
{"name": "delivery", "type": "service"}
)
cls.service_product = cls.env["product.product"].create(
{"name": "service", "type": "service"}
)
def _mock_delivery(self, delivery_prod=None):
delivery_prod = delivery_prod or self.delivery_cost
return mock.patch.object(
type(self.env["sale.order.line"]),
"_is_delivery",
lambda self: self.product_id == delivery_prod,
)
def _add_delivery_cost_line(self):
self.env["sale.order.line"].create(
{
"order_id": self.order.id,
"name": "Delivery cost",
"product_id": self.delivery_cost.id,
"product_uom_qty": 1,
"product_uom": self.env.ref("uom.product_uom_unit").id,
"price_unit": 10.0,
}
)
def _add_service_line(self, skip_sale_delivery_state=False):
self.env["sale.order.line"].create(
{
"order_id": self.order.id,
"name": "Service",
"product_id": self.service_product.id,
"product_uom_qty": 1,
"product_uom": self.env.ref("uom.product_uom_unit").id,
"price_unit": 10.0,
"skip_sale_delivery_state": skip_sale_delivery_state,
}
)
def test_no_delivery(self):
self.assertFalse(self.order.delivery_status)
def test_unprocessed_delivery(self):
self.order.action_confirm()
self.assertEqual(self.order.delivery_status, "pending")
def test_partially(self):
self.order.action_confirm()
self.order.order_line[0].qty_delivered = 2
self.assertEqual(self.order.delivery_status, "partial")
def test_delivery_done(self):
self.order.action_confirm()
for line in self.order.order_line:
line.qty_delivered = line.product_uom_qty
self.assertEqual(self.order.delivery_status, "full")
def test_no_delivery_delivery_cost(self):
self._add_delivery_cost_line()
with self._mock_delivery():
self.assertFalse(self.order.delivery_status)
def test_unprocessed_delivery_delivery_cost(self):
self._add_delivery_cost_line()
with self._mock_delivery():
self.order.action_confirm()
self.assertEqual(self.order.delivery_status, "pending")
def test_partially_delivery_cost(self):
self._add_delivery_cost_line()
with self._mock_delivery():
self.order.action_confirm()
self.order.order_line[0].qty_delivered = 2
self.assertEqual(self.order.delivery_status, "partial")
def test_forced_delivery_cost(self):
self._add_delivery_cost_line()
with self._mock_delivery():
self.order.action_confirm()
self.order.order_line[0].qty_delivered = 2
self.order.force_delivery_state = True
self.assertEqual(self.order.delivery_status, "full")
def test_delivery_done_delivery_cost(self):
self._add_delivery_cost_line()
with self._mock_delivery():
self.order.action_confirm()
for line in self.order.order_line:
if line._is_delivery():
continue
line.qty_delivered = line.product_uom_qty
self.assertEqual(self.order.delivery_status, "full")
def test_skip_service_line(self):
self._add_service_line()
self.order.action_confirm()
for line in self.order.order_line:
if line.product_id == self.service_product:
continue
line.qty_delivered = line.product_uom_qty
self.assertEqual(self.order.delivery_status, "partial")
self.order.order_line.filtered(
lambda a: a.product_id and a.product_id == self.service_product
).write({"skip_sale_delivery_state": True})
self.assertEqual(self.order.delivery_status, "full")

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="sale_delivery_state_res_config_settings_view_form" model="ir.ui.view">
<field name="name">sale.delivery.state.res.config.settings.view.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="sale.res_config_settings_view_form" />
<field name="arch" type="xml">
<setting id="proforma_configuration" position="after">
<setting id="skip_service_sale_delivery_state_configuration">
<field name="skip_service_sale_delivery_state" />
<div class="text-muted">
If active, sale order lines containing Service products will not be evaluated by default when determining the Delivery State.
</div>
</setting>
</setting>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_order_form_inherit_delivery_state" model="ir.ui.view">
<field name="name">sale.order.form.sale.stock</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="arch" type="xml">
<field name="state" position="before">
<button
name="action_force_delivery_state"
type="object"
string="Force delivery done"
invisible="force_delivery_state or delivery_status == 'full' or state != 'sale' or not locked"
/>
<button
name="action_unforce_delivery_state"
type="object"
string="Unforce delivery done"
invisible="not force_delivery_state or state != 'sale' or not locked"
/>
</field>
<group name="sale_shipping" position="inside">
<field name="delivery_status" invisible="state != 'sale'" />
<field name="force_delivery_state" invisible="1" />
</group>
<xpath expr="//field[@name='order_line']//list" position="inside">
<field name="skip_sale_delivery_state" optional="hide" />
</xpath>
</field>
</record>
<record id="view_order_tree_inherit_delivery_status" model="ir.ui.view">
<field name="name">sale.order.tree</field>
<field name="inherit_id" ref="sale.view_order_tree" />
<field name="model">sale.order</field>
<field name="arch" type="xml">
<field name="invoice_status" position="before">
<field
name="delivery_status"
widget="badge"
optional="hide"
decoration-info="delivery_status == 'pending'"
decoration-warning="delivery_status in ('partial', 'started')"
decoration-success="delivery_status == 'full'"
/>
</field>
</field>
</record>
<record
id="sale_order_view_search_inherit_sale_inherit_delivery_status"
model="ir.ui.view"
>
<field name="name">sale.order.search</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.sale_order_view_search_inherit_sale" />
<field name="arch" type="xml">
<filter name="order_date" position="after">
<separator />
<filter
string="Pending Deliveries"
name="filter_delivery_status_pending"
domain="[('delivery_status','in',['pending', 'started', 'partial'])]"
/>
</filter>
<filter name="order_month" position="after">
<filter
string="Delivery Status"
name="delivery_status"
context="{'group_by': 'delivery_status'}"
/>
</filter>
</field>
</record>
</odoo>