From 30508ddf1289b462eff2d88addd741104b1807f8 Mon Sep 17 00:00:00 2001 From: CarlosRoca13 Date: Tue, 23 Aug 2022 12:23:23 +0200 Subject: [PATCH] [ADD] account_sale_stock_report_non_billed: New module With this module we are able to show non invoiced stock moves in a concrete date. TT38550 --- .../README.rst | 95 ++++ .../__init__.py | 2 + .../__manifest__.py | 18 + .../account_sale_stock_report_non_billed.pot | 157 +++++++ .../i18n/es.po | 163 +++++++ .../models/__init__.py | 4 + .../models/account_move_line.py | 14 + .../models/res_company.py | 12 + .../models/res_config_settings.py | 12 + .../models/stock_move.py | 180 ++++++++ .../readme/CONTRIBUTORS.rst | 4 + .../readme/DESCRIPTION.rst | 2 + .../readme/USAGE.rst | 6 + .../static/description/index.html | 437 ++++++++++++++++++ .../tests/__init__.py | 1 + ...st_account_sale_stock_report_non_billed.py | 209 +++++++++ .../views/res_config_settings_views.xml | 25 + .../views/stock_move_non_billed_views.xml | 82 ++++ .../wizard/__init__.py | 1 + ...ccount_sale_stock_report_non_billed_wiz.py | 103 +++++ ...sale_stock_report_non_billed_wiz_views.xml | 42 ++ .../account_sale_stock_report_non_billed | 1 + .../setup.py | 6 + 23 files changed, 1576 insertions(+) create mode 100644 account_sale_stock_report_non_billed/README.rst create mode 100644 account_sale_stock_report_non_billed/__init__.py create mode 100644 account_sale_stock_report_non_billed/__manifest__.py create mode 100644 account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot create mode 100644 account_sale_stock_report_non_billed/i18n/es.po create mode 100644 account_sale_stock_report_non_billed/models/__init__.py create mode 100644 account_sale_stock_report_non_billed/models/account_move_line.py create mode 100644 account_sale_stock_report_non_billed/models/res_company.py create mode 100644 account_sale_stock_report_non_billed/models/res_config_settings.py create mode 100644 account_sale_stock_report_non_billed/models/stock_move.py create mode 100644 account_sale_stock_report_non_billed/readme/CONTRIBUTORS.rst create mode 100644 account_sale_stock_report_non_billed/readme/DESCRIPTION.rst create mode 100644 account_sale_stock_report_non_billed/readme/USAGE.rst create mode 100644 account_sale_stock_report_non_billed/static/description/index.html create mode 100644 account_sale_stock_report_non_billed/tests/__init__.py create mode 100644 account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py create mode 100644 account_sale_stock_report_non_billed/views/res_config_settings_views.xml create mode 100644 account_sale_stock_report_non_billed/views/stock_move_non_billed_views.xml create mode 100644 account_sale_stock_report_non_billed/wizard/__init__.py create mode 100644 account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py create mode 100644 account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz_views.xml create mode 120000 setup/account_sale_stock_report_non_billed/odoo/addons/account_sale_stock_report_non_billed create mode 100644 setup/account_sale_stock_report_non_billed/setup.py diff --git a/account_sale_stock_report_non_billed/README.rst b/account_sale_stock_report_non_billed/README.rst new file mode 100644 index 00000000..40dfba06 --- /dev/null +++ b/account_sale_stock_report_non_billed/README.rst @@ -0,0 +1,95 @@ +==================================== +Account Sale Stock Report Non Billed +==================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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--financial--reporting-lightgray.png?logo=github + :target: https://github.com/OCA/account-financial-reporting/tree/15.0/account_sale_stock_report_non_billed + :alt: OCA/account-financial-reporting +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-financial-reporting-15-0/account-financial-reporting-15-0-account_sale_stock_report_non_billed + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/91/15.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Module to allow list stock moves that have not being invoiced yet, by adding a wizard +that supports show the pickings not invoiced at a specific date. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +#. Go to `Invicing > Reporting > Non Billed Stock Moves`. +#. Select a concrete date. +#. The stock moves created before this date with quantity to be invoiced, are being + showed at the tree view. + +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 +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * Carlos Roca + * Pedro M. Baeza + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-CarlosRoca13| image:: https://github.com/CarlosRoca13.png?size=40px + :target: https://github.com/CarlosRoca13 + :alt: CarlosRoca13 + +Current `maintainer `__: + +|maintainer-CarlosRoca13| + +This module is part of the `OCA/account-financial-reporting `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_sale_stock_report_non_billed/__init__.py b/account_sale_stock_report_non_billed/__init__.py new file mode 100644 index 00000000..9b429614 --- /dev/null +++ b/account_sale_stock_report_non_billed/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/account_sale_stock_report_non_billed/__manifest__.py b/account_sale_stock_report_non_billed/__manifest__.py new file mode 100644 index 00000000..be899ecb --- /dev/null +++ b/account_sale_stock_report_non_billed/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2022 Tecnativa - Carlos Roca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Account Sale Stock Report Non Billed", + "version": "13.0.1.0.0", + "license": "AGPL-3", + "author": "Tecnativa, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-financial-reporting", + "depends": ["stock_picking_invoice_link"], + "data": [ + "views/res_config_settings_views.xml", + "views/stock_move_non_billed_views.xml", + "wizard/account_sale_stock_report_non_billed_wiz_views.xml", + ], + "installable": True, + "maintainers": ["CarlosRoca13"], + "development_status": "Beta", +} diff --git a/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot b/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot new file mode 100644 index 00000000..833ce252 --- /dev/null +++ b/account_sale_stock_report_non_billed/i18n/account_sale_stock_report_non_billed.pot @@ -0,0 +1,157 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_sale_stock_report_non_billed +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-09-26 09:37+0000\n" +"PO-Revision-Date: 2022-09-26 09:37+0000\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: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__price_not_invoiced +msgid "Amount to invoice" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.account_sale_stock_report_non_billed_wiz_form +msgid "Cancel" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_res_company +msgid "Companies" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.account_sale_stock_report_non_billed_wiz_form +msgid "Confirm" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__create_uid +msgid "Created by" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__create_date +msgid "Created on" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__currency_id +msgid "Currency" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__date_check +msgid "Date" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.res_config_settings_view_form +msgid "" +"Date from which stock movements are to be taken into account\n" +" for the non billed movements report." +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__display_name +msgid "Display Name" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__date_done +msgid "Effective Date" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_search +msgid "Effective date" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__id +msgid "ID" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_account_move_line +msgid "Journal Item" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz____last_update +msgid "Last Modified on" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__write_date +msgid "Last Updated on" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.actions.act_window,name:account_sale_stock_report_non_billed.action_open_non_billed_stock_move +#: model:ir.ui.menu,name:account_sale_stock_report_non_billed.menu_non_billed_stock_move +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.account_sale_stock_report_non_billed_wiz_form +msgid "Non Billed Stock Moves" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_res_company__stock_move_non_billed_threshold +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_res_config_settings__stock_move_non_billed_threshold +msgid "Non Billed Threshold Date" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: code:addons/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py:0 +#, python-format +msgid "Non billed moves (%(from)s -> %(to)s)" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_tree +msgid "Open document" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_tree +msgid "Picking" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__quantity_not_invoiced +msgid "Qty. to invoice" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_pivot_no_invoiced +msgid "Stock Moves Analysis" +msgstr "" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_account_sale_stock_report_non_billed_wiz +msgid "Wizard to open stock moves that have not been invoiced at that time" +msgstr "" diff --git a/account_sale_stock_report_non_billed/i18n/es.po b/account_sale_stock_report_non_billed/i18n/es.po new file mode 100644 index 00000000..62d275de --- /dev/null +++ b/account_sale_stock_report_non_billed/i18n/es.po @@ -0,0 +1,163 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_sale_stock_report_non_billed +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-09-26 09:37+0000\n" +"PO-Revision-Date: 2022-09-26 11:38+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.3\n" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__price_not_invoiced +msgid "Amount to invoice" +msgstr "Importe a facturar" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.account_sale_stock_report_non_billed_wiz_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_res_company +msgid "Companies" +msgstr "Compañías" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_res_config_settings +msgid "Config Settings" +msgstr "Opciones de Configuración" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.account_sale_stock_report_non_billed_wiz_form +msgid "Confirm" +msgstr "Confirmar" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__currency_id +msgid "Currency" +msgstr "Moneda" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__date_check +msgid "Date" +msgstr "Fecha" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.res_config_settings_view_form +msgid "" +"Date from which stock movements are to be taken into account\n" +" for the non billed movements report." +msgstr "" +"Fecha a partir de la que se van a tener en cuenta los movimientos\n" +"\t\t\tpara el informe de movimientos no facturados." + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__date_done +msgid "Effective Date" +msgstr "Fecha efectiva" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_search +msgid "Effective date" +msgstr "Fecha efectiva" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__id +msgid "ID" +msgstr "ID" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_account_move_line +msgid "Journal Item" +msgstr "Apunte contable" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_account_sale_stock_report_non_billed_wiz__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: account_sale_stock_report_non_billed +#: model:ir.actions.act_window,name:account_sale_stock_report_non_billed.action_open_non_billed_stock_move +#: model:ir.ui.menu,name:account_sale_stock_report_non_billed.menu_non_billed_stock_move +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.account_sale_stock_report_non_billed_wiz_form +msgid "Non Billed Stock Moves" +msgstr "Movimientos de albarán no facturados" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_res_company__stock_move_non_billed_threshold +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_res_config_settings__stock_move_non_billed_threshold +msgid "Non Billed Threshold Date" +msgstr "Fecha umbral movimientos no facturados" + +#. module: account_sale_stock_report_non_billed +#: code:addons/account_sale_stock_report_non_billed/wizard/account_sale_stock_report_non_billed_wiz.py:0 +#, python-format +msgid "Non billed moves (%(from)s -> %(to)s)" +msgstr "Movimientos no facturados (%(from)s -> %(to)s)" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_tree +msgid "Open document" +msgstr "Abrir documento" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_tree +msgid "Picking" +msgstr "Albarán" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model.fields,field_description:account_sale_stock_report_non_billed.field_stock_move__quantity_not_invoiced +msgid "Qty. to invoice" +msgstr "Ctd. a facturar" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de stock" + +#. module: account_sale_stock_report_non_billed +#: model_terms:ir.ui.view,arch_db:account_sale_stock_report_non_billed.view_move_pivot_no_invoiced +msgid "Stock Moves Analysis" +msgstr "Análisis de movimientos de stock" + +#. module: account_sale_stock_report_non_billed +#: model:ir.model,name:account_sale_stock_report_non_billed.model_account_sale_stock_report_non_billed_wiz +msgid "Wizard to open stock moves that have not been invoiced at that time" +msgstr "" +"Asistente para abrir movimientos de stock que no han sido facturados a una " +"fecha dada" diff --git a/account_sale_stock_report_non_billed/models/__init__.py b/account_sale_stock_report_non_billed/models/__init__.py new file mode 100644 index 00000000..69f308aa --- /dev/null +++ b/account_sale_stock_report_non_billed/models/__init__.py @@ -0,0 +1,4 @@ +from . import account_move_line +from . import res_company +from . import res_config_settings +from . import stock_move diff --git a/account_sale_stock_report_non_billed/models/account_move_line.py b/account_sale_stock_report_non_billed/models/account_move_line.py new file mode 100644 index 00000000..fc26a138 --- /dev/null +++ b/account_sale_stock_report_non_billed/models/account_move_line.py @@ -0,0 +1,14 @@ +# Copyright 2022 Tecnativa - Carlos Roca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class StockMove(models.Model): + _inherit = "account.move.line" + + def check_invoice_line_in_date(self, date_check): + self.ensure_one() + return ( + self.move_id.date or self.move_id.invoice_date or self.create_date.date() + ) <= date_check diff --git a/account_sale_stock_report_non_billed/models/res_company.py b/account_sale_stock_report_non_billed/models/res_company.py new file mode 100644 index 00000000..ee76fd3d --- /dev/null +++ b/account_sale_stock_report_non_billed/models/res_company.py @@ -0,0 +1,12 @@ +# Copyright 2022 Tecnativa - Carlos Roca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + stock_move_non_billed_threshold = fields.Date( + string="Non Billed Threshold Date", default=fields.Date.today + ) diff --git a/account_sale_stock_report_non_billed/models/res_config_settings.py b/account_sale_stock_report_non_billed/models/res_config_settings.py new file mode 100644 index 00000000..1e662c6e --- /dev/null +++ b/account_sale_stock_report_non_billed/models/res_config_settings.py @@ -0,0 +1,12 @@ +# Copyright 2022 Tecnativa - Carlos Roca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + stock_move_non_billed_threshold = fields.Date( + related="company_id.stock_move_non_billed_threshold", readonly=False + ) diff --git a/account_sale_stock_report_non_billed/models/stock_move.py b/account_sale_stock_report_non_billed/models/stock_move.py new file mode 100644 index 00000000..9d3f3c8a --- /dev/null +++ b/account_sale_stock_report_non_billed/models/stock_move.py @@ -0,0 +1,180 @@ +# Copyright 2022 Tecnativa - Carlos Roca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class StockMove(models.Model): + _inherit = "stock.move" + + quantity_not_invoiced = fields.Float( + string="Qty. to invoice", + compute="_compute_not_invoiced_values", + digits="Product Unit of Measure", + ) + price_not_invoiced = fields.Float( + string="Amount to invoice", + compute="_compute_not_invoiced_values", + digits="Product Price", + ) + currency_id = fields.Many2one( + comodel_name="res.currency", compute="_compute_currency_id" + ) + date_done = fields.Date( + string="Effective Date", compute="_compute_date_done", store=True + ) + + @api.depends("picking_id.date_done") + def _compute_date_done(self): + self.date_done = False + for move in self: + if move.picking_id.date_done: + move.date_done = move.picking_id.date_done.date() + + @api.depends("sale_line_id") + def _compute_currency_id(self): + """Method to be overwritten when new implementations are made, e.g. with + purchase_stock_picking_invoice_link. + """ + self.currency_id = False + for move in self: + if move.sale_line_id: + move.currency_id = move.sale_line_id.currency_id + + def check_is_return(self): + self.ensure_one() + if not self.origin_returned_move_id: + return False + else: + return not self.origin_returned_move_id.check_is_return() + + def get_total_devolution_moves(self): + total_qty = 0 + for move in self: + if not move.check_is_return(): + total_qty += move.quantity_done + else: + total_qty -= move.quantity_done + return total_qty + + def get_quantity_invoiced(self, invoice_lines): + if not invoice_lines: + return 0 + total_invoiced = abs( + sum( + invoice_lines.mapped( + lambda l: l.quantity + if (l.move_id.type == "out_invoice" and not self.to_refund) + or (l.move_id.type == "out_refund" and self.to_refund) + else -l.quantity + ) + ) + ) + # Check when grouping different moves in an invoice line + moves = invoice_lines.mapped("move_line_ids") + total_qty = moves.get_total_devolution_moves() + if total_invoiced != total_qty: + invoiced = 0.0 + for move in moves: + qty = ( + move.quantity_done + if move.quantity_done <= (total_invoiced - invoiced) + else total_invoiced - invoiced + ) + if move.check_is_return(): + qty = -qty + if move == self: + return qty + invoiced += qty + return 0 + return self.quantity_done if not self.check_is_return() else -self.quantity_done + + def _set_not_invoiced_values(self, qty_to_invoice, invoiced_qty): + self.ensure_one() + self.quantity_not_invoiced = qty_to_invoice - invoiced_qty + self.price_not_invoiced = ( + qty_to_invoice - invoiced_qty + ) * self.sale_line_id.price_unit + + @api.depends("sale_line_id") + @api.depends_context("date_check_invoiced_moves") + def _compute_not_invoiced_values(self): + for move in self: + if not self.env.context.get("date_check_invoiced_moves"): + move.quantity_not_invoiced = 0 + move.price_not_invoiced = 0 + continue + inv_lines = ( + move.invoice_line_ids.filtered(lambda l: l.move_id.state != "cancel") + .mapped("move_line_ids.invoice_line_ids") + .filtered( + lambda l: l.check_invoice_line_in_date( + fields.Date.from_string( + self.env.context["date_check_invoiced_moves"] + ) + ) + ) + ) + qty_to_invoice = ( + move.quantity_done + if not move.check_is_return() + else -move.quantity_done + ) + calculated_qty = move.get_quantity_invoiced(inv_lines) + move._set_not_invoiced_values(qty_to_invoice, calculated_qty) + + @api.model + def read_group( + self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True + ): + """Method to add the computed values 'quantity_not_invoiced' and + 'price_not_invoiced' to the result. Without doing it we get an error when trying + to get the info on a pivot view. + As the fields are not stored, before call super() method we had to remove + the keys from 'fields' argument to avoid errors. + """ + aux_fields = [] + if "quantity_not_invoiced:sum" in fields: + aux_fields.append("quantity_not_invoiced:sum") + fields.remove("quantity_not_invoiced:sum") + if "price_not_invoiced:sum" in fields: + aux_fields.append("price_not_invoiced:sum") + fields.remove("price_not_invoiced:sum") + res = super().read_group( + domain, + fields, + groupby, + offset=offset, + limit=limit, + orderby=orderby, + lazy=lazy, + ) + qty_not_inv = "quantity_not_invoiced:sum" in aux_fields + price_not_inv = "price_not_invoiced:sum" in aux_fields + if qty_not_inv or price_not_inv: + for line in res: + quantity = 0.0 + price = 0.0 + moves = self.search(line.get("__domain", domain)) + for move in moves: + quantity += move.quantity_not_invoiced if qty_not_inv else 0.0 + price += move.price_not_invoiced if price_not_inv else 0.0 + line["quantity_not_invoiced"] = quantity + line["price_not_invoiced"] = price + return res + + def _get_model_id_origin_document(self): + if not self.sale_line_id: + return + return self.sale_line_id.order_id._name, self.sale_line_id.order_id.id + + def open_origin_document(self): + model, res_id = self._get_model_id_origin_document() + return { + "type": "ir.actions.act_window", + "views": [(False, "form")], + "view_mode": "form", + "res_model": model, + "res_id": res_id, + "context": self.env.context, + } diff --git a/account_sale_stock_report_non_billed/readme/CONTRIBUTORS.rst b/account_sale_stock_report_non_billed/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..bd8c9d93 --- /dev/null +++ b/account_sale_stock_report_non_billed/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Tecnativa `_: + + * Carlos Roca + * Pedro M. Baeza diff --git a/account_sale_stock_report_non_billed/readme/DESCRIPTION.rst b/account_sale_stock_report_non_billed/readme/DESCRIPTION.rst new file mode 100644 index 00000000..348add3b --- /dev/null +++ b/account_sale_stock_report_non_billed/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +Module to allow list stock moves that have not being invoiced yet, by adding a wizard +that supports show the pickings not invoiced at a specific date. diff --git a/account_sale_stock_report_non_billed/readme/USAGE.rst b/account_sale_stock_report_non_billed/readme/USAGE.rst new file mode 100644 index 00000000..0d477b84 --- /dev/null +++ b/account_sale_stock_report_non_billed/readme/USAGE.rst @@ -0,0 +1,6 @@ +To use this module, you need to: + +#. Go to `Invicing > Reporting > Non Billed Stock Moves`. +#. Select a concrete date. +#. The stock moves created before this date with quantity to be invoiced, are being + showed at the tree view. diff --git a/account_sale_stock_report_non_billed/static/description/index.html b/account_sale_stock_report_non_billed/static/description/index.html new file mode 100644 index 00000000..3c2d4975 --- /dev/null +++ b/account_sale_stock_report_non_billed/static/description/index.html @@ -0,0 +1,437 @@ + + + + + + +Account Sale Stock Report Non Billed + + + +
+

Account Sale Stock Report Non Billed

+ + +

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

+

Module to allow list stock moves that have not being invoiced yet, by adding a wizard +that supports show the pickings not invoiced at a specific date.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to Invicing > Reporting > Non Billed Stock Moves.
  2. +
  3. Select a concrete date.
  4. +
  5. The stock moves created before this date with quantity to be invoiced, are being +showed at the tree view.
  6. +
+
+
+

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

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+
    +
  • Tecnativa:
      +
    • Carlos Roca
    • +
    • Pedro M. Baeza
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

CarlosRoca13

+

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

+

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

+
+
+
+ + diff --git a/account_sale_stock_report_non_billed/tests/__init__.py b/account_sale_stock_report_non_billed/tests/__init__.py new file mode 100644 index 00000000..aaeba002 --- /dev/null +++ b/account_sale_stock_report_non_billed/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_sale_stock_report_non_billed diff --git a/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py b/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py new file mode 100644 index 00000000..9cd2e98f --- /dev/null +++ b/account_sale_stock_report_non_billed/tests/test_account_sale_stock_report_non_billed.py @@ -0,0 +1,209 @@ +# Copyright 2022 Tecnativa - Carlos Roca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import fields +from odoo.tests import Form + +from odoo.addons.stock_picking_invoice_link.tests.test_stock_picking_invoice_link import ( + TestStockPickingInvoiceLink, +) + + +class TestAccountSaleStrockReportNonBilled(TestStockPickingInvoiceLink): + def setUp(self): + super().setUp() + self.prod_order.invoice_policy = "delivery" + + def get_picking_done_so(self): + picking = self.so.picking_ids.filtered( + lambda x: x.picking_type_code == "outgoing" + and x.state in ("confirmed", "assigned", "partially_available") + ) + picking.move_line_ids.write({"qty_done": 2}) + picking.action_done() + return picking + + def test_01_report_move_not_invoiced(self): + pick_1 = self.get_picking_done_so() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in pick_1.move_lines: + self.assertIn(move.id, domain_ids) + + def test_02_report_move_full_invoiced(self): + pick_1 = self.get_picking_done_so() + inv = self.so._create_invoices() + inv.action_post() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in pick_1.move_lines: + self.assertNotIn(move.id, domain_ids) + + def test_03_report_move_partially_invoiced(self): + # First done just one move + invoice + picking = self.so.picking_ids.filtered( + lambda x: x.picking_type_code == "outgoing" + and x.state in ("confirmed", "assigned", "partially_available") + ) + move_done = picking.move_lines[0] + moves_not_done = picking.move_lines[1:] + move_done.move_line_ids.write({"qty_done": 2}) + picking.action_done() + inv = self.so._create_invoices() + inv.action_post() + # Done other moves to appear at report + self.get_picking_done_so() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + self.assertNotIn(move_done.id, domain_ids) + for move in moves_not_done: + self.assertIn(move.id, domain_ids) + + def test_04_report_move_full_invoice_refund(self): + pick_1 = self.get_picking_done_so() + inv = self.so._create_invoices() + inv.action_post() + # Refund invoice + wiz_invoice_refund = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=inv.ids) + .create({"refund_method": "cancel", "reason": "test"}) + ) + wiz_invoice_refund.reverse_moves() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in pick_1.move_lines: + self.assertIn(move.id, domain_ids) + + def test_05_report_move_full_return_no_invoiced(self): + picking = self.get_picking_done_so() + wiz_return_form = Form( + self.env["stock.return.picking"].with_context( + active_model="stock.picking", active_id=picking.id + ) + ) + wiz_return = wiz_return_form.save() + return_id = wiz_return.create_returns()["res_id"] + picking_return = self.env["stock.picking"].browse(return_id) + picking_return.move_line_ids.write({"qty_done": 2}) + picking_return.action_done() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in picking.move_lines: + self.assertNotIn(move.id, domain_ids) + for move in picking_return.move_lines: + self.assertNotIn(move.id, domain_ids) + + def test_06_report_move_full_return_invoiced(self): + picking = self.get_picking_done_so() + inv = self.so._create_invoices() + inv.action_post() + wiz_return_form = Form( + self.env["stock.return.picking"].with_context( + active_model="stock.picking", active_id=picking.id + ) + ) + wiz_return = wiz_return_form.save() + return_id = wiz_return.create_returns()["res_id"] + picking_return = self.env["stock.picking"].browse(return_id) + picking_return.move_line_ids.write({"qty_done": 2}) + picking_return.action_done() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in picking.move_lines: + self.assertNotIn(move.id, domain_ids) + for move in picking_return.move_lines: + self.assertIn(move.id, domain_ids) + inv = self.so._create_invoices(final=True) + inv.post() + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in picking_return.move_lines: + self.assertNotIn(move.id, domain_ids) + + def test_07_move_return_return_full_invoiced(self): + picking = self.get_picking_done_so() + wiz_return_form = Form( + self.env["stock.return.picking"].with_context( + active_model="stock.picking", active_id=picking.id + ) + ) + wiz_return = wiz_return_form.save() + return_id = wiz_return.create_returns()["res_id"] + picking_return = self.env["stock.picking"].browse(return_id) + picking_return.move_line_ids.write({"qty_done": 2}) + picking_return.action_done() + wiz_return_return_form = Form( + self.env["stock.return.picking"].with_context( + active_model="stock.picking", active_id=picking_return.id + ) + ) + wiz_return_return = wiz_return_return_form.save() + return_return_id = wiz_return_return.create_returns()["res_id"] + picking_return_return = self.env["stock.picking"].browse(return_return_id) + picking_return_return.move_line_ids.write({"qty_done": 2}) + picking_return_return.action_done() + self.so._create_invoices(final=True) + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in picking.move_lines: + self.assertNotIn(move.id, domain_ids) + for move in picking_return.move_lines: + self.assertNotIn(move.id, domain_ids) + for move in picking_return_return.move_lines: + self.assertNotIn(move.id, domain_ids) + + def test_08_move_return_return_non_invoiced(self): + picking = self.get_picking_done_so() + wiz_return_form = Form( + self.env["stock.return.picking"].with_context( + active_model="stock.picking", active_id=picking.id + ) + ) + wiz_return = wiz_return_form.save() + return_id = wiz_return.create_returns()["res_id"] + picking_return = self.env["stock.picking"].browse(return_id) + picking_return.move_line_ids.write({"qty_done": 2}) + picking_return.action_done() + wiz_return_return_form = Form( + self.env["stock.return.picking"].with_context( + active_model="stock.picking", active_id=picking_return.id + ) + ) + wiz_return_return = wiz_return_return_form.save() + return_return_id = wiz_return_return.create_returns()["res_id"] + picking_return_return = self.env["stock.picking"].browse(return_return_id) + picking_return_return.move_line_ids.write({"qty_done": 2}) + picking_return_return.action_done() + wiz = self.env["account.sale.stock.report.non.billed.wiz"].create( + {"date_check": fields.Date.today()} + ) + action = wiz.open_at_date() + domain_ids = action["domain"][0][2] + for move in picking.move_lines: + self.assertNotIn(move.id, domain_ids) + for move in picking_return.move_lines: + self.assertNotIn(move.id, domain_ids) + for move in picking_return_return.move_lines: + self.assertIn(move.id, domain_ids) diff --git a/account_sale_stock_report_non_billed/views/res_config_settings_views.xml b/account_sale_stock_report_non_billed/views/res_config_settings_views.xml new file mode 100644 index 00000000..a934230c --- /dev/null +++ b/account_sale_stock_report_non_billed/views/res_config_settings_views.xml @@ -0,0 +1,25 @@ + + + + + res.config.settings + + + +
+
+
+
+
+
+
+
+
+
diff --git a/account_sale_stock_report_non_billed/views/stock_move_non_billed_views.xml b/account_sale_stock_report_non_billed/views/stock_move_non_billed_views.xml new file mode 100644 index 00000000..e4efe46b --- /dev/null +++ b/account_sale_stock_report_non_billed/views/stock_move_non_billed_views.xml @@ -0,0 +1,82 @@ + + + + + stock.move + + 9999 + primary + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + + + +