From 3bd848e826225c283c6e62193ae88b050f29c702 Mon Sep 17 00:00:00 2001 From: Angel Moya Pardo Date: Thu, 10 Aug 2017 14:11:49 +0200 Subject: [PATCH 01/37] ADD contract_sale_generation module --- contract_sale_generation/README.rst | 57 +++++++++ contract_sale_generation/__init__.py | 2 + contract_sale_generation/__manifest__.py | 22 ++++ contract_sale_generation/models/__init__.py | 5 + .../models/account_analytic_account.py | 80 +++++++++++++ .../models/account_analytic_contract.py | 20 ++++ contract_sale_generation/tests/__init__.py | 5 + .../tests/test_contract_invoice.py | 87 ++++++++++++++ .../tests/test_contract_sale.py | 113 ++++++++++++++++++ .../views/account_analytic_account_view.xml | 39 ++++++ .../views/account_analytic_contract_view.xml | 15 +++ contract_sale_generation/views/sale_view.xml | 15 +++ 12 files changed, 460 insertions(+) create mode 100644 contract_sale_generation/README.rst create mode 100644 contract_sale_generation/__init__.py create mode 100644 contract_sale_generation/__manifest__.py create mode 100644 contract_sale_generation/models/__init__.py create mode 100644 contract_sale_generation/models/account_analytic_account.py create mode 100644 contract_sale_generation/models/account_analytic_contract.py create mode 100644 contract_sale_generation/tests/__init__.py create mode 100644 contract_sale_generation/tests/test_contract_invoice.py create mode 100644 contract_sale_generation/tests/test_contract_sale.py create mode 100644 contract_sale_generation/views/account_analytic_account_view.xml create mode 100644 contract_sale_generation/views/account_analytic_contract_view.xml create mode 100644 contract_sale_generation/views/sale_view.xml diff --git a/contract_sale_generation/README.rst b/contract_sale_generation/README.rst new file mode 100644 index 0000000000..dda5002294 --- /dev/null +++ b/contract_sale_generation/README.rst @@ -0,0 +1,57 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============================= +Contracts for recurrent sales +============================= + +This module extends functionality of contracts to be able to generate sales +orders instead of invoices. + +Usage +===== + +To use this module, you need to: + +#. Go to Accounting -> Contracts and select or create a new contract. +#. Check *Generate recurring invoices automatically*. +#. Fill fields for selecting the recurrency and invoice parameters: + + * Type defines document that contract will generate, can be "Sales" or "Invoices" + * Sale Autoconfirm, validate Sales Orders if type is "Sales" + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/110/10.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. + +Credits +======= + +Contributors +------------ + +* Angel Moya + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/contract_sale_generation/__init__.py b/contract_sale_generation/__init__.py new file mode 100644 index 0000000000..a0fdc10fe1 --- /dev/null +++ b/contract_sale_generation/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import models diff --git a/contract_sale_generation/__manifest__.py b/contract_sale_generation/__manifest__.py new file mode 100644 index 0000000000..072fa46147 --- /dev/null +++ b/contract_sale_generation/__manifest__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Pesol () +# Copyright 2017 Angel Moya +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + + +{ + 'name': 'Contracts Management - Recurring Sales', + 'version': '10.0.1.0.0', + 'category': 'Contract Management', + 'license': 'AGPL-3', + 'author': "PESOL, " + "Odoo Community Association (OCA)", + 'website': 'https://github.com/oca/contract', + 'depends': ['contract', 'sale'], + 'data': [ + 'views/account_analytic_account_view.xml', + 'views/account_analytic_contract_view.xml', + 'views/sale_view.xml', + ], + 'installable': True, +} diff --git a/contract_sale_generation/models/__init__.py b/contract_sale_generation/models/__init__.py new file mode 100644 index 0000000000..a3782ea728 --- /dev/null +++ b/contract_sale_generation/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import account_analytic_contract +from . import account_analytic_account diff --git a/contract_sale_generation/models/account_analytic_account.py b/contract_sale_generation/models/account_analytic_account.py new file mode 100644 index 0000000000..b29b4afd0c --- /dev/null +++ b/contract_sale_generation/models/account_analytic_account.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# © 2004-2010 OpenERP SA +# © 2014 Angel Moya +# © 2015 Pedro M. Baeza +# © 2016 Carlos Dauden +# Copyright 2016-2017 LasLabs Inc. +# Copyright 2017 Pesol () +# Copyright 2017 Angel Moya +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models +from odoo.exceptions import ValidationError +from odoo.tools.translate import _ + + +class AccountAnalyticAccount(models.Model): + _inherit = 'account.analytic.account' + + @api.model + def _prepare_sale_line(self, line, order_id): + sale_line = self.env['sale.order.line'].new({ + 'order_id': order_id, + 'product_id': line.product_id.id, + 'proudct_uom_qty': line.quantity, + 'proudct_uom_id': line.uom_id.id, + }) + # Get other invoice line values from product onchange + sale_line.product_id_change() + sale_line_vals = sale_line._convert_to_write(sale_line._cache) + # Insert markers + name = line.name + contract = line.analytic_account_id + if 'old_date' in self.env.context and 'next_date' in self.env.context: + lang_obj = self.env['res.lang'] + lang = lang_obj.search( + [('code', '=', contract.partner_id.lang)]) + date_format = lang.date_format or '%m/%d/%Y' + name = self._insert_markers( + line, self.env.context['old_date'], + self.env.context['next_date'], date_format) + sale_line_vals.update({ + 'name': name, + 'discount': line.discount, + 'price_unit': line.price_unit, + }) + return sale_line_vals + + @api.multi + def _prepare_sale(self): + self.ensure_one() + if not self.partner_id: + raise ValidationError( + _("You must first select a Customer for Contract %s!") % + self.name) + sale = self.env['sale.order'].new({ + 'partner_id': self.partner_id, + 'date_order': self.recurring_next_date, + 'origin': self.name, + 'company_id': self.company_id.id, + 'user_id': self.partner_id.user_id.id, + 'project_id': self.id + }) + # Get other invoice values from partner onchange + sale.onchange_partner_id() + return sale._convert_to_write(sale._cache) + + @api.multi + def _create_invoice(self): + self.ensure_one() + if self.type == 'invoice': + return super(AccountAnalyticAccount, self)._create_invoice() + else: + sale_vals = self._prepare_sale() + sale = self.env['sale.order'].create(sale_vals) + for line in self.recurring_invoice_line_ids: + sale_line_vals = self._prepare_sale_line(line, sale.id) + self.env['sale.order.line'].create(sale_line_vals) + if self.sale_autoconfirm: + sale.action_confirm() + return sale diff --git a/contract_sale_generation/models/account_analytic_contract.py b/contract_sale_generation/models/account_analytic_contract.py new file mode 100644 index 0000000000..2db200daab --- /dev/null +++ b/contract_sale_generation/models/account_analytic_contract.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Pesol () +# Copyright 2017 Angel Moya +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class AccountAnalyticContract(models.Model): + _inherit = 'account.analytic.contract' + + type = fields.Selection( + string='Type', + selection=[('invoice', 'Invoice'), + ('sale', 'Sale')], + default='invoice', + required=True, + ) + sale_autoconfirm = fields.Boolean( + string='Sale autoconfirm') diff --git a/contract_sale_generation/tests/__init__.py b/contract_sale_generation/tests/__init__.py new file mode 100644 index 0000000000..dc292d5e39 --- /dev/null +++ b/contract_sale_generation/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_contract_invoice +from . import test_contract_sale diff --git a/contract_sale_generation/tests/test_contract_invoice.py b/contract_sale_generation/tests/test_contract_invoice.py new file mode 100644 index 0000000000..5974b6bb7f --- /dev/null +++ b/contract_sale_generation/tests/test_contract_invoice.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# © 2016 Carlos Dauden +# Copyright 2017 Pesol () +# Copyright 2017 Angel Moya +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase + + +class TestContractInvoice(TransactionCase): + # Use case : Prepare some data for current test case + + def setUp(self): + super(TestContractInvoice, self).setUp() + self.partner = self.env.ref('base.res_partner_2') + self.product = self.env.ref('product.product_product_2') + self.product.taxes_id += self.env['account.tax'].search( + [('type_tax_use', '=', 'sale')], limit=1) + self.product.description_sale = 'Test description sale' + self.template_vals = { + 'recurring_rule_type': 'yearly', + 'recurring_interval': 1, + 'name': 'Test Contract Template', + 'type': 'invoice' + } + self.template = self.env['account.analytic.contract'].create( + self.template_vals, + ) + self.contract = self.env['account.analytic.account'].create({ + 'name': 'Test Contract', + 'partner_id': self.partner.id, + 'pricelist_id': self.partner.property_product_pricelist.id, + 'recurring_invoices': True, + 'date_start': '2016-02-15', + 'recurring_next_date': '2016-02-29', + }) + self.contract.contract_template_id = self.template + self.contract._onchange_contract_template_id() + self.contract_line = self.env['account.analytic.invoice.line'].create({ + 'analytic_account_id': self.contract.id, + 'product_id': self.product.id, + 'name': 'Services from #START# to #END#', + 'quantity': 1, + 'uom_id': self.product.uom_id.id, + 'price_unit': 100, + 'discount': 50, + }) + + def test_check_discount(self): + with self.assertRaises(ValidationError): + self.contract_line.write({'discount': 120}) + + def test_contract(self): + self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0) + res = self.contract_line._onchange_product_id() + self.assertIn('uom_id', res['domain']) + self.contract_line.price_unit = 100.0 + + self.contract.partner_id = False + with self.assertRaises(ValidationError): + self.contract.recurring_create_invoice() + self.contract.partner_id = self.partner.id + + self.contract.recurring_create_invoice() + self.invoice_monthly = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)]) + self.assertTrue(self.invoice_monthly) + self.assertEqual(self.contract.recurring_next_date, '2017-02-28') + + self.inv_line = self.invoice_monthly.invoice_line_ids[0] + self.assertTrue(self.inv_line.invoice_line_tax_ids) + self.assertAlmostEqual(self.inv_line.price_subtotal, 50.0) + self.assertEqual(self.contract.partner_id.user_id, + self.invoice_monthly.user_id) + + def test_onchange_contract_template_id(self): + """ It should change the contract values to match the template. """ + self.contract.contract_template_id = self.template + self.contract._onchange_contract_template_id() + res = { + 'recurring_rule_type': self.contract.recurring_rule_type, + 'recurring_interval': self.contract.recurring_interval, + 'type': 'invoice' + } + del self.template_vals['name'] + self.assertDictEqual(res, self.template_vals) diff --git a/contract_sale_generation/tests/test_contract_sale.py b/contract_sale_generation/tests/test_contract_sale.py new file mode 100644 index 0000000000..02aacac5c1 --- /dev/null +++ b/contract_sale_generation/tests/test_contract_sale.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# © 2016 Carlos Dauden +# Copyright 2017 Pesol () +# Copyright 2017 Angel Moya +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase + + +class TestContractSale(TransactionCase): + # Use case : Prepare some data for current test case + + def setUp(self): + super(TestContractSale, self).setUp() + self.partner = self.env.ref('base.res_partner_2') + self.product = self.env.ref('product.product_product_2') + self.product.taxes_id += self.env['account.tax'].search( + [('type_tax_use', '=', 'sale')], limit=1) + self.product.description_sale = 'Test description sale' + self.template_vals = { + 'recurring_rule_type': 'yearly', + 'recurring_interval': 1, + 'name': 'Test Contract Template', + 'type': 'sale', + 'sale_autoconfirm': False + } + self.template = self.env['account.analytic.contract'].create( + self.template_vals, + ) + self.contract = self.env['account.analytic.account'].create({ + 'name': 'Test Contract', + 'partner_id': self.partner.id, + 'pricelist_id': self.partner.property_product_pricelist.id, + 'recurring_invoices': True, + 'date_start': '2016-02-15', + 'recurring_next_date': '2016-02-29', + }) + self.contract.contract_template_id = self.template + self.contract._onchange_contract_template_id() + self.contract_line = self.env['account.analytic.invoice.line'].create({ + 'analytic_account_id': self.contract.id, + 'product_id': self.product.id, + 'name': 'Services from #START# to #END#', + 'quantity': 1, + 'uom_id': self.product.uom_id.id, + 'price_unit': 100, + 'discount': 50, + }) + + def test_check_discount(self): + with self.assertRaises(ValidationError): + self.contract_line.write({'discount': 120}) + + def test_contract(self): + self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0) + res = self.contract_line._onchange_product_id() + self.assertIn('uom_id', res['domain']) + self.contract_line.price_unit = 100.0 + + self.contract.partner_id = False + with self.assertRaises(ValidationError): + self.contract.recurring_create_invoice() + self.contract.partner_id = self.partner.id + + self.contract.recurring_create_invoice() + self.sale_monthly = self.env['sale.order'].search( + [('project_id', '=', self.contract.id), + ('state', '=', 'draft')]) + self.assertTrue(self.sale_monthly) + self.assertEqual(self.contract.recurring_next_date, '2017-02-28') + + self.sale_line = self.sale_monthly.order_line[0] + self.assertAlmostEqual(self.sale_line.price_subtotal, 50.0) + self.assertEqual(self.contract.partner_id.user_id, + self.sale_monthly.user_id) + + def test_contract_autoconfirm(self): + self.contract.sale_autoconfirm = True + self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0) + res = self.contract_line._onchange_product_id() + self.assertIn('uom_id', res['domain']) + self.contract_line.price_unit = 100.0 + + self.contract.partner_id = False + with self.assertRaises(ValidationError): + self.contract.recurring_create_invoice() + self.contract.partner_id = self.partner.id + + self.contract.recurring_create_invoice() + self.sale_monthly = self.env['sale.order'].search( + [('project_id', '=', self.contract.id), + ('state', '=', 'sale')]) + self.assertTrue(self.sale_monthly) + self.assertEqual(self.contract.recurring_next_date, '2017-02-28') + + self.sale_line = self.sale_monthly.order_line[0] + self.assertAlmostEqual(self.sale_line.price_subtotal, 50.0) + self.assertEqual(self.contract.partner_id.user_id, + self.sale_monthly.user_id) + + def test_onchange_contract_template_id(self): + """ It should change the contract values to match the template. """ + self.contract.contract_template_id = self.template + self.contract._onchange_contract_template_id() + res = { + 'recurring_rule_type': self.contract.recurring_rule_type, + 'recurring_interval': self.contract.recurring_interval, + 'type': 'sale', + 'sale_autoconfirm': False + } + del self.template_vals['name'] + self.assertDictEqual(res, self.template_vals) diff --git a/contract_sale_generation/views/account_analytic_account_view.xml b/contract_sale_generation/views/account_analytic_account_view.xml new file mode 100644 index 0000000000..9157863392 --- /dev/null +++ b/contract_sale_generation/views/account_analytic_account_view.xml @@ -0,0 +1,39 @@ + + + + + account.analytic.account.invoice.recurring.sale.form + account.analytic.account + + + + + + + + {'invisible': ['|',('recurring_invoices','!=',True),('type','!=','invoice')]} + + + + + + + + diff --git a/contract_sale_generation/views/contract_template.xml b/contract_sale_generation/views/contract_template.xml new file mode 100644 index 0000000000..9a4707c5a7 --- /dev/null +++ b/contract_sale_generation/views/contract_template.xml @@ -0,0 +1,14 @@ + + + + contract.template form view (in contract) + contract.template + + + + + + + + + diff --git a/contract_sale_generation/views/sale_view.xml b/contract_sale_generation/views/sale_view.xml deleted file mode 100644 index e23bded0b2..0000000000 --- a/contract_sale_generation/views/sale_view.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - {'search_default_project_id': - [active_id], - 'default_project_id': active_id} - - Sales - sale.order - - - - - From 757b407afdff6b2b3c491651da74894c08e0d53f Mon Sep 17 00:00:00 2001 From: Eder Brito Date: Fri, 6 Nov 2020 05:25:10 +0000 Subject: [PATCH 12/37] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (15 of 15 strings) Translation: contract-12.0/contract-12.0-contract_sale_generation Translate-URL: https://translation.odoo-community.org/projects/contract-12-0/contract-12-0-contract_sale_generation/pt_BR/ --- contract_sale_generation/i18n/de.po | 2 -- contract_sale_generation/i18n/es.po | 2 -- contract_sale_generation/i18n/fi.po | 2 -- contract_sale_generation/i18n/fr.po | 2 -- contract_sale_generation/i18n/gl.po | 2 -- contract_sale_generation/i18n/hr.po | 2 -- contract_sale_generation/i18n/pt_BR.po | 39 ++++++++++++++------------ contract_sale_generation/i18n/ru.po | 1 - contract_sale_generation/i18n/tr.po | 2 -- 9 files changed, 21 insertions(+), 33 deletions(-) diff --git a/contract_sale_generation/i18n/de.po b/contract_sale_generation/i18n/de.po index 948c7f1985..45208dab37 100644 --- a/contract_sale_generation/i18n/de.po +++ b/contract_sale_generation/i18n/de.po @@ -81,7 +81,6 @@ msgstr "Verkaufsaufträge" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "automatisches Bestätigen der Verkaufsaufträge" @@ -93,7 +92,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Verkäufe" diff --git a/contract_sale_generation/i18n/es.po b/contract_sale_generation/i18n/es.po index c8f184613b..3d0592741d 100644 --- a/contract_sale_generation/i18n/es.po +++ b/contract_sale_generation/i18n/es.po @@ -81,7 +81,6 @@ msgstr "Venta" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "Autoconfirmar venta" @@ -93,7 +92,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Ventas" diff --git a/contract_sale_generation/i18n/fi.po b/contract_sale_generation/i18n/fi.po index eba320656d..c45918938b 100644 --- a/contract_sale_generation/i18n/fi.po +++ b/contract_sale_generation/i18n/fi.po @@ -81,7 +81,6 @@ msgstr "Myynti" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "Myynnin automaattivahvistus" @@ -93,7 +92,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Myynnit" diff --git a/contract_sale_generation/i18n/fr.po b/contract_sale_generation/i18n/fr.po index 28a98b15c2..d471ccb70a 100644 --- a/contract_sale_generation/i18n/fr.po +++ b/contract_sale_generation/i18n/fr.po @@ -81,7 +81,6 @@ msgstr "Vente" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "Confirmation automatique des commandes" @@ -93,7 +92,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Ventes" diff --git a/contract_sale_generation/i18n/gl.po b/contract_sale_generation/i18n/gl.po index 0e1e152c88..435c880ac2 100644 --- a/contract_sale_generation/i18n/gl.po +++ b/contract_sale_generation/i18n/gl.po @@ -81,7 +81,6 @@ msgstr "Venda" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "Autoconfirmar venda" @@ -93,7 +92,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Vendas" diff --git a/contract_sale_generation/i18n/hr.po b/contract_sale_generation/i18n/hr.po index 1907cd897a..8ccef407b0 100644 --- a/contract_sale_generation/i18n/hr.po +++ b/contract_sale_generation/i18n/hr.po @@ -82,7 +82,6 @@ msgstr "Prodaja" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "Automatski potvrdi ponude" @@ -94,7 +93,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Prodaje" diff --git a/contract_sale_generation/i18n/pt_BR.po b/contract_sale_generation/i18n/pt_BR.po index f8485a3420..451ef6f645 100644 --- a/contract_sale_generation/i18n/pt_BR.po +++ b/contract_sale_generation/i18n/pt_BR.po @@ -10,40 +10,41 @@ msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-04-03 12:19+0000\n" -"PO-Revision-Date: 2018-04-03 12:19+0000\n" -"Last-Translator: Albert Vonpupp , 2017\n" -"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/" -"teams/23907/pt_BR/)\n" +"PO-Revision-Date: 2020-11-06 08:08+0000\n" +"Last-Translator: Eder Brito \n" +"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/teams/" +"23907/pt_BR/)\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" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.10\n" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_abstract_contract msgid "Abstract Recurring Contract" -msgstr "" +msgstr "Contrato Recorrente Abstrato" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form msgid "CREATE SALES" -msgstr "" +msgstr "CRIAR VENDAS" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_contract msgid "Contract" -msgstr "" +msgstr "Contrato" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_line msgid "Contract Line" -msgstr "" +msgstr "Linha do Contrato" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_sale_order_line__contract_line_id msgid "Contract Line to replace" -msgstr "" +msgstr "Linha do Contrato para substituir" #. module: contract_sale_generation #: code:addons/contract_sale_generation/models/contract.py:79 @@ -52,13 +53,15 @@ msgid "" "Contract manually sale order: Sale Order" msgstr "" +"Contratar pedido de venda manual: Pedido de Venda" #. module: contract_sale_generation #: model:ir.actions.server,name:contract_sale_generation.contract_cron_for_sale_ir_actions_server #: model:ir.cron,cron_name:contract_sale_generation.contract_cron_for_sale #: model:ir.cron,name:contract_sale_generation.contract_cron_for_sale msgid "Generate Recurring sales from Contracts" -msgstr "" +msgstr "Gerar vendas recorrentes a partir de Contratos" #. module: contract_sale_generation #: selection:contract.abstract.contract,type:0 @@ -69,42 +72,42 @@ msgstr "Fatura" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form msgid "Recurring Sales/Invoicing" -msgstr "" +msgstr "Vendas/Faturas Recorrentes" #. module: contract_sale_generation #: selection:contract.abstract.contract,type:0 #: selection:contract.contract,type:0 selection:contract.template,type:0 msgid "Sale" -msgstr "" +msgstr "Venda" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_abstract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm msgid "Sale Autoconfirm" -msgstr "" +msgstr "Autoconfirmar Venda" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_count msgid "Sale Count" -msgstr "" +msgstr "Contagem de Venda" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form msgid "Sales Order" -msgstr "" +msgstr "Pedidos de Venda" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_sale_order_line msgid "Sales Order Line" -msgstr "" +msgstr "Linhas dos Pedidos de Venda" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_abstract_contract__type #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__type #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__type msgid "Type" -msgstr "" +msgstr "Tipo" #~ msgid "Analytic Account" #~ msgstr "Conta Analítica" diff --git a/contract_sale_generation/i18n/ru.po b/contract_sale_generation/i18n/ru.po index aebad3f2ff..f6009cd0e3 100644 --- a/contract_sale_generation/i18n/ru.po +++ b/contract_sale_generation/i18n/ru.po @@ -93,7 +93,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Продажи" diff --git a/contract_sale_generation/i18n/tr.po b/contract_sale_generation/i18n/tr.po index 5c20def0c8..3b9e81b021 100644 --- a/contract_sale_generation/i18n/tr.po +++ b/contract_sale_generation/i18n/tr.po @@ -80,7 +80,6 @@ msgstr "Satış" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm #, fuzzy -#| msgid "Sale autoconfirm" msgid "Sale Autoconfirm" msgstr "Satış otomatik onaylama" @@ -92,7 +91,6 @@ msgstr "" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form #, fuzzy -#| msgid "Sales" msgid "Sales Order" msgstr "Satışlar" From 875b5e65b6321dbc4738a0d68ca6bbdbf7e4a971 Mon Sep 17 00:00:00 2001 From: Florent THOMAS Date: Sat, 2 Jan 2021 21:44:43 +0100 Subject: [PATCH 13/37] add display type in default values --- contract_sale_generation/models/contract_line.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contract_sale_generation/models/contract_line.py b/contract_sale_generation/models/contract_line.py index 02dd76ad1d..d75351654f 100644 --- a/contract_sale_generation/models/contract_line.py +++ b/contract_sale_generation/models/contract_line.py @@ -19,6 +19,7 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): 'uom_id': self.uom_id.id, 'discount': self.discount, 'contract_line_id': self.id, + 'display_type': self.display_type, } if order_id: sale_line_vals['order_id'] = order_id.id From 34801b1f7339f6ba8001003fe88c1a674810f69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= Date: Mon, 4 Jan 2021 09:56:16 +0000 Subject: [PATCH 14/37] Translated using Weblate (French) Currently translated at 100.0% (15 of 15 strings) Translation: contract-12.0/contract-12.0-contract_sale_generation Translate-URL: https://translation.odoo-community.org/projects/contract-12-0/contract-12-0-contract_sale_generation/fr/ --- contract_sale_generation/__manifest__.py | 2 +- contract_sale_generation/i18n/fr.po | 31 ++++++++++++------------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/contract_sale_generation/__manifest__.py b/contract_sale_generation/__manifest__.py index 0c68fd6486..f4f5df03f7 100644 --- a/contract_sale_generation/__manifest__.py +++ b/contract_sale_generation/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Contracts Management - Recurring Sales', - 'version': '12.0.1.0.0', + 'version': '12.0.1.0.1', 'category': 'Contract Management', 'license': 'AGPL-3', 'author': "PESOL, " diff --git a/contract_sale_generation/i18n/fr.po b/contract_sale_generation/i18n/fr.po index d471ccb70a..24e94ddef4 100644 --- a/contract_sale_generation/i18n/fr.po +++ b/contract_sale_generation/i18n/fr.po @@ -10,39 +10,40 @@ msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-05-19 02:01+0000\n" -"PO-Revision-Date: 2018-05-19 02:01+0000\n" -"Last-Translator: Fabien Bourgeois , 2018\n" +"PO-Revision-Date: 2021-01-04 11:44+0000\n" +"Last-Translator: Rémi \n" "Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" "Language: fr\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" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.3.2\n" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_abstract_contract msgid "Abstract Recurring Contract" -msgstr "" +msgstr "Base pour les contrats récurrents" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form msgid "CREATE SALES" -msgstr "" +msgstr "CRÉER LES COMMANDES" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_contract msgid "Contract" -msgstr "" +msgstr "Contrat" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_line msgid "Contract Line" -msgstr "" +msgstr "Ligne de Contrat" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_sale_order_line__contract_line_id msgid "Contract Line to replace" -msgstr "" +msgstr "Ligne de contrat à remplacer" #. module: contract_sale_generation #: code:addons/contract_sale_generation/models/contract.py:79 @@ -51,13 +52,15 @@ msgid "" "Contract manually sale order: Sale Order" msgstr "" +"Création manuelle de la commande depuis le contrat : Commande" #. module: contract_sale_generation #: model:ir.actions.server,name:contract_sale_generation.contract_cron_for_sale_ir_actions_server #: model:ir.cron,cron_name:contract_sale_generation.contract_cron_for_sale #: model:ir.cron,name:contract_sale_generation.contract_cron_for_sale msgid "Generate Recurring sales from Contracts" -msgstr "" +msgstr "Générer les ventes récurrentes depuis les Contrats" #. module: contract_sale_generation #: selection:contract.abstract.contract,type:0 @@ -68,7 +71,7 @@ msgstr "Facture" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form msgid "Recurring Sales/Invoicing" -msgstr "" +msgstr "Commandes / Factures Récurrentes" #. module: contract_sale_generation #: selection:contract.abstract.contract,type:0 @@ -80,25 +83,23 @@ msgstr "Vente" #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_abstract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_autoconfirm #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__sale_autoconfirm -#, fuzzy msgid "Sale Autoconfirm" msgstr "Confirmation automatique des commandes" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_count msgid "Sale Count" -msgstr "" +msgstr "Nombre de Commandes" #. module: contract_sale_generation #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form -#, fuzzy msgid "Sales Order" -msgstr "Ventes" +msgstr "Commandes" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_sale_order_line msgid "Sales Order Line" -msgstr "" +msgstr "Ligne de commande" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_abstract_contract__type From 599773c92400bfd532bbc61ff9170972f6f5fda4 Mon Sep 17 00:00:00 2001 From: Mkxm Awilix Date: Wed, 27 Jan 2021 10:15:39 +0100 Subject: [PATCH 15/37] [12.0][FIX] contract: Incorrect product UOM qty dict key for the sale.order.line The product UOM qty was not correctly set on the Sale Order Line During the creation of a recurring Order from a Contract, the given quantity on the Contract Line was not correctly set on the created Sale Order Line. --- contract_sale_generation/__manifest__.py | 2 +- contract_sale_generation/models/contract_line.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contract_sale_generation/__manifest__.py b/contract_sale_generation/__manifest__.py index f4f5df03f7..2dd931b40b 100644 --- a/contract_sale_generation/__manifest__.py +++ b/contract_sale_generation/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Contracts Management - Recurring Sales', - 'version': '12.0.1.0.1', + 'version': '12.0.1.0.2', 'category': 'Contract Management', 'license': 'AGPL-3', 'author': "PESOL, " diff --git a/contract_sale_generation/models/contract_line.py b/contract_sale_generation/models/contract_line.py index d75351654f..bdb571fe05 100644 --- a/contract_sale_generation/models/contract_line.py +++ b/contract_sale_generation/models/contract_line.py @@ -15,7 +15,7 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): ) sale_line_vals = { 'product_id': self.product_id.id, - 'quantity': self._get_quantity_to_invoice(*dates), + 'product_uom_qty': self._get_quantity_to_invoice(*dates), 'uom_id': self.uom_id.id, 'discount': self.discount, 'contract_line_id': self.id, From 781328f29ba051a022ae152694d40bf59fe5218c Mon Sep 17 00:00:00 2001 From: Freni-OSI Date: Wed, 7 Apr 2021 16:41:41 +0530 Subject: [PATCH 16/37] [14.0][FIX] Travis --- contract_sale_generation/__init__.py | 1 - contract_sale_generation/__manifest__.py | 25 ++- .../data/contract_cron.xml | 6 +- .../models/abstract_contract.py | 12 +- contract_sale_generation/models/contract.py | 76 ++++--- .../models/contract_line.py | 44 ++-- .../models/sale_order_line.py | 4 +- .../readme/DESCRIPTION.rst | 2 +- .../tests/test_contract_sale.py | 202 +++++++++--------- contract_sale_generation/views/contract.xml | 68 +++--- .../views/contract_template.xml | 4 +- 11 files changed, 231 insertions(+), 213 deletions(-) diff --git a/contract_sale_generation/__init__.py b/contract_sale_generation/__init__.py index a9e3372262..0650744f6b 100644 --- a/contract_sale_generation/__init__.py +++ b/contract_sale_generation/__init__.py @@ -1,2 +1 @@ - from . import models diff --git a/contract_sale_generation/__manifest__.py b/contract_sale_generation/__manifest__.py index 2dd931b40b..053a252392 100644 --- a/contract_sale_generation/__manifest__.py +++ b/contract_sale_generation/__manifest__.py @@ -4,18 +4,17 @@ { - 'name': 'Contracts Management - Recurring Sales', - 'version': '12.0.1.0.2', - 'category': 'Contract Management', - 'license': 'AGPL-3', - 'author': "PESOL, " - "Odoo Community Association (OCA)", - 'website': 'https://github.com/oca/contract', - 'depends': ['contract', 'sale'], - 'data': [ - 'data/contract_cron.xml', - 'views/contract.xml', - 'views/contract_template.xml', + "name": "Contracts Management - Recurring Sales", + "version": "14.0.1.0.0", + "category": "Contract Management", + "license": "AGPL-3", + "author": "PESOL, " "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/contract", + "depends": ["contract", "sale"], + "data": [ + "data/contract_cron.xml", + "views/contract.xml", + "views/contract_template.xml", ], - 'installable': True, + "installable": True, } diff --git a/contract_sale_generation/data/contract_cron.xml b/contract_sale_generation/data/contract_cron.xml index 841f529711..c2f206dc16 100644 --- a/contract_sale_generation/data/contract_cron.xml +++ b/contract_sale_generation/data/contract_cron.xml @@ -1,8 +1,7 @@ - - + Generate Recurring sales from Contracts - + code model.cron_recurring_create_sale() @@ -11,5 +10,4 @@ -1 - diff --git a/contract_sale_generation/models/abstract_contract.py b/contract_sale_generation/models/abstract_contract.py index bda9742c10..e5c4a60c32 100644 --- a/contract_sale_generation/models/abstract_contract.py +++ b/contract_sale_generation/models/abstract_contract.py @@ -6,14 +6,12 @@ class ContractAbstractContract(models.AbstractModel): - _inherit = 'contract.abstract.contract' + _inherit = "contract.abstract.contract" type = fields.Selection( - [('invoice', 'Invoice'), - ('sale', 'Sale')], - string='Type', - default='invoice', + [("invoice", "Invoice"), ("sale", "Sale")], + string="Type", + default="invoice", required=True, ) - sale_autoconfirm = fields.Boolean( - string='Sale Autoconfirm') + sale_autoconfirm = fields.Boolean(string="Sale Autoconfirm") diff --git a/contract_sale_generation/models/contract.py b/contract_sale_generation/models/contract.py index 17c622d12a..d8d966e5d6 100644 --- a/contract_sale_generation/models/contract.py +++ b/contract_sale_generation/models/contract.py @@ -8,24 +8,26 @@ # Copyright 2018 Therp BV . # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models class ContractContract(models.Model): - _inherit = 'contract.contract' + _inherit = "contract.contract" sale_count = fields.Integer(compute="_compute_sale_count") @api.multi def _prepare_sale(self, date_ref): self.ensure_one() - sale = self.env['sale.order'].new({ - 'partner_id': self.partner_id, - 'date_order': fields.Date.to_string(date_ref), - 'origin': self.name, - 'company_id': self.company_id.id, - 'user_id': self.partner_id.user_id.id, - }) + sale = self.env["sale.order"].new( + { + "partner_id": self.partner_id, + "date_order": fields.Date.to_string(date_ref), + "origin": self.name, + "company_id": self.company_id.id, + "user_id": self.partner_id.user_id.id, + } + ) if self.payment_term_id: sale.payment_term_id = self.payment_term_id.id if self.fiscal_position_id: @@ -37,10 +39,11 @@ def _prepare_sale(self, date_ref): @api.multi def _get_related_sales(self): self.ensure_one() - sales = (self.env['sale.order.line'] - .search([('contract_line_id', 'in', - self.contract_line_ids.ids) - ]).mapped('order_id')) + sales = ( + self.env["sale.order.line"] + .search([("contract_line_id", "in", self.contract_line_ids.ids)]) + .mapped("order_id") + ) return sales @api.multi @@ -51,20 +54,18 @@ def _compute_sale_count(self): @api.multi def action_show_sales(self): self.ensure_one() - tree_view = self.env.ref('sale.view_order_tree', - raise_if_not_found=False) - form_view = self.env.ref('sale.view_order_form', - raise_if_not_found=False) + tree_view = self.env.ref("sale.view_order_tree", raise_if_not_found=False) + form_view = self.env.ref("sale.view_order_form", raise_if_not_found=False) action = { - 'type': 'ir.actions.act_window', - 'name': 'Sales Orders', - 'res_model': 'sale.order', - 'view_type': 'form', - 'view_mode': 'tree,kanban,form,calendar,pivot,graph,activity', - 'domain': [('id', 'in', self._get_related_sales().ids)], + "type": "ir.actions.act_window", + "name": "Sales Orders", + "res_model": "sale.order", + "view_type": "form", + "view_mode": "tree,kanban,form,calendar,pivot,graph,activity", + "domain": [("id", "in", self._get_related_sales().ids)], } if tree_view and form_view: - action['views'] = [(tree_view.id, 'tree'), (form_view.id, 'form')] + action["views"] = [(tree_view.id, "tree"), (form_view.id, "form")] return action @api.multi @@ -77,10 +78,10 @@ def recurring_create_sale(self): for sale_rec in sales: self.message_post( body=_( - 'Contract manually sale order: ' + "Contract manually sale order: " '' - 'Sale Order' - '' + "Sale Order" + "" ) % (sale_rec._name, sale_rec.id) ) @@ -107,14 +108,12 @@ def _prepare_recurring_sales_values(self, date_ref=False): continue sale_values = contract._prepare_sale(date_ref) for line in contract_lines: - sale_values.setdefault('order_line', []) + sale_values.setdefault("order_line", []) invoice_line_values = line._prepare_sale_line( sale_values=sale_values, ) if invoice_line_values: - sale_values['order_line'].append( - (0, 0, invoice_line_values) - ) + sale_values["order_line"].append((0, 0, invoice_line_values)) sales_values.append(sale_values) contract_lines._update_recurring_next_date() return sales_values @@ -123,7 +122,7 @@ def _prepare_recurring_sales_values(self, date_ref=False): def _recurring_create_sale(self, date_ref=False): sales_values = self._prepare_recurring_sales_values(date_ref) so_rec = self.env["sale.order"].create(sales_values) - for rec in self.filtered(lambda c: c.sale_autoconfirm): + for _rec in self.filtered(lambda c: c.sale_autoconfirm): so_rec.action_confirm() return so_rec @@ -132,11 +131,10 @@ def cron_recurring_create_sale(self, date_ref=None): if not date_ref: date_ref = fields.Date.context_today(self) domain = self._get_contracts_to_invoice_domain(date_ref) - domain.extend([('type', '=', 'sale')]) + domain.extend([("type", "=", "sale")]) sales = self.env["sale.order"] # Sales by companies, so assignation emails get correct context - companies_to_sale = self.read_group( - domain, ["company_id"], ["company_id"]) + companies_to_sale = self.read_group(domain, ["company_id"], ["company_id"]) for row in companies_to_sale: contracts_to_sale = self.search(row["__domain"]).with_context( allowed_company_ids=[row["company_id"][0]] @@ -149,15 +147,13 @@ def cron_recurring_create_invoice(self, date_ref=None): if not date_ref: date_ref = fields.Date.context_today(self) domain = self._get_contracts_to_invoice_domain(date_ref) - domain.extend([('type', '=', 'invoice')]) + domain.extend([("type", "=", "invoice")]) invoices = self.env["account.invoice"] # Invoice by companies, so assignation emails get correct context - companies_to_invoice = self.read_group( - domain, ["company_id"], ["company_id"]) + companies_to_invoice = self.read_group(domain, ["company_id"], ["company_id"]) for row in companies_to_invoice: contracts_to_invoice = self.search(row["__domain"]).with_context( allowed_company_ids=[row["company_id"][0]] ) - invoices |= contracts_to_invoice._recurring_create_invoice( - date_ref) + invoices |= contracts_to_invoice._recurring_create_invoice(date_ref) return invoices diff --git a/contract_sale_generation/models/contract_line.py b/contract_sale_generation/models/contract_line.py index bdb571fe05..bc9df45af3 100644 --- a/contract_sale_generation/models/contract_line.py +++ b/contract_sale_generation/models/contract_line.py @@ -5,7 +5,7 @@ class ContractLine(models.Model): - _inherit = 'contract.line' + _inherit = "contract.line" @api.multi def _prepare_sale_line(self, order_id=False, sale_values=False): @@ -14,22 +14,30 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): self.last_date_invoiced, self.recurring_next_date ) sale_line_vals = { - 'product_id': self.product_id.id, - 'product_uom_qty': self._get_quantity_to_invoice(*dates), - 'uom_id': self.uom_id.id, - 'discount': self.discount, - 'contract_line_id': self.id, - 'display_type': self.display_type, + "product_id": self.product_id.id, + "product_uom_qty": self._get_quantity_to_invoice(*dates), + "uom_id": self.uom_id.id, + "discount": self.discount, + "contract_line_id": self.id, + "display_type": self.display_type, } if order_id: - sale_line_vals['order_id'] = order_id.id - order_line = self.env['sale.order.line'].with_context( - force_company=self.contract_id.company_id.id, - ).new(sale_line_vals) - if sale_values and not order_id: - sale = self.env['sale.order'].with_context( + sale_line_vals["order_id"] = order_id.id + order_line = ( + self.env["sale.order.line"] + .with_context( force_company=self.contract_id.company_id.id, - ).new(sale_values) + ) + .new(sale_line_vals) + ) + if sale_values and not order_id: + sale = ( + self.env["sale.order"] + .with_context( + force_company=self.contract_id.company_id.id, + ) + .new(sale_values) + ) order_line.order_id = sale # Get other order line values from product onchange order_line.product_id_change() @@ -38,10 +46,10 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): name = self._insert_markers(dates[0], dates[1]) sale_line_vals.update( { - 'sequence': self.sequence, - 'name': name, - 'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)], - 'price_unit': self.price_unit, + "sequence": self.sequence, + "name": name, + "analytic_tag_ids": [(6, 0, self.analytic_tag_ids.ids)], + "price_unit": self.price_unit, } ) return sale_line_vals diff --git a/contract_sale_generation/models/sale_order_line.py b/contract_sale_generation/models/sale_order_line.py index 08abb1332c..cb9451ce8c 100644 --- a/contract_sale_generation/models/sale_order_line.py +++ b/contract_sale_generation/models/sale_order_line.py @@ -5,8 +5,8 @@ class SaleOrderLine(models.Model): - _inherit = 'sale.order.line' + _inherit = "sale.order.line" contract_line_id = fields.Many2one( - 'contract.line', string='Contract Line', index=True + "contract.line", string="Contract Line", index=True ) diff --git a/contract_sale_generation/readme/DESCRIPTION.rst b/contract_sale_generation/readme/DESCRIPTION.rst index 2ea92d9eb8..f8ff4d1939 100644 --- a/contract_sale_generation/readme/DESCRIPTION.rst +++ b/contract_sale_generation/readme/DESCRIPTION.rst @@ -1,2 +1,2 @@ -This module extends functionality of contracts to be able to generate sales +This module extends functionality of contracts to be able to generate sales orders instead of invoices. diff --git a/contract_sale_generation/tests/test_contract_sale.py b/contract_sale_generation/tests/test_contract_sale.py index 1f83a4e933..14f8aa5ae5 100644 --- a/contract_sale_generation/tests/test_contract_sale.py +++ b/contract_sale_generation/tests/test_contract_sale.py @@ -3,8 +3,8 @@ # Copyright 2017 Angel Moya # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.exceptions import ValidationError from odoo import fields +from odoo.exceptions import ValidationError from odoo.tests.common import TransactionCase @@ -17,95 +17,95 @@ class TestContractSale(TransactionCase): def setUp(self): super(TestContractSale, self).setUp() - self.pricelist = self.env['product.pricelist'].create({ - 'name': 'pricelist for contract test', - }) - self.partner = self.env['res.partner'].create({ - 'name': 'partner test contract', - 'property_product_pricelist': self.pricelist.id, - }) - self.product_1 = self.env.ref('product.product_product_1') - self.product_1.taxes_id += self.env['account.tax'].search( - [('type_tax_use', '=', 'sale')], limit=1 + self.pricelist = self.env["product.pricelist"].create( + { + "name": "pricelist for contract test", + } + ) + self.partner = self.env["res.partner"].create( + { + "name": "partner test contract", + "property_product_pricelist": self.pricelist.id, + } ) - self.product_1.description_sale = 'Test description sale' + self.product_1 = self.env.ref("product.product_product_1") + self.product_1.taxes_id += self.env["account.tax"].search( + [("type_tax_use", "=", "sale")], limit=1 + ) + self.product_1.description_sale = "Test description sale" self.line_template_vals = { - 'product_id': self.product_1.id, - 'name': 'Test Contract Template', - 'quantity': 1, - 'uom_id': self.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'yearly', - 'recurring_interval': 1, + "product_id": self.product_1.id, + "name": "Test Contract Template", + "quantity": 1, + "uom_id": self.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "yearly", + "recurring_interval": 1, } self.template_vals = { - 'name': 'Test Contract Template', - 'contract_line_ids': [ + "name": "Test Contract Template", + "contract_line_ids": [ (0, 0, self.line_template_vals), ], } - self.template = self.env['contract.template'].create( - self.template_vals - ) + self.template = self.env["contract.template"].create(self.template_vals) # For being sure of the applied price - self.env['product.pricelist.item'].create( + self.env["product.pricelist.item"].create( { - 'pricelist_id': self.partner.property_product_pricelist.id, - 'product_id': self.product_1.id, - 'compute_price': 'formula', - 'base': 'list_price', + "pricelist_id": self.partner.property_product_pricelist.id, + "product_id": self.product_1.id, + "compute_price": "formula", + "base": "list_price", } ) - self.contract = self.env['contract.contract'].create( + self.contract = self.env["contract.contract"].create( { - 'name': 'Test Contract', - 'partner_id': self.partner.id, - 'pricelist_id': self.partner.property_product_pricelist.id, - 'type': 'sale', - 'sale_autoconfirm': False + "name": "Test Contract", + "partner_id": self.partner.id, + "pricelist_id": self.partner.property_product_pricelist.id, + "type": "sale", + "sale_autoconfirm": False, } ) self.line_vals = { - 'contract_id': self.contract.id, - 'product_id': self.product_1.id, - 'name': 'Services from #START# to #END#', - 'quantity': 1, - 'uom_id': self.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'monthly', - 'recurring_interval': 1, - 'date_start': '2020-01-01', - 'recurring_next_date': '2020-01-15', + "contract_id": self.contract.id, + "product_id": self.product_1.id, + "name": "Services from #START# to #END#", + "quantity": 1, + "uom_id": self.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "monthly", + "recurring_interval": 1, + "date_start": "2020-01-01", + "recurring_next_date": "2020-01-15", } self.contract.contract_template_id = self.template self.contract._onchange_contract_template_id() - self.contract_line = self.env['contract.line'].create( - self.line_vals - ) - self.contract2 = self.env['contract.contract'].create( + self.contract_line = self.env["contract.line"].create(self.line_vals) + self.contract2 = self.env["contract.contract"].create( { - 'name': 'Test Contract 2', - 'type': 'sale', - 'partner_id': self.partner.id, - 'pricelist_id': self.partner.property_product_pricelist.id, - 'contract_type': 'purchase', - 'contract_line_ids': [ + "name": "Test Contract 2", + "type": "sale", + "partner_id": self.partner.id, + "pricelist_id": self.partner.property_product_pricelist.id, + "contract_type": "purchase", + "contract_line_ids": [ ( 0, 0, { - 'product_id': self.product_1.id, - 'name': 'Services from #START# to #END#', - 'quantity': 1, - 'uom_id': self.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'monthly', - 'recurring_interval': 1, - 'date_start': '2018-02-15', - 'recurring_next_date': '2018-02-22', + "product_id": self.product_1.id, + "name": "Services from #START# to #END#", + "quantity": 1, + "uom_id": self.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "monthly", + "recurring_interval": 1, + "date_start": "2018-02-15", + "recurring_next_date": "2018-02-22", }, ) ], @@ -114,40 +114,36 @@ def setUp(self): def test_check_discount(self): with self.assertRaises(ValidationError): - self.contract_line.write({'discount': 120}) + self.contract_line.write({"discount": 120}) def test_contract(self): - recurring_next_date = to_date('2020-02-15') + recurring_next_date = to_date("2020-02-15") self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0) res = self.contract_line._onchange_product_id() - self.assertIn('uom_id', res['domain']) + self.assertIn("uom_id", res["domain"]) self.contract_line.price_unit = 100.0 self.contract.partner_id = self.partner.id self.contract.recurring_create_sale() self.sale_monthly = self.contract._get_related_sales() self.assertTrue(self.sale_monthly) - self.assertEqual( - self.contract_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.contract_line.recurring_next_date, recurring_next_date) self.order_line = self.sale_monthly.order_line[0] self.assertTrue(self.order_line.tax_id) self.assertAlmostEqual(self.order_line.price_subtotal, 50.0) self.assertEqual(self.contract.user_id, self.sale_monthly.user_id) def test_contract_autoconfirm(self): - recurring_next_date = to_date('2020-02-15') + recurring_next_date = to_date("2020-02-15") self.contract.sale_autoconfirm = True self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0) res = self.contract_line._onchange_product_id() - self.assertIn('uom_id', res['domain']) + self.assertIn("uom_id", res["domain"]) self.contract_line.price_unit = 100.0 self.contract.partner_id = self.partner.id self.contract.recurring_create_sale() self.sale_monthly = self.contract._get_related_sales() self.assertTrue(self.sale_monthly) - self.assertEqual( - self.contract_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.contract_line.recurring_next_date, recurring_next_date) self.order_line = self.sale_monthly.order_line[0] self.assertTrue(self.order_line.tax_id) self.assertAlmostEqual(self.order_line.price_subtotal, 50.0) @@ -160,19 +156,24 @@ def test_onchange_contract_template_id(self): self.contract.contract_template_id = self.template self.contract._onchange_contract_template_id() res = { - 'contract_line_ids': - [(0, 0, { - 'product_id': self.product_1.id, - 'name': 'Test Contract Template', - 'quantity': 1, - 'uom_id': self.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'yearly', - 'recurring_interval': 1, - })] + "contract_line_ids": [ + ( + 0, + 0, + { + "product_id": self.product_1.id, + "name": "Test Contract Template", + "quantity": 1, + "uom_id": self.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "yearly", + "recurring_interval": 1, + }, + ) + ] } - del self.template_vals['name'] + del self.template_vals["name"] self.assertDictEqual(res, self.template_vals) def test_contract_count_sale(self): @@ -183,27 +184,26 @@ def test_contract_count_sale(self): self.assertEqual(self.contract.sale_count, 3) def test_contract_count_sale_2(self): - orders = self.env['sale.order'] + orders = self.env["sale.order"] orders |= self.contract.recurring_create_sale() orders |= self.contract.recurring_create_sale() orders |= self.contract.recurring_create_sale() action = self.contract.action_show_sales() - self.assertEqual(set(action['domain'][0][2]), set(orders.ids)) + self.assertEqual(set(action["domain"][0][2]), set(orders.ids)) def test_cron_recurring_create_sale(self): - self.contract_line.date_start = '2020-01-01' - self.contract_line.recurring_invoicing_type = 'post-paid' - self.contract_line.date_end = '2020-03-15' + self.contract_line.date_start = "2020-01-01" + self.contract_line.recurring_invoicing_type = "post-paid" + self.contract_line.date_end = "2020-03-15" self.contract_line._onchange_date_start() contracts = self.contract2 for _i in range(10): - contracts |= self.contract.copy({'type': 'sale'}) - self.env['contract.contract'].cron_recurring_create_sale() - order_lines = self.env['sale.order.line'].search( - [('contract_line_id', 'in', - contracts.mapped('contract_line_ids').ids)] + contracts |= self.contract.copy({"type": "sale"}) + self.env["contract.contract"].cron_recurring_create_sale() + order_lines = self.env["sale.order.line"].search( + [("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)] ) self.assertEqual( - len(contracts.mapped('contract_line_ids')), + len(contracts.mapped("contract_line_ids")), len(order_lines), ) diff --git a/contract_sale_generation/views/contract.xml b/contract_sale_generation/views/contract.xml index 647a8906c9..a22babd61d 100644 --- a/contract_sale_generation/views/contract.xml +++ b/contract_sale_generation/views/contract.xml @@ -3,38 +3,58 @@ contract.contract.form.recurring.sale.form contract.contract - + - - - + + + - - {'invisible': ['|', ('create_invoice_visibility', '=', False),('type','!=','invoice')]} - + + {'invisible': ['|', ('create_invoice_visibility', '=', False),('type','!=','invoice')]} + - - + diff --git a/contract_sale_generation/views/contract_template.xml b/contract_sale_generation/views/contract_template.xml index 9a4707c5a7..129da21c7c 100644 --- a/contract_sale_generation/views/contract_template.xml +++ b/contract_sale_generation/views/contract_template.xml @@ -3,10 +3,10 @@ contract.template form view (in contract) contract.template - + - + From effb90a02c1b1db23607be17b383389b75a4494d Mon Sep 17 00:00:00 2001 From: Freni-OSI Date: Wed, 21 Apr 2021 13:42:13 +0530 Subject: [PATCH 17/37] [14.0][MIG] contract_sale_generation --- contract_sale_generation/__manifest__.py | 2 +- contract_sale_generation/models/contract.py | 9 +----- .../models/contract_line.py | 13 +++------ contract_sale_generation/views/contract.xml | 29 ++++++++----------- .../views/contract_template.xml | 2 -- 5 files changed, 18 insertions(+), 37 deletions(-) diff --git a/contract_sale_generation/__manifest__.py b/contract_sale_generation/__manifest__.py index 053a252392..9a492577c3 100644 --- a/contract_sale_generation/__manifest__.py +++ b/contract_sale_generation/__manifest__.py @@ -10,7 +10,7 @@ "license": "AGPL-3", "author": "PESOL, " "Odoo Community Association (OCA)", "website": "https://github.com/OCA/contract", - "depends": ["contract", "sale"], + "depends": ["contract_sale"], "data": [ "data/contract_cron.xml", "views/contract.xml", diff --git a/contract_sale_generation/models/contract.py b/contract_sale_generation/models/contract.py index d8d966e5d6..ed048091c1 100644 --- a/contract_sale_generation/models/contract.py +++ b/contract_sale_generation/models/contract.py @@ -16,7 +16,6 @@ class ContractContract(models.Model): sale_count = fields.Integer(compute="_compute_sale_count") - @api.multi def _prepare_sale(self, date_ref): self.ensure_one() sale = self.env["sale.order"].new( @@ -36,7 +35,6 @@ def _prepare_sale(self, date_ref): sale.onchange_partner_id() return sale._convert_to_write(sale._cache) - @api.multi def _get_related_sales(self): self.ensure_one() sales = ( @@ -46,12 +44,10 @@ def _get_related_sales(self): ) return sales - @api.multi def _compute_sale_count(self): for rec in self: rec.sale_count = len(rec._get_related_sales()) - @api.multi def action_show_sales(self): self.ensure_one() tree_view = self.env.ref("sale.view_order_tree", raise_if_not_found=False) @@ -68,7 +64,6 @@ def action_show_sales(self): action["views"] = [(tree_view.id, "tree"), (form_view.id, "form")] return action - @api.multi def recurring_create_sale(self): """ This method triggers the creation of the next sale order of the @@ -87,7 +82,6 @@ def recurring_create_sale(self): ) return sales - @api.multi def _prepare_recurring_sales_values(self, date_ref=False): """ This method builds the list of sales values to create, based on @@ -118,7 +112,6 @@ def _prepare_recurring_sales_values(self, date_ref=False): contract_lines._update_recurring_next_date() return sales_values - @api.multi def _recurring_create_sale(self, date_ref=False): sales_values = self._prepare_recurring_sales_values(date_ref) so_rec = self.env["sale.order"].create(sales_values) @@ -148,7 +141,7 @@ def cron_recurring_create_invoice(self, date_ref=None): date_ref = fields.Date.context_today(self) domain = self._get_contracts_to_invoice_domain(date_ref) domain.extend([("type", "=", "invoice")]) - invoices = self.env["account.invoice"] + invoices = self.env["account.move"] # Invoice by companies, so assignation emails get correct context companies_to_invoice = self.read_group(domain, ["company_id"], ["company_id"]) for row in companies_to_invoice: diff --git a/contract_sale_generation/models/contract_line.py b/contract_sale_generation/models/contract_line.py index bc9df45af3..98b3cb3522 100644 --- a/contract_sale_generation/models/contract_line.py +++ b/contract_sale_generation/models/contract_line.py @@ -1,13 +1,12 @@ # Copyright (C) 2020 Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, models +from odoo import models class ContractLine(models.Model): _inherit = "contract.line" - @api.multi def _prepare_sale_line(self, order_id=False, sale_values=False): self.ensure_one() dates = self._get_period_to_invoice( @@ -16,7 +15,7 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): sale_line_vals = { "product_id": self.product_id.id, "product_uom_qty": self._get_quantity_to_invoice(*dates), - "uom_id": self.uom_id.id, + "product_uom": self.uom_id.id, "discount": self.discount, "contract_line_id": self.id, "display_type": self.display_type, @@ -25,17 +24,13 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): sale_line_vals["order_id"] = order_id.id order_line = ( self.env["sale.order.line"] - .with_context( - force_company=self.contract_id.company_id.id, - ) + .with_company(self.contract_id.company_id.id) .new(sale_line_vals) ) if sale_values and not order_id: sale = ( self.env["sale.order"] - .with_context( - force_company=self.contract_id.company_id.id, - ) + .with_company(self.contract_id.company_id.id) .new(sale_values) ) order_line.order_id = sale diff --git a/contract_sale_generation/views/contract.xml b/contract_sale_generation/views/contract.xml index a22babd61d..7b44541622 100644 --- a/contract_sale_generation/views/contract.xml +++ b/contract_sale_generation/views/contract.xml @@ -1,5 +1,4 @@ - contract.contract.form.recurring.sale.form contract.contract @@ -7,18 +6,18 @@ - @@ -28,34 +27,30 @@ - diff --git a/contract_sale_generation/views/contract_template.xml b/contract_sale_generation/views/contract_template.xml index 129da21c7c..cf821dcdec 100644 --- a/contract_sale_generation/views/contract_template.xml +++ b/contract_sale_generation/views/contract_template.xml @@ -1,5 +1,4 @@ - contract.template form view (in contract) contract.template @@ -10,5 +9,4 @@ - From 7fd3439984835ea7520f20e1e6812b23aec1dd12 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Sun, 7 Nov 2021 10:08:41 +0100 Subject: [PATCH 18/37] [14.0][IMP] contract_sale_generation Use the generation_type field defined now in contract base module. Improve tests --- contract_sale_generation/README.rst | 14 +-- contract_sale_generation/__manifest__.py | 3 +- contract_sale_generation/models/__init__.py | 1 + .../models/abstract_contract.py | 14 +-- contract_sale_generation/models/contract.py | 40 ++------ contract_sale_generation/models/sale_order.py | 24 +++++ .../readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 10 +- .../tests/test_contract_sale.py | 97 +++++++++++-------- contract_sale_generation/views/contract.xml | 13 +-- .../views/contract_template.xml | 12 --- 11 files changed, 119 insertions(+), 110 deletions(-) create mode 100644 contract_sale_generation/models/sale_order.py delete mode 100644 contract_sale_generation/views/contract_template.xml diff --git a/contract_sale_generation/README.rst b/contract_sale_generation/README.rst index 24e5d22839..1ad37d0857 100644 --- a/contract_sale_generation/README.rst +++ b/contract_sale_generation/README.rst @@ -14,18 +14,18 @@ Contracts Management - Recurring Sales :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github - :target: https://github.com/OCA/contract/tree/12.0/contract_sale_generation + :target: https://github.com/OCA/contract/tree/14.0/contract_sale_generation :alt: OCA/contract .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/contract-12-0/contract-12-0-contract_sale_generation + :target: https://translation.odoo-community.org/projects/contract-14-0/contract-14-0-contract_sale_generation :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/110/12.0 + :target: https://runbot.odoo-community.org/runbot/110/14.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| -This module extends functionality of contracts to be able to generate sales +This module extends functionality of contracts to be able to generate sales orders instead of invoices. **Table of contents** @@ -50,7 +50,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -60,6 +60,7 @@ Credits Authors ~~~~~~~ +* ACSONE SA/NV * PESOL Contributors @@ -68,6 +69,7 @@ Contributors * Angel Moya * Florent THOMAS * Serpent Consulting Services Pvt. Ltd. +* Denis Roussel Maintainers ~~~~~~~~~~~ @@ -82,6 +84,6 @@ 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/contract `_ project on GitHub. +This module is part of the `OCA/contract `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/contract_sale_generation/__manifest__.py b/contract_sale_generation/__manifest__.py index 9a492577c3..758a23e0c7 100644 --- a/contract_sale_generation/__manifest__.py +++ b/contract_sale_generation/__manifest__.py @@ -8,13 +8,12 @@ "version": "14.0.1.0.0", "category": "Contract Management", "license": "AGPL-3", - "author": "PESOL, " "Odoo Community Association (OCA)", + "author": "ACSONE SA/NV, PESOL, Odoo Community Association (OCA)", "website": "https://github.com/OCA/contract", "depends": ["contract_sale"], "data": [ "data/contract_cron.xml", "views/contract.xml", - "views/contract_template.xml", ], "installable": True, } diff --git a/contract_sale_generation/models/__init__.py b/contract_sale_generation/models/__init__.py index 5a5b6e24bb..69f40465fa 100644 --- a/contract_sale_generation/models/__init__.py +++ b/contract_sale_generation/models/__init__.py @@ -2,5 +2,6 @@ from . import abstract_contract from . import contract +from . import sale_order from . import sale_order_line from . import contract_line diff --git a/contract_sale_generation/models/abstract_contract.py b/contract_sale_generation/models/abstract_contract.py index e5c4a60c32..e5452dca5a 100644 --- a/contract_sale_generation/models/abstract_contract.py +++ b/contract_sale_generation/models/abstract_contract.py @@ -2,16 +2,16 @@ # Copyright 2017 Angel Moya # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import api, fields, models class ContractAbstractContract(models.AbstractModel): _inherit = "contract.abstract.contract" - type = fields.Selection( - [("invoice", "Invoice"), ("sale", "Sale")], - string="Type", - default="invoice", - required=True, - ) sale_autoconfirm = fields.Boolean(string="Sale Autoconfirm") + + @api.model + def _get_generation_type_selection(self): + res = super()._get_generation_type_selection() + res.append(("sale", "Sale")) + return res diff --git a/contract_sale_generation/models/contract.py b/contract_sale_generation/models/contract.py index ed048091c1..030cbdc46f 100644 --- a/contract_sale_generation/models/contract.py +++ b/contract_sale_generation/models/contract.py @@ -114,39 +114,13 @@ def _prepare_recurring_sales_values(self, date_ref=False): def _recurring_create_sale(self, date_ref=False): sales_values = self._prepare_recurring_sales_values(date_ref) - so_rec = self.env["sale.order"].create(sales_values) - for _rec in self.filtered(lambda c: c.sale_autoconfirm): - so_rec.action_confirm() - return so_rec + sale_orders = self.env["sale.order"].create(sales_values) + sale_orders_to_confirm = sale_orders.filtered( + lambda sale: sale.contract_auto_confirm + ) + sale_orders_to_confirm.action_confirm() + return sale_orders @api.model def cron_recurring_create_sale(self, date_ref=None): - if not date_ref: - date_ref = fields.Date.context_today(self) - domain = self._get_contracts_to_invoice_domain(date_ref) - domain.extend([("type", "=", "sale")]) - sales = self.env["sale.order"] - # Sales by companies, so assignation emails get correct context - companies_to_sale = self.read_group(domain, ["company_id"], ["company_id"]) - for row in companies_to_sale: - contracts_to_sale = self.search(row["__domain"]).with_context( - allowed_company_ids=[row["company_id"][0]] - ) - sales |= contracts_to_sale._recurring_create_sale(date_ref) - return sales - - @api.model - def cron_recurring_create_invoice(self, date_ref=None): - if not date_ref: - date_ref = fields.Date.context_today(self) - domain = self._get_contracts_to_invoice_domain(date_ref) - domain.extend([("type", "=", "invoice")]) - invoices = self.env["account.move"] - # Invoice by companies, so assignation emails get correct context - companies_to_invoice = self.read_group(domain, ["company_id"], ["company_id"]) - for row in companies_to_invoice: - contracts_to_invoice = self.search(row["__domain"]).with_context( - allowed_company_ids=[row["company_id"][0]] - ) - invoices |= contracts_to_invoice._recurring_create_invoice(date_ref) - return invoices + return self._cron_recurring_create(date_ref, create_type="sale") diff --git a/contract_sale_generation/models/sale_order.py b/contract_sale_generation/models/sale_order.py new file mode 100644 index 0000000000..fb94846778 --- /dev/null +++ b/contract_sale_generation/models/sale_order.py @@ -0,0 +1,24 @@ +# Copyright 2021 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + contract_auto_confirm = fields.Boolean( + compute="_compute_contract_auto_confirm", + help="This is a technical field in order to know if the order should" + "be automatically confirmed if generated by contract.", + ) + + def _compute_contract_auto_confirm(self): + sale_auto_confirm = self.filtered( + lambda sale: any( + line.contract_line_id.contract_id.sale_autoconfirm + for line in sale.order_line + ) + ) + sale_auto_confirm.contract_auto_confirm = True + (self - sale_auto_confirm).contract_auto_confirm = False diff --git a/contract_sale_generation/readme/CONTRIBUTORS.rst b/contract_sale_generation/readme/CONTRIBUTORS.rst index 4c26c04804..21cb886478 100644 --- a/contract_sale_generation/readme/CONTRIBUTORS.rst +++ b/contract_sale_generation/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * Angel Moya * Florent THOMAS * Serpent Consulting Services Pvt. Ltd. +* Denis Roussel diff --git a/contract_sale_generation/static/description/index.html b/contract_sale_generation/static/description/index.html index 74937050d5..62720c8c8f 100644 --- a/contract_sale_generation/static/description/index.html +++ b/contract_sale_generation/static/description/index.html @@ -3,7 +3,7 @@ - + Contracts Management - Recurring Sales