From a894052adf0613ef640f555c30badf305b5b40e2 Mon Sep 17 00:00:00 2001 From: Angel Moya Pardo Date: Thu, 10 Aug 2017 14:11:49 +0200 Subject: [PATCH 01/60] 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 b92a081844bfe4902282cc60e8df2ca93f52b56b Mon Sep 17 00:00:00 2001 From: Eder Brito Date: Fri, 6 Nov 2020 05:25:10 +0000 Subject: [PATCH 12/60] 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 cc317ee78e1207c5de692599a2fbcceba82d06fc Mon Sep 17 00:00:00 2001 From: Florent THOMAS Date: Sat, 2 Jan 2021 21:44:43 +0100 Subject: [PATCH 13/60] 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 c1ce6b833af3c0bd9300ee15fa0096c9ff7c91be 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/60] 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 0a6d503897f6f2ce8f5f123f5f7d7b36359eb898 Mon Sep 17 00:00:00 2001 From: Mkxm Awilix Date: Wed, 27 Jan 2021 10:15:39 +0100 Subject: [PATCH 15/60] [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 72d8463d4df877ed6aa7adcb0c9ee1e3fea00ae1 Mon Sep 17 00:00:00 2001 From: Freni-OSI Date: Wed, 7 Apr 2021 16:41:41 +0530 Subject: [PATCH 16/60] [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 fc1cae452e2bb985663fc54da5de9ff30f528d55 Mon Sep 17 00:00:00 2001 From: Freni-OSI Date: Wed, 21 Apr 2021 13:42:13 +0530 Subject: [PATCH 17/60] [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 f852f01b522f26c30c8b36b6a739314b90f947be Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Sun, 7 Nov 2021 10:08:41 +0100 Subject: [PATCH 18/60] [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 -
-

Contracts Management - Recurring Sales

+
+ + +Odoo Community Association + +
+

Contracts Management - Recurring Sales

-

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

+

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

This module extends functionality of contracts to be able to generate sales orders instead of invoices.

Table of contents

@@ -386,7 +391,7 @@

Contracts Management - Recurring Sales

-

Usage

+

Usage

To use this module, you need to:

  1. Go to Sales -> Contracts and select or create a new contract.
  2. @@ -398,7 +403,7 @@

    Usage

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -406,16 +411,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ACSONE SA/NV
  • PESOL
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -437,5 +442,6 @@

Maintainers

+
From 913b16e7afda0d66df895e355a6c1d88a6d23167 Mon Sep 17 00:00:00 2001 From: Wodran Van de Sande Date: Thu, 30 Oct 2025 16:08:00 +0100 Subject: [PATCH 59/60] [IMP] contract_sale_generation: pre-commit stuff --- contract_sale_generation/README.rst | 37 ++++++++++--------- contract_sale_generation/pyproject.toml | 3 ++ .../readme/CONTRIBUTORS.md | 4 ++ .../readme/CONTRIBUTORS.rst | 4 -- .../{DESCRIPTION.rst => DESCRIPTION.md} | 4 +- contract_sale_generation/readme/USAGE.md | 7 ++++ contract_sale_generation/readme/USAGE.rst | 7 ---- .../static/description/index.html | 13 ++++--- .../views/contract_template.xml | 2 - 9 files changed, 42 insertions(+), 39 deletions(-) create mode 100644 contract_sale_generation/pyproject.toml create mode 100644 contract_sale_generation/readme/CONTRIBUTORS.md delete mode 100644 contract_sale_generation/readme/CONTRIBUTORS.rst rename contract_sale_generation/readme/{DESCRIPTION.rst => DESCRIPTION.md} (61%) create mode 100644 contract_sale_generation/readme/USAGE.md delete mode 100644 contract_sale_generation/readme/USAGE.rst diff --git a/contract_sale_generation/README.rst b/contract_sale_generation/README.rst index e3f619c65d..b065e00fca 100644 --- a/contract_sale_generation/README.rst +++ b/contract_sale_generation/README.rst @@ -21,19 +21,19 @@ 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/16.0/contract_sale_generation + :target: https://github.com/OCA/contract/tree/19.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-16-0/contract-16-0-contract_sale_generation + :target: https://translation.odoo-community.org/projects/contract-19-0/contract-19-0-contract_sale_generation :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/contract&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/contract&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -This module extends functionality of contracts to be able to generate sales -orders instead of invoices. +This module extends functionality of contracts to be able to generate +sales orders instead of invoices. **Table of contents** @@ -45,11 +45,12 @@ Usage To use this module, you need to: -#. Go to Sales -> Contracts and select or create a new contract. -#. Fill fields for selecting the recurrency and invoice parameters: +1. Go to Sales -> Contracts and select or create a new contract. +2. 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" + - Type defines document that contract will generate, can be "Sales" + or "Invoices" + - Sale Autoconfirm, validate Sales Orders if type is "Sales" Bug Tracker =========== @@ -57,7 +58,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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -65,21 +66,21 @@ Credits ======= Authors -~~~~~~~ +------- * ACSONE SA/NV * PESOL Contributors -~~~~~~~~~~~~ +------------ -* Angel Moya -* Florent THOMAS -* Serpent Consulting Services Pvt. Ltd. -* Denis Roussel +- Angel Moya +- Florent THOMAS +- Serpent Consulting Services Pvt. Ltd. +- Denis Roussel Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -91,6 +92,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/pyproject.toml b/contract_sale_generation/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/contract_sale_generation/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/contract_sale_generation/readme/CONTRIBUTORS.md b/contract_sale_generation/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..12490e20a9 --- /dev/null +++ b/contract_sale_generation/readme/CONTRIBUTORS.md @@ -0,0 +1,4 @@ +- Angel Moya \<\> +- Florent THOMAS \<\> +- Serpent Consulting Services Pvt. Ltd. \<\> +- Denis Roussel \<\> diff --git a/contract_sale_generation/readme/CONTRIBUTORS.rst b/contract_sale_generation/readme/CONTRIBUTORS.rst deleted file mode 100644 index 21cb886478..0000000000 --- a/contract_sale_generation/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1,4 +0,0 @@ -* Angel Moya -* Florent THOMAS -* Serpent Consulting Services Pvt. Ltd. -* Denis Roussel diff --git a/contract_sale_generation/readme/DESCRIPTION.rst b/contract_sale_generation/readme/DESCRIPTION.md similarity index 61% rename from contract_sale_generation/readme/DESCRIPTION.rst rename to contract_sale_generation/readme/DESCRIPTION.md index f8ff4d1939..36b9cedca7 100644 --- a/contract_sale_generation/readme/DESCRIPTION.rst +++ b/contract_sale_generation/readme/DESCRIPTION.md @@ -1,2 +1,2 @@ -This module extends functionality of contracts to be able to generate sales -orders instead of invoices. +This module extends functionality of contracts to be able to generate +sales orders instead of invoices. diff --git a/contract_sale_generation/readme/USAGE.md b/contract_sale_generation/readme/USAGE.md new file mode 100644 index 0000000000..695898cc97 --- /dev/null +++ b/contract_sale_generation/readme/USAGE.md @@ -0,0 +1,7 @@ +To use this module, you need to: + +1. Go to Sales -\> Contracts and select or create a new contract. +2. 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" diff --git a/contract_sale_generation/readme/USAGE.rst b/contract_sale_generation/readme/USAGE.rst deleted file mode 100644 index 4f7623f664..0000000000 --- a/contract_sale_generation/readme/USAGE.rst +++ /dev/null @@ -1,7 +0,0 @@ -To use this module, you need to: - -#. Go to Sales -> Contracts and select or create a new contract. -#. 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" diff --git a/contract_sale_generation/static/description/index.html b/contract_sale_generation/static/description/index.html index 408d6098bd..06a3cbd7e1 100644 --- a/contract_sale_generation/static/description/index.html +++ b/contract_sale_generation/static/description/index.html @@ -374,9 +374,9 @@

Contracts Management - Recurring Sales

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:91370204ddeaf10693389d695a20d77c00135106f9f8a3157bb4945ed3eacba3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

-

This module extends functionality of contracts to be able to generate sales -orders instead of invoices.

+

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

+

This module extends functionality of contracts to be able to generate +sales orders instead of invoices.

Table of contents

    @@ -396,7 +396,8 @@

    Usage

    1. Go to Sales -> Contracts and select or create a new contract.
    2. Fill fields for selecting the recurrency and invoice parameters:
        -
      • Type defines document that contract will generate, can be “Sales” or “Invoices”
      • +
      • Type defines document that contract will generate, can be “Sales” +or “Invoices”
      • Sale Autoconfirm, validate Sales Orders if type is “Sales”
    3. @@ -407,7 +408,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 to smash it by providing a detailed and welcomed -feedback.

      +feedback.

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

@@ -437,7 +438,7 @@

Maintainers

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/views/contract_template.xml b/contract_sale_generation/views/contract_template.xml index c7324cedc6..21cb9a6189 100644 --- a/contract_sale_generation/views/contract_template.xml +++ b/contract_sale_generation/views/contract_template.xml @@ -1,6 +1,5 @@ - contract.template form view contract.template @@ -11,5 +10,4 @@ - From 86717be1ef5ef1b6292820febb8238a03e6f2558 Mon Sep 17 00:00:00 2001 From: Wodran Van de Sande Date: Fri, 31 Oct 2025 10:47:07 +0100 Subject: [PATCH 60/60] 19.0 [MIG] contract_sale_generation: Migration to 19.0 --- contract_sale_generation/README.rst | 32 ++++++++----------- contract_sale_generation/__manifest__.py | 3 +- .../data/contract_cron.xml | 2 -- contract_sale_generation/i18n/tr.po | 32 ++++++++----------- contract_sale_generation/models/__init__.py | 2 +- contract_sale_generation/models/contract.py | 19 +++++------ .../models/contract_line.py | 2 +- ...tract_contract.py => contract_template.py} | 4 +-- .../readme/CONTRIBUTORS.md | 8 ++--- .../static/description/index.html | 32 ++++++++----------- contract_sale_generation/tests/__init__.py | 2 ++ contract_sale_generation/tests/common.py | 31 +++++++++--------- .../tests/test_contract_sale.py | 12 +++---- .../tests/test_contract_sale_recurrency.py | 6 ++-- contract_sale_generation/views/contract.xml | 9 ++---- .../views/contract_template.xml | 13 -------- 16 files changed, 88 insertions(+), 121 deletions(-) rename contract_sale_generation/models/{abstract_contract.py => contract_template.py} (76%) 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 b065e00fca..18d240e1be 100644 --- a/contract_sale_generation/README.rst +++ b/contract_sale_generation/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ====================================== Contracts Management - Recurring Sales ====================================== @@ -11,23 +7,23 @@ Contracts Management - Recurring Sales !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:91370204ddeaf10693389d695a20d77c00135106f9f8a3157bb4945ed3eacba3 + !! source digest: sha256:56b2435c5af989f9e5292e51764d66cb27109c9078bf85334cf40b807b1da757 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png +.. |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%2Fcontract-lightgray.png?logo=github - :target: https://github.com/OCA/contract/tree/19.0/contract_sale_generation + :target: https://github.com/OCA/contract/tree/18.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-19-0/contract-19-0-contract_sale_generation + :target: https://translation.odoo-community.org/projects/contract-18-0/contract-18-0-contract_sale_generation :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/contract&target_branch=19.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/contract&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -48,9 +44,9 @@ To use this module, you need to: 1. Go to Sales -> Contracts and select or create a new contract. 2. 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" + - Type defines document that contract will generate, can be "Sales" + or "Invoices" + - Sale Autoconfirm, validate Sales Orders if type is "Sales" Bug Tracker =========== @@ -58,7 +54,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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -74,10 +70,10 @@ Authors Contributors ------------ -- Angel Moya -- Florent THOMAS -- Serpent Consulting Services Pvt. Ltd. -- Denis Roussel +- Angel Moya +- Florent THOMAS +- Serpent Consulting Services Pvt. Ltd. +- Denis Roussel Maintainers ----------- @@ -92,6 +88,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 768c5f28b8..616e548064 100644 --- a/contract_sale_generation/__manifest__.py +++ b/contract_sale_generation/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Contracts Management - Recurring Sales", - "version": "16.0.1.2.0", + "version": "19.0.1.0.0", "category": "Contract Management", "license": "AGPL-3", "author": "ACSONE SA/NV, PESOL, Odoo Community Association (OCA)", @@ -14,7 +14,6 @@ "data": [ "data/contract_cron.xml", "views/contract.xml", - "views/contract_template.xml", ], "installable": True, } diff --git a/contract_sale_generation/data/contract_cron.xml b/contract_sale_generation/data/contract_cron.xml index c2f206dc16..2b82638071 100644 --- a/contract_sale_generation/data/contract_cron.xml +++ b/contract_sale_generation/data/contract_cron.xml @@ -7,7 +7,5 @@ 1 days - -1 - diff --git a/contract_sale_generation/i18n/tr.po b/contract_sale_generation/i18n/tr.po index 5779029468..c0c28c1fa1 100644 --- a/contract_sale_generation/i18n/tr.po +++ b/contract_sale_generation/i18n/tr.po @@ -9,48 +9,47 @@ msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-04-21 01:47+0000\n" -"PO-Revision-Date: 2025-06-12 15:26+0000\n" -"Last-Translator: Betül Öğmen \n" +"PO-Revision-Date: 2018-04-21 01:47+0000\n" +"Last-Translator: Ediz Duman , 2017\n" "Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Weblate 5.10.4\n" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_abstract_contract msgid "Abstract Recurring Contract" -msgstr "Temel Yinelenen Sözleşme" +msgstr "" #. 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 "SATIŞ OLUŞTUR" +msgstr "" #. module: contract_sale_generation #: model:ir.model.fields,help:contract_sale_generation.field_contract_abstract_contract__generation_type #: model:ir.model.fields,help:contract_sale_generation.field_contract_contract__generation_type #: model:ir.model.fields,help:contract_sale_generation.field_contract_template__generation_type msgid "Choose the document that will be automatically generated by cron." -msgstr "Cron tarafından otomatik olarak oluşturulacak belgeyi seçin." +msgstr "" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_contract msgid "Contract" -msgstr "Sözleşme" +msgstr "" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_sale_order__contract_auto_confirm msgid "Contract Auto Confirm" -msgstr "Sözleşme Otomatik Onay" +msgstr "" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_contract_line #: model:ir.model.fields,field_description:contract_sale_generation.field_sale_order_line__contract_line_id msgid "Contract Line" -msgstr "Sözleşme Satırı" +msgstr "" #. module: contract_sale_generation #. odoo-python @@ -60,21 +59,19 @@ msgid "" "Contract manually sale order: Sale Order" msgstr "" -"Sözleşme manuel satış emri: Satış Siparişi" #. 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 msgid "Generate Recurring sales from Contracts" -msgstr "Sözleşmelerden Tekrarlayan Satışlar Oluşturun" +msgstr "" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_abstract_contract__generation_type #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__generation_type #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_template__generation_type msgid "Generation Type" -msgstr "Oluşturulma Türü" +msgstr "" #. module: contract_sale_generation #: model:ir.model.fields.selection,name:contract_sale_generation.selection__contract_abstract_contract__generation_type__sale @@ -94,18 +91,19 @@ msgstr "Satış otomatik onaylama" #. module: contract_sale_generation #: model:ir.model.fields,field_description:contract_sale_generation.field_contract_contract__sale_count msgid "Sale Count" -msgstr "Satış Sayısı" +msgstr "" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_sale_order #: model_terms:ir.ui.view,arch_db:contract_sale_generation.contract_contract_form_view_recurring_sale_form +#, fuzzy msgid "Sales Order" -msgstr "Satış Siparişi" +msgstr "Satışlar" #. module: contract_sale_generation #: model:ir.model,name:contract_sale_generation.model_sale_order_line msgid "Sales Order Line" -msgstr "Satış Sipariş Satırı" +msgstr "" #. module: contract_sale_generation #: model:ir.model.fields,help:contract_sale_generation.field_sale_order__contract_auto_confirm @@ -113,8 +111,6 @@ msgid "" "This is a technical field in order to know if the order shouldbe " "automatically confirmed if generated by contract." msgstr "" -"Sözleşme ile siparişin oluşturulması durumunda siparişin otomatik olarak " -"onaylanıp onaylanmayacağını bilmek için kullanılan teknik bir alandır." #~ msgid "Invoice" #~ msgstr "Fatura" diff --git a/contract_sale_generation/models/__init__.py b/contract_sale_generation/models/__init__.py index 69f40465fa..4a180e8ddc 100644 --- a/contract_sale_generation/models/__init__.py +++ b/contract_sale_generation/models/__init__.py @@ -1,6 +1,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from . import abstract_contract +from . import contract_template from . import contract from . import sale_order from . import sale_order_line diff --git a/contract_sale_generation/models/contract.py b/contract_sale_generation/models/contract.py index e9ab9b1620..873f8ff427 100644 --- a/contract_sale_generation/models/contract.py +++ b/contract_sale_generation/models/contract.py @@ -8,7 +8,7 @@ # 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 Command, api, fields, models class ContractContract(models.Model): @@ -21,11 +21,10 @@ def _prepare_sale(self, date_ref): sale = self.env["sale.order"].new( { "partner_id": self.partner_id, - "date_order": fields.Date.to_string(date_ref), + "date_order": date_ref, "origin": self.name, "company_id": self.company_id.id, "user_id": self.partner_id.user_id.id, - "analytic_account_id": self.group_id.id, } ) if self.payment_term_id: @@ -56,11 +55,11 @@ def action_show_sales(self): "name": "Sales Orders", "res_model": "sale.order", "view_type": "form", - "view_mode": "tree,kanban,form,calendar,pivot,graph,activity", + "view_mode": "list,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, "list"), (form_view.id, "form")] return action def recurring_create_sale(self): @@ -70,8 +69,8 @@ def recurring_create_sale(self): """ sales = self._recurring_create_sale() for sale_rec in sales: - self.message_post( - body=_( + sale_rec.message_post( + body=self.env._( "Contract manually sale order: " '' "Sale Order" @@ -106,9 +105,11 @@ def _prepare_recurring_sales_values(self, date_ref=False): sale_values=sale_values, ) if invoice_line_values: - sale_values["order_line"].append((0, 0, invoice_line_values)) + sale_values["order_line"].append( + Command.create(invoice_line_values) + ) sales_values.append(sale_values) - contract_lines._update_recurring_next_date() + contract_lines._update_last_date_invoiced() return sales_values def _recurring_create_sale(self, date_ref=False): diff --git a/contract_sale_generation/models/contract_line.py b/contract_sale_generation/models/contract_line.py index 1837e91e79..21911826c6 100644 --- a/contract_sale_generation/models/contract_line.py +++ b/contract_sale_generation/models/contract_line.py @@ -40,7 +40,7 @@ def _prepare_sale_line(self, order_id=False, sale_values=False): ) order_line.order_id = sale # Get other order line values from product onchange - order_line._onchange_product_id_warning() + order_line._onchange_product_id() sale_line_vals = order_line._convert_to_write(order_line._cache) # Insert markers name = self._insert_markers(dates[0], dates[1]) diff --git a/contract_sale_generation/models/abstract_contract.py b/contract_sale_generation/models/contract_template.py similarity index 76% rename from contract_sale_generation/models/abstract_contract.py rename to contract_sale_generation/models/contract_template.py index f9b56e3a52..794f663094 100644 --- a/contract_sale_generation/models/abstract_contract.py +++ b/contract_sale_generation/models/contract_template.py @@ -5,8 +5,8 @@ from odoo import fields, models -class ContractAbstractContract(models.AbstractModel): - _inherit = "contract.abstract.contract" +class ContractTemplate(models.AbstractModel): + _inherit = "contract.template" sale_autoconfirm = fields.Boolean() diff --git a/contract_sale_generation/readme/CONTRIBUTORS.md b/contract_sale_generation/readme/CONTRIBUTORS.md index 12490e20a9..c3d885fe39 100644 --- a/contract_sale_generation/readme/CONTRIBUTORS.md +++ b/contract_sale_generation/readme/CONTRIBUTORS.md @@ -1,4 +1,4 @@ -- Angel Moya \<\> -- Florent THOMAS \<\> -- Serpent Consulting Services Pvt. Ltd. \<\> -- Denis Roussel \<\> +- 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 06a3cbd7e1..8fcf67f597 100644 --- a/contract_sale_generation/static/description/index.html +++ b/contract_sale_generation/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Contracts Management - Recurring Sales -
+
+

Contracts Management - Recurring Sales

- -
-Odoo Community Association - -
-

Contracts Management - Recurring Sales

-

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

+

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

This module extends functionality of contracts to be able to generate sales orders instead of invoices.

Table of contents

@@ -391,7 +386,7 @@

Contracts Management - Recurring Sales

-

Usage

+

Usage

To use this module, you need to:

  1. Go to Sales -> Contracts and select or create a new contract.
  2. @@ -404,24 +399,24 @@

    Usage

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ACSONE SA/NV
  • PESOL
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -438,11 +433,10 @@

Maintainers

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/tests/__init__.py b/contract_sale_generation/tests/__init__.py index ea35715b01..92799191b1 100644 --- a/contract_sale_generation/tests/__init__.py +++ b/contract_sale_generation/tests/__init__.py @@ -1 +1,3 @@ +from . import common +from . import test_contract_sale_recurrency from . import test_contract_sale diff --git a/contract_sale_generation/tests/common.py b/contract_sale_generation/tests/common.py index 8047964981..6b0948633e 100644 --- a/contract_sale_generation/tests/common.py +++ b/contract_sale_generation/tests/common.py @@ -5,7 +5,7 @@ from freezegun import freeze_time from odoo import fields -from odoo.tests import Form, tagged +from odoo.tests import Form, TransactionCase, tagged def to_date(date): @@ -13,26 +13,25 @@ def to_date(date): @tagged("post_install", "-at_install") -class ContractSaleCommon: +class ContractSaleCommon(TransactionCase): # Use case : Prepare some data for current test case @classmethod def setUpClass(cls): super().setUpClass() - if not cls.env.company.chart_template_id: - # Load a CoA if there's none in current company - coa = cls.env.ref("l10n_generic_coa.configurable_chart_template", False) - if not coa: - # Load the first available CoA - coa = cls.env["account.chart.template"].search( - [("visible", "=", True)], limit=1 - ) - coa.try_loading(company=cls.env.company, install_demo=False) + chart_template = cls.env["account.chart.template"]._guess_chart_template( + cls.env.company.country_id + ) + cls.env["account.chart.template"].try_loading( + chart_template, company=cls.env.company, install_demo=False + ) cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + analytic_plan = cls.env["account.analytic.plan"].create({"name": "Test Plan"}) + cls.analytic_account = cls.env["account.analytic.account"].create( { "name": "Contracts", - "plan_id": cls.env.ref("analytic.analytic_plan_internal").id, + "plan_id": analytic_plan.id, } ) cls.payment_term_id = cls.env.ref( @@ -56,7 +55,9 @@ def setUpClass(cls): "user_id": cls.env.user.id, } ) - cls.product_1 = cls.env.ref("product.product_product_1") + # Avoid error cause sale_timesheet overwriting demo product.product_product_2 + # and making mandatory to link a project to that product or to the sale order + cls.product_1 = cls.env.ref("product.product_product_2") cls.product_1.taxes_id += cls.env["account.tax"].search( [("type_tax_use", "=", "sale")], limit=1 ) @@ -113,9 +114,9 @@ def setUpClass(cls): "recurring_next_date": "2020-01-15", "display_type": False, } - discount_line_group_id = cls.env.ref("product.group_discount_per_so_line") + discount_line_group_id = cls.env.ref("sale.group_discount_per_so_line") uom_group_id = cls.env.ref("uom.group_uom") - cls.env.user.groups_id = [(4, discount_line_group_id.id), (4, uom_group_id.id)] + cls.env.user.group_ids = [(4, discount_line_group_id.id), (4, uom_group_id.id)] with Form(cls.contract) as contract_form, freeze_time(contract_date): contract_form.contract_template_id = cls.template diff --git a/contract_sale_generation/tests/test_contract_sale.py b/contract_sale_generation/tests/test_contract_sale.py index 2668dad664..02831eb559 100644 --- a/contract_sale_generation/tests/test_contract_sale.py +++ b/contract_sale_generation/tests/test_contract_sale.py @@ -3,13 +3,13 @@ # Copyright 2017 Angel Moya # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import Command from odoo.exceptions import ValidationError -from odoo.tests.common import TransactionCase from .common import ContractSaleCommon, to_date -class TestContractSale(ContractSaleCommon, TransactionCase): +class TestContractSale(ContractSaleCommon): def test_check_discount(self): with self.assertRaises(ValidationError): self.contract_line.write({"discount": 120}) @@ -52,9 +52,7 @@ def test_onchange_contract_template_id(self): res = { "contract_type": "sale", "contract_line_ids": [ - ( - 0, - 0, + Command.create( { "product_id": self.product_1.id, "name": "Test Contract Template", @@ -65,7 +63,7 @@ def test_onchange_contract_template_id(self): "recurring_rule_type": "yearly", "recurring_interval": 1, "display_type": False, - }, + } ) ], } @@ -91,7 +89,6 @@ 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._onchange_is_auto_renew() # If we do not recompute recurring_next_date # then it maintains it's 'old' value. # TODO: Research that @@ -115,7 +112,6 @@ def test_contract_sale_analytic_payment_term_fiscal_position(self): self.contract._onchange_partner_id() orders = self.env["sale.order"].browse() orders |= self.contract.recurring_create_sale() - self.assertEqual(self.analytic_account, orders.mapped("analytic_account_id")) self.assertEqual(self.payment_term_id, orders.mapped("payment_term_id")) self.assertEqual(self.fiscal_position_id, orders.mapped("fiscal_position_id")) diff --git a/contract_sale_generation/tests/test_contract_sale_recurrency.py b/contract_sale_generation/tests/test_contract_sale_recurrency.py index 5c63a9e764..7af2d916e3 100644 --- a/contract_sale_generation/tests/test_contract_sale_recurrency.py +++ b/contract_sale_generation/tests/test_contract_sale_recurrency.py @@ -1,18 +1,17 @@ # Copyright 2022 ACSONE SA/NV # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from freezegun.api import freeze_time +from freezegun import freeze_time from odoo import fields from odoo.tests import Form -from odoo.tests.common import TransactionCase from .common import ContractSaleCommon today = "2020-01-15" -class TestContractSale(ContractSaleCommon, TransactionCase): +class TestContractSaleRecurrency(ContractSaleCommon): @classmethod def setUpClass(cls): super().setUpClass() @@ -29,6 +28,7 @@ def _create_contract(cls): with Form(cls.contract) as contract_form: contract_form.partner_id = cls.partner contract_form.generation_type = "sale" + contract_form.line_recurrence = True contract_form.group_id = cls.analytic_account cls.contract = contract_form.save() diff --git a/contract_sale_generation/views/contract.xml b/contract_sale_generation/views/contract.xml index 02e0468090..779f92b5de 100644 --- a/contract_sale_generation/views/contract.xml +++ b/contract_sale_generation/views/contract.xml @@ -5,14 +5,11 @@ - +