diff --git a/README.md b/README.md index a3d6ec94f50..f4fbc0f6ec2 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,18 @@ addon | version | maintainers | summary [purchase_commercial_partner](purchase_commercial_partner/) | 18.0.1.0.0 | [![alexis-via](https://github.com/alexis-via.png?size=30px)](https://github.com/alexis-via) | Add stored related field 'Commercial Supplier' on POs [purchase_deposit](purchase_deposit/) | 18.0.1.0.0 | | Option to create deposit from purchase order [purchase_exception](purchase_exception/) | 18.0.1.0.0 | | Custom exceptions on purchase order +[purchase_invoice_plan](purchase_invoice_plan/) | 18.0.1.0.0 | [![kittiu](https://github.com/kittiu.png?size=30px)](https://github.com/kittiu) | Add to purchases order, ability to manage future invoice plan [purchase_last_price_info](purchase_last_price_info/) | 18.0.1.0.0 | [![LoisRForgeFlow](https://github.com/LoisRForgeFlow.png?size=30px)](https://github.com/LoisRForgeFlow) | Purchase Product Last Price Info [purchase_open_qty](purchase_open_qty/) | 18.0.1.0.0 | | Allows to identify the purchase orders that have quantities pending to invoice or to receive. [purchase_order_archive](purchase_order_archive/) | 18.0.1.0.0 | | Archive Purchase Orders [purchase_order_line_menu](purchase_order_line_menu/) | 18.0.1.0.0 | | Adds Purchase Order Lines Menu [purchase_order_qty_change_no_recompute](purchase_order_qty_change_no_recompute/) | 18.0.1.0.0 | [![victoralmau](https://github.com/victoralmau.png?size=30px)](https://github.com/victoralmau) | Prevent recompute if only quantity has changed in purchase order line [purchase_order_type](purchase_order_type/) | 18.0.1.0.0 | | Purchase Order Type +[purchase_order_uninvoiced_amount](purchase_order_uninvoiced_amount/) | 18.0.1.0.0 | | Purchase Order Univoiced Amount [purchase_request](purchase_request/) | 18.0.1.0.1 | | Use this module to have notification of requirements of materials and/or external services and keep track of such requirements. [purchase_request_department](purchase_request_department/) | 18.0.1.0.0 | | Purchase Request Department [purchase_request_tier_validation](purchase_request_tier_validation/) | 18.0.1.0.0 | | Extends the functionality of Purchase Requests to support a tier validation process. +[purchase_tier_validation](purchase_tier_validation/) | 18.0.1.0.0 | | Extends the functionality of Purchase Orders to support a tier validation process. [vendor_transport_lead_time](vendor_transport_lead_time/) | 18.0.1.0.1 | | Purchase delay based on transport and supplier delays [//]: # (end addons) diff --git a/purchase_invoice_plan/README.rst b/purchase_invoice_plan/README.rst new file mode 100644 index 00000000000..e2c0ad9d980 --- /dev/null +++ b/purchase_invoice_plan/README.rst @@ -0,0 +1,106 @@ +===================== +Purchase Invoice Plan +===================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:57f4d376faf44506b07b9a667a8266bd85999c40eed582b42101247a1c1281bd + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpurchase--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/purchase-workflow/tree/18.0/purchase_invoice_plan + :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-18-0/purchase-workflow-18-0-purchase_invoice_plan + :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=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +By standard feature, user can gradually create partial invoices, one by +one and in step create invoice the standard call invoice. This module +add ability to create invoices based on the predefined invoice plan, +either all at once, or one by one. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +- Create new purchase quotation as per normal process +- Select option "Use Invoice Plan", a new Invoice Plan tab will appear +- Click on "=> Create Invoice Plan" link to open invoice planning wizard +- Do plan for number of installment, start date and interval +- Double check that each installment has correct plan percentage +- After confirm purchases order, we have new option to "Create Bill by + Plan" +- User can create only next bill or create all bills at the same time + +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 +------- + +* Ecosoft + +Contributors +------------ + +- Kitti Upariphutthiphong +- Rattapong Chokmasermkul +- Italo Lopes + +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-kittiu| image:: https://github.com/kittiu.png?size=40px + :target: https://github.com/kittiu + :alt: kittiu + +Current `maintainer `__: + +|maintainer-kittiu| + +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_invoice_plan/__init__.py b/purchase_invoice_plan/__init__.py new file mode 100644 index 00000000000..d5a964721a2 --- /dev/null +++ b/purchase_invoice_plan/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import models +from . import wizard diff --git a/purchase_invoice_plan/__manifest__.py b/purchase_invoice_plan/__manifest__.py new file mode 100644 index 00000000000..1ce98ccaa85 --- /dev/null +++ b/purchase_invoice_plan/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +{ + "name": "Purchase Invoice Plan", + "summary": "Add to purchases order, ability to manage future invoice plan", + "version": "18.0.1.0.0", + "author": "Ecosoft,Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/purchase-workflow", + "category": "Purchase", + "depends": ["purchase_open_qty", "purchase_stock"], + "data": [ + "security/ir.model.access.csv", + "data/purchase_data.xml", + "wizard/purchase_create_invoice_plan_view.xml", + "wizard/purchase_make_planned_invoice_view.xml", + "views/purchase_view.xml", + ], + "installable": True, + "maintainers": ["kittiu"], + "development_status": "Alpha", +} diff --git a/purchase_invoice_plan/data/purchase_data.xml b/purchase_invoice_plan/data/purchase_data.xml new file mode 100644 index 00000000000..a1f367d7278 --- /dev/null +++ b/purchase_invoice_plan/data/purchase_data.xml @@ -0,0 +1,6 @@ + + + Purchase Invoice Plan Percent + 6 + + diff --git a/purchase_invoice_plan/i18n/es.po b/purchase_invoice_plan/i18n/es.po new file mode 100644 index 00000000000..4578c3d557d --- /dev/null +++ b/purchase_invoice_plan/i18n/es.po @@ -0,0 +1,432 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_invoice_plan +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-10-12 16:36+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\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 4.17\n" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__amount +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree_readonly +msgid "Amount" +msgstr "Importe" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__amount_invoiced +msgid "Amount Invoiced" +msgstr "Importe Facturado" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Are you sure to remove this invoice plan?" +msgstr "¿Estás seguro de eliminar este plan de facturas?" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_order__ip_invoice_plan +msgid "At least one invoice plan line pending to create invoice" +msgstr "Al menos una línea del plan de factura pendiente para crear la factura" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Bill Purchase Order" +msgstr "Factura Orden de compra" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Bills Received" +msgstr "Facturas Recibidas" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "" +"Bills will be created in draft for this installment\n" +" so that you can review them before validation." +msgstr "" +"Las facturas se crearán en borrador para este plazo\n" +" para que pueda revisarlas antes de la validación." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Cancel" +msgstr "Cancelar" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Create All Remaining Bills" +msgstr "Crear todas las facturas restantes" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Create Bill by Plan" +msgstr "Crear factura por plan" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_purchase_create_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +msgid "Create Invoice Plan" +msgstr "Crear plan de facturas" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Create Next Bill" +msgstr "Crear factura siguiente" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__create_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__create_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__create_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__create_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__day +msgid "Day" +msgstr "Día" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__display_name +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__display_name +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_create_invoice_plan +msgid "Fillig invoice planning criteria" +msgstr "Cumplimiento de criterios de planificación de facturas" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Group By" +msgstr "Agrupar Por" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__id +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__id +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__invoiced +msgid "If this line already invoiced" +msgstr "Si esta línea ya se facturó" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__to_invoice +msgid "If this line is ready to create new invoice" +msgstr "Si esta línea está lista para crear una nueva factura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__installment +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_invoice_plan__invoice_type__installment +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Installment" +msgstr "Cuota" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_invoice_plan.py:0 +msgid "" +"Installment %s: already used and not allowed to delete.\n" +"Please discard changes." +msgstr "" +"Plazo %s: ya utilizado y no se permite borrar.\n" +"Por favor, descarte los cambios." + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__installment_date +msgid "Installment Date" +msgstr "Fecha de la cuota" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__interval +msgid "Interval" +msgstr "Intervalo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__interval_type +msgid "Interval Type" +msgstr "Tipo de Intervalo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoiced +msgid "Invoice Created" +msgstr "Factura Creada" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_view_purchase_make_planned_invoice +msgid "Invoice Order" +msgstr "Orden de factura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__invoice_plan_ids +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Invoice Plan" +msgstr "Plan de factura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_invoice_plan +msgid "Invoice Plan In Process" +msgstr "Plan de Factura en Proceso" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_invoice_plan +msgid "Invoice Planning Detail" +msgstr "Detalle de Planificación de Facturas" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Invoice plan total percentage must not exceed 100%" +msgstr "El porcentaje total del plan de facturación no debe superar el 100%" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoice_ids +msgid "Invoices" +msgstr "Facturas" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__last +msgid "Last Installment" +msgstr "Última cuota" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__write_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__write_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__write_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__write_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__last +msgid "Last installment will create invoice use remaining amount" +msgstr "La última cuota creará el importe restante del uso de la factura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__month +msgid "Month" +msgstr "Mes" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__to_invoice +msgid "Next Invoice" +msgstr "Próxima Factura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__no_edit +msgid "No Edit" +msgstr "No Editar" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/wizard/purchase_create_invoice_plan.py:0 +msgid "Number Installment must greater than 1" +msgstr "El número de cuotas debe ser mayor que 1" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__num_installment +msgid "Number of Installment" +msgstr "Número de cuotas" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__percent +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_total_percent +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree_readonly +msgid "Percent" +msgstr "Porcentaje" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__plan_date +msgid "Plan Date" +msgstr "Fecha del Plan" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_invoice_plan.py:0 +msgid "" +"Plan quantity: %(plan)s, exceed invoiceable quantity: %(qty)s\n" +"Product should be delivered before invoice" +msgstr "" +"Cantidad planificada: %(plan)s, supera la cantidad facturable: %(qty)s\n" +"El producto debe entregarse antes de la factura" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Please fill percentage for all invoice plan lines" +msgstr "Complete el porcentaje para todas las líneas del plan de factura" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_purchase_invoice_plan +#: model:ir.ui.menu,name:purchase_invoice_plan.menu_purchase_invoice_plan +msgid "Purchase Invoice Plan" +msgstr "Plan de Facturación de Compra" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_order +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase Order" +msgstr "Orden de Compra" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase Orders" +msgstr "Órdenes de Compra" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase orders that have been invoiced." +msgstr "Órdenes de compra que han sido facturadas." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase orders that include lines not invoiced." +msgstr "Pedidos que incluyen líneas no facturadas." + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__purchase_id +msgid "Purchases Order" +msgstr "Órdenes de compra" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Quotations" +msgstr "Presupuestos" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_form +msgid "Related Bills" +msgstr "Facturas relacionadas" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Search Purchase Invoice Plan Lines" +msgstr "Buscar líneas del plan de facturas de compra" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__state +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Status" +msgstr "Estados" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__partner_id +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Supplier" +msgstr "Proveedor" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__amount +msgid "This amount will be used to calculate the percent" +msgstr "Este importe se utilizará para calcular el porcentaje" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__percent +msgid "This percent will be used to calculate new quantity" +msgstr "Este porcentaje se utilizará para calcular la nueva cantidad" + +#. module: purchase_invoice_plan +#: model_terms:ir.actions.act_window,help:purchase_invoice_plan.action_purchase_invoice_plan +msgid "This view show all available invoice plan line for reporting purposes" +msgstr "" +"Esta vista muestra todas las líneas del plan de facturas disponibles para " +"fines de informes" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +msgid "This wizard help you quickly create invoice plan." +msgstr "Este asistente le ayuda a crear rápidamente un plan de facturación." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "To Approve" +msgstr "A Aprobar" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_total_amount +msgid "Total Amount" +msgstr "Importe Total" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoice_type +msgid "Type" +msgstr "Tipo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__use_invoice_plan +msgid "Use Invoice Plan" +msgstr "Usar Plan de Facturas" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Use Invoice Plan selected, but no plan created" +msgstr "Usar plan de factura seleccionado, pero no creado ningún plan" + +#. module: purchase_invoice_plan +#: model_terms:ir.actions.act_window,help:purchase_invoice_plan.action_purchase_invoice_plan +msgid "View purchase invoice plan lines" +msgstr "Ver líneas del plan de facturas de compra" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Waiting Bills" +msgstr "Facturas en espera" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_make_planned_invoice +msgid "Wizard when create invoice by plan" +msgstr "Asistente al crear factura por plan" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__year +msgid "Year" +msgstr "Año" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__partner_id +msgid "You can find a vendor by its Name, TIN, Email or Internal Reference." +msgstr "" +"Puede encontrar un vendedor por su nombre, NIF, correo electrónico o " +"referencia interna." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "⇒ Create Invoice Plan" +msgstr "⇒ Crear plan de facturas" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "⇒ Remove Invoice Plan" +msgstr "⇒ Eliminar plan de factura" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación el" diff --git a/purchase_invoice_plan/i18n/it.po b/purchase_invoice_plan/i18n/it.po new file mode 100644 index 00000000000..4288a794abc --- /dev/null +++ b/purchase_invoice_plan/i18n/it.po @@ -0,0 +1,435 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_invoice_plan +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-12-10 17:21+0000\n" +"Last-Translator: mymage \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.6.2\n" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__amount +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree_readonly +msgid "Amount" +msgstr "Importo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__amount_invoiced +msgid "Amount Invoiced" +msgstr "Importo fatturato" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Are you sure to remove this invoice plan?" +msgstr "Si è sicuri di rimuovere questo piano di fatturazione?" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_order__ip_invoice_plan +msgid "At least one invoice plan line pending to create invoice" +msgstr "Almeno una riga di fattura in attesa di creare la fattura" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Bill Purchase Order" +msgstr "Conto ordine acquisto" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Bills Received" +msgstr "Fatture ricevute" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "" +"Bills will be created in draft for this installment\n" +" so that you can review them before validation." +msgstr "" +"I conti saranno creati in bozza per questa rata\n" +" in modo che si possano rivedere prima della " +"validazione." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Cancel" +msgstr "Annulla" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Create All Remaining Bills" +msgstr "Creare tutti i conti rimanenti" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Create Bill by Plan" +msgstr "Crea il conto per piano" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_purchase_create_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +msgid "Create Invoice Plan" +msgstr "Crea un piano di fatturazione" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Create Next Bill" +msgstr "Crea conto successivo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__create_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__create_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__create_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__create_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__day +msgid "Day" +msgstr "Giorno" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__display_name +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__display_name +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_create_invoice_plan +msgid "Fillig invoice planning criteria" +msgstr "Riempire i criteri del piano di fatturazione" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Group By" +msgstr "Raggruppa per" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__id +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__id +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__id +msgid "ID" +msgstr "ID" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__invoiced +msgid "If this line already invoiced" +msgstr "Se questa riga è già fatturata" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__to_invoice +msgid "If this line is ready to create new invoice" +msgstr "Se questa riga è pronta per creare una nuova fattura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__installment +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_invoice_plan__invoice_type__installment +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Installment" +msgstr "Rata" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_invoice_plan.py:0 +msgid "" +"Installment %s: already used and not allowed to delete.\n" +"Please discard changes." +msgstr "" +"Rata %s: già utilizzata e non cancellabile.\n" +"Annullare le modifiche." + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__installment_date +msgid "Installment Date" +msgstr "Giorno della rata" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__interval +msgid "Interval" +msgstr "Intervallo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__interval_type +msgid "Interval Type" +msgstr "Tipo intervallo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoiced +msgid "Invoice Created" +msgstr "Fattura creata" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_view_purchase_make_planned_invoice +msgid "Invoice Order" +msgstr "Ordine fattura" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__invoice_plan_ids +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Invoice Plan" +msgstr "Piano di fatturazione" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_invoice_plan +msgid "Invoice Plan In Process" +msgstr "Piano di fatturazione in corso" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_invoice_plan +msgid "Invoice Planning Detail" +msgstr "Dettaglio piano di fatturazione" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Invoice plan total percentage must not exceed 100%" +msgstr "Il totale percentuale del piano fatturazione non può superare il 100%" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoice_ids +msgid "Invoices" +msgstr "Fatture" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__last +msgid "Last Installment" +msgstr "Ultima rata" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__write_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__write_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__write_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__write_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__last +msgid "Last installment will create invoice use remaining amount" +msgstr "L'ultima rata creerà la fattura usando l'ammontare residuo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__month +msgid "Month" +msgstr "Mese" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__to_invoice +msgid "Next Invoice" +msgstr "Fattura successiva" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__no_edit +msgid "No Edit" +msgstr "Non modifcare" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/wizard/purchase_create_invoice_plan.py:0 +msgid "Number Installment must greater than 1" +msgstr "Il numero di rate deve essere maggiore di 1" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__num_installment +msgid "Number of Installment" +msgstr "Numero di rate" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__percent +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_total_percent +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree_readonly +msgid "Percent" +msgstr "Percentuale" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__plan_date +msgid "Plan Date" +msgstr "Pianifica data" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_invoice_plan.py:0 +msgid "" +"Plan quantity: %(plan)s, exceed invoiceable quantity: %(qty)s\n" +"Product should be delivered before invoice" +msgstr "" +"Pianifica quantità: %(plan)s, quantità in esubero fatturabile: %(qty)s\n" +"Il prodotto deve essere consegnato prima di essere fatturato" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Please fill percentage for all invoice plan lines" +msgstr "Inserire la percentuale per tutte le righe del piano di fatturazione" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_purchase_invoice_plan +#: model:ir.ui.menu,name:purchase_invoice_plan.menu_purchase_invoice_plan +msgid "Purchase Invoice Plan" +msgstr "Totale fattura di acquisto" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_order +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase Order" +msgstr "Ordine di acquisto" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase Orders" +msgstr "Ordini di acquisto" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase orders that have been invoiced." +msgstr "Ordini di acquisto che sono stati fatturati." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase orders that include lines not invoiced." +msgstr "Ordini di acquisto che hanno righe non fatturate." + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__purchase_id +msgid "Purchases Order" +msgstr "Ordine di acquisto" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Quotations" +msgstr "Preventivi" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_form +msgid "Related Bills" +msgstr "Conti correlati" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Search Purchase Invoice Plan Lines" +msgstr "Ricerca righe piano di fatturazione acquisti" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__state +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Status" +msgstr "Stato" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__partner_id +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Supplier" +msgstr "Fornitore" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__amount +msgid "This amount will be used to calculate the percent" +msgstr "Questo valore verrà usato per calcolare la percentuale" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__percent +msgid "This percent will be used to calculate new quantity" +msgstr "Questa percentuale sarà usata per calcolare una nuova quantità" + +#. module: purchase_invoice_plan +#: model_terms:ir.actions.act_window,help:purchase_invoice_plan.action_purchase_invoice_plan +msgid "This view show all available invoice plan line for reporting purposes" +msgstr "" +"Questa vista mostra tutte le righe disponibile per il piano di fatturazione " +"a sconto di reportistica" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +msgid "This wizard help you quickly create invoice plan." +msgstr "" +"Questa procedura guidata aiuterà a creare velocemente un piano di " +"fatturazione." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "To Approve" +msgstr "Da approvare" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_total_amount +msgid "Total Amount" +msgstr "Importo totale" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoice_type +msgid "Type" +msgstr "Tipo" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__use_invoice_plan +msgid "Use Invoice Plan" +msgstr "Utilizzare il piano di fatturazione" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Use Invoice Plan selected, but no plan created" +msgstr "Piano di fatturazione selezionato, ma nessun piano creato" + +#. module: purchase_invoice_plan +#: model_terms:ir.actions.act_window,help:purchase_invoice_plan.action_purchase_invoice_plan +msgid "View purchase invoice plan lines" +msgstr "Visualizza le righe di piano di fatturazione acquisti" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Waiting Bills" +msgstr "Fatture in attesa" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_make_planned_invoice +msgid "Wizard when create invoice by plan" +msgstr "Procedura guidata per creare fatturazione in base al piano" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__year +msgid "Year" +msgstr "Anno" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__partner_id +msgid "You can find a vendor by its Name, TIN, Email or Internal Reference." +msgstr "" +"Un fornitore può essere trovato per nome, codice fiscale, e-mail o " +"riferimento interno." + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "⇒ Create Invoice Plan" +msgstr "⇒ Crea un piano di fatturazione" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "⇒ Remove Invoice Plan" +msgstr "⇒ Rimuovi il piano di fatturazione" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" diff --git a/purchase_invoice_plan/i18n/purchase_invoice_plan.pot b/purchase_invoice_plan/i18n/purchase_invoice_plan.pot new file mode 100644 index 00000000000..e6378cb7890 --- /dev/null +++ b/purchase_invoice_plan/i18n/purchase_invoice_plan.pot @@ -0,0 +1,416 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_invoice_plan +# +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_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__amount +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree_readonly +msgid "Amount" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__amount_invoiced +msgid "Amount Invoiced" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Are you sure to remove this invoice plan?" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_order__ip_invoice_plan +msgid "At least one invoice plan line pending to create invoice" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Bill Purchase Order" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Bills Received" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "" +"Bills will be created in draft for this installment\n" +" so that you can review them before validation." +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Cancel" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Create All Remaining Bills" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Create Bill by Plan" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_purchase_create_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +msgid "Create Invoice Plan" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_make_planned_invoice +msgid "Create Next Bill" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__create_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__create_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__create_uid +msgid "Created by" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__create_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__create_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__create_date +msgid "Created on" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__day +msgid "Day" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__display_name +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__display_name +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__display_name +msgid "Display Name" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_create_invoice_plan +msgid "Fillig invoice planning criteria" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Group By" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__id +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__id +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__id +msgid "ID" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__invoiced +msgid "If this line already invoiced" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__to_invoice +msgid "If this line is ready to create new invoice" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__installment +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_invoice_plan__invoice_type__installment +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Installment" +msgstr "" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_invoice_plan.py:0 +msgid "" +"Installment %s: already used and not allowed to delete.\n" +"Please discard changes." +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__installment_date +msgid "Installment Date" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__interval +msgid "Interval" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__interval_type +msgid "Interval Type" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoiced +msgid "Invoice Created" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_view_purchase_make_planned_invoice +msgid "Invoice Order" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__invoice_plan_ids +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "Invoice Plan" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_invoice_plan +msgid "Invoice Plan In Process" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_invoice_plan +msgid "Invoice Planning Detail" +msgstr "" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Invoice plan total percentage must not exceed 100%" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoice_ids +msgid "Invoices" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__last +msgid "Last Installment" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__write_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__write_uid +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__write_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__write_date +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_make_planned_invoice__write_date +msgid "Last Updated on" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__last +msgid "Last installment will create invoice use remaining amount" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__month +msgid "Month" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__to_invoice +msgid "Next Invoice" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__no_edit +msgid "No Edit" +msgstr "" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/wizard/purchase_create_invoice_plan.py:0 +msgid "Number Installment must greater than 1" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_create_invoice_plan__num_installment +msgid "Number of Installment" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__percent +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_total_percent +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_tree_readonly +msgid "Percent" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__plan_date +msgid "Plan Date" +msgstr "" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_invoice_plan.py:0 +msgid "" +"Plan quantity: %(plan)s, exceed invoiceable quantity: %(qty)s\n" +"Product should be delivered before invoice" +msgstr "" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Please fill percentage for all invoice plan lines" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.actions.act_window,name:purchase_invoice_plan.action_purchase_invoice_plan +#: model:ir.ui.menu,name:purchase_invoice_plan.menu_purchase_invoice_plan +msgid "Purchase Invoice Plan" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_order +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase Order" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase Orders" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase orders that have been invoiced." +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Purchase orders that include lines not invoiced." +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__purchase_id +msgid "Purchases Order" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Quotations" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_form +msgid "Related Bills" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Search Purchase Invoice Plan Lines" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__state +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Status" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__partner_id +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Supplier" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__amount +msgid "This amount will be used to calculate the percent" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__percent +msgid "This percent will be used to calculate new quantity" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.actions.act_window,help:purchase_invoice_plan.action_purchase_invoice_plan +msgid "This view show all available invoice plan line for reporting purposes" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_create_invoice_plan +msgid "This wizard help you quickly create invoice plan." +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "To Approve" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__ip_total_amount +msgid "Total Amount" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_invoice_plan__invoice_type +msgid "Type" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,field_description:purchase_invoice_plan.field_purchase_order__use_invoice_plan +msgid "Use Invoice Plan" +msgstr "" + +#. module: purchase_invoice_plan +#. odoo-python +#: code:addons/purchase_invoice_plan/models/purchase_order.py:0 +msgid "Use Invoice Plan selected, but no plan created" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.actions.act_window,help:purchase_invoice_plan.action_purchase_invoice_plan +msgid "View purchase invoice plan lines" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.view_purchase_invoice_plan_filter +msgid "Waiting Bills" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model,name:purchase_invoice_plan.model_purchase_make_planned_invoice +msgid "Wizard when create invoice by plan" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields.selection,name:purchase_invoice_plan.selection__purchase_create_invoice_plan__interval_type__year +msgid "Year" +msgstr "" + +#. module: purchase_invoice_plan +#: model:ir.model.fields,help:purchase_invoice_plan.field_purchase_invoice_plan__partner_id +msgid "You can find a vendor by its Name, TIN, Email or Internal Reference." +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "⇒ Create Invoice Plan" +msgstr "" + +#. module: purchase_invoice_plan +#: model_terms:ir.ui.view,arch_db:purchase_invoice_plan.purchase_order_form +msgid "⇒ Remove Invoice Plan" +msgstr "" diff --git a/purchase_invoice_plan/models/__init__.py b/purchase_invoice_plan/models/__init__.py new file mode 100644 index 00000000000..542054a3cf5 --- /dev/null +++ b/purchase_invoice_plan/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import purchase_order +from . import purchase_invoice_plan diff --git a/purchase_invoice_plan/models/purchase_invoice_plan.py b/purchase_invoice_plan/models/purchase_invoice_plan.py new file mode 100644 index 00000000000..1400486dd05 --- /dev/null +++ b/purchase_invoice_plan/models/purchase_invoice_plan.py @@ -0,0 +1,205 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + + +from odoo import api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.tools.float_utils import float_compare + + +class PurchaseInvoicePlan(models.Model): + _name = "purchase.invoice.plan" + _description = "Invoice Planning Detail" + _order = "installment" + + purchase_id = fields.Many2one( + comodel_name="purchase.order", + string="Purchases Order", + index=True, + readonly=True, + ondelete="cascade", + ) + partner_id = fields.Many2one( + comodel_name="res.partner", + string="Supplier", + related="purchase_id.partner_id", + store=True, + index=True, + ) + state = fields.Selection( + string="Status", + related="purchase_id.state", + store=True, + index=True, + ) + installment = fields.Integer() + plan_date = fields.Date( + required=True, + ) + invoice_type = fields.Selection( + selection=[("installment", "Installment")], + string="Type", + required=True, + default="installment", + ) + last = fields.Boolean( + string="Last Installment", + compute="_compute_last", + help="Last installment will create invoice use remaining amount", + ) + percent = fields.Float( + digits="Purchase Invoice Plan Percent", + help="This percent will be used to calculate new quantity", + ) + amount = fields.Float( + digits="Product Price", + compute="_compute_amount", + inverse="_inverse_amount", + help="This amount will be used to calculate the percent", + ) + invoice_ids = fields.Many2many( + comodel_name="account.move", + relation="purchase_invoice_plan_invoice_rel", + column1="plan_id", + column2="move_id", + string="Invoices", + readonly=True, + ) + amount_invoiced = fields.Float( + compute="_compute_invoiced", + store=True, + readonly=False, + ) + to_invoice = fields.Boolean( + string="Next Invoice", + compute="_compute_to_invoice", + help="If this line is ready to create new invoice", + store=True, + ) + invoiced = fields.Boolean( + string="Invoice Created", + compute="_compute_invoiced", + help="If this line already invoiced", + store=True, + ) + no_edit = fields.Boolean( + compute="_compute_no_edit", + ) + + @api.depends("percent") + def _compute_amount(self): + for rec in self: + amount_untaxed = rec.purchase_id._origin.amount_untaxed + # With invoice already created, no recompute + if rec.invoiced: + rec.amount = rec.amount_invoiced + rec.percent = rec.amount / amount_untaxed * 100 + continue + # For last line, amount is the left over + if rec.last: + installments = rec.purchase_id.invoice_plan_ids.filtered( + lambda pln: pln.invoice_type == "installment" + ) + prev_amount = sum((installments - rec).mapped("amount")) + rec.amount = amount_untaxed - prev_amount + continue + rec.amount = rec.percent * amount_untaxed / 100 + + @api.onchange("amount", "percent") + def _inverse_amount(self): + for rec in self: + if rec.purchase_id.amount_untaxed != 0: + if rec.last: + installments = rec.purchase_id.invoice_plan_ids.filtered( + lambda pln: pln.invoice_type == "installment" + ) + prev_percent = sum((installments - rec).mapped("percent")) + rec.percent = 100 - prev_percent + continue + rec.percent = rec.amount / rec.purchase_id.amount_untaxed * 100 + continue + rec.percent = 0 + + @api.depends("purchase_id.state", "purchase_id.invoice_plan_ids.invoiced") + def _compute_to_invoice(self): + """If any invoice is in draft/open/paid do not allow to create inv + Only if previous to_invoice is False, it is eligible to_invoice + """ + for rec in self: + rec.to_invoice = False + for rec in self.sorted("installment"): + if rec.purchase_id.state != "purchase": + continue + if not rec.invoiced: + rec.to_invoice = True + break + + def _get_amount_invoice(self, invoices): + """Hook function""" + return sum(invoices.mapped("amount_untaxed")) + + @api.depends("invoice_ids.state") + def _compute_invoiced(self): + for rec in self: + invoiced = rec.invoice_ids.filtered( + lambda inv: inv.state in ("draft", "posted") + ) + rec.invoiced = invoiced and True or False + rec.amount_invoiced = rec._get_amount_invoice(invoiced[:1]) + + def _compute_last(self): + for rec in self: + last = max(rec.purchase_id.invoice_plan_ids.mapped("installment")) + rec.last = rec.installment == last + + def _no_edit(self): + self.ensure_one() + return self.invoiced + + def _compute_no_edit(self): + for rec in self: + rec.no_edit = rec._no_edit() + + def _compute_new_invoice_quantity(self, invoice_move): + self.ensure_one() + if self.last: # For last install, let the system do the calc. + return + percent = self.percent + move = invoice_move.with_context(**{"check_move_validity": False}) + for line in move.invoice_line_ids: + self._update_new_quantity(line, percent) + + def _update_new_quantity(self, line, percent): + """Hook function""" + plan_qty = self._get_plan_qty(line.purchase_line_id, percent) + prec = line.purchase_line_id.product_uom.rounding + if ( + float_compare(abs(plan_qty), abs(line.quantity), precision_rounding=prec) + == 1 + ): + raise ValidationError( + self.env._( + "Plan quantity: %(plan)s, exceed invoiceable quantity: %(qty)s" + "\nProduct should be delivered before invoice" + ) + % {"plan": plan_qty, "qty": line.quantity} + ) + line.write({"quantity": plan_qty}) + + @api.model + def _get_plan_qty(self, order_line, percent): + plan_qty = order_line.product_qty * (percent / 100) + return plan_qty + + @api.ondelete(at_uninstall=False) + def _unlink_except_no_edit(self): + lines = self.filtered("no_edit") + if lines: + installments = [str(x) for x in lines.mapped("installment")] + raise UserError( + self.env._( + "Installment %s: already used and not allowed to delete.\n" + "Please discard changes." + ) + % ", ".join(installments) + ) diff --git a/purchase_invoice_plan/models/purchase_order.py b/purchase_invoice_plan/models/purchase_order.py new file mode 100644 index 00000000000..d89f9e6ee0e --- /dev/null +++ b/purchase_invoice_plan/models/purchase_order.py @@ -0,0 +1,136 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from dateutil.relativedelta import relativedelta + +from odoo import api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.tools.float_utils import float_round + + +class PurchaseOrder(models.Model): + _inherit = "purchase.order" + + invoice_plan_ids = fields.One2many( + comodel_name="purchase.invoice.plan", + inverse_name="purchase_id", + string="Invoice Plan", + copy=False, + ) + use_invoice_plan = fields.Boolean( + default=False, + copy=False, + ) + ip_invoice_plan = fields.Boolean( + string="Invoice Plan In Process", + compute="_compute_ip_invoice_plan", + help="At least one invoice plan line pending to create invoice", + ) + ip_total_percent = fields.Float( + compute="_compute_ip_total", + string="Percent", + ) + ip_total_amount = fields.Monetary( + compute="_compute_ip_total", + string="Total Amount", + ) + + @api.depends("invoice_plan_ids") + def _compute_ip_total(self): + for rec in self: + installments = rec.invoice_plan_ids.filtered("installment") + rec.ip_total_percent = sum(installments.mapped("percent")) + rec.ip_total_amount = sum(installments.mapped("amount")) + + def _compute_ip_invoice_plan(self): + for rec in self: + rec.ip_invoice_plan = ( + rec.use_invoice_plan + and rec.invoice_plan_ids + and len(rec.invoice_plan_ids.filtered(lambda pln: not pln.invoiced)) + ) + + @api.constrains("invoice_plan_ids") + def _check_ip_total_percent(self): + for rec in self: + installments = rec.invoice_plan_ids.filtered("installment") + ip_total_percent = sum(installments.mapped("percent")) + if float_round(ip_total_percent, 0) > 100: + raise UserError( + self.env._("Invoice plan total percentage must not exceed 100%") + ) + + @api.constrains("state") + def _check_invoice_plan(self): + for rec in self: + if rec.state != "draft": + if rec.invoice_plan_ids.filtered(lambda pln: not pln.percent): + raise ValidationError( + self.env._("Please fill percentage for all invoice plan lines") + ) + + def button_confirm(self): + if self.filtered(lambda r: r.use_invoice_plan and not r.invoice_plan_ids): + raise UserError( + self.env._("Use Invoice Plan selected, but no plan created") + ) + return super().button_confirm() + + def create_invoice_plan( + self, num_installment, installment_date, interval, interval_type + ): + self.ensure_one() + self.invoice_plan_ids.unlink() + invoice_plans = [] + Decimal = self.env["decimal.precision"] + prec = Decimal.precision_get("Purchase Invoice Plan Percent") + percent = float_round(1.0 / num_installment * 100, prec) + percent_last = 100 - (percent * (num_installment - 1)) + for i in range(num_installment): + this_installment = i + 1 + if num_installment == this_installment: + percent = percent_last + vals = { + "installment": this_installment, + "plan_date": installment_date, + "invoice_type": "installment", + "percent": percent, + } + invoice_plans.append((0, 0, vals)) + installment_date = self._next_date( + installment_date, interval, interval_type + ) + self.write({"invoice_plan_ids": invoice_plans}) + return True + + def remove_invoice_plan(self): + self.ensure_one() + self.invoice_plan_ids.unlink() + return True + + @api.model + def _next_date(self, installment_date, interval, interval_type): + installment_date = fields.Date.from_string(installment_date) + if interval_type == "month": + next_date = installment_date + relativedelta(months=+interval) + elif interval_type == "year": + next_date = installment_date + relativedelta(years=+interval) + else: + next_date = installment_date + relativedelta(days=+interval) + next_date = fields.Date.to_string(next_date) + return next_date + + def action_view_invoice(self, invoices=False): + invoice_plan_id = self.env.context.get("invoice_plan_id") + if invoice_plan_id and invoices: + plan = self.env["purchase.invoice.plan"].browse(invoice_plan_id) + for invoice in invoices: + plan._compute_new_invoice_quantity(invoice) + invoice.write( + { + "date": plan.plan_date, + "invoice_date": plan.plan_date, + } + ) + plan.invoice_ids += invoice + return super().action_view_invoice(invoices=invoices) diff --git a/purchase_invoice_plan/pyproject.toml b/purchase_invoice_plan/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/purchase_invoice_plan/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/purchase_invoice_plan/readme/CONTRIBUTORS.md b/purchase_invoice_plan/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..e9a63f0e53e --- /dev/null +++ b/purchase_invoice_plan/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Kitti Upariphutthiphong \<\> +- Rattapong Chokmasermkul \<\> +- Italo Lopes \<\> diff --git a/purchase_invoice_plan/readme/DESCRIPTION.md b/purchase_invoice_plan/readme/DESCRIPTION.md new file mode 100644 index 00000000000..2006a6546b9 --- /dev/null +++ b/purchase_invoice_plan/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +By standard feature, user can gradually create partial invoices, one by +one and in step create invoice the standard call invoice. This module +add ability to create invoices based on the predefined invoice plan, +either all at once, or one by one. diff --git a/purchase_invoice_plan/readme/USAGE.md b/purchase_invoice_plan/readme/USAGE.md new file mode 100644 index 00000000000..189fe06e84a --- /dev/null +++ b/purchase_invoice_plan/readme/USAGE.md @@ -0,0 +1,9 @@ +- Create new purchase quotation as per normal process +- Select option "Use Invoice Plan", a new Invoice Plan tab will appear +- Click on "=\> Create Invoice Plan" link to open invoice planning + wizard +- Do plan for number of installment, start date and interval +- Double check that each installment has correct plan percentage +- After confirm purchases order, we have new option to "Create Bill by + Plan" +- User can create only next bill or create all bills at the same time diff --git a/purchase_invoice_plan/security/ir.model.access.csv b/purchase_invoice_plan/security/ir.model.access.csv new file mode 100644 index 00000000000..e89ee7e38c7 --- /dev/null +++ b/purchase_invoice_plan/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_purchase_invoice_plan,access_purchase_invoice_plan,model_purchase_invoice_plan,purchase.group_purchase_user,1,1,1,1 +access_purchase_create_invoice_plan,access_purchase_create_invoice_plan,model_purchase_create_invoice_plan,purchase.group_purchase_user,1,1,1,1 +access_purchase_make_planned_invoice,access_purchase_make_planned_invoice,model_purchase_make_planned_invoice,purchase.group_purchase_user,1,1,1,1 diff --git a/purchase_invoice_plan/static/description/icon.png b/purchase_invoice_plan/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/purchase_invoice_plan/static/description/icon.png differ diff --git a/purchase_invoice_plan/static/description/index.html b/purchase_invoice_plan/static/description/index.html new file mode 100644 index 00000000000..3f5dae5afdc --- /dev/null +++ b/purchase_invoice_plan/static/description/index.html @@ -0,0 +1,450 @@ + + + + + +Purchase Invoice Plan + + + +
+

Purchase Invoice Plan

+ + +

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

+

By standard feature, user can gradually create partial invoices, one by +one and in step create invoice the standard call invoice. This module +add ability to create invoices based on the predefined invoice plan, +either all at once, or one by one.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Usage

+
    +
  • Create new purchase quotation as per normal process
  • +
  • Select option “Use Invoice Plan”, a new Invoice Plan tab will appear
  • +
  • Click on “=> Create Invoice Plan” link to open invoice planning wizard
  • +
  • Do plan for number of installment, start date and interval
  • +
  • Double check that each installment has correct plan percentage
  • +
  • After confirm purchases order, we have new option to “Create Bill by +Plan”
  • +
  • User can create only next bill or create all bills at the same time
  • +
+
+
+

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

+
    +
  • Ecosoft
  • +
+
+
+

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:

+

kittiu

+

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_invoice_plan/tests/__init__.py b/purchase_invoice_plan/tests/__init__.py new file mode 100644 index 00000000000..f718d3b69c9 --- /dev/null +++ b/purchase_invoice_plan/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from . import test_purchase_invoice_plan diff --git a/purchase_invoice_plan/tests/test_purchase_invoice_plan.py b/purchase_invoice_plan/tests/test_purchase_invoice_plan.py new file mode 100644 index 00000000000..61dc008198f --- /dev/null +++ b/purchase_invoice_plan/tests/test_purchase_invoice_plan.py @@ -0,0 +1,245 @@ +# Copyright 2019 Ecosoft (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from freezegun import freeze_time + +from odoo import fields +from odoo.exceptions import UserError, ValidationError +from odoo.tests import Form + +from odoo.addons.base.tests.common import BaseCommon + + +class TestPurchaseInvoicePlan(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Create a PO + cls.PurchaseOrder = cls.env["purchase.order"] + cls.PurchaseInvoicePlan = cls.env["purchase.create.invoice.plan"] + cls.StockBackorderConfirm = cls.env["stock.backorder.confirmation"] + cls.StockPicking = cls.env["stock.picking"] + + cls.test_partner = cls.env.ref("base.res_partner_12") + cls.test_service = cls.env.ref("product.product_product_2") + cls.test_product = cls.env.ref("product.product_product_7") + + cls.test_po_service = cls.env["purchase.order"].create( + { + "partner_id": cls.test_partner.id, + "use_invoice_plan": True, + "order_line": [ + ( + 0, + 0, + { + "name": "PO-Service", + "product_id": cls.test_service.id, + "date_planned": fields.Datetime.now(), + "product_qty": 1, + "product_uom": cls.test_service.uom_id.id, + "price_unit": 500, + "taxes_id": False, + }, + ) + ], + } + ) + cls.test_po_product = cls.env["purchase.order"].create( + { + "partner_id": cls.test_partner.id, + "use_invoice_plan": True, + "order_line": [ + ( + 0, + 0, + { + "name": "PO-Product", + "product_id": cls.test_product.id, + "date_planned": fields.Datetime.now(), + "product_qty": 10, + "product_uom": cls.test_product.uom_id.id, + "price_unit": 1000, + "taxes_id": False, + }, + ) + ], + } + ) + + def test_invoice_plan(self): + ctx = { + "active_id": self.test_po_product.id, + "active_ids": [self.test_po_product.id], + "all_remain_invoices": True, + } + # Create purchase plan + with Form(self.PurchaseInvoicePlan) as p: + p.num_installment = 5 + purchase_plan = p.save() + purchase_plan.with_context(**ctx).purchase_create_invoice_plan() + # Change plan, so that the 1st installment is 1000 and 5th is 3000 + self.assertEqual(len(self.test_po_product.invoice_plan_ids), 5) + self.test_po_product.invoice_plan_ids[0].amount = 1000 + self.test_po_product.invoice_plan_ids[4].amount = 3000 + self.test_po_product.button_confirm() + self.assertEqual(self.test_po_product.state, "purchase") + # Receive all products + receive = self.test_po_product.picking_ids.filtered( + lambda pick: pick.state != "done" + ) + receive.move_ids_without_package.quantity = 10.0 + receive.button_validate() + purchase_create = self.env["purchase.make.planned.invoice"].create({}) + purchase_create.with_context(**ctx).create_invoices_by_plan() + self.assertEqual( + self.test_po_product.amount_total, + sum(self.test_po_product.invoice_ids.mapped("amount_total")), + ) + + def test_unlink_invoice_plan(self): + ctx = { + "active_id": self.test_po_product.id, + "active_ids": [self.test_po_product.id], + } + with Form(self.PurchaseInvoicePlan) as p: + p.num_installment = 5 + plan = p.save() + plan.with_context(**ctx).purchase_create_invoice_plan() + # Remove it + self.test_po_product.remove_invoice_plan() + self.assertFalse(self.test_po_product.invoice_plan_ids) + + def test_error(self): + ctx = { + "active_id": self.test_po_product.id, + "active_ids": [self.test_po_product.id], + "all_remain_invoices": True, + } + # UserError Use Invoice Plan selected, but no plan created + with self.assertRaises(UserError): + self.test_po_product.button_confirm() + # ValidationError Number of Installment <= 1 + with self.assertRaises(ValidationError) as e: + with Form(self.PurchaseInvoicePlan) as p: + p.num_installment = 0 + p.save() + error_message = "Number Installment must greater than 1" + self.assertEqual(e.exception.args[0], error_message) + # Create purchase plan + with Form(self.PurchaseInvoicePlan) as p: + p.num_installment = 5 + purchase_plan = p.save() + purchase_plan.with_context(**ctx).purchase_create_invoice_plan() + # Test exceed percent + with self.assertRaises(UserError): + self.test_po_product.invoice_plan_ids[0].percent = 99 + self.test_po_product._check_ip_total_percent() + self.test_po_product.button_confirm() + self.assertEqual(self.test_po_product.state, "purchase") + # UserError Please fill percentage for all invoice plan lines + with self.assertRaises(UserError): + for per in self.test_po_product.invoice_plan_ids: + per.percent = 0 + self.test_po_product._check_invoice_plan() + # Receive product 1 unit + receive = self.test_po_product.picking_ids.filtered( + lambda pick: pick.state != "done" + ) + receive.move_ids_without_package.quantity = 1.0 + # receive.button_validate() + backorder_wizard_dict = receive.button_validate() + backorder_wizard = Form( + self.env[backorder_wizard_dict["res_model"]].with_context( + **backorder_wizard_dict["context"] + ) + ).save() + backorder_wizard.process() + # ValidationError Create all invoice plan - Receive < Invoice require + purchase_create = self.env["purchase.make.planned.invoice"].create({}) + with self.assertRaises(ValidationError) as e: + purchase_create.with_context(**ctx).create_invoices_by_plan() + error_message = ( + "Plan quantity: 2.0, exceed invoiceable quantity: 1.0" + "\nProduct should be delivered before invoice" + ) + self.assertEqual(e.exception.args[0], error_message) + + def test_invoice_plan_po_edit(self): + """Case when some installment already invoiced, + but then, the PO line added. Test to ensure that + the invoiced amount of the done installment is fixed""" + ctx = { + "active_id": self.test_po_product.id, + "active_ids": [self.test_po_product.id], + "all_remain_invoices": False, + } + # Create purchase plan + with Form(self.PurchaseInvoicePlan) as p: + p.num_installment = 5 + purchase_plan = p.save() + purchase_plan.with_context(**ctx).purchase_create_invoice_plan() + # Change plan, so that the 1st installment is 1000 and 5th is 3000 + self.assertEqual(len(self.test_po_product.invoice_plan_ids), 5) + first_install = self.test_po_product.invoice_plan_ids[0] + first_install.amount = 1000 + self.test_po_product.invoice_plan_ids[4].amount = 3000 + self.test_po_product.button_confirm() + self.assertEqual(self.test_po_product.state, "purchase") + # Receive all products + receive = self.test_po_product.picking_ids.filtered( + lambda pick: pick.state != "done" + ) + receive.move_ids_without_package.quantity = 10.0 + receive.button_validate() + purchase_create = self.env["purchase.make.planned.invoice"].create({}) + # Create only the 1st invoice, amount should be 1000, and percent is 10 + purchase_create.with_context(**ctx).create_invoices_by_plan() + self.assertEqual(first_install.amount, 1000) + self.assertEqual(first_install.percent, 10) + # Add new PO line with amount = 1000, check that only percent is changed + self.test_po_product.write( + { + "order_line": [ + ( + 0, + 0, + { + "name": "PO-Product-NEW", + "product_id": self.test_product.id, + "date_planned": fields.Datetime.now(), + "product_qty": 1, + "product_uom": self.test_product.uom_id.id, + "price_unit": 1000, + "taxes_id": False, + }, + ) + ], + } + ) + # Overall amount changed to 11000, install amount not changed, only percent + # changed. + self.assertEqual(self.test_po_product.amount_total, 11000) + self.test_po_product.invoice_plan_ids._compute_amount() + self.assertEqual(first_install.amount, 1000) + self.assertEqual(first_install.percent, 9.090909) + with self.assertRaises(UserError): + self.test_po_product.remove_invoice_plan() + + @freeze_time("2022-01-01") + def test_next_date(self): + ctx = { + "active_id": self.test_po_product.id, + "active_ids": [self.test_po_product.id], + "all_remain_invoices": False, + } + # Create purchase plan + for item in ["day", "month", "year"]: + with Form(self.PurchaseInvoicePlan) as p: + p.num_installment = 5 + p.interval = 5 + p.interval_type = item + purchase_plan = p.save() + purchase_plan.with_context(**ctx).purchase_create_invoice_plan() + self.assertEqual(len(self.test_po_product.invoice_plan_ids), 5) + self.test_po_product.remove_invoice_plan() diff --git a/purchase_invoice_plan/views/purchase_view.xml b/purchase_invoice_plan/views/purchase_view.xml new file mode 100644 index 00000000000..19d7a69bbcd --- /dev/null +++ b/purchase_invoice_plan/views/purchase_view.xml @@ -0,0 +1,203 @@ + + + view.purchase.invoice.plan.tree + purchase.invoice.plan + + + + + + + + + + + + + + + + + view.purchase.invoice.plan.form + purchase.invoice.plan + +
+ + + + + + + + + + + + + + + + + +
+ + purchase_order_form + purchase.order + + + +
+ +
+
+ +