diff --git a/setup/stock_picking_invoicing/odoo/addons/stock_picking_invoicing b/setup/stock_picking_invoicing/odoo/addons/stock_picking_invoicing new file mode 120000 index 00000000000..3bb49528bae --- /dev/null +++ b/setup/stock_picking_invoicing/odoo/addons/stock_picking_invoicing @@ -0,0 +1 @@ +../../../../stock_picking_invoicing \ No newline at end of file diff --git a/setup/stock_picking_invoicing/setup.py b/setup/stock_picking_invoicing/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/stock_picking_invoicing/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_picking_invoicing/README.rst b/stock_picking_invoicing/README.rst new file mode 100644 index 00000000000..46b6430d486 --- /dev/null +++ b/stock_picking_invoicing/README.rst @@ -0,0 +1,131 @@ +======================= +Stock Picking Invoicing +======================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/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%2Faccount--invoicing-lightgray.png?logo=github + :target: https://github.com/OCA/account-invoicing/tree/15.0/stock_picking_invoicing + :alt: OCA/account-invoicing +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-invoicing-15-0/account-invoicing-15-0-stock_picking_invoicing + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/95/15.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to create invoices directly from picking, without having to +use sale or purchase orders. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +This module depends on *stock_picking_invoice_link* module that is hosted on +https://github.com/OCA/stock-logistics-workflow.git. + +Usage +===== + +To use this module, you need to: + +#. Go to your picking; +#. If the invoice status is 'To be invoiced', a button will ask you to create an invoice; +#. Into the Tree view, you can select many pickings and create a grouped invoice; +#. If at least an invoice is created for a picking, a new "Invoicing" tab appears. + + +If an invoice (not refund) is cancelled or deleted, invoice status of related picking is automatically +updated to "To be invoiced". + +Changelog +========= + +15.0.1.0.0 (2023-04-28) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 15.0 . + +14.0.1.0.0 (2021-11-12) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 14.0 . + +13.0.3.1.0 (2021-10-05) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 13.0 . + +12.0.2.0.0 (2019-12-19) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Included dependency from module stock_picking_invoice_link + from repository https://github.com/OCA/stock-logistics-workflow.git. + +12.0.1.0.0 (2019-07-16) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 12.0 . + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Agile Business Group + +Contributors +~~~~~~~~~~~~ + +* Lorenzo Battistini +* Leonardo Pistone +* Daniel Sadamo +* Alex Comba +* Florent THOMAS +* François Honoré +* Magno Costa +* Luis Felipe Mileo +* Radovan Skolnik + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/account-invoicing `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_picking_invoicing/__init__.py b/stock_picking_invoicing/__init__.py new file mode 100644 index 00000000000..972dbef6e43 --- /dev/null +++ b/stock_picking_invoicing/__init__.py @@ -0,0 +1,5 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models +from . import wizards diff --git a/stock_picking_invoicing/__manifest__.py b/stock_picking_invoicing/__manifest__.py new file mode 100644 index 00000000000..34104168ffb --- /dev/null +++ b/stock_picking_invoicing/__manifest__.py @@ -0,0 +1,26 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Stock Picking Invoicing", + "version": "16.0.1.0.0", + "category": "Warehouse Management", + "author": "Agile Business Group,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-invoicing", + "license": "AGPL-3", + "depends": [ + "stock", + "account", + "stock_picking_invoice_link", + "base_view_inheritance_extension", + ], + "data": [ + "security/ir.model.access.csv", + "wizards/stock_invoice_onshipping_view.xml", + "wizards/stock_return_picking_view.xml", + "views/stock_move_views.xml", + "views/stock_picking_views.xml", + "views/stock_picking_type_views.xml", + ], + "demo": ["demo/stock_picking_demo.xml"], + "installable": True, +} diff --git a/stock_picking_invoicing/demo/stock_picking_demo.xml b/stock_picking_invoicing/demo/stock_picking_demo.xml new file mode 100644 index 00000000000..2c2625e67ae --- /dev/null +++ b/stock_picking_invoicing/demo/stock_picking_demo.xml @@ -0,0 +1,271 @@ + + + + + + Test - Stock Picking Invocing + + 1 + + + + + + + + 2binvoiced + stock_picking_invoicing demo + + + + + + Test + + 2binvoiced + + + 1 + + + + + Test + + 2binvoiced + + + 1 + + + + + + + 2binvoiced + stock_picking_invoicing demo + + + + + + Test + + 2binvoiced + + + 1 + + + + + Test + + 2binvoiced + + + 1 + + + + + + + + + + 2binvoiced + stock_picking_invoicing demo + + + + + + Test + + 2binvoiced + + + 1 + + + + + Test + + 2binvoiced + + + 1 + + + + + + + + invoiced + stock_picking_invoicing demo + + + + + + Test + + invoiced + + + 1 + + + + + Test + + invoiced + + + 1 + + + + + + + none + stock_picking_invoicing demo + + + + + + Test + + none + + + 1 + + + + + Test + + none + + + 1 + + + + + + + + + + none + stock_picking_invoicing demo + + + + + + Test + + none + + + 1 + + + + + Test + + none + + + 1 + + + + + + + + + 2binvoiced + stock_picking_invoicing demo + + + + + + Test + + 2binvoiced + + + 1 + + + + + Test + + 2binvoiced + + + 1 + + + + + + diff --git a/stock_picking_invoicing/i18n/ca.po b/stock_picking_invoicing/i18n/ca.po new file mode 100644 index 00000000000..9166bddcb07 --- /dev/null +++ b/stock_picking_invoicing/i18n/ca.po @@ -0,0 +1,299 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:0 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__journal_type__sale +msgid "Create Customer Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Create Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__journal_type__purchase +msgid "Create Supplier Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_account_move__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_return_picking__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "" +"Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a single invoice line." +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_account_move__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_return_picking__id +msgid "ID" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +msgid "Invoice Date" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_state_mixin__invoice_state__invoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_move__invoice_state__invoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_picking__invoice_state__invoiced +msgid "Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "" +"Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_return_picking__invoice_state +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +msgid "Journal Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_account_move____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_return_picking____last_update +msgid "Last Modified on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:0 +#, python-format +msgid "No invoice created!" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_return_picking__invoice_state__none +msgid "No invoicing" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_state_mixin__invoice_state__none +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_move__invoice_state__none +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_picking__invoice_state__none +msgid "Not Applicable" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__group__partner +msgid "Partner" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__group__partner_product +msgid "Partner/Product" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__group__picking +msgid "Picking" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +msgid "Picking Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +msgid "Picking to Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +msgid "Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_return_picking +msgid "Return Picking" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +msgid "Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +msgid "Shipments to Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +msgid "Show Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +msgid "Show Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +msgid "Stock Invoice State Mixin" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_state_mixin__invoice_state__2binvoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_move__invoice_state__2binvoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_picking__invoice_state__2binvoiced +msgid "To Be Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +msgid "To be Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_return_picking__invoice_state__2binvoiced +msgid "To be refunded/invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "" diff --git a/stock_picking_invoicing/i18n/de.po b/stock_picking_invoicing/i18n/de.po new file mode 100644 index 00000000000..a32fa38080c --- /dev/null +++ b/stock_picking_invoicing/i18n/de.po @@ -0,0 +1,266 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:494 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Customer Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Create Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Supplier Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a single invoice line." +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__id +msgid "ID" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +msgid "Invoice Date" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 +#: selection:stock.picking,invoice_state:0 +msgid "Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +msgid "Journal Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin____last_update +msgid "Last Modified on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:192 +#, python-format +msgid "No invoice created!" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 +#: selection:stock.picking,invoice_state:0 +msgid "Not Applicable" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner/Product" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Picking" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +msgid "Picking Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +msgid "Picking to Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +msgid "Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +msgid "Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +msgid "Shipments to Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +msgid "Show Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +msgid "Show Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +msgid "Stock Invoice State Mixin" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 +#: selection:stock.picking,invoice_state:0 +msgid "To Be Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +msgid "To be Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "" diff --git a/stock_picking_invoicing/i18n/es.po b/stock_picking_invoicing/i18n/es.po new file mode 100644 index 00000000000..dabf4bc1399 --- /dev/null +++ b/stock_picking_invoicing/i18n/es.po @@ -0,0 +1,276 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2020-06-20 05:19+0000\n" +"Last-Translator: Nelson Ramírez Sánchez \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 3.10\n" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:494 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "¡Todas los despachos no están relacionadas con su empresa!" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "Cancelar" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "Contar despachos a ser facturados" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "Crear" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Customer Invoice" +msgstr "Crear Factura de Cliente" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "Crear Facturas Borrador" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Create Invoice" +msgstr "Crear Factura" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Supplier Invoice" +msgstr "Crear Factura de Proveedor" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create invoice" +msgstr "Crear Factura" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__display_name +msgid "Display Name" +msgstr "Nombre Mostrado" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "Grupo" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a single invoice line." +msgstr "" +"Agrupar picking / movimientos para crear facturas:\n" +"Picking: una factura por picking;\n" +"Contacto: una factura para cada contacto de picking;\n" +"Contacto / Producto: Una factura por contacto del picking y producto grupal " +"en una sola línea de factura." + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__id +msgid "ID" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_invoice +msgid "Invoice" +msgstr "Factura" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +msgid "Invoice Date" +msgstr "Fecha de Factura" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "Estado de Factura" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 +#: selection:stock.picking,invoice_state:0 +msgid "Invoiced" +msgstr "Facturado" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" +"Facturado: ya existe una factura\n" +"Para ser facturado: necesita ser facturado\n" +"No aplicable: sin factura para crear" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "Facturación" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +msgid "Journal Type" +msgstr "Tipo de Diario" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin____last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:192 +#, python-format +msgid "No invoice created!" +msgstr "No se creó factura!" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 +#: selection:stock.picking,invoice_state:0 +msgid "Not Applicable" +msgstr "No aplica" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner" +msgstr "Contacto" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner/Product" +msgstr "Contacto/Producto" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Picking" +msgstr "Picking" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +msgid "Picking Type" +msgstr "Tipo de Picking" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +msgid "Picking to Invoice" +msgstr "Picking a facturar" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +msgid "Purchase Journal" +msgstr "Diario de Compra" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +msgid "Sale Journal" +msgstr "Diario de Venta" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "Configurado para ser facturado" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +msgid "Shipments to Invoice" +msgstr "Envíos a facturar" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +msgid "Show Purchase Journal" +msgstr "Mostrar Diario de Compras" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +msgid "Show Sale Journal" +msgstr "Mostrar Diario de Venta" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "Envío de factura de stock" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +msgid "Stock Invoice State Mixin" +msgstr "Estado de la factura de existencias Mixin" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de Stock" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 +#: selection:stock.picking,invoice_state:0 +msgid "To Be Invoiced" +msgstr "Para ser facturado" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +msgid "To be Invoiced" +msgstr "Para ser facturado" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "Transferir" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "Verdadero" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "o" diff --git a/stock_picking_invoicing/i18n/fr.po b/stock_picking_invoicing/i18n/fr.po new file mode 100644 index 00000000000..d32d33fe2a7 --- /dev/null +++ b/stock_picking_invoicing/i18n/fr.po @@ -0,0 +1,325 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-09-09 12:43+0000\n" +"PO-Revision-Date: 2019-03-15 10:32+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:494 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "Les pickings ne sont pas liés à la même société!" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "Annuler" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "Créer" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Customer Invoice" +msgstr "Créer une facture client" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "Créer factures brouillons" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Create Invoice" +msgstr "Créer une facture" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Supplier Invoice" +msgstr "Créer facture fournisseur" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create invoice" +msgstr "Créer facture" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__display_name +msgid "Display Name" +msgstr "Nom à afficher" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "Groupe" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "" +"Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a " +"single invoice line." +msgstr "" +"Grouper les pickings/mouvements à facturer:\n" +"Picking: Une facture par picking;\n" +"Partenaire: Une facture par partenaire du picking;\n" +"Partenaire/Article: Une facture par partenaire du picking et grouper les " +"articles similaires dans une seule ligne de facture." + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__id +msgid "ID" +msgstr "ID" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_invoice +msgid "Invoice" +msgstr "Facture" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +#, fuzzy +#| msgid "Invoice date" +msgid "Invoice Date" +msgstr "Date de facturation" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "État de la facture" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "Invoiced" +msgstr "Facturé" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "" +"Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" +"Facturé: Une facture existe déjà\n" +"À facturer: facturation à faire\n" +"Non applicable: Pas de facturer à créer" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "Facturation" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +#, fuzzy +#| msgid "Journal type" +msgid "Journal Type" +msgstr "Type de journal" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin____last_update +msgid "Last Modified on" +msgstr "Dernière Modification le" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:192 +#, python-format +msgid "No invoice created!" +msgstr "Pas de facture créée!" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "Not Applicable" +msgstr "Non applicable" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner" +msgstr "Partenaire" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner/Product" +msgstr "Partenaire/Article" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Picking" +msgstr "Picking" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +#, fuzzy +#| msgid "Picking" +msgid "Picking Type" +msgstr "Picking" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +#, fuzzy +msgid "Picking to Invoice" +msgstr "Marquer comme à facturer" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +#, fuzzy +#| msgid "Purchase journal" +msgid "Purchase Journal" +msgstr "Journal d'achat" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +#, fuzzy +msgid "Sale Journal" +msgstr "Journal d'achat" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "Marquer comme à facturer" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +#, fuzzy +msgid "Shipments to Invoice" +msgstr "Marquer comme à facturer" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +#, fuzzy +msgid "Show Purchase Journal" +msgstr "Journal d'achat" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +#, fuzzy +msgid "Show Sale Journal" +msgstr "Journal d'achat" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "Facturation livraison" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +#, fuzzy +#| msgid "Stock Invoice Onshipping" +msgid "Stock Invoice State Mixin" +msgstr "Facturation livraison" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "Mouvement de stock" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "To Be Invoiced" +msgstr "À facturer" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +#, fuzzy +#| msgid "To Be Invoiced" +msgid "To be Invoiced" +msgstr "À facturer" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "Transfert" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "ou" + +#~ msgid "Invoice Line" +#~ msgstr "Ligne de facture" + +#~ msgid "Invoice ids" +#~ msgstr "Factures" + +#~ msgid "Picking ids" +#~ msgstr "Pickings" + +#~ msgid "Purchase refund journal" +#~ msgstr "Journal note de crédits d'achat" + +#, fuzzy +#~ msgid "Sale refund journal" +#~ msgstr "Journal note de crédits d'achat" + +#, fuzzy +#~ msgid "Show Refund Purchase Journal" +#~ msgstr "Journal d'achat" + +#~ msgid "Stock moves" +#~ msgstr "Mouvements de stock" + +#~ msgid "Procurement" +#~ msgstr "Approvisionnement" + +#~ msgid "Procurement Rule" +#~ msgstr "Règle d'approvisionnement" + +#~ msgid "Pushed Flow" +#~ msgstr "Flux poussés" diff --git a/stock_picking_invoicing/i18n/pt_BR.po b/stock_picking_invoicing/i18n/pt_BR.po new file mode 100644 index 00000000000..f3fc6f6e2ff --- /dev/null +++ b/stock_picking_invoicing/i18n/pt_BR.po @@ -0,0 +1,276 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-08-13 00:07+0000\n" +"Last-Translator: Douglas Custódio \n" +"Language-Team: none\n" +"Language: pt_BR\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.3.2\n" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:494 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "Todas as coletas não estão relacionadas à sua empresa!" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "Cancelar" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "Contagem de coletas a serem faturadas" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "Criar" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Customer Invoice" +msgstr "Criar fatura do cliente" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "Criar rascunho das faturas" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Create Invoice" +msgstr "Criar Fatura" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Supplier Invoice" +msgstr "Criar Fatura de Fornecedor" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create invoice" +msgstr "Criar Fatura" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "Criado por" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "Criado em" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__display_name +msgid "Display Name" +msgstr "Exibir nome" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "Grupo" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "" +"Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a " +"single invoice line." +msgstr "" +"Grupo de coletas/Movimentos para criar faturas:\n" +"Coleta: uma fatura por Coleta;\n" +"Parceiro: uma fatura para cada parceiro de Coleta;\n" +"Parceiro/Produto: uma fatura por parceiro da Coleta e agrupar o produto em " +"uma única linha da fatura." + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__id +msgid "ID" +msgstr "ID" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_invoice +msgid "Invoice" +msgstr "Fatura" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +msgid "Invoice Date" +msgstr "Data da Fatura" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "Status (situação) da Fatura" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "Invoiced" +msgstr "Faturado" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "" +"Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" +"Faturado: já existe uma fatura\n" +"Para ser faturado: precisa ser faturado\n" +"Não aplicável: nenhuma fatura para criar" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "Faturamento" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +msgid "Journal Type" +msgstr "Tipo de diário" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin____last_update +msgid "Last Modified on" +msgstr "Última modificação em" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "Última modificação feita por" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "Última modificação feita em" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:192 +#, python-format +msgid "No invoice created!" +msgstr "Nenhuma fatura criada!" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "Not Applicable" +msgstr "Não se aplica" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner" +msgstr "Parceiro" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner/Product" +msgstr "Parceiro/Produto" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Picking" +msgstr "Coleta" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +msgid "Picking Type" +msgstr "Tipo de Coleta" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +msgid "Picking to Invoice" +msgstr "Coleta a Faturar" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +msgid "Purchase Journal" +msgstr "Diário de compras" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +msgid "Sale Journal" +msgstr "Diário de vendas" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "Marcado para ser faturado" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +msgid "Shipments to Invoice" +msgstr "Remessas para faturar" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +msgid "Show Purchase Journal" +msgstr "Mostrar diário de compras" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +msgid "Show Sale Journal" +msgstr "Mostrar diário de vendas" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "Fatura de Estoque em Transporte" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +msgid "Stock Invoice State Mixin" +msgstr "Fatura de Estoque com Situação Misturado" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "Movimentação de Estoque" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "To Be Invoiced" +msgstr "A ser faturado" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +msgid "To be Invoiced" +msgstr "A ser faturado" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "Transferir" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "Verdadeiro" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "ou" diff --git a/stock_picking_invoicing/i18n/sl.po b/stock_picking_invoicing/i18n/sl.po new file mode 100644 index 00000000000..e95123349ac --- /dev/null +++ b/stock_picking_invoicing/i18n/sl.po @@ -0,0 +1,297 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +# Translators: +# Matjaž Mozetič , 2015 +msgid "" +msgstr "" +"Project-Id-Version: account-invoicing (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-25 16:48+0000\n" +"PO-Revision-Date: 2015-08-16 11:38+0000\n" +"Last-Translator: Matjaž Mozetič \n" +"Language-Team: Slovenian (http://www.transifex.com/oca/OCA-account-" +"invoicing-8-0/language/sl/)\n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:494 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +#, fuzzy +msgid "Create Customer Invoice" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +#, fuzzy +msgid "Create Invoice" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,journal_type:0 +msgid "Create Supplier Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +#, fuzzy +msgid "Create invoice" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "" +"Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a " +"single invoice line." +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__id +msgid "ID" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +msgid "Invoice Date" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "" +"Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +msgid "Journal Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin____last_update +msgid "Last Modified on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:192 +#, python-format +msgid "No invoice created!" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +msgid "Not Applicable" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +msgid "Partner/Product" +msgstr "" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.onshipping,group:0 +#, fuzzy +msgid "Picking" +msgstr "Zbirni seznam" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +#, fuzzy +msgid "Picking Type" +msgstr "Zbirni seznam" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +#, fuzzy +msgid "Picking to Invoice" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +msgid "Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +msgid "Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +#, fuzzy +msgid "Shipments to Invoice" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +msgid "Show Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +msgid "Show Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +msgid "Stock Invoice State Mixin" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "Premik zaloge" + +#. module: stock_picking_invoicing +#: selection:stock.invoice.state.mixin,invoice_state:0 +#: selection:stock.move,invoice_state:0 selection:stock.picking,invoice_state:0 +#, fuzzy +msgid "To Be Invoiced" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +#, fuzzy +msgid "To be Invoiced" +msgstr "Nastavljeno za obračun" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "" + +#~ msgid "" +#~ "Can't update invoice control for picking %s: It's 'to be invoiced' yet" +#~ msgstr "" +#~ "Nadzora obračuna za zbirnik %s ni mogoče posodobiti: ni še zaračunan" + +#~ msgid "Picking %s has linked invoice %s" +#~ msgstr "Zbirnik %s je povezan z računom %s" + +#, fuzzy +#~ msgid "Picking ids" +#~ msgstr "Zbirni seznam" + +#, fuzzy +#~ msgid "Stock moves" +#~ msgstr "Premik zaloge" diff --git a/stock_picking_invoicing/i18n/stock_picking_invoicing.pot b/stock_picking_invoicing/i18n/stock_picking_invoicing.pot new file mode 100644 index 00000000000..1669012cab8 --- /dev/null +++ b/stock_picking_invoicing/i18n/stock_picking_invoicing.pot @@ -0,0 +1,280 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_invoicing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.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: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:0 +#, python-format +msgid "All pickings are not related to your company!" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Cancel" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking_type__count_picking_2binvoiced +msgid "Count Picking 2Binvoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__journal_type__sale +msgid "Create Customer Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.action_stock_invoice_onshipping +msgid "Create Draft Invoices" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Create Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__journal_type__purchase +msgid "Create Supplier Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "Create invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__create_date +msgid "Created on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "Group" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_onshipping__group +msgid "" +"Group pickings/moves to create invoice(s):\n" +"Picking: One invoice per picking;\n" +"Partner: One invoice for each picking's partner;\n" +"Partner/Product: One invoice per picking's partner and group product into a single invoice line." +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__id +msgid "ID" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__invoice_date +msgid "Invoice Date" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "Invoice Status" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_state_mixin__invoice_state__invoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_move__invoice_state__invoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_picking__invoice_state__invoiced +msgid "Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_invoice_state_mixin__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_move__invoice_state +#: model:ir.model.fields,help:stock_picking_invoicing.field_stock_picking__invoice_state +msgid "" +"Invoiced: an invoice already exists\n" +"To Be Invoiced: need to be invoiced\n" +"Not Applicable: no invoice to create" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_return_picking__invoice_state +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_move_picking_form +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Invoicing" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__journal_type +msgid "Journal Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping____last_update +msgid "Last Modified on" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_picking_invoicing +#: code:addons/stock_picking_invoicing/wizards/stock_invoice_onshipping.py:0 +#, python-format +msgid "No invoice created!" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_return_picking__invoice_state__none +msgid "No invoicing" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_state_mixin__invoice_state__none +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_move__invoice_state__none +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_picking__invoice_state__none +msgid "Not Applicable" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__group__partner +msgid "Partner" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__group__partner_product +msgid "Partner/Product" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_onshipping__group__picking +msgid "Picking" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking_type +msgid "Picking Type" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.actions.act_window,name:stock_picking_invoicing.2binvoiced_action_picking_dashboard +msgid "Picking to Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__purchase_journal +msgid "Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_return_picking +msgid "Return Picking" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__sale_journal +msgid "Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "Set to be invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_invoicing_internal_search +msgid "Shipments to Invoice" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_purchase_journal +msgid "Show Purchase Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields,field_description:stock_picking_invoicing.field_stock_invoice_onshipping__show_sale_journal +msgid "Show Sale Journal" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_onshipping +msgid "Stock Invoice Onshipping" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_invoice_state_mixin +msgid "Stock Invoice State Mixin" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_invoice_state_mixin__invoice_state__2binvoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_move__invoice_state__2binvoiced +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_picking__invoice_state__2binvoiced +msgid "To Be Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.stock_picking_type_kanban +msgid "To be Invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model.fields.selection,name:stock_picking_invoicing.selection__stock_return_picking__invoice_state__2binvoiced +msgid "To be refunded/invoiced" +msgstr "" + +#. module: stock_picking_invoicing +#: model:ir.model,name:stock_picking_invoicing.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_picking_form +msgid "True" +msgstr "" + +#. module: stock_picking_invoicing +#: model_terms:ir.ui.view,arch_db:stock_picking_invoicing.view_stock_invoice_onshipping +msgid "or" +msgstr "" diff --git a/stock_picking_invoicing/models/__init__.py b/stock_picking_invoicing/models/__init__.py new file mode 100644 index 00000000000..e7c89b79855 --- /dev/null +++ b/stock_picking_invoicing/models/__init__.py @@ -0,0 +1,8 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import stock_invoice_state_mixin +from . import account_move +from . import stock_move +from . import stock_picking +from . import stock_picking_type diff --git a/stock_picking_invoicing/models/account_move.py b/stock_picking_invoicing/models/account_move.py new file mode 100644 index 00000000000..7ef27cb89bf --- /dev/null +++ b/stock_picking_invoicing/models/account_move.py @@ -0,0 +1,57 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def button_cancel(self): + """ + Inherit to update related picking as '2binvoiced' when the invoice is + cancelled (only for invoices, not refunds) + :return: bool + """ + result = super().button_cancel() + pickings = self.filtered( + lambda i: i.picking_ids and i.move_type in ["out_invoice", "in_invoice"] + ).mapped("picking_ids") + self.mapped("invoice_line_ids.move_line_ids")._set_as_2binvoiced() + pickings._set_as_2binvoiced() + return result + + def button_draft(self): + result = super().button_draft() + pickings = self.filtered( + lambda i: i.picking_ids and i.move_type in ["out_invoice", "in_invoice"] + ).mapped("picking_ids") + self.mapped("invoice_line_ids.move_line_ids")._set_as_invoiced() + pickings._set_as_invoiced() + return result + + def unlink(self): + """ + Inherit the unlink to update related picking as "2binvoiced" + (only for invoices, not refunds) + :return: + """ + pickings = self.filtered( + lambda i: i.picking_ids and i.move_type in ["out_invoice", "in_invoice"] + ).mapped("picking_ids") + self.mapped("invoice_line_ids.move_line_ids")._set_as_2binvoiced() + pickings._set_as_2binvoiced() + return super().unlink() + + def _reverse_moves(self, default_values_list=None, cancel=False): + reverse_moves = super()._reverse_moves( + default_values_list=default_values_list, cancel=cancel + ) + for move, reverse_move in zip(self, reverse_moves): + for line in move.invoice_line_ids: + reverse_line = reverse_move.invoice_line_ids.filtered( + lambda l: l.product_id == line.product_id + ) + reverse_line.move_line_ids = line.move_line_ids.ids + + return reverse_moves diff --git a/stock_picking_invoicing/models/stock_invoice_state_mixin.py b/stock_picking_invoicing/models/stock_invoice_state_mixin.py new file mode 100644 index 00000000000..d956f00191f --- /dev/null +++ b/stock_picking_invoicing/models/stock_invoice_state_mixin.py @@ -0,0 +1,59 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class StockInvoiceStateMixin(models.AbstractModel): + """ + Abstract model used to define invoice state with selection choices + """ + + _name = "stock.invoice.state.mixin" + _description = "Stock Invoice State Mixin" + + invoice_state = fields.Selection( + selection=[ + ("invoiced", "Invoiced"), + ("2binvoiced", "To Be Invoiced"), + ("none", "Not Applicable"), + ], + string="Invoice Status", + default="none", + help="Invoiced: an invoice already exists\n" + "To Be Invoiced: need to be invoiced\n" + "Not Applicable: no invoice to create", + copy=False, + ) + + def _set_as_invoiced(self): + """ + Update invoice_state on current recordset to 'invoiced' + :return: self recordset (where the updated has been executed) + """ + return self._update_invoice_state("invoiced") + + def _set_as_2binvoiced(self): + """ + Update invoice_state on current recordset to '2binvoiced' + :return: self recordset (where the updated has been executed) + """ + return self._update_invoice_state("2binvoiced") + + def _set_as_not_billable(self): + """ + Update invoice_state on current recordset to 'invoiced' + :return: self recordset (where the updated has been executed) + """ + return self._update_invoice_state("none") + + def _update_invoice_state(self, invoice_state): + """ + Execute the write + :param invoice_state: str + :return: self recordset (where the updated has been executed) + """ + records = self.filtered(lambda r: r.invoice_state != invoice_state) + if records: + records.write({"invoice_state": invoice_state}) + return records diff --git a/stock_picking_invoicing/models/stock_move.py b/stock_picking_invoicing/models/stock_move.py new file mode 100644 index 00000000000..2771caa2ceb --- /dev/null +++ b/stock_picking_invoicing/models/stock_move.py @@ -0,0 +1,144 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models +from odoo.tools.float_utils import float_round + + +class StockMove(models.Model): + _name = "stock.move" + _inherit = [ + _name, + "stock.invoice.state.mixin", + ] + + def _get_price_unit_invoice(self, inv_type, partner, qty=1): + """ + Gets price unit for invoice + :param inv_type: str + :param partner: res.partner + :param qty: float + :return: float + """ + + if inv_type in ("in_invoice", "in_refund"): + price_unit = min(self.mapped("price_unit")) + else: + price_unit = max(self.mapped("price_unit")) + + if price_unit > 0.0: + # Value informed by user should has preferency + return price_unit + + product = self.mapped("product_id") + product.ensure_one() + sum(self.mapped("product_uom_qty")) + product_uom = self.mapped("product_uom") + company = fields.first(self).picking_id.company_id + # Only in the cases the stock.move has linked to Sale or + # Purchase Order it's possible use different Currencys + # TODO: Should this module make possible by include field + # currency_id in Stock.picking? + currency = company.currency_id + pickings = self.mapped("picking_id") + date_done = min(pickings.mapped("date_done")) + + if inv_type in ("in_invoice", "in_refund"): + + seller = product._select_seller( + partner_id=partner, quantity=qty, date=date_done + ) + if not seller: + po_line_uom = self.mapped("product_uom") or product.uom_po_id + price_unit = self.env["account.tax"]._fix_tax_included_price_company( + product.uom_id._compute_price(product.standard_price, po_line_uom), + product.supplier_taxes_id, + # TODO: Should inform taxes_ids in stock.move? + product.supplier_taxes_id, + fields.first(self).company_id, + ) + price_unit = product.currency_id._convert( + price_unit, currency, company, date_done, False + ) + result = float_round( + price_unit, + precision_digits=max( + currency.decimal_places, + self.env["decimal.precision"].precision_get("Product Price"), + ), + ) + else: + price_unit = self.env["account.tax"]._fix_tax_included_price_company( + seller.price, + product.supplier_taxes_id, + # TODO: Should inform taxes_ids in stock.move? + product.supplier_taxes_id, + fields.first(self).company_id, + ) + price_unit = seller.currency_id._convert( + price_unit, currency, company, date_done, False + ) + price_unit = float_round( + price_unit, + precision_digits=max( + currency.decimal_places, + self.env["decimal.precision"].precision_get("Product Price"), + ), + ) + result = seller.product_uom._compute_price(price_unit, product_uom) + + else: + # If partner given, search price in its sale pricelist + fiscal_position = ( + self.env["account.fiscal.position"] + .with_company(company) + ._get_fiscal_position(partner) + ) + + if partner and partner.property_product_pricelist: + price_unit = None + pricelist_rule_id = ( + partner.property_product_pricelist._get_product_rule( + product, + qty or 1.0, + uom=product_uom, + date=date_done, + ) + ) + pricelist_rule = self.env["product.pricelist.item"].browse( + pricelist_rule_id + ) + price_unit = pricelist_rule._compute_price( + product, + qty, + product_uom, + date_done, + currency=currency, + ) + + else: + price_unit = product.lst_price + + result = product._get_tax_included_unit_price( + company, + currency, + date_done, + "sale", + fiscal_position=fiscal_position, + product_price_unit=price_unit, + product_currency=currency, + ) + + return result + + def _prepare_extra_move_vals(self, qty): + """Copy invoice state for a new extra stock move""" + values = super()._prepare_extra_move_vals(qty) + values["invoice_state"] = self.invoice_state + return values + + def _prepare_move_split_vals(self, uom_qty): + """Copy invoice state for a new splitted stock move""" + values = super()._prepare_move_split_vals(uom_qty) + values["invoice_state"] = self.invoice_state + return values diff --git a/stock_picking_invoicing/models/stock_picking.py b/stock_picking_invoicing/models/stock_picking.py new file mode 100644 index 00000000000..ffbc36974d6 --- /dev/null +++ b/stock_picking_invoicing/models/stock_picking.py @@ -0,0 +1,50 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models + + +class StockPicking(models.Model): + _name = "stock.picking" + _inherit = [ + _name, + "stock.invoice.state.mixin", + ] + + def set_to_be_invoiced(self): + """ + Button to set Invoice State to To Be Invoice. + """ + self._set_as_2binvoiced() + self.mapped("move_ids")._set_as_2binvoiced() + + def set_as_invoiced(self): + """ + Button to set Invoice State to Invoiced. + """ + self._set_as_invoiced() + self.mapped("move_ids")._set_as_invoiced() + + def set_as_not_billable(self): + """ + Button to set Invoice State to Not Billable. + """ + self._set_as_not_billable() + self.mapped("move_ids")._set_as_not_billable() + + def _get_partner_to_invoice(self): + self.ensure_one() + partner = self.partner_id + return partner.address_get(["invoice"]).get("invoice") + + def action_assign(self): + """If any stock move is to be invoiced, picking status is updated""" + if any(m.invoice_state == "2binvoiced" for m in self.mapped("move_ids")): + self.write({"invoice_state": "2binvoiced"}) + return super().action_assign() + + @api.onchange("invoice_state") + def _onchange_invoice_state(self): + for record in self: + record._update_invoice_state(record.invoice_state) + record.mapped("move_ids")._update_invoice_state(record.invoice_state) diff --git a/stock_picking_invoicing/models/stock_picking_type.py b/stock_picking_invoicing/models/stock_picking_type.py new file mode 100644 index 00000000000..54ceda10ef1 --- /dev/null +++ b/stock_picking_invoicing/models/stock_picking_type.py @@ -0,0 +1,35 @@ +# Copyright (C) 2019-Today: Odoo Community Association +# @ 2019-Today: Akretion - www.akretion.com.br - +# Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class PickingType(models.Model): + _inherit = "stock.picking.type" + + count_picking_2binvoiced = fields.Integer(compute="_compute_picking_2binvoiced") + + def _compute_picking_2binvoiced(self): + domains = { + "count_picking_2binvoiced": [("invoice_state", "=", "2binvoiced")], + } + for field in domains: + data = self.env["stock.picking"].read_group( + domains[field] + + [ + ("state", "!=", "cancel"), + ("invoice_state", "=", "2binvoiced"), + ("picking_type_id", "in", self.ids), + ], + ["picking_type_id"], + ["picking_type_id"], + ) + count = { + x["picking_type_id"][0]: x["picking_type_id_count"] + for x in data + if x["picking_type_id"] + } + for record in self: + record[field] = count.get(record.id, 0) diff --git a/stock_picking_invoicing/readme/CONTRIBUTORS.rst b/stock_picking_invoicing/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..3f24f0d5a16 --- /dev/null +++ b/stock_picking_invoicing/readme/CONTRIBUTORS.rst @@ -0,0 +1,9 @@ +* Lorenzo Battistini +* Leonardo Pistone +* Daniel Sadamo +* Alex Comba +* Florent THOMAS +* François Honoré +* Magno Costa +* Luis Felipe Mileo +* Radovan Skolnik diff --git a/stock_picking_invoicing/readme/DESCRIPTION.rst b/stock_picking_invoicing/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..1eb316ffb8c --- /dev/null +++ b/stock_picking_invoicing/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows to create invoices directly from picking, without having to +use sale or purchase orders. diff --git a/stock_picking_invoicing/readme/HISTORY.rst b/stock_picking_invoicing/readme/HISTORY.rst new file mode 100644 index 00000000000..79b5f2f4d28 --- /dev/null +++ b/stock_picking_invoicing/readme/HISTORY.rst @@ -0,0 +1,32 @@ +16.0.1.0.0 (2023-05-25) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 16.0 . + * Included dependency from module base_view_inheritance_extension + from repository https://https://github.com/OCA/server-tools . + +15.0.1.0.0 (2023-04-28) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 15.0 . + +14.0.1.0.0 (2021-11-12) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 14.0 . + +13.0.3.1.0 (2021-10-05) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 13.0 . + +12.0.2.0.0 (2019-12-19) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Included dependency from module stock_picking_invoice_link + from repository https://github.com/OCA/stock-logistics-workflow.git. + +12.0.1.0.0 (2019-07-16) +~~~~~~~~~~~~~~~~~~~~~~~ + + * Migration to version 12.0 . diff --git a/stock_picking_invoicing/readme/INSTALL.rst b/stock_picking_invoicing/readme/INSTALL.rst new file mode 100644 index 00000000000..f5942642777 --- /dev/null +++ b/stock_picking_invoicing/readme/INSTALL.rst @@ -0,0 +1,2 @@ +This module depends on *stock_picking_invoice_link* module that is hosted on +https://github.com/OCA/stock-logistics-workflow.git. diff --git a/stock_picking_invoicing/readme/USAGE.rst b/stock_picking_invoicing/readme/USAGE.rst new file mode 100644 index 00000000000..cd7bbcc119b --- /dev/null +++ b/stock_picking_invoicing/readme/USAGE.rst @@ -0,0 +1,10 @@ +To use this module, you need to: + +#. Go to your picking; +#. If the invoice status is 'To be invoiced', a button will ask you to create an invoice; +#. Into the Tree view, you can select many pickings and create a grouped invoice; +#. If at least an invoice is created for a picking, a new "Invoicing" tab appears. + + +If an invoice (not refund) is cancelled or deleted, invoice status of related picking is automatically +updated to "To be invoiced". diff --git a/stock_picking_invoicing/security/ir.model.access.csv b/stock_picking_invoicing/security/ir.model.access.csv new file mode 100644 index 00000000000..1b3d2be5e7a --- /dev/null +++ b/stock_picking_invoicing/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_stock_invoice_onshipping,access_stock_invoice_onshipping,model_stock_invoice_onshipping,base.group_user,1,1,1,1 diff --git a/stock_picking_invoicing/static/description/icon.png b/stock_picking_invoicing/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/stock_picking_invoicing/static/description/icon.png differ diff --git a/stock_picking_invoicing/static/description/index.html b/stock_picking_invoicing/static/description/index.html new file mode 100644 index 00000000000..88d6285b244 --- /dev/null +++ b/stock_picking_invoicing/static/description/index.html @@ -0,0 +1,499 @@ + + + + + + +Stock Picking Invoicing + + + +
+

Stock Picking Invoicing

+ + +

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

+

This module allows to create invoices directly from picking, without having to +use sale or purchase orders.

+

Table of contents

+ +
+

Installation

+

This module depends on stock_picking_invoice_link module that is hosted on +https://github.com/OCA/stock-logistics-workflow.git.

+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to your picking;
  2. +
  3. If the invoice status is ‘To be invoiced’, a button will ask you to create an invoice;
  4. +
  5. Into the Tree view, you can select many pickings and create a grouped invoice;
  6. +
  7. If at least an invoice is created for a picking, a new “Invoicing” tab appears.
  8. +
+

If an invoice (not refund) is cancelled or deleted, invoice status of related picking is automatically +updated to “To be invoiced”.

+
+
+

Changelog

+
+

15.0.1.0.0 (2023-04-28)

+
+
    +
  • Migration to version 15.0 .
  • +
+
+
+
+

14.0.1.0.0 (2021-11-12)

+
+
    +
  • Migration to version 14.0 .
  • +
+
+
+
+

13.0.3.1.0 (2021-10-05)

+
+
    +
  • Migration to version 13.0 .
  • +
+
+
+
+

12.0.2.0.0 (2019-12-19)

+
+ +
+
+
+

12.0.1.0.0 (2019-07-16)

+
+
    +
  • Migration to version 12.0 .
  • +
+
+
+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Agile Business Group
  • +
+
+
+

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.

+

This module is part of the OCA/account-invoicing project on GitHub.

+

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

+
+
+
+ + diff --git a/stock_picking_invoicing/tests/__init__.py b/stock_picking_invoicing/tests/__init__.py new file mode 100644 index 00000000000..297fa8819ff --- /dev/null +++ b/stock_picking_invoicing/tests/__init__.py @@ -0,0 +1,5 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import common +from . import test_picking_invoicing diff --git a/stock_picking_invoicing/tests/common.py b/stock_picking_invoicing/tests/common.py new file mode 100644 index 00000000000..473855d0145 --- /dev/null +++ b/stock_picking_invoicing/tests/common.py @@ -0,0 +1,73 @@ +# Copyright (C) 2023-Today - Akretion (). +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import Form, TransactionCase + + +class TestPickingInvoicingCommon(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + def _run_picking_onchanges(self, record): + record._onchange_invoice_state() + + def _run_line_onchanges(self, record): + record._onchange_product_id() + + def picking_move_state(self, picking): + self._run_picking_onchanges(picking) + picking.action_confirm() + # Check product availability + picking.action_assign() + # Force product availability + for move in picking.move_ids_without_package: + self._run_line_onchanges(move) + move.quantity_done = move.product_uom_qty + picking.button_validate() + + def create_invoice_wizard(self, pickings): + wizard_obj = self.env["stock.invoice.onshipping"].with_context( + active_ids=pickings.ids, + active_model=pickings._name, + ) + fields_list = wizard_obj.fields_get().keys() + wizard_values = wizard_obj.default_get(fields_list) + wizard_values.update({"group": "partner_product"}) + wizard = wizard_obj.create(wizard_values) + wizard.onchange_group() + wizard.action_generate() + domain = [("picking_ids", "in", pickings.ids)] + invoice = self.env["account.move"].search(domain) + return invoice + + def return_picking_wizard(self, picking): + # Return Picking + return_wizard_form = Form( + self.env["stock.return.picking"].with_context( + **dict(active_id=picking.id, active_model="stock.picking") + ) + ) + return_wizard_form.invoice_state = "2binvoiced" + self.return_wizard = return_wizard_form.save() + + result_wizard = self.return_wizard.create_returns() + self.assertTrue(result_wizard, "Create returns wizard fail.") + picking_devolution = self.env["stock.picking"].browse( + result_wizard.get("res_id") + ) + return picking_devolution + + def create_backorder_wizard(self, picking): + res_dict_for_back_order = picking.button_validate() + backorder_wizard = Form( + self.env[res_dict_for_back_order["res_model"]].with_context( + **res_dict_for_back_order["context"] + ) + ).save() + backorder_wizard.process() + backorder = self.env["stock.picking"].search( + [("backorder_id", "=", picking.id)] + ) + return backorder diff --git a/stock_picking_invoicing/tests/test_picking_invoicing.py b/stock_picking_invoicing/tests/test_picking_invoicing.py new file mode 100644 index 00000000000..18b5c927649 --- /dev/null +++ b/stock_picking_invoicing/tests/test_picking_invoicing.py @@ -0,0 +1,757 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import exceptions + +from .common import TestPickingInvoicingCommon + + +class TestPickingInvoicing(TestPickingInvoicingCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.picking_model = cls.env["stock.picking"] + cls.move_model = cls.env["stock.move"] + cls.invoice_model = cls.env["account.move"] + cls.partner_model = cls.env["res.partner"] + cls.partner = cls.env.ref("base.res_partner_2") + cls.partner2 = cls.env.ref("base.res_partner_address_4") + cls.partner3 = cls.env.ref("base.res_partner_18") + cls.supplier = cls.env.ref("base.res_partner_12") + cls.pick_type_in = cls.env.ref("stock.picking_type_in") + cls.pick_type_out = cls.env.ref("stock.picking_type_out") + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.customers_location = cls.env.ref("stock.stock_location_customers") + cls.suppliers_location = cls.env.ref("stock.stock_location_suppliers") + cls.journal = cls.env["account.journal"].create( + { + "name": "A super journal name", + "code": "ABC", + "type": "sale", + "refund_sequence": True, + } + ) + + cls.product_model = cls.env["product.product"] + cls.fiscal_position_model = cls.env["account.fiscal.position"] + cls.fiscal_position_tax_model = cls.env["account.fiscal.position.tax"] + cls.fiscal_position_account_model = cls.env["account.fiscal.position.account"] + cls.tax_model = cls.env["account.tax"] + cls.product_tmpl_model = cls.env["product.template"] + cls.account_receivable = cls.env["account.account"].search( + [ + ( + "account_type", + "=", + "asset_receivable", + ) + ], + limit=1, + ) + cls.account_revenue = cls.env["account.account"].search( + [("account_type", "=", "expense_direct_cost")], limit=1 + ) + + cls.tax_sale_1 = cls.tax_model.create( + {"name": "Sale tax 20", "type_tax_use": "sale", "amount": "20.00"} + ) + cls.tax_sale_2 = cls.tax_model.create( + {"name": "Sale tax 10", "type_tax_use": "sale", "amount": "10.00"} + ) + cls.tax_purchase_1 = cls.tax_model.create( + {"name": "Purchase tax 10", "type_tax_use": "purchase", "amount": "10.00"} + ) + cls.tax_purchase_2 = cls.tax_model.create( + {"name": "Purchase tax 20", "type_tax_use": "purchase", "amount": "20.00"} + ) + + cls.product_test_1 = cls.product_model.create( + { + "name": "Test 1", + "lst_price": "15000", + "taxes_id": [(6, 0, [cls.tax_sale_1.id, cls.tax_sale_2.id])], + "supplier_taxes_id": [ + (6, 0, [cls.tax_purchase_1.id, cls.tax_purchase_2.id]) + ], + "property_account_income_id": cls.account_revenue.id, + "standard_price": "500", + } + ) + cls.product_test_2 = cls.product_model.create( + { + "name": "Test 2", + "lst_price": "15000", + "taxes_id": [(6, 0, [cls.tax_sale_1.id, cls.tax_sale_2.id])], + "supplier_taxes_id": [ + (6, 0, [cls.tax_purchase_1.id, cls.tax_purchase_2.id]) + ], + "property_account_income_id": cls.account_revenue.id, + "standard_price": "500", + } + ) + + # Test PriceList and Sellers Price + product_price_test = cls.env.ref("product.product_product_6") + cls.price_list = cls.env.ref("product.list0") + cls.price_list.item_ids.create( + { + "compute_price": "fixed", + "fixed_price": 1234.0, + "applied_on": "0_product_variant", + "product_id": product_price_test.id, + } + ) + # Data has duplicate line with 2 Prices for same Partner, + # just remove one for the test. + seller_to_delete = product_price_test.seller_ids.filtered( + lambda l: l.price == 785.0 + and l.partner_id == cls.env.ref("base.res_partner_4") + ) + seller_to_delete.unlink() + + def test_0_picking_out_invoicing(self): + # setting Agrolait type to default, because it's 'contact' in demo data + nb_invoice_before = self.invoice_model.search_count([]) + # Test case to Get Price Unit to Invoice when Partner don't has Pricelist + self.partner.write({"type": "invoice", "property_product_pricelist": False}) + picking = self.picking_model.create( + { + "partner_id": self.partner2.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 2, + "product_uom": self.product_test_1.uom_id.id, + } + new_move = self.move_model.create(move_vals) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) + assert invoice.invoice_user_id, "Error to map User in Invoice." + assert invoice.invoice_payment_term_id, "Error to map Payment Term in Invoice." + assert invoice.fiscal_position_id, "Error to map Fiscal Position in Invoice." + assert invoice.company_id, "Error to map Company in Invoice." + assert invoice.invoice_line_ids, "Error to create invoice line." + for inv_line in invoice.invoice_line_ids: + assert inv_line.account_id, "Error to map Account in Invoice Line." + assert inv_line.tax_ids, "Error to map Sale Tax in Invoice Line." + assert inv_line.product_uom_id, "Error to map Product UOM in Invoice Line." + assert inv_line.price_unit, "Error in Price Unit" + assert ( + inv_line.move_line_ids + ), "Error, there no relation between Invoice Line and Stock Move Line." + for mv_line in inv_line.move_line_ids: + self.assertEqual( + mv_line.id, + new_move.id, + "Error to link stock.move with invoice.line.", + ) + + def test_1_picking_out_invoicing(self): + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner2.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 2, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals) + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + + # Test Wizard Error + # self.create_invoice_wizard(picking) + wizard_obj = self.env["stock.invoice.onshipping"].with_context( + active_ids=picking.ids, + active_model=picking._name, + active_id=picking.id, + ) + fields_list = wizard_obj.fields_get().keys() + wizard_values = wizard_obj.default_get(fields_list) + wizard = wizard_obj.create(wizard_values) + wizard.onchange_group() + with self.assertRaises(exceptions.UserError) as e: + wizard.with_context(lang="en_US").action_generate() + msg = "No invoice created!" + self.assertIn(msg, e.exception.args[0]) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after) + + def test_2_picking_out_invoicing(self): + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner2.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 2, + "product_uom": self.product_test_1.uom_id.id, + } + new_move = self.move_model.create(move_vals) + picking.set_to_be_invoiced() + + # Test Set Not Invoice + picking.set_as_not_billable() + self.assertEqual(picking.invoice_state, "none") + # Test Set Invoiced + picking.set_as_invoiced() + self.assertEqual(picking.invoice_state, "invoiced") + + picking.set_to_be_invoiced() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) + assert invoice.invoice_line_ids, "Error to create invoice line." + for inv_line in invoice.invoice_line_ids: + for mv_line in inv_line.move_line_ids: + self.assertEqual( + mv_line.id, + new_move.id, + "Error to link stock.move with invoice.line.", + ) + self.assertTrue(inv_line.tax_ids, "Error to map Sale Tax in invoice.line.") + + def test_3_picking_out_invoicing(self): + """ + Test invoicing picking in to check if get the taxes + from supplier_taxes_id. + """ + nb_invoice_before = self.invoice_model.search_count([]) + picking = self.picking_model.create( + { + "partner_id": self.supplier.id, + "picking_type_id": self.pick_type_in.id, + "location_id": self.suppliers_location.id, + "location_dest_id": self.stock_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.stock_location.id, + "location_id": self.suppliers_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 2, + "product_uom": self.product_test_1.uom_id.id, + } + new_move = self.move_model.create(move_vals) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.supplier) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) + assert invoice.invoice_line_ids, "Error to create invoice line." + for inv_line in invoice.invoice_line_ids: + for mv_line in inv_line.move_line_ids: + self.assertEqual( + mv_line.id, + new_move.id, + "Error to link stock.move with invoice.line.", + ) + self.assertTrue( + inv_line.tax_ids, + "Error to map Purchase Tax in invoice.line.", + ) + + def test_4_picking_out_invoicing_backorder(self): + """ + Test invoicing picking out to check if backorder is create + with same invoice state. + """ + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner2.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 4, + "product_uom": self.product_test_1.uom_id.id, + } + new_move = self.move_model.create(move_vals) + new_move._onchange_product_id() + picking.set_to_be_invoiced() + # Test BackOrder need to open Wizard + # self.picking_move_state(picking) + picking.action_confirm() + # Check product availability + picking.action_assign() + # Force product availability + for move in picking.move_ids_without_package: + move.quantity_done = move.product_uom_qty / 2.0 + # Test Price Unit informed by User + move.price_unit = 345.0 + + backorder = self.create_backorder_wizard(picking) + backorder.action_assign() + self.assertEqual(backorder.invoice_state, "2binvoiced") + + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) + assert invoice.invoice_line_ids, "Error to create invoice line." + for inv_line in invoice.invoice_line_ids: + for mv_line in inv_line.move_line_ids: + self.assertEqual( + mv_line.id, + new_move.id, + "Error to link stock.move with invoice.line.", + ) + self.assertTrue(inv_line.tax_ids, "Error to map Sale Tax in invoice.line.") + # Test Price Unit informed by user + self.assertEqual( + inv_line.price_unit, 345.0, "Error in Price Unit informed by User." + ) + + def test_picking_cancel(self): + """ + Ensure that the invoice_state of the picking is correctly + updated when an invoice is cancelled + :return: + """ + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner2.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 2, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + invoice.button_cancel() + self.assertEqual(picking.invoice_state, "2binvoiced") + invoice.button_draft() + self.assertEqual(picking.invoice_state, "invoiced") + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) + + def test_picking_invoice_refund(self): + """ + Ensure that a refund keep the link to the picking + :return: + """ + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner2.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 2, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + invoice.action_post() + refund = invoice._reverse_moves(cancel=True) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertIn(picking, refund.picking_ids) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice | refund)) + + def test_picking_invoicing_by_product1(self): + """ + Test the invoice generation grouped by partner/product with 1 + picking and 2 moves. + :return: + """ + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 1, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals) + move_vals2 = { + "product_id": self.product_test_2.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_2.name, + "product_uom_qty": 1, + "product_uom": self.product_test_2.uom_id.id, + } + self.move_model.create(move_vals2) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + products = invoice.invoice_line_ids.mapped("product_id") + self.assertEqual(len(invoice.invoice_line_ids), 2) + self.assertIn(self.product_test_1, products) + self.assertIn(self.product_test_2, products) + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) + + def test_picking_invoicing_by_product2(self): + """ + Test the invoice generation grouped by partner/product with 2 + picking and 2 moves per picking. + We use same partner for 2 picking so we should have 1 invoice with 2 + lines (and qty 2) + :return: + """ + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 1, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals) + picking2 = picking.copy() + move_vals2 = { + "product_id": self.product_test_1.id, + "picking_id": picking2.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 1, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals2) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + picking2.set_to_be_invoiced() + self.picking_move_state(picking2) + self.assertEqual(picking.state, "done") + self.assertEqual(picking2.state, "done") + pickings = picking | picking2 + invoice = self.create_invoice_wizard(pickings) + self.assertEqual(len(invoice), 1) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(picking2.invoice_state, "invoiced") + self.assertEqual(invoice.partner_id, self.partner) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(invoice, picking2.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + self.assertIn(picking2, invoice.picking_ids) + products = invoice.invoice_line_ids.mapped("product_id") + self.assertIn(self.product_test_1, products) + for inv_line in invoice.invoice_line_ids: + # qty = 3 because 1 move + duplicate one + 1 new + self.assertAlmostEqual(inv_line.quantity, 3) + self.assertTrue(inv_line.tax_ids, "Error to map Sale Tax in invoice.line.") + # Now test behaviour if the invoice is delete + invoice.unlink() + for picking in pickings: + self.assertEqual(picking.invoice_state, "2binvoiced") + nb_invoice_after = self.invoice_model.search_count([]) + # Should be equals because we delete the invoice + self.assertEqual(nb_invoice_before, nb_invoice_after) + + def test_picking_invoicing_by_product3(self): + """ + Test the invoice generation grouped by partner/product with 2 + picking and 2 moves per picking. + We use different partner for 2 picking so we should have 2 invoice + with 2 lines (and qty 1) + :return: + """ + nb_invoice_before = self.invoice_model.search_count([]) + self.partner.write({"type": "invoice"}) + picking = self.picking_model.create( + { + "partner_id": self.partner.id, + "picking_type_id": self.pick_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customers_location.id, + } + ) + move_vals = { + "product_id": self.product_test_1.id, + "picking_id": picking.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_1.name, + "product_uom_qty": 1, + "product_uom": self.product_test_1.uom_id.id, + } + self.move_model.create(move_vals) + picking2 = picking.copy({"partner_id": self.partner3.id}) + move_vals2 = { + "product_id": self.product_test_2.id, + "picking_id": picking2.id, + "location_dest_id": self.customers_location.id, + "location_id": self.stock_location.id, + "name": self.product_test_2.name, + "product_uom_qty": 1, + "product_uom": self.product_test_2.uom_id.id, + } + self.move_model.create(move_vals2) + picking.set_to_be_invoiced() + self.picking_move_state(picking) + + picking2.set_to_be_invoiced() + self.picking_move_state(picking2) + self.assertEqual(picking.state, "done") + self.assertEqual(picking2.state, "done") + pickings = picking | picking2 + invoices = self.create_invoice_wizard(pickings) + + self.assertEqual(len(invoices), 2) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual(picking2.invoice_state, "invoiced") + self.assertIn(self.partner, invoices.mapped("partner_id")) + self.assertIn(self.partner3, invoices.mapped("partner_id")) + for invoice in invoices: + self.assertEqual(len(invoice.picking_ids), 1) + picking = invoice.picking_ids + self.assertIn(invoice, picking.invoice_ids) + for inv_line in invoice.invoice_line_ids: + self.assertAlmostEqual(inv_line.quantity, 1) + self.assertTrue( + inv_line.tax_ids, + "Error to map Sale Tax in invoice.line.", + ) + # Test the behaviour when the invoice is cancelled + # The picking invoice_status should be updated + invoice.button_cancel() + self.assertEqual(picking.invoice_state, "2binvoiced") + nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoices)) + + def test_0_counting_2binvoiced(self): + """ + Check method counting 2binvoice used in kanban view + """ + self.assertEqual(1, self.pick_type_in.count_picking_2binvoiced) + + def test_return_customer_picking(self): + """ + Test Return Customer Picking and Invoice created. + """ + picking = self.env.ref("stock_picking_invoicing.stock_picking_invoicing_2") + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + # Confirm Invoice + invoice.action_post() + self.assertEqual(invoice.state, "posted", "Invoice should be in state Posted") + # Check Invoice Type + self.assertEqual( + invoice.move_type, "out_invoice", "Invoice Type should be Out Invoice" + ) + + # Return Picking + picking_devolution = self.return_picking_wizard(picking) + + self.assertEqual(picking_devolution.invoice_state, "2binvoiced") + for line in picking_devolution.move_ids: + self.assertEqual(line.invoice_state, "2binvoiced") + + self.picking_move_state(picking_devolution) + self.assertEqual(picking_devolution.state, "done", "Change state fail.") + invoice_devolution = self.create_invoice_wizard(picking_devolution) + # Confirm Return Invoice + invoice_devolution.action_post() + self.assertEqual( + invoice_devolution.state, "posted", "Invoice should be in state Posted" + ) + # Check Invoice Type + self.assertEqual( + invoice_devolution.move_type, + "out_refund", + "Invoice Type should be Out Refund", + ) + + def test_return_supplier_picking(self): + """ + Test Return Supplier Picking and Invoice created. + """ + picking = self.env.ref("stock_picking_invoicing.stock_picking_invoicing_7") + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + for line in invoice.invoice_line_ids: + for seller in line.product_id.seller_ids: + if seller.partner_id == invoice.partner_id: + self.assertEqual( + seller.price, + line.price_unit, + "Product Price in invoice line should be the same of Seller Price.", + ) + # Confirm Invoice + invoice.action_post() + self.assertEqual(invoice.state, "posted", "Invoice should be in state Posted") + # Check Invoice Type + self.assertEqual( + invoice.move_type, "in_invoice", "Invoice Type should be In Invoice" + ) + + # Return Picking + picking_devolution = self.return_picking_wizard(picking) + + self.assertEqual(picking_devolution.invoice_state, "2binvoiced") + for line in picking_devolution.move_ids: + self.assertEqual(line.invoice_state, "2binvoiced") + + self.picking_move_state(picking_devolution) + self.assertEqual(picking_devolution.state, "done", "Change state fail.") + + invoice_devolution = self.create_invoice_wizard(picking_devolution) + # Confirm Return Invoice + invoice_devolution.action_post() + self.assertEqual( + invoice_devolution.state, "posted", "Invoice should be in state Posted" + ) + # Check Invoice Type + self.assertEqual( + invoice_devolution.move_type, + "in_refund", + "Invoice Type should be In Refund", + ) + + def test_get_price_from_pricelist(self): + """Test get Price from PriceList.""" + picking = self.env.ref("stock_picking_invoicing.stock_picking_invoicing_1") + self.picking_move_state(picking) + self.assertEqual(picking.state, "done") + invoice = self.create_invoice_wizard(picking) + self.assertEqual(picking.invoice_state, "invoiced") + for inv_line in invoice.invoice_line_ids: + if inv_line.product_id == self.env.ref("product.product_product_6"): + self.assertEqual( + inv_line.price_unit, + 1234.0, + "Error to get sale Price from Price List.", + ) + + def test_picking_extra_vals(self): + """Test Picking Extra Vals""" + picking = self.env.ref("stock_picking_invoicing.stock_picking_invoicing_1") + + self._run_picking_onchanges(picking) + + for line in picking.move_ids_without_package: + self._run_line_onchanges(line) + # Force Split + line.quantity_done = 10 + + picking.button_validate() diff --git a/stock_picking_invoicing/views/stock_move_views.xml b/stock_picking_invoicing/views/stock_move_views.xml new file mode 100644 index 00000000000..50ab801dcd4 --- /dev/null +++ b/stock_picking_invoicing/views/stock_move_views.xml @@ -0,0 +1,62 @@ + + + + stock.move.form.invoice_state + stock.move + + + + + + + + + + + + + + + stock.move.form.inherit + stock.move + + + + + + + + {'invisible': [('invoice_state', 'in', [False, 'none'])]} + + + + + stock.move.tree (in stock_picking_invoicing) + stock.move + + + + + + + + + + stock.move.tree (in stock_picking_invoicing) + stock.move + + + + + + + + diff --git a/stock_picking_invoicing/views/stock_picking_type_views.xml b/stock_picking_invoicing/views/stock_picking_type_views.xml new file mode 100644 index 00000000000..aa6d2a82fa6 --- /dev/null +++ b/stock_picking_invoicing/views/stock_picking_type_views.xml @@ -0,0 +1,37 @@ + + + + Picking to Invoice + ir.actions.act_window + stock.picking + tree,form + + [('state', '!=', 'cancel'), ('picking_type_id', '=', active_id), + ('invoice_state', '=', '2binvoiced')] + {'default_picking_type_id': active_id} + + + stock.picking.type.kanban + stock.picking.type + + + + + + +
+ +
+ +
+
+
+
+
+
diff --git a/stock_picking_invoicing/views/stock_picking_views.xml b/stock_picking_invoicing/views/stock_picking_views.xml new file mode 100644 index 00000000000..d8581682a28 --- /dev/null +++ b/stock_picking_invoicing/views/stock_picking_views.xml @@ -0,0 +1,117 @@ + + + + stock.picking.tree.inherit + stock.picking + + + + + + + + + stock.picking.search.inherit + stock.picking + + + + + + + + + stock.picking.form.inherit + stock.picking + + + + + + + + + + + + + + + + + + + + + + { + 'default_invoice_state': invoice_state, + } + + + + + + + + + + + + + + + diff --git a/stock_picking_invoicing/wizards/__init__.py b/stock_picking_invoicing/wizards/__init__.py new file mode 100644 index 00000000000..00f959aa074 --- /dev/null +++ b/stock_picking_invoicing/wizards/__init__.py @@ -0,0 +1,5 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import stock_invoice_onshipping +from . import stock_return_picking diff --git a/stock_picking_invoicing/wizards/stock_invoice_onshipping.py b/stock_picking_invoicing/wizards/stock_invoice_onshipping.py new file mode 100644 index 00000000000..f316e37ea69 --- /dev/null +++ b/stock_picking_invoicing/wizards/stock_invoice_onshipping.py @@ -0,0 +1,532 @@ +# Copyright (C) 2019-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + +JOURNAL_TYPE_MAP = { + ("outgoing", "customer"): ["sale"], + ("outgoing", "supplier"): ["purchase"], + ("outgoing", "transit"): ["sale", "purchase"], + ("incoming", "supplier"): ["purchase"], + ("incoming", "customer"): ["sale"], + ("incoming", "transit"): ["purchase", "sale"], +} + +INVOICE_TYPE_MAP = { + # Picking Type Code | Local Origin Usage | Local Dest Usage + ("outgoing", "internal", "customer"): "out_invoice", + ("incoming", "customer", "internal"): "out_refund", + ("incoming", "customer", "customer"): "out_refund", + ("incoming", "supplier", "internal"): "in_invoice", + ("outgoing", "internal", "supplier"): "in_refund", + ("outgoing", "internal", "internal"): "in_refund", + ("incoming", "transit", "internal"): "in_invoice", + ("outgoing", "transit", "supplier"): "in_refund", + ("outgoing", "transit", "customer"): "out_invoice", +} + + +class StockInvoiceOnshipping(models.TransientModel): + _name = "stock.invoice.onshipping" + _description = "Stock Invoice Onshipping" + + @api.model + def _get_journal_type(self): + active_ids = self.env.context.get("active_ids", []) + if active_ids: + active_ids = active_ids[0] + pick_obj = self.env["stock.picking"] + picking = pick_obj.browse(active_ids) + if not picking or not picking.move_ids: + return "sale" + pick_type_code = picking.picking_type_id.code + line = fields.first(picking.move_ids) + if pick_type_code == "incoming": + usage = line.location_id.usage + else: + usage = line.location_dest_id.usage + return JOURNAL_TYPE_MAP.get((pick_type_code, usage), ["sale"])[0] + + journal_type = fields.Selection( + selection=[ + ("purchase", "Create Supplier Invoice"), + ("sale", "Create Customer Invoice"), + ], + default=_get_journal_type, + readonly=True, + ) + group = fields.Selection( + selection=[ + ("picking", "Picking"), + ("partner", "Partner"), + ("partner_product", "Partner/Product"), + ], + default="picking", + help="Group pickings/moves to create invoice(s):\n" + "Picking: One invoice per picking;\n" + "Partner: One invoice for each picking's partner;\n" + "Partner/Product: One invoice per picking's partner and group " + "product into a single invoice line.", + required=True, + ) + invoice_date = fields.Date() + sale_journal = fields.Many2one( + comodel_name="account.journal", + domain="[('type', '=', 'sale')]", + default=lambda self: self._default_journal("sale"), + ondelete="cascade", + ) + purchase_journal = fields.Many2one( + comodel_name="account.journal", + domain="[('type', '=', 'purchase')]", + default=lambda self: self._default_journal("purchase"), + ondelete="cascade", + ) + show_sale_journal = fields.Boolean() + show_purchase_journal = fields.Boolean() + + @api.model + def default_get(self, fields_list): + """ + Inherit to add default invoice_date + :param fields_list: list of str + :return: dict + """ + result = super().default_get(fields_list) + result.update({"invoice_date": fields.Date.today()}) + return result + + @api.onchange("group") + def onchange_group(self): + self.ensure_one() + ( + sale_pickings, + sale_refund_pickings, + purchase_pickings, + purchase_refund_pickings, + ) = self.get_split_pickings() + self.show_sale_journal = bool(sale_pickings) + self.show_purchase_journal = bool(purchase_pickings) + + def get_partner_sum(self, pickings, partner, inv_type, picking_type, usage): + pickings = pickings.filtered( + lambda x: x.picking_type_id.code == picking_type and x.partner_id == partner + ) + lines = pickings.mapped("move_ids") + if picking_type == "outgoing": + moves = lines.filtered(lambda x: x.location_dest_id.usage == usage) + else: + moves = lines.filtered(lambda x: x.location_id.usage == usage) + total = sum( + ( + m._get_price_unit_invoice(inv_type, m.picking_id.partner_id) + * m.product_uom_qty + ) + for m in moves + ) + return total, moves.mapped("picking_id") + + def get_split_pickings(self): + self.ensure_one() + picking_obj = self.env["stock.picking"] + pickings = picking_obj.browse(self.env.context.get("active_ids", [])) + if self.group != "picking": + return self.get_split_pickings_grouped(pickings) + return self.get_split_pickings_nogrouped(pickings) + + def get_split_pickings_grouped(self, pickings): + sale_pickings = self.env["stock.picking"].browse() + sale_refund_pickings = self.env["stock.picking"].browse() + purchase_pickings = self.env["stock.picking"].browse() + purchase_refund_pickings = self.env["stock.picking"].browse() + + for partner in pickings.mapped("partner_id"): + so_sum, so_pickings = self.get_partner_sum( + pickings, partner, "out_invoice", "outgoing", "customer" + ) + si_sum, si_pickings = self.get_partner_sum( + pickings, partner, "out_invoice", "incoming", "customer" + ) + if (so_sum - si_sum) >= 0: + sale_pickings |= so_pickings | si_pickings + else: + sale_refund_pickings |= so_pickings | si_pickings + pi_sum, pi_pickings = self.get_partner_sum( + pickings, partner, "in_invoice", "incoming", "supplier" + ) + po_sum, po_pickings = self.get_partner_sum( + pickings, partner, "in_invoice", "outgoing", "supplier" + ) + if (pi_sum - po_sum) >= 0: + purchase_pickings |= pi_pickings | po_pickings + else: + purchase_refund_pickings |= pi_pickings | po_pickings + + return ( + sale_pickings, + sale_refund_pickings, + purchase_pickings, + purchase_refund_pickings, + ) + + def get_split_pickings_nogrouped(self, pickings): + first = fields.first + sale_pickings = pickings.filtered( + lambda x: x.picking_type_id.code == "outgoing" + and first(x.move_ids).location_dest_id.usage == "customer" + ) + sale_refund_pickings = pickings.filtered( + lambda x: x.picking_type_id.code == "incoming" + and first(x.move_ids).location_id.usage == "customer" + ) + purchase_pickings = pickings.filtered( + lambda x: x.picking_type_id.code == "incoming" + and first(x.move_ids).location_id.usage == "supplier" + ) + purchase_refund_pickings = pickings.filtered( + lambda x: x.picking_type_id.code == "outgoing" + and first(x.move_ids).location_dest_id.usage == "supplier" + ) + + return ( + sale_pickings, + sale_refund_pickings, + purchase_pickings, + purchase_refund_pickings, + ) + + @api.model + def _default_journal(self, journal_type): + """ + Get the default journal based on the given type + :param journal_type: str + :return: account.journal recordset + """ + default_journal = self.env["account.journal"].search( + [ + ("type", "=", journal_type), + ("company_id", "=", self.env.company.id), + ], + limit=1, + ) + return default_journal + + def action_generate(self): + """ + Launch the invoice generation + :return: + """ + self.ensure_one() + invoices = self._action_generate_invoices() + if not invoices: + raise UserError(_("No invoice created!")) + + # Update the state on pickings related to new invoices only + self._update_picking_invoice_status(invoices.mapped("picking_ids")) + + inv_type = self._get_invoice_type() + if inv_type in ["out_invoice", "out_refund"]: + xmlid = "account.action_move_out_invoice_type" + else: + xmlid = "account.action_move_in_invoice_type" + action_dict = self.env["ir.actions.act_window"]._for_xml_id(xmlid) + + if len(invoices) > 1: + action_dict["domain"] = [("id", "in", invoices.ids)] + elif len(invoices) == 1: + if inv_type in ["out_invoice", "out_refund"]: + form_view = [(self.env.ref("account.view_move_form").id, "form")] + else: + form_view = [(self.env.ref("account.view_move_form").id, "form")] + if "views" in action_dict: + action_dict["views"] = form_view + [ + (state, view) + for state, view in action_dict["views"] + if view != "form" + ] + else: + action_dict["views"] = form_view + action_dict["res_id"] = invoices.ids[0] + + return action_dict + + def _load_pickings(self): + """ + Load pickings from context + :return: stock.picking recordset + """ + picking_obj = self.env["stock.picking"] + active_ids = self.env.context.get("active_ids", []) + pickings = picking_obj.browse(active_ids) + pickings = pickings.filtered(lambda p: p.invoice_state == "2binvoiced") + return pickings + + def _get_journal(self): + """ + Get the journal depending on the journal_type + :return: account.journal recordset + """ + self.ensure_one() + journal_field = "%s_journal" % self.journal_type + journal = self[journal_field] + return journal + + def _get_invoice_type(self): + """ + Get the invoice type + :return: str + """ + self.ensure_one() + + active_ids = self.env.context.get("active_ids", []) + if active_ids: + active_ids = active_ids[0] + picking = self.env["stock.picking"].browse(active_ids) + + inv_type = ( + INVOICE_TYPE_MAP.get( + ( + picking.picking_type_code, + picking.location_id.usage, + picking.location_dest_id.usage, + ) + ) + or "out_invoice" + ) + + return inv_type + + @api.model + def _get_picking_key(self, picking): + """ + Get the key for the given picking. + By default, it's based on the invoice partner and the picking_type_id + of the picking + :param picking: stock.picking recordset + :return: key (tuple,...) + """ + key = (picking,) + if self.group in ["partner", "partner_product"]: + # Pickings with same Partner to create Invoice but the + # Partner to Shipping is different should not be grouping. + key = ( + picking._get_partner_to_invoice(), + picking.picking_type_id, + picking.partner_id, + ) + return key + + def _group_pickings(self, pickings): + """ + Group given picking + :param pickings: + :return: list of stock.picking recordset + """ + grouped_picking = {} + pickings = pickings.filtered(lambda p: p.invoice_state == "2binvoiced") + for picking in pickings: + key = self._get_picking_key(picking) + picks_grouped = grouped_picking.get(key, self.env["stock.picking"].browse()) + picks_grouped |= picking + grouped_picking.update({key: picks_grouped}) + return grouped_picking.values() + + def _simulate_invoice_onchange(self, values): + """ + Simulate onchange for invoice + :param values: dict + :return: dict + """ + invoice = self.env["account.move"].new(values.copy()) + invoice._onchange_partner_id() + invoice._inverse_company_id() + invoice._inverse_currency_id() + invoice._onchange_date() + new_values = invoice._convert_to_write(invoice._cache) + # Ensure basic values are not updated + values.update(new_values) + return invoice, values + + def _build_invoice_values_from_pickings(self, pickings): + """ + Build dict to create a new invoice from given pickings + :param pickings: stock.picking recordset + :return: dict + """ + picking = fields.first(pickings) + partner_id = picking._get_partner_to_invoice() + partner = self.env["res.partner"].browse(partner_id) + inv_type = self._get_invoice_type() + currency = self.env.company.currency_id + if partner: + code = picking.picking_type_id.code + if partner.property_product_pricelist and code == "outgoing": + currency = partner.property_product_pricelist.currency_id + journal = self._get_journal() + invoice_obj = self.env["account.move"] + values = invoice_obj.default_get(invoice_obj.fields_get().keys()) + values.update( + { + "invoice_origin": ", ".join(pickings.mapped("name")), + "partner_id": partner_id, + "move_type": inv_type, + "currency_id": currency.id, + "journal_id": journal.id, + } + ) + + invoice, values = self._simulate_invoice_onchange(values) + return invoice, values + + def _get_move_key(self, move): + """ + Get the key based on the given move + :param move: stock.move recordset + :return: (key,) + """ + key = (move,) + if self.group == "partner_product": + key = (move.product_id,) + return key + + def _group_moves(self, moves): + """ + Possibility to group moves (to create 1 invoice line with many moves) + :param moves: stock.move recordset + :return: list of stock.move recordset + """ + grouped_moves = {} + moves = moves.filtered(lambda m: m.invoice_state == "2binvoiced") + for move in moves: + key = self._get_move_key(move) + move_grouped = grouped_moves.get(key, self.env["stock.move"].browse()) + move_grouped |= move + grouped_moves.update({key: move_grouped}) + return grouped_moves.values() + + def _simulate_invoice_line_onchange(self, values, price_unit=None): + """ + Simulate onchange for invoice line + :param values: dict + :return: dict + """ + line = self.env["account.move.line"].new(values.copy()) + line._inverse_partner_id() + line._inverse_product_id() + line._inverse_account_id() + line._inverse_amount_currency() + new_values = line._convert_to_write(line._cache) + if price_unit: + new_values["price_unit"] = price_unit + # Ensure basic values are not updated + values.update(new_values) + return values + + def _get_invoice_line_values(self, moves, invoice_values, invoice): + """ + Create invoice line values from given moves + :param moves: stock.move + :param invoice: account.move + :return: dict + """ + move = fields.first(moves) + product = move.product_id + partner_id = self.env["res.partner"].browse(invoice_values["partner_id"]) + inv_type = invoice_values["move_type"] + quantity = 0 + move_line_ids = [] + for move in moves: + qty = move.product_uom_qty + loc = move.location_id + loc_dst = move.location_dest_id + # Better to understand with IF/ELIF than many OR + if inv_type == "out_invoice" and loc.usage == "customer": + qty *= -1 + elif inv_type == "out_refund" and loc_dst.usage == "customer": + qty *= -1 + elif inv_type == "in_invoice" and loc_dst.usage == "supplier": + qty *= -1 + elif inv_type == "in_refund" and loc.usage == "supplier": + qty *= -1 + quantity += qty + move_line_ids.append((4, move.id)) + price = moves._get_price_unit_invoice(inv_type, partner_id, quantity) + line_obj = self.env["account.move.line"] + values = line_obj.default_get(line_obj.fields_get().keys()) + values.update( + { + "name": move.name, + "product_id": product.id, + "quantity": quantity, + "price_unit": price, + "move_line_ids": move_line_ids, + "move_id": invoice.id, + } + ) + values = self._simulate_invoice_line_onchange(values, price_unit=price) + return values + + def _update_picking_invoice_status(self, pickings): + """ + Update invoice_state on pickings + :param pickings: stock.picking recordset + :return: stock.picking recordset + """ + return pickings._set_as_invoiced() + + def ungroup_moves(self, grouped_moves_list): + """Ungroup your moves, split them again, grouping by + fiscal position, max itens per invoice and etc + :param grouped_moves_list: + :return: list of grouped moves list + """ + return [grouped_moves_list] + + def _create_invoice(self, invoice_values): + """Override this method if you need to change any values of the + invoice and the lines before the invoice creation + :param invoice_values: dict with the invoice and its lines + :return: invoice + """ + return self.env["account.move"].create(invoice_values) + + def _action_generate_invoices(self): + """ + Action to generate invoices based on pickings + :return: account.move recordset + """ + pickings = self._load_pickings() + company = pickings.mapped("company_id") + if company and company != self.env.company: + raise UserError(_("All pickings are not related to your company!")) + pick_list = self._group_pickings(pickings) + invoices = self.env["account.move"].browse() + for pickings in pick_list: + moves = pickings.mapped("move_ids") + grouped_moves_list = self._group_moves(moves) + parts = self.ungroup_moves(grouped_moves_list) + for moves_list in parts: + invoice, invoice_values = self._build_invoice_values_from_pickings( + pickings + ) + lines = [(5, 0, {})] + line_values = False + for moves in moves_list: + line_values = self._get_invoice_line_values( + moves, invoice_values, invoice + ) + if line_values: + lines.append((0, 0, line_values)) + if line_values: # Only create the invoice if it has lines + invoice_values["invoice_line_ids"] = lines + # Necessary inform line_ids with empty list to avoid error + # addons/account/models/account_move.py", line 2251, + # in _sanitize_vals + # assert command not in (Command.SET, Command.CLEAR) + invoice_values["line_ids"] = [] + invoice_values["invoice_date"] = self.invoice_date + invoice = self._create_invoice(invoice_values) + invoice._compute_amount() + invoices |= invoice + return invoices diff --git a/stock_picking_invoicing/wizards/stock_invoice_onshipping_view.xml b/stock_picking_invoicing/wizards/stock_invoice_onshipping_view.xml new file mode 100644 index 00000000000..85ec6117f34 --- /dev/null +++ b/stock_picking_invoicing/wizards/stock_invoice_onshipping_view.xml @@ -0,0 +1,47 @@ + + + + Stock Invoice Onshipping + stock.invoice.onshipping + +
+

+ +

+ + + + + + + + +
+
+
+
+
+ + Create Draft Invoices + ir.actions.act_window + stock.invoice.onshipping + + + list,form + new + +
diff --git a/stock_picking_invoicing/wizards/stock_return_picking.py b/stock_picking_invoicing/wizards/stock_return_picking.py new file mode 100644 index 00000000000..927fe8e70dc --- /dev/null +++ b/stock_picking_invoicing/wizards/stock_return_picking.py @@ -0,0 +1,23 @@ +# @ 2021-Today: Akretion - www.akretion.com - +# Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class StockReturnPicking(models.TransientModel): + _inherit = "stock.return.picking" + + invoice_state = fields.Selection( + selection=[("2binvoiced", "To be refunded/invoiced"), ("none", "No invoicing")], + string="Invoicing", + required=True, + default="none", + ) + + def _prepare_move_default_values(self, return_line, new_picking): + vals = super()._prepare_move_default_values(return_line, new_picking) + if self.invoice_state == "2binvoiced": + vals.update({"invoice_state": self.invoice_state}) + + return vals diff --git a/stock_picking_invoicing/wizards/stock_return_picking_view.xml b/stock_picking_invoicing/wizards/stock_return_picking_view.xml new file mode 100644 index 00000000000..7c9b00360d1 --- /dev/null +++ b/stock_picking_invoicing/wizards/stock_return_picking_view.xml @@ -0,0 +1,15 @@ + + + + Return lines + stock.return.picking + + + + + + + + + +