diff --git a/purchase_reception_status_line/README.rst b/purchase_reception_status_line/README.rst new file mode 100644 index 00000000000..ecacff862d0 --- /dev/null +++ b/purchase_reception_status_line/README.rst @@ -0,0 +1,108 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +============================== +Purchase Reception Status Line +============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:584e98c86a9713c48bc45e5918b47794a8e3b6369586bca23d49282fe4162eb8 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fpurchase--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/purchase-workflow/tree/19.0/purchase_reception_status_line + :alt: OCA/purchase-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/purchase-workflow-19-0/purchase-workflow-19-0-purchase_reception_status_line + :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/purchase-workflow&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds a field *Reception Status* on purchase orders line. On +a confirmed purchase order line, it can have 3 different values: + +- Nothing Received +- Partially Received +- Fully Received + +Also takes this into account when computing the reception status for the +purchase order. + +**Highly Recommended:** Install the ``purchase_order_line_menu`` module +to access the reception status field in the purchase order line tree +view for better visibility and management. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +If you are part of the *Purchase Manager* group, you can force a +confirmed purchase order to **Full Received** status: you have to check +the field **Force Received** located in the hidden fields on the tree +view (Order Lines tab). + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* ForgeFlow + +Contributors +------------ + +- David Jiménez + +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. + +.. |maintainer-DavidJForgeFlow| image:: https://github.com/DavidJForgeFlow.png?size=40px + :target: https://github.com/DavidJForgeFlow + :alt: DavidJForgeFlow + +Current `maintainer `__: + +|maintainer-DavidJForgeFlow| + +This module is part of the `OCA/purchase-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/purchase_reception_status_line/__init__.py b/purchase_reception_status_line/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/purchase_reception_status_line/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/purchase_reception_status_line/__manifest__.py b/purchase_reception_status_line/__manifest__.py new file mode 100644 index 00000000000..ac06c278ea7 --- /dev/null +++ b/purchase_reception_status_line/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2024 ForgeFlow (http://www.akretion.com/) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Purchase Reception Status Line", + "version": "19.0.1.1.0", + "category": "Purchases", + "license": "AGPL-3", + "summary": "Add reception status on purchase order lines", + "author": "ForgeFlow,Odoo Community Association (OCA)", + "maintainers": ["DavidJForgeFlow"], + "website": "https://github.com/OCA/purchase-workflow", + "depends": ["purchase_reception_status"], + "data": [ + "views/purchase_order.xml", + "views/purchase_order_line_views.xml", + ], + "installable": True, +} diff --git a/purchase_reception_status_line/i18n/it.po b/purchase_reception_status_line/i18n/it.po new file mode 100644 index 00000000000..e4163d68303 --- /dev/null +++ b/purchase_reception_status_line/i18n/it.po @@ -0,0 +1,244 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_reception_status_line +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-10-27 09:50+0000\n" +"Last-Translator: Francesco Foresti \n" +"Language-Team: none\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: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_needaction +msgid "Action Needed" +msgstr "Azione richiesta" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_ids +msgid "Activities" +msgstr "Attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_exception_decoration +msgid "Activity Exception Decoration" +msgstr "Decorazione eccezione attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_state +msgid "Activity State" +msgstr "Stato attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_type_icon +msgid "Activity Type Icon" +msgstr "Icona tipo attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_attachment_count +msgid "Attachment Count" +msgstr "Conteggio allegati" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_follower_ids +msgid "Followers" +msgstr "Seguito da" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_partner_ids +msgid "Followers (Partners)" +msgstr "Seguito da (partner)" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_type_icon +msgid "Font awesome icon e.g. fa-tasks" +msgstr "Icona Font Awesome es. fa-tasks" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order__force_received +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__force_received +msgid "Force Received" +msgstr "Forza a ricevuto" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__full +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Fully Received" +msgstr "Ricevuto completamente" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__has_message +msgid "Has Message" +msgstr "Ha un messaggio" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_exception_icon +msgid "Icon" +msgstr "Icona" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_exception_icon +msgid "Icon to indicate an exception activity." +msgstr "Icona per indicare un'attività eccezione." + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_needaction +msgid "If checked, new messages require your attention." +msgstr "Se selezionata, nuovi messaggi richiedono attenzione." + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "Se selezionata, alcuni messaggi hanno un errore di consegna." + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order__force_received +msgid "" +"If true, the order is marked forced only when all lines are fully received " +"and at least one line was manually forced." +msgstr "" +"Se è vero, l'ordine viene contrassegnato come forzato solo quando tutte le " +"righe sono state ricevute completamente e almeno una riga è stata forzata " +"manualmente." + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__force_received +msgid "" +"If true, the reception status will be forced to Fully Received, even if some" +" quantities are not fully received. " +msgstr "" +"Se vero, lo stato di ricezione verrà forzato su completamente ricevuto, " +"anche se alcune quantità non sono state ricevute completamente. " + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_is_follower +msgid "Is Follower" +msgstr "Segue" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_has_error +msgid "Message Delivery error" +msgstr "Errore di consegna messaggio" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_ids +msgid "Messages" +msgstr "Messaggi" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__my_activity_date_deadline +msgid "My Activity Deadline" +msgstr "Scadenza mia attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "Scadenza prossima attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_summary +msgid "Next Activity Summary" +msgstr "Riepilogo prossima attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_type_id +msgid "Next Activity Type" +msgstr "Tipo prossima attività" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__pending +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Nothing Received" +msgstr "Nulla ricevuto" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_needaction_counter +msgid "Number of Actions" +msgstr "Numero di azioni" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_has_error_counter +msgid "Number of errors" +msgstr "Numero di errori" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_needaction_counter +msgid "Number of messages requiring action" +msgstr "Numero di messaggi che richiedono un'azione" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "Numero di messaggi con errore di consegna" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__over +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Over Received" +msgstr "Eccesso ricezione" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__partial +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Partially Received" +msgstr "Ricevuto parzialmente" + +#. module: purchase_reception_status_line +#: model:ir.model,name:purchase_reception_status_line.model_purchase_order +msgid "Purchase Order" +msgstr "Ordine di acquisto" + +#. module: purchase_reception_status_line +#: model:ir.model,name:purchase_reception_status_line.model_purchase_order_line +msgid "Purchase Order Line" +msgstr "Riga ordine di acquisto" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__receipt_status +msgid "Receipt Status" +msgstr "Stato ricevuta" + +#. module: purchase_reception_status_line +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Reception Status" +msgstr "Stato ricezione" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_user_id +msgid "Responsible User" +msgstr "Utente responsabile" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_state +msgid "" +"Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" +"Stato in base alle attività\n" +"Scaduto: la data richiesta è trascorsa\n" +"Oggi: la data attività è oggi\n" +"Pianificato: attività future." + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_exception_decoration +msgid "Type of the exception activity on record." +msgstr "Tipo di attività eccezione sul record." + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__website_message_ids +msgid "Website Messages" +msgstr "Messaggi sito web" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__website_message_ids +msgid "Website communication history" +msgstr "Cronologia comunicazioni sito web" diff --git a/purchase_reception_status_line/i18n/purchase_reception_status_line.pot b/purchase_reception_status_line/i18n/purchase_reception_status_line.pot new file mode 100644 index 00000000000..5e6e4f5bd70 --- /dev/null +++ b/purchase_reception_status_line/i18n/purchase_reception_status_line.pot @@ -0,0 +1,232 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_reception_status_line +# +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: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_ids +msgid "Activities" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_exception_decoration +msgid "Activity Exception Decoration" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_state +msgid "Activity State" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_type_icon +msgid "Activity Type Icon" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_type_icon +msgid "Font awesome icon e.g. fa-tasks" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order__force_received +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__force_received +msgid "Force Received" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__full +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Fully Received" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__has_message +msgid "Has Message" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_exception_icon +msgid "Icon" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_exception_icon +msgid "Icon to indicate an exception activity." +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order__force_received +msgid "" +"If true, the order is marked forced only when all lines are fully received " +"and at least one line was manually forced." +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__force_received +msgid "" +"If true, the reception status will be forced to Fully Received, even if some" +" quantities are not fully received. " +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_ids +msgid "Messages" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__my_activity_date_deadline +msgid "My Activity Deadline" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_summary +msgid "Next Activity Summary" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_type_id +msgid "Next Activity Type" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__pending +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Nothing Received" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__message_has_error_counter +msgid "Number of errors" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_needaction_counter +msgid "Number of messages requiring action" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__over +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Over Received" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields.selection,name:purchase_reception_status_line.selection__purchase_order_line__receipt_status__partial +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Partially Received" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model,name:purchase_reception_status_line.model_purchase_order +msgid "Purchase Order" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model,name:purchase_reception_status_line.model_purchase_order_line +msgid "Purchase Order Line" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__receipt_status +msgid "Receipt Status" +msgstr "" + +#. module: purchase_reception_status_line +#: model_terms:ir.ui.view,arch_db:purchase_reception_status_line.purchase_order_line_search_filters +msgid "Reception Status" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__activity_user_id +msgid "Responsible User" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_state +msgid "" +"Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__activity_exception_decoration +msgid "Type of the exception activity on record." +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,field_description:purchase_reception_status_line.field_purchase_order_line__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: purchase_reception_status_line +#: model:ir.model.fields,help:purchase_reception_status_line.field_purchase_order_line__website_message_ids +msgid "Website communication history" +msgstr "" diff --git a/purchase_reception_status_line/models/__init__.py b/purchase_reception_status_line/models/__init__.py new file mode 100644 index 00000000000..677dbb3b247 --- /dev/null +++ b/purchase_reception_status_line/models/__init__.py @@ -0,0 +1,2 @@ +from . import purchase_order +from . import purchase_order_line diff --git a/purchase_reception_status_line/models/purchase_order.py b/purchase_reception_status_line/models/purchase_order.py new file mode 100644 index 00000000000..114f8b82eb6 --- /dev/null +++ b/purchase_reception_status_line/models/purchase_order.py @@ -0,0 +1,61 @@ +# Copyright 2024 ForgeFlow (http://www.akretion.com/) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class PurchaseOrder(models.Model): + _inherit = "purchase.order" + + force_received = fields.Boolean( + compute="_compute_force_received", + inverse="_inverse_force_received", + store=True, + tracking=True, + help="If true, the order is marked forced only when all lines " + "are fully received and at least one line was manually forced.", + ) + + @api.depends("order_line.receipt_status", "order_line.force_received") + def _compute_force_received(self): + for po in self: + all_received = all(line.receipt_status == "full" for line in po.order_line) + any_forced = any(line.force_received for line in po.order_line) + po.force_received = all_received and any_forced + + def _inverse_force_received(self): + for po in self: + if po.force_received: + to_force = po.order_line.filtered( + lambda line: line.receipt_status != "full" + ) + to_force.write({"force_received": True}) + else: + forced_lines = po.order_line.filtered(lambda line: line.force_received) + forced_lines.write({"force_received": False}) + forced_lines._compute_receipt_status() + + @api.depends( + "state", + "force_received", + "order_line.qty_received", + "order_line.product_qty", + "order_line.force_received", + "order_line.receipt_status", + ) + def _compute_oca_receipt_status(self): + result = super()._compute_oca_receipt_status() + for order in self.filtered(lambda po: po.receipt_status != "full"): + status = order.receipt_status + if order.state in ("purchase", "done"): + if all([line.receipt_status == "full" for line in order.order_line]): + status = "full" + elif any( + [ + line.receipt_status in ["full", "partial"] + for line in order.order_line + ] + ): + status = "partial" + order.receipt_status = status + return result diff --git a/purchase_reception_status_line/models/purchase_order_line.py b/purchase_reception_status_line/models/purchase_order_line.py new file mode 100644 index 00000000000..96db4c87123 --- /dev/null +++ b/purchase_reception_status_line/models/purchase_order_line.py @@ -0,0 +1,60 @@ +# Copyright 2024 ForgeFlow (http://www.akretion.com/) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models +from odoo.tools import float_compare + + +class PurchaseOrderLine(models.Model): + _name = "purchase.order.line" + _inherit = ["purchase.order.line", "mail.thread", "mail.activity.mixin"] + + receipt_status = fields.Selection( + [ + ("pending", "Nothing Received"), + ("partial", "Partially Received"), + ("full", "Fully Received"), + ("over", "Over Received"), + ], + compute="_compute_receipt_status", + store=True, + ) + force_received = fields.Boolean( + store=True, + copy=False, + help="If true, the reception status will be forced to Fully Received, " + "even if some quantities are not fully received. ", + tracking=True, + ) + + @api.depends( + "state", + "force_received", + "qty_received", + "product_qty", + ) + def _compute_receipt_status(self): + prec = self.env["decimal.precision"].precision_get("Product Unit of Measure") + for line in self: + status = "pending" + if line.order_id.state in ("purchase", "done"): + if line.force_received: + status = "full" + else: + if ( + float_compare( + line.qty_received, line.product_qty, precision_digits=prec + ) + > 0 + ): + status = "over" + elif ( + float_compare( + line.qty_received, line.product_qty, precision_digits=prec + ) + == 0 + ): + status = "full" + elif float_compare(line.qty_received, 0, precision_digits=prec) > 0: + status = "partial" + line.receipt_status = status diff --git a/purchase_reception_status_line/pyproject.toml b/purchase_reception_status_line/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/purchase_reception_status_line/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/purchase_reception_status_line/readme/CONTRIBUTORS.md b/purchase_reception_status_line/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..a996bb9ab86 --- /dev/null +++ b/purchase_reception_status_line/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- David Jiménez \ diff --git a/purchase_reception_status_line/readme/DESCRIPTION.md b/purchase_reception_status_line/readme/DESCRIPTION.md new file mode 100644 index 00000000000..d220d911bb5 --- /dev/null +++ b/purchase_reception_status_line/readme/DESCRIPTION.md @@ -0,0 +1,13 @@ +This module adds a field *Reception Status* on purchase orders line. On +a confirmed purchase order line, it can have 3 different values: + +- Nothing Received +- Partially Received +- Fully Received + +Also takes this into account when computing the reception status for the +purchase order. + +**Highly Recommended:** Install the `purchase_order_line_menu` module to access +the reception status field in the purchase order line tree view for better +visibility and management. diff --git a/purchase_reception_status_line/readme/USAGE.md b/purchase_reception_status_line/readme/USAGE.md new file mode 100644 index 00000000000..5cc748009ee --- /dev/null +++ b/purchase_reception_status_line/readme/USAGE.md @@ -0,0 +1,4 @@ +If you are part of the *Purchase Manager* group, you can force a +confirmed purchase order to **Full Received** status: you have to check +the field **Force Received** located in the hidden fields on the tree +view (Order Lines tab). diff --git a/purchase_reception_status_line/static/description/icon.png b/purchase_reception_status_line/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/purchase_reception_status_line/static/description/icon.png differ diff --git a/purchase_reception_status_line/static/description/index.html b/purchase_reception_status_line/static/description/index.html new file mode 100644 index 00000000000..7a85f42c82a --- /dev/null +++ b/purchase_reception_status_line/static/description/index.html @@ -0,0 +1,450 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Purchase Reception Status Line

+ +

Beta License: AGPL-3 OCA/purchase-workflow Translate me on Weblate Try me on Runboat

+

This module adds a field Reception Status on purchase orders line. On +a confirmed purchase order line, it can have 3 different values:

+
    +
  • Nothing Received
  • +
  • Partially Received
  • +
  • Fully Received
  • +
+

Also takes this into account when computing the reception status for the +purchase order.

+

Highly Recommended: Install the purchase_order_line_menu module +to access the reception status field in the purchase order line tree +view for better visibility and management.

+

Table of contents

+ +
+

Usage

+

If you are part of the Purchase Manager group, you can force a +confirmed purchase order to Full Received status: you have to check +the field Force Received located in the hidden fields on the tree +view (Order Lines tab).

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

Current maintainer:

+

DavidJForgeFlow

+

This module is part of the OCA/purchase-workflow project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/purchase_reception_status_line/tests/__init__.py b/purchase_reception_status_line/tests/__init__.py new file mode 100644 index 00000000000..fbaa84a130e --- /dev/null +++ b/purchase_reception_status_line/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2024 ForgeFlow (http://www.akretion.com/) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_purchase_receipt_status_line diff --git a/purchase_reception_status_line/tests/test_purchase_receipt_status_line.py b/purchase_reception_status_line/tests/test_purchase_receipt_status_line.py new file mode 100644 index 00000000000..eb4a127a286 --- /dev/null +++ b/purchase_reception_status_line/tests/test_purchase_receipt_status_line.py @@ -0,0 +1,126 @@ +# Copyright 2024 ForgeFlow (http://www.akretion.com/) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import TransactionCase + + +class TestPurchaseReceiptionStatusLine(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.partner = cls.env["res.partner"].create({"name": "Purchase Partner"}) + cls.product = cls.env["product.product"].create( + # Use "service" type product to be able to set receipt qty manually + {"name": "Purchase Product", "type": "service"} + ) + cls.order = cls.env["purchase.order"].create( + { + "partner_id": cls.partner.id, + "company_id": cls.env.user.company_id.id, + } + ) + + def test_01_order_empty_with_lines(self): + """Test empty order w/ lines: receipt status should be received""" + line1 = self.env["purchase.order.line"].create( + { + "order_id": self.order.id, + "name": self.product.name, + "product_id": self.product.id, + "product_qty": 0.0, + } + ) + self.order.button_confirm() + self.assertEqual(line1.receipt_status, "full") + + def test_02_order_with_lines(self): + """Test order w/ lines + + Add 2 lines: + 1) 20u ordered, 0u received + 2) 5u ordered, 5u received + """ + self.env["purchase.order.line"].create( + [ + { + "order_id": self.order.id, + "name": self.product.name, + "product_id": self.product.id, + "product_qty": 20.0, + "qty_received_manual": 0.0, + }, + { + "order_id": self.order.id, + "name": self.product.name, + "product_id": self.product.id, + "product_qty": 5.0, + "qty_received_manual": 3.0, + }, + ] + ) + self.order.button_confirm() + self.assertEqual(self.order.order_line[0].receipt_status, "pending") + self.assertEqual(self.order.order_line[1].receipt_status, "partial") + self.order.order_line[0].force_received = True + self.assertEqual(self.order.order_line[0].receipt_status, "full") + self.assertEqual(self.order.order_line[1].receipt_status, "partial") + self.order.order_line[1].force_received = True + self.assertEqual(self.order.order_line[0].receipt_status, "full") + self.assertEqual(self.order.order_line[1].receipt_status, "full") + self.order.order_line[1].force_received = False + self.assertEqual(self.order.order_line[0].receipt_status, "full") + self.assertEqual(self.order.order_line[1].receipt_status, "partial") + self.order.force_received = True + self.assertEqual(self.order.order_line[0].receipt_status, "full") + self.assertEqual(self.order.order_line[1].receipt_status, "full") + self.assertEqual(self.order.order_line[1].force_received, True) + + def test_03_over_received_status(self): + over_line = self.env["purchase.order.line"].create( + { + "order_id": self.order.id, + "name": self.product.name, + "product_id": self.product.id, + "product_qty": 5.0, + "qty_received_manual": 7.0, + } + ) + self.order.button_confirm() + self.assertEqual(over_line.receipt_status, "over") + over_line.force_received = True + self.assertEqual(over_line.receipt_status, "full") + + def test_04_order_force_logic_and_propagation(self): + l1 = self.env["purchase.order.line"].create( + { + "order_id": self.order.id, + "name": self.product.name, + "product_id": self.product.id, + "product_qty": 4.0, + "qty_received_manual": 0.0, + } + ) + l2 = self.env["purchase.order.line"].create( + { + "order_id": self.order.id, + "name": self.product.name, + "product_id": self.product.id, + "product_qty": 3.0, + "qty_received_manual": 0.0, + } + ) + self.order.button_confirm() + self.assertTrue(l1.receipt_status == "pending") + self.assertTrue(l2.receipt_status == "pending") + self.assertFalse(self.order.force_received) + l1.force_received = True + self.assertFalse(self.order.force_received) + l2.force_received = True + self.assertTrue(self.order.force_received) + l1.force_received = False + self.assertFalse(self.order.force_received) + self.assertTrue(l2.force_received) + self.order.force_received = True + self.assertTrue(all(line.force_received for line in self.order.order_line)) + self.order.force_received = False + self.assertFalse(any(line.force_received for line in self.order.order_line)) diff --git a/purchase_reception_status_line/views/purchase_order.xml b/purchase_reception_status_line/views/purchase_order.xml new file mode 100644 index 00000000000..2257c85c3e4 --- /dev/null +++ b/purchase_reception_status_line/views/purchase_order.xml @@ -0,0 +1,26 @@ + + + + + received_status.purchase.order.form + purchase.order + + + + + + + + + diff --git a/purchase_reception_status_line/views/purchase_order_line_views.xml b/purchase_reception_status_line/views/purchase_order_line_views.xml new file mode 100644 index 00000000000..87f697f910f --- /dev/null +++ b/purchase_reception_status_line/views/purchase_order_line_views.xml @@ -0,0 +1,68 @@ + + + + purchase.order.line.tree - purchase_reception_status_line + purchase.order.line + + + + + + + + + + + + purchase.order.line.form - purchase_reception_status_line + purchase.order.line + + + + + + + + + + purchase.order.line.search.reception_status.filters + purchase.order.line + + + + + + + + + + + + +