first push message
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import random
|
||||
import re
|
||||
import secrets
|
||||
import string
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class SaasTrialRequest(models.Model):
|
||||
"""Flow 1: User Registration & App Selection Flow
|
||||
|
||||
Visits domain-name.com/trial
|
||||
-> Select Apps (Website, CRM, Accounting, ...)
|
||||
-> Fill Form (Email, Company, Phone, Name, ...)
|
||||
-> Create Account & Verify Email
|
||||
-> 15-Day Free Trial Activated
|
||||
-> User Clicks "Continue" --> triggers Flow 2 (provisioning)
|
||||
"""
|
||||
_name = 'saas.trial.request'
|
||||
_description = 'SaaS Trial Signup Request'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'create_date desc'
|
||||
|
||||
# ---- Step: Fill Form (Email, Company, Phone, Name) ----
|
||||
name = fields.Char('Full Name', required=True, tracking=True)
|
||||
company_name = fields.Char('Company Name', tracking=True)
|
||||
email = fields.Char('Email', required=True, tracking=True)
|
||||
phone = fields.Char('Phone')
|
||||
country_id = fields.Many2one('res.country', string='Country')
|
||||
lang = fields.Selection(lambda self: self.env['res.lang'].get_installed(), string='Language')
|
||||
company_size = fields.Selection([
|
||||
('1-5', '1 - 5 employees'),
|
||||
('6-20', '6 - 20 employees'),
|
||||
('21-50', '21 - 50 employees'),
|
||||
('51-200', '51 - 200 employees'),
|
||||
('200+', '200+ employees'),
|
||||
], string='Company Size')
|
||||
primary_interest = fields.Selection([
|
||||
('my_company', 'Use it in my company'),
|
||||
('client', 'Use it for a client'),
|
||||
('explore', 'Just exploring'),
|
||||
], string='Primary Interest')
|
||||
|
||||
# ---- Step: Select Apps ----
|
||||
app_ids = fields.Many2many('saas.app', string='Selected Apps', required=True)
|
||||
|
||||
# ---- Step: Create Account & Verify Email ----
|
||||
state = fields.Selection([
|
||||
('draft', 'Form Submitted'),
|
||||
('pending_verification', 'Pending Email Verification'),
|
||||
('verified', 'Email Verified'),
|
||||
('trial_active', '15-Day Trial Activated'),
|
||||
('provisioning', 'Provisioning Database'),
|
||||
('ready', 'Instance Ready'),
|
||||
('failed', 'Provisioning Failed'),
|
||||
], default='draft', tracking=True, required=True)
|
||||
|
||||
verification_token = fields.Char(copy=False)
|
||||
verification_sent_date = fields.Datetime()
|
||||
verified_date = fields.Datetime()
|
||||
|
||||
# ---- Step: 15-Day Free Trial Activated ----
|
||||
trial_start_date = fields.Datetime()
|
||||
trial_end_date = fields.Datetime()
|
||||
|
||||
# Link forward to Flow 2
|
||||
database_id = fields.Many2one('saas.database', string='Provisioned Database', copy=False)
|
||||
subscription_id = fields.Many2one('saas.subscription', string='Subscription', copy=False)
|
||||
|
||||
_sql_constraints = [
|
||||
('email_unique', 'unique(email)', 'A trial request with this email already exists.'),
|
||||
]
|
||||
|
||||
@api.constrains('email')
|
||||
def _check_email(self):
|
||||
pattern = r"^[^@\s]+@[^@\s]+\.[^@\s]+$"
|
||||
for rec in self:
|
||||
if not re.match(pattern, rec.email or ''):
|
||||
raise ValidationError(_("Please enter a valid email address."))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step: Create Account -> send verification email
|
||||
# ------------------------------------------------------------------
|
||||
def action_submit_and_send_verification(self):
|
||||
"""Called right after the public form is submitted."""
|
||||
for rec in self:
|
||||
rec.verification_token = ''.join(
|
||||
secrets.choice(string.ascii_letters + string.digits) for _ in range(32)
|
||||
)
|
||||
rec.verification_sent_date = fields.Datetime.now()
|
||||
rec.state = 'pending_verification'
|
||||
rec._send_verification_email()
|
||||
return True
|
||||
|
||||
def _send_verification_email(self):
|
||||
template = self.env.ref('saas_trial_portal.mail_template_verify_email')
|
||||
for rec in self:
|
||||
template.send_mail(rec.id, force_send=True)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step: Verify Email (user clicks link from email)
|
||||
# ------------------------------------------------------------------
|
||||
def action_verify_email(self, token):
|
||||
"""Validates token coming from the verification link."""
|
||||
self.ensure_one()
|
||||
if token != self.verification_token:
|
||||
raise ValidationError(_("Invalid or expired verification link."))
|
||||
self.write({
|
||||
'state': 'verified',
|
||||
'verified_date': fields.Datetime.now(),
|
||||
})
|
||||
self._activate_trial()
|
||||
return True
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step: 15-Day Free Trial Activated
|
||||
# ------------------------------------------------------------------
|
||||
def _activate_trial(self):
|
||||
self.ensure_one()
|
||||
now = fields.Datetime.now()
|
||||
self.write({
|
||||
'state': 'trial_active',
|
||||
'trial_start_date': now,
|
||||
'trial_end_date': now + timedelta(days=15),
|
||||
})
|
||||
# Create the subscription record in trial mode (Flow 3 baseline state)
|
||||
if not self.subscription_id:
|
||||
self.subscription_id = self.env['saas.subscription'].create({
|
||||
'trial_request_id': self.id,
|
||||
'is_trial': True,
|
||||
'is_premium': False,
|
||||
'expiry_date': self.trial_end_date,
|
||||
})
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step: User Clicks "Continue" -> kicks off Flow 2 provisioning
|
||||
# ------------------------------------------------------------------
|
||||
def action_continue_to_provisioning(self):
|
||||
self.ensure_one()
|
||||
if self.state != 'trial_active':
|
||||
raise ValidationError(_("Trial must be active before provisioning a database."))
|
||||
self.state = 'provisioning'
|
||||
database = self.env['saas.database'].create({
|
||||
'trial_request_id': self.id,
|
||||
'company_name': self.company_name,
|
||||
'app_ids': [(6, 0, self.app_ids.ids)],
|
||||
})
|
||||
self.database_id = database.id
|
||||
# Run the full provisioning pipeline (Flow 2)
|
||||
database.action_provision()
|
||||
return database
|
||||
Reference in New Issue
Block a user