From d64b0a27d74185e6e553b2ea1464c5dc18721547 Mon Sep 17 00:00:00 2001 From: Franco Leyes Date: Tue, 27 Aug 2024 17:34:01 -0300 Subject: [PATCH 1/2] [ADD] academic_sale_subscription: add new module --- academic_sale_subscription/README.rst | 70 +++++ academic_sale_subscription/__init__.py | 4 + academic_sale_subscription/__manifest__.py | 24 ++ academic_sale_subscription/i18n/es.po | 270 ++++++++++++++++++ academic_sale_subscription/models/__init__.py | 4 + .../models/sale_order.py | 96 +++++++ .../models/sale_order_template.py | 45 +++ .../security/ir.model.access.csv | 2 + .../views/sale_order_template_views.xml | 13 + .../views/sale_order_views.xml | 67 +++++ academic_sale_subscription/wizard/__init__.py | 3 + .../wizard/reenrollment.py | 47 +++ .../wizard/reenrollment_views.xml | 17 ++ 13 files changed, 662 insertions(+) create mode 100644 academic_sale_subscription/README.rst create mode 100644 academic_sale_subscription/__init__.py create mode 100644 academic_sale_subscription/__manifest__.py create mode 100644 academic_sale_subscription/i18n/es.po create mode 100644 academic_sale_subscription/models/__init__.py create mode 100644 academic_sale_subscription/models/sale_order.py create mode 100644 academic_sale_subscription/models/sale_order_template.py create mode 100644 academic_sale_subscription/security/ir.model.access.csv create mode 100644 academic_sale_subscription/views/sale_order_template_views.xml create mode 100644 academic_sale_subscription/views/sale_order_views.xml create mode 100644 academic_sale_subscription/wizard/__init__.py create mode 100644 academic_sale_subscription/wizard/reenrollment.py create mode 100644 academic_sale_subscription/wizard/reenrollment_views.xml diff --git a/academic_sale_subscription/README.rst b/academic_sale_subscription/README.rst new file mode 100644 index 00000000..7fd6ce2b --- /dev/null +++ b/academic_sale_subscription/README.rst @@ -0,0 +1,70 @@ +.. |company| replace:: ADHOC SA + +.. |company_logo| image:: https://raw.githubusercontent.com/ingadhoc/maintainer-tools/master/resources/adhoc-logo.png + :alt: ADHOC SA + :target: https://www.adhoc.com.ar + +.. |icon| image:: https://raw.githubusercontent.com/ingadhoc/maintainer-tools/master/resources/adhoc-icon.png + +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: https://www.gnu.org/licenses/agpl + :alt: License: AGPL-3 + +========================== +Academic Sale Subscription +========================== + +This module extends the standard Odoo subscription management capabilities to cater specifically to academic institutions. + +Installation +============ + +To install this module, you need to: + +#. Only need to install the module + +Configuration +============= + +To configure this module, you need to: + +#. Nothing to configure + +Usage +===== + +To use this module, you need to: + +#. Just use + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: http://runbot.adhoc.com.ar/ + +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 +======= + +Images +------ + +* |company| |icon| + +Contributors +------------ + +Maintainer +---------- + +|company_logo| + +This module is maintained by the |company|. + +To contribute to this module, please visit https://www.adhoc.com.ar. \ No newline at end of file diff --git a/academic_sale_subscription/__init__.py b/academic_sale_subscription/__init__.py new file mode 100644 index 00000000..4538bb6d --- /dev/null +++ b/academic_sale_subscription/__init__.py @@ -0,0 +1,4 @@ +# © 2016 ADHOC SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import models +from . import wizard diff --git a/academic_sale_subscription/__manifest__.py b/academic_sale_subscription/__manifest__.py new file mode 100644 index 00000000..6e44a9c5 --- /dev/null +++ b/academic_sale_subscription/__manifest__.py @@ -0,0 +1,24 @@ +# © 2016 ADHOC SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + 'name': 'Academic Sale Subscription', + 'version': "16.0.1.0.0", + 'sequence': 14, + 'summary': '', + 'author': 'ADHOC SA', + 'website': 'www.adhoc.com.ar', + 'license': 'AGPL-3', + 'depends': [ + 'academic', + 'sale_subscription' + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/sale_order_template_views.xml', + 'views/sale_order_views.xml', + 'wizard/reenrollment_views.xml' + ], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/academic_sale_subscription/i18n/es.po b/academic_sale_subscription/i18n/es.po new file mode 100644 index 00000000..95cc8909 --- /dev/null +++ b/academic_sale_subscription/i18n/es.po @@ -0,0 +1,270 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * academic_sale_subscription +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-08-29 17:09+0000\n" +"PO-Revision-Date: 2024-08-29 17:09+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: academic_sale_subscription +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_order_view_form +msgid "" +"Re-enrollment\n" +" Confirmed\n" +" In process\n" +" No" +msgstr "" +"Rematriculación\n" +" Confirmada\n" +" En proceso\n" +" No" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__4 +msgid "April" +msgstr "Abril" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__8 +msgid "August" +msgstr "Agosto" + +#. module: academic_sale_subscription +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_order_reenrollment_wizard_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: academic_sale_subscription +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_view_search +msgid "Current" +msgstr "Vigente" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__12 +msgid "December" +msgstr "Diciembre" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__display_name +msgid "Display Name" +msgstr "Nombre para mostrar" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__2 +msgid "February" +msgstr "Febrero" + +#. module: academic_sale_subscription +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_order_reenrollment_wizard_form +msgid "Generate" +msgstr "Generar" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__id +msgid "ID" +msgstr "ID" + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/models/sale_order_template.py:0 +#, python-format +msgid "If a month is specified, a day must also be specified, and vice versa." +msgstr "Si se especifica un mes, también se debe especificar un día, y viceversa." + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order__renewal_state__er +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_view_search +msgid "In re-enrollment process" +msgstr "En proceso de rematriculación" + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/wizard/reenrollment.py:0 +#, python-format +msgid "" +"It is required to have at least one recurring product and one non-recurring " +"product." +msgstr "Es necesario tener al menos un producto recurrente y un producto no recurrente." + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__1 +msgid "January" +msgstr "Enero" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__7 +msgid "July" +msgstr "Julio" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__6 +msgid "June" +msgstr "Junio" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__3 +msgid "March" +msgstr "Marzo" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__5 +msgid "May" +msgstr "Mayo" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order__renewal_state__sr +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_view_search +msgid "No re-enrollment process" +msgstr "Sin proceso de rematriculación" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order__renewal_state__nr +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_view_search +msgid "Not re-enrolled" +msgstr "No rematriculado" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__11 +msgid "November" +msgstr "Noviembre" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__10 +msgid "October" +msgstr "Octubre" + +#. module: academic_sale_subscription +#: model:ir.model,name:academic_sale_subscription.model_sale_order_template +msgid "Quotation Template" +msgstr "Plantilla de presupuesto" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order__renewal_state__r +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_view_search +msgid "Re-enrolled" +msgstr "Rematriculado" + +#. module: academic_sale_subscription +#: model:ir.actions.server,name:academic_sale_subscription.model_sale_order_action_reenrollment +msgid "Re-enrollment" +msgstr "Rematriculación" + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/models/sale_order.py:0 +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order__renewal_order_id +#, python-format +msgid "Renewal Order" +msgstr "Orden de renovación" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order__renewal_state +#: model_terms:ir.ui.view,arch_db:academic_sale_subscription.sale_subscription_view_search +msgid "Renewal State" +msgstr "Estado de renovación" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_reenrollment_wizard__sale_order_template_id +msgid "Sale Order Template" +msgstr "Plantilla de pedido de venta" + +#. module: academic_sale_subscription +#: model:ir.model,name:academic_sale_subscription.model_sale_order +msgid "Sales Order" +msgstr "Pedido de venta" + +#. module: academic_sale_subscription +#: model:ir.model.fields.selection,name:academic_sale_subscription.selection__sale_order_template__start_month__9 +msgid "September" +msgstr "Septiembre" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_template__start_day +msgid "Start Day" +msgstr "Día de inicio" + +#. module: academic_sale_subscription +#: model:ir.model.fields,field_description:academic_sale_subscription.field_sale_order_template__start_month +msgid "Start Month" +msgstr "Mes de inicio" + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/models/sale_order_template.py:0 +#, python-format +msgid "" +"The combination of month and day is not valid. Please enter a correct date." +msgstr "La combinación de mes y día no es válida. Por favor, ingrese una fecha correcta." + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/wizard/reenrollment.py:0 +#, python-format +msgid "" +"The following subscriptions have already a linked renewal order:\n" +"- %s\n" +"Please follow up the renewal on those orders.\n" +"To create the renewal for the other orders, you can filter by 'No re-enrollment process'." +msgstr "" +"Las siguientes suscripciones ya tienen una orden de renovación vinculada:\n" +"- %s\n" +"Por favor, siga el proceso de renovación en esas órdenes.\n" +"Para crear la renovación de las otras órdenes, puede filtrar por 'Sin proceso de rematriculación'." + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/wizard/reenrollment.py:0 +#, python-format +msgid "" +"The selected subscription plan does not have a start day or start month." +msgstr "El plan de suscripción seleccionado no tiene un día o mes de inicio." + +#. module: academic_sale_subscription +#. odoo-python +#: code:addons/academic_sale_subscription/models/sale_order.py:0 +#, python-format +msgid "" +"This re-enrollment sale order was generated from subscription %s." +msgstr "" +"Esta orden de venta de rematriculación se generó a partir de la suscripción %s." + +#. module: academic_sale_subscription +#: model:ir.model,name:academic_sale_subscription.model_sale_order_reenrollment_wizard +msgid "sale.order.reenrollment.wizard" +msgstr "Asistente de rematriculación de pedidos de venta" diff --git a/academic_sale_subscription/models/__init__.py b/academic_sale_subscription/models/__init__.py new file mode 100644 index 00000000..46ccc19b --- /dev/null +++ b/academic_sale_subscription/models/__init__.py @@ -0,0 +1,4 @@ +# © 2016 ADHOC SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import sale_order_template +from . import sale_order diff --git a/academic_sale_subscription/models/sale_order.py b/academic_sale_subscription/models/sale_order.py new file mode 100644 index 00000000..c0003ceb --- /dev/null +++ b/academic_sale_subscription/models/sale_order.py @@ -0,0 +1,96 @@ +############################################################################## +# For copyright and license notices, see __manifest__.py file in module root +# directory +############################################################################## +from odoo import models, fields, api, _ +from datetime import datetime + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + renewal_order_id = fields.Many2one('sale.order', on_delete="set null", readonly=True) + renewal_state = fields.Selection(selection=[ + ('er', 'In re-enrollment process'), + ('r', 'Re-enrolled'), + ('nr', 'Not re-enrolled'), + ('sr', 'No re-enrollment process')], + compute="_compute_renewal_state", + store=True + ) + + @api.depends('renewal_order_id', 'renewal_order_id.state') + def _compute_renewal_state(self): + for rec in self: + if not rec.renewal_order_id: + rec.renewal_state = 'sr' + elif rec.renewal_order_id.state in ['sale', 'done']: + rec.renewal_state = 'r' + elif rec.renewal_order_id.state == 'cancel': + rec.renewal_state = 'nr' + else: + rec.renewal_state = 'er' + + def action_open_reenrollment_wizard(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'Re-enrollment Wizard', + 'res_model': 'sale.order.reenrollment.wizard', + 'view_mode': 'form', + 'view_id': self.env.ref('academic_sale_subscription.sale_order_reenrollment_wizard_form').id, + 'target': 'new', + 'context': {'active_ids': self.env.context.get('active_ids', [])}, + } + + def generate_reenrollment(self): + sale_order_template_id = self.env.context.get('sale_order_template_id') + subscriptions = self.env['sale.order'] + for subscription in self: + new_subscription = self.create({ + 'partner_id': subscription.partner_id.id, + 'sale_order_template_id': sale_order_template_id, + }) + + new_subscription._onchange_sale_order_template_id() + new_subscription.order_line.filtered(lambda x: x.product_id and x.product_id.recurring_invoice).write({'product_uom_qty': 0}) + + subscription.renewal_order_id = new_subscription + subscriptions += new_subscription + + message_body = _("This re-enrollment sale order was generated from subscription %s.") % ( + subscription.id, subscription.name + ) + new_subscription.message_post( + body=message_body, + ) + return subscriptions + + def action_confirm(self): + super().action_confirm() + for rec in self.filtered(lambda x: x.is_subscription and x.sale_order_template_id and x.sale_order_template_id.start_day): + rec.order_line.filtered(lambda x: x.product_id and x.product_id.recurring_invoice).write({'product_uom_qty': 1}) + + start_day = rec.sale_order_template_id.start_day + start_month = int(rec.sale_order_template_id.start_month) + + today = fields.Date.today() + current_year = today.year + + next_start_date = datetime(current_year, start_month, start_day).date() + if next_start_date < today: + next_start_date = datetime(current_year + 1, start_month, rec.sale_order_template_id.start_day) + + rec.next_invoice_date = next_start_date + rec.start_date = next_start_date + + def action_open_renewal_order(self): + self.ensure_one() + if self.renewal_order_id: + return { + 'type': 'ir.actions.act_window', + 'name': _('Renewal Order'), + 'view_mode': 'form', + 'res_model': 'sale.order', + 'res_id': self.renewal_order_id.id, + 'target': 'current', + } diff --git a/academic_sale_subscription/models/sale_order_template.py b/academic_sale_subscription/models/sale_order_template.py new file mode 100644 index 00000000..c18551b9 --- /dev/null +++ b/academic_sale_subscription/models/sale_order_template.py @@ -0,0 +1,45 @@ +############################################################################## +# For copyright and license notices, see __manifest__.py file in module root +# directory +############################################################################## +from odoo import fields, models, api, _ +from odoo.exceptions import ValidationError +from datetime import datetime + + +class SaleOrderTemplate(models.Model): + _inherit = "sale.order.template" + + start_day = fields.Integer() + start_month = fields.Selection( + selection=[ + ('1', 'January'), + ('2', 'February'), + ('3', 'March'), + ('4', 'April'), + ('5', 'May'), + ('6', 'June'), + ('7', 'July'), + ('8', 'August'), + ('9', 'September'), + ('10', 'October'), + ('11', 'November'), + ('12', 'December') + ] + ) + + @api.constrains('start_day', 'start_month') + def _check_valid_date(self): + for rec in self: + if not rec.start_month and not rec.start_day: + continue + + if bool(rec.start_month) != bool(rec.start_day): + raise ValidationError(_("If a month is specified, a day must also be specified, and vice versa.")) + + try: + month = int(rec.start_month) + # Validate that the combination of month and day is correct, considering non-leap years + datetime(year=2023, month=month, day=rec.start_day) + except ValueError: + raise ValidationError(_("The combination of month and day is not valid. Please enter a correct date.")) diff --git a/academic_sale_subscription/security/ir.model.access.csv b/academic_sale_subscription/security/ir.model.access.csv new file mode 100644 index 00000000..933020cf --- /dev/null +++ b/academic_sale_subscription/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_reenrollment_wizard,academic.group.user,model_sale_order_reenrollment_wizard,academic.group_user,1,1,1,1 diff --git a/academic_sale_subscription/views/sale_order_template_views.xml b/academic_sale_subscription/views/sale_order_template_views.xml new file mode 100644 index 00000000..193fdb53 --- /dev/null +++ b/academic_sale_subscription/views/sale_order_template_views.xml @@ -0,0 +1,13 @@ + + + sale.order.template.form + sale.order.template + + + + + + + + + diff --git a/academic_sale_subscription/views/sale_order_views.xml b/academic_sale_subscription/views/sale_order_views.xml new file mode 100644 index 00000000..c3020b7c --- /dev/null +++ b/academic_sale_subscription/views/sale_order_views.xml @@ -0,0 +1,67 @@ + + + Re-enrollment + + + list,form + code + + if records: + action = records.action_open_reenrollment_wizard() + + + + + sale.subscription.order.form + sale.order + + + + + + + + + + + + sale.order.search + sale.order + + + + + + + + + + + + + + + + + + + { + 'default_is_subscription': 1, + 'search_default_current': 1, + } + + + diff --git a/academic_sale_subscription/wizard/__init__.py b/academic_sale_subscription/wizard/__init__.py new file mode 100644 index 00000000..0083b854 --- /dev/null +++ b/academic_sale_subscription/wizard/__init__.py @@ -0,0 +1,3 @@ +# © 2016 ADHOC SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import reenrollment diff --git a/academic_sale_subscription/wizard/reenrollment.py b/academic_sale_subscription/wizard/reenrollment.py new file mode 100644 index 00000000..d45ae879 --- /dev/null +++ b/academic_sale_subscription/wizard/reenrollment.py @@ -0,0 +1,47 @@ +############################################################################## +# For copyright and license notices, see __manifest__.py file in module root +# directory +############################################################################## +from odoo import fields, models, _ +from odoo.exceptions import ValidationError + + +class SaleOrderReenrollmentWizard(models.TransientModel): + _name = 'sale.order.reenrollment.wizard' + + sale_order_template_id = fields.Many2one( + 'sale.order.template', + required=True, + domain=[('recurrence_id', '!=', False)] + ) + + def action_generate_reenrollment(self): + if not (self.sale_order_template_id.start_day and self.sale_order_template_id.start_month): + raise ValidationError(_("The selected subscription plan does not have a start day or start month.")) + + products = self.sale_order_template_id.sale_order_template_line_ids + recurring_product = products.filtered(lambda x: x.recurring_invoice) + no_recurring_product = products - recurring_product + if not (recurring_product and no_recurring_product): + raise ValidationError(_("It is required to have at least one recurring product and one non-recurring product.")) + + active_ids = self.env.context.get('active_ids', []) + sale_order_ids = self.env['sale.order'].browse(active_ids) + + sale_orders_with_active_renewal = sale_order_ids.filtered('renewal_order_id') + if sale_orders_with_active_renewal: + sale_order_names = "\n- ".join(sale_orders_with_active_renewal.mapped('name')) + raise ValidationError(_( + "The following subscriptions have already a linked renewal order:\n- %s\nPlease follow up the renewal on those orders." + "\nTo create the renewal for the other orders, you can filter by 'No re-enrollment process'." + ) % sale_order_names) + + subscriptions = sale_order_ids.with_context(sale_order_template_id=self.sale_order_template_id.id).generate_reenrollment() + + action = self.env.ref('sale_subscription.sale_subscription_action').read()[0] + action.update({ + 'domain': [('id', 'in', subscriptions.ids)], + 'views': sorted(action['views'], key=lambda v: v[1] != 'tree'), # show tree view first + 'context': {'default_is_subscription': 1} + }) + return action diff --git a/academic_sale_subscription/wizard/reenrollment_views.xml b/academic_sale_subscription/wizard/reenrollment_views.xml new file mode 100644 index 00000000..396d7a97 --- /dev/null +++ b/academic_sale_subscription/wizard/reenrollment_views.xml @@ -0,0 +1,17 @@ + + + sale.order.reenrollment.wizard.form + sale.order.reenrollment.wizard + +
+ + + +
+
+
+
+
+
From 4fecd2f19345992442c752cdc04b515283015e14 Mon Sep 17 00:00:00 2001 From: Franco Leyes Date: Mon, 9 Sep 2024 13:47:11 -0300 Subject: [PATCH 2/2] [IMP] academic_sale_subscription: check same subscription --- .../models/sale_order.py | 39 +++++++++++++++++++ .../views/sale_order_views.xml | 5 +++ 2 files changed, 44 insertions(+) diff --git a/academic_sale_subscription/models/sale_order.py b/academic_sale_subscription/models/sale_order.py index c0003ceb..92ca1cd0 100644 --- a/academic_sale_subscription/models/sale_order.py +++ b/academic_sale_subscription/models/sale_order.py @@ -18,6 +18,7 @@ class SaleOrder(models.Model): compute="_compute_renewal_state", store=True ) + same_subscription_id = fields.Many2one('sale.order', compute='_compute_same_subscription_id', store=False) @api.depends('renewal_order_id', 'renewal_order_id.state') def _compute_renewal_state(self): @@ -94,3 +95,41 @@ def action_open_renewal_order(self): 'res_id': self.renewal_order_id.id, 'target': 'current', } + + @api.depends('order_line.product_id', 'partner_id', 'start_date', 'state') + def _compute_same_subscription_id(self): + for subscription in self: + recurring_lines = subscription.order_line.filtered(lambda line: line.product_id.recurring_invoice) + + if recurring_lines: + subscription_id = subscription._origin.id + Subscription = self.with_context(active_test=False).sudo() + + domain = [ + ('partner_id', '=', subscription.partner_id.id), + ('order_line.product_id', 'in', recurring_lines.product_id.ids), + ('state', '=', 'sale'), + ('stage_id.category', '!=', 'closed') + ] + + if subscription_id: + domain += [('id', '!=', subscription_id)] + + if not subscription.start_date: + domain += [ + ('start_date', '<=', fields.Date.today()), + '|', + ('end_date', '=', False), + ('end_date', '>=', fields.Date.today()) + ] + else: + domain += [ + ('start_date', '<=', subscription.start_date), + '|', + ('end_date', '=', False), + ('end_date', '>=', subscription.start_date) + ] + + subscription.same_subscription_id = Subscription.search(domain, limit=1) + else: + subscription.same_subscription_id = False diff --git a/academic_sale_subscription/views/sale_order_views.xml b/academic_sale_subscription/views/sale_order_views.xml index c3020b7c..ae937304 100644 --- a/academic_sale_subscription/views/sale_order_views.xml +++ b/academic_sale_subscription/views/sale_order_views.xml @@ -16,6 +16,11 @@ sale.order + + +