diff --git a/odex25_sales/dev_membership/__manifest__.py b/odex25_sales/dev_membership/__manifest__.py index 0bf562f66..890306c1d 100644 --- a/odex25_sales/dev_membership/__manifest__.py +++ b/odex25_sales/dev_membership/__manifest__.py @@ -70,6 +70,7 @@ odoo app manage Membership subscription plans, odoo membership memeber, odoo mem 'data/sequence.xml', 'views/main_menu.xml', 'wizard/renew_membership.xml', + 'wizard/cancel_membership.xml', 'views/partner_extended.xml', 'views/dev_membership.xml', 'views/product_template.xml', diff --git a/odex25_sales/dev_membership/data/mail_template.xml b/odex25_sales/dev_membership/data/mail_template.xml index 4da794406..2eeaffbe0 100644 --- a/odex25_sales/dev_membership/data/mail_template.xml +++ b/odex25_sales/dev_membership/data/mail_template.xml @@ -1,5 +1,6 @@ + membership.email.template Membership Detail @@ -12,7 +13,9 @@

Hello ${object.partner_id.name},

-

Your ${object.product_id.name} membership of amount ${object.membership_fees} have activated on ${object.from_date} - ${object.to_date} .

+

Your ${object.product_id.name} membership of amount ${object.membership_fees} have + activated on ${object.from_date} - ${object.to_date} . +




@@ -21,21 +24,35 @@
- + - Membership Expire Reminder - ${(object.company_id.email or '') | safe} - ${(object.partner_id.email or '') | safe} - Membership Expire Reminder - - - Membership Expire Reminder + ${(object.company_id.email or '') | safe} + ${(object.partner_id.email or '') | safe} + Membership Expire Reminder + + + Hello ${object.partner_id.name}.

Hope you doing well!

It's gentle reminder that your membership is about to expire on ${object.datetime_convert()}.

]]>
-
- + + + + Membership Expire Second Reminder + ${(object.company_id.email or '') | safe} + ${(object.partner_id.email or '') | safe} + Membership Second Expire Reminder + + + Hello ${object.partner_id.name}.

+

Hope you doing well!

+

It's gentle reminder that your membership is about to expire on ${object.datetime_convert()}.

+ ]]>
+
+ Membership Expired Mail ${(object.company_id.email or '') | safe} @@ -49,5 +66,5 @@

Your membership ${(object.name)} was expired on ${object.datetime_convert()} date.

]]>
- +
diff --git a/odex25_sales/dev_membership/data/sequence.xml b/odex25_sales/dev_membership/data/sequence.xml index 46c7681ab..6bcdcc389 100644 --- a/odex25_sales/dev_membership/data/sequence.xml +++ b/odex25_sales/dev_membership/data/sequence.xml @@ -26,7 +26,20 @@ model.membership_reminder_email_cron() + + + Membership Secand Reminder + + 1 + days + -1 + + + code + model.membership_secand_reminder_email_cron() + + Auto Expire Membership diff --git a/odex25_sales/dev_membership/models/dev_membership.py b/odex25_sales/dev_membership/models/dev_membership.py index 2f61560d1..812d51f70 100644 --- a/odex25_sales/dev_membership/models/dev_membership.py +++ b/odex25_sales/dev_membership/models/dev_membership.py @@ -26,10 +26,15 @@ class DevMembership(models.Model): from_date = fields.Date(string="Membership From Date", tracking=3, required=1, default=lambda *a: (datetime.now().date())) to_date = fields.Date(string="Membership To Date", tracking=3) partner_id = fields.Many2one('res.partner', string="Partner", domain="[('is_member', '=', True)]", tracking=2, required=1) + id_no = fields.Char(string='',related='partner_id.identification_number',store=True) + phone = fields.Char(string='Phone',related='partner_id.phone',store=True) + email = fields.Char(string='Email',related='partner_id.email',store=True) product_id = fields.Many2one('product.product', string="Membership Product", domain="[('is_membership', '=', True)]", tracking=2, required=1) - membership_fees = fields.Float(string="Membership Fees", related="product_id.list_price", readonly=1) + membership_fees = fields.Float(string="Membership Fees",readonly=0) + is_free = fields.Boolean(string="Is Free",related="product_id.is_free",) + company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.company, required=1, tracking=3) - duration = fields.Integer(string="Duration", related="product_id.duration") + duration = fields.Integer(string="Duration",readonly=0,) description = fields.Text(string="Description", related="product_id.description", readonly=False) interval = fields.Selection(string="Interval", related="product_id.interval") @@ -42,14 +47,55 @@ class DevMembership(models.Model): membership_id = fields.Many2one('dev.membership', string='Renew Membership') invoice_id = fields.Many2one('account.move', string='Invoice') user_id = fields.Many2one('res.users', string='Resposible', default=lambda self:self.env.user) - - + cancel_reason_id = fields.Many2one('cancellation.reason',string='Cancel Membership Reason') + + @api.onchange('product_id') + def _onchange_membership_type(self): + if self.product_id: + self.membership_fees = self.product_id.list_price + self.duration = self.product_id.duration + + @api.constrains('membership_fees') + def _check_subscription_fee(self): + for record in self: + if record.membership_fees < record.product_id.list_price: + raise ValidationError(_('Membership fees cannot be less than the default value in Setting of membrship type.')) + + + @api.constrains('duration') + def _check_duration(self): + for record in self: + if record.duration < record.product_id.duration: + raise ValidationError(_('Duration cannot be less than the default value in Setting of membrship type.')) + @api.constrains('from_date') def _check_from_date(self): for rec in self: if not rec.from_date >= datetime.now().date(): raise ValidationError("Membership date should be greater than or equal to today's date!!") + def make_activity_group(self): + # templet_id = self.env.ref('dev_membership.template_membership_cancell') + # templet2_id = self.env.ref('dev_membership.template_membership_cancell2') + date_deadline = fields.Date.today() + note=_('Membership %s is Cancelled') % self.name + + summary = _("Membership Cancellation") + self.sudo().activity_schedule( + 'mail.mail_activity_data_todo', date_deadline, + note=note, + user_id=self.partner_id.user_id.id, + res_id=self.id, + summary=summary + ) + self.sudo().activity_schedule( + 'mail.mail_activity_data_todo', date_deadline, + note=note, + user_id=self.user_id.id, + res_id=self.id, + summary=summary + ) + @api.constrains('partner_id', 'from_date') def _check_if_membership_exists(self): membership_obj = self.env['dev.membership'].search([('partner_id.id', '=', self.partner_id.id), ('state', 'in', ['draft', 'active', 'confirm']), ('id', '!=', self.id)]) @@ -75,9 +121,9 @@ class DevMembership(models.Model): self.state = 'confirm' def action_active_membership(self): - if not self.invoice_id: + if not self.invoice_id and not self.is_free: raise ValidationError(_('Please Create Membership Invoice')) - if self.invoice_id.payment_state != 'paid': + if self.invoice_id.payment_state != 'paid' and not self.is_free: raise ValidationError(_('Membership Invoice is not paid.\nPlease Paid membership invoice and active the membership.')) self.state = 'active' @@ -141,7 +187,17 @@ class DevMembership(models.Model): for membership in membership_ids: tmpl_id.send_mail(membership.id, force_send=True) return True - + def membership_secand_reminder_email_cron(self): + membership_pool = self.env['dev.membership'] + tmpl_id = self.env.ref('dev_membership.dev_membership_expire_second_reminder_mail_template') + days_before_second = self.env['ir.config_parameter'].get_param('dev_membership.days_before_second') + if tmpl_id: + date = datetime.now().date() + relativedelta(days=int(days_before)) + membership_ids = membership_pool.search([('state', '=', 'active'), + ('to_date', '<=', date)]) + for membership in membership_ids: + tmpl_id.send_mail(membership.id, force_send=True) + return True def datetime_convert(self): convert_date = self.to_date.strftime("%d-%m-%Y") return convert_date diff --git a/odex25_sales/dev_membership/security/ir.model.access.csv b/odex25_sales/dev_membership/security/ir.model.access.csv index 64ac76336..19c1875a0 100644 --- a/odex25_sales/dev_membership/security/ir.model.access.csv +++ b/odex25_sales/dev_membership/security/ir.model.access.csv @@ -6,5 +6,7 @@ access_dev_membership_user,dev.membership.user,model_dev_membership,group_member access_dev_membership_manager,dev.membership.manager,model_dev_membership,group_membership_manager,1,1,1,1 access_renew_membership_user,renew.membership.user,model_renew_membership,group_membership_user,1,1,1,1 access_renew_membership_manager,renew.membership.manager,model_renew_membership,group_membership_manager,1,1,1,1 -access_renew_membership_resone,renew.membership.resone,model_cancellation_reason,,1,1,1,1 +access_renew_membership_resone,renew.membership.resone,model_cancellation_reason,group_membership_manager,1,1,1,1 +access_renew_membership_resone2,renew.membership.resone2,model_cancellation_reason,group_membership_user,1,0,0,0 +access_renew_membership_wiz_resone2,renew.membership.wiz.resone2,model_membership_request_cancel_wizard,,1,1,1,1 diff --git a/odex25_sales/dev_membership/views/dev_membership.xml b/odex25_sales/dev_membership/views/dev_membership.xml index 3bd0efb5b..1202a7ad1 100644 --- a/odex25_sales/dev_membership/views/dev_membership.xml +++ b/odex25_sales/dev_membership/views/dev_membership.xml @@ -8,9 +8,13 @@ + + + +
@@ -65,6 +71,10 @@ + + + + @@ -101,7 +111,7 @@
- +
@@ -121,6 +131,7 @@ +
@@ -137,7 +148,9 @@ Membership
- - + + - +
@@ -151,6 +164,15 @@ options="{'classes': {'draft': 'warning', 'expire': 'danger', 'confirm': 'success', 'active' : 'success'}}"/>
+
+
+ + + +
+
+ +
@@ -181,31 +203,52 @@
+ + + activity.dev.membership + dev.membership + + + + +
+ +
+ + +
+
+
+
+
+
+ Memberships ir.actions.act_window dev.membership - kanban,tree,form + kanban,tree,activity,form - + Active Memberships ir.actions.act_window dev.membership - kanban,tree,form + kanban,tree,activity,form [('state', '=', 'active')] - + Expire Memberships ir.actions.act_window dev.membership - kanban,tree,form - [('state', '=', 'expire')] + kanban,tree,activity,form + [('state', 'in', ['cancel','expire'])] - + - + - + @@ -43,7 +43,9 @@ + + @@ -122,99 +124,112 @@ - - - - - - + +
+
+ + + +
+
+ +
+ + + + + +
+ - - - view.res.partner.member.form - res.partner - - - - - - - - - - - - - - - - + + +view.res.partner.member.form +res.partner + + + + + + + + + + + + + + + + - - - - - - - - - - True - - - True - - - - - - - - - res.partner.search - res.partner - - - - - - - - - - - - - - - - - Member - ir.actions.act_window - res.partner - [('is_member', '=', True)] - {'default_is_member' : 1} - kanban,tree,activity,form - + + + + + + + + + True + + + True + + + + + + + + +res.partner.search +res.partner + + + + + + + + + + + + + + + + + + +Member +ir.actions.act_window +res.partner +[('is_member', '=', True)] +{'default_is_member' : 1} +kanban,tree,activity,form + - - + - - - + + + diff --git a/odex25_sales/dev_membership/views/res_config_settings.xml b/odex25_sales/dev_membership/views/res_config_settings.xml index 5a7959e23..77028b9ca 100644 --- a/odex25_sales/dev_membership/views/res_config_settings.xml +++ b/odex25_sales/dev_membership/views/res_config_settings.xml @@ -110,10 +110,24 @@ {'module' : 'dev_membership', 'bin_size': False} + + Cancell Resone + ir.actions.act_window + cancellation.reason + form,tree + + + + + diff --git a/odex25_sales/dev_membership/wizard/__init__.py b/odex25_sales/dev_membership/wizard/__init__.py index a276d27f2..dedd77d3b 100644 --- a/odex25_sales/dev_membership/wizard/__init__.py +++ b/odex25_sales/dev_membership/wizard/__init__.py @@ -2,3 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import renew_membership +from . import cancel_membership diff --git a/odex25_sales/dev_membership/wizard/cancel_membership.py b/odex25_sales/dev_membership/wizard/cancel_membership.py new file mode 100644 index 000000000..e03fd0b8f --- /dev/null +++ b/odex25_sales/dev_membership/wizard/cancel_membership.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models, _ + + +class MembershipRefues(models.TransientModel): + _name = "membership.request.cancel.wizard" + _description = "Membership refuse Reason wizard" + + reason_id = fields.Many2one('cancellation.reason',string='Cancel Membership Reason' ,required=True) + request_id = fields.Many2one('dev.membership') + user_id = fields.Many2one('res.users', string='User', default=lambda self: self.env.user,) + + + @api.model + def default_get(self, fields): + res = super(MembershipRefues, self).default_get(fields) + active_ids = self.env.context.get('active_ids', []) + active_model = self.env.context.get('active_model', []) + if active_model == 'dev.membership': + res.update({'request_id': active_ids[0] if active_ids else False}) + return res + + def request_cancel_reason(self): + for record in self: + record.ensure_one() + subject = _("Membership Cancelled") + body = _('The Membership was Cancelled by %s for the following reason: %s ') % ( + self.env.user.name, record.reason_id.name) + + if record.request_id: + record.request_id.cancel_reason_id.name = record.reason_id.name + record.request_id.state = 'cancel' + record.request_id.message_post(body=body, subject=subject) + record.request_id.make_activity_group() + # end chatter + return {'type': 'ir.actions.act_window_close'} + diff --git a/odex25_sales/dev_membership/wizard/cancel_membership.xml b/odex25_sales/dev_membership/wizard/cancel_membership.xml new file mode 100644 index 000000000..c43d8de5f --- /dev/null +++ b/odex25_sales/dev_membership/wizard/cancel_membership.xml @@ -0,0 +1,28 @@ + + + + membership.request.cancel.wizard.form + membership.request.cancel.wizard + +
+ + + + + +
+
+ +
+
+ + + Cancel Membership Reason + membership.request.cancel.wizard + form + + new + +