218 lines
8.1 KiB
Python
218 lines
8.1 KiB
Python
from odoo import models, fields, api, _
|
|
from odoo.exceptions import UserError
|
|
from datetime import datetime, timedelta
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class UserSubscription(models.Model):
|
|
_name = 'user.subscription'
|
|
_description = 'User Subscription'
|
|
_inherit = ['mail.thread']
|
|
_rec_name = 'user_email'
|
|
|
|
user_id = fields.Many2one('res.users', string='User', ondelete='cascade')
|
|
user_email = fields.Char(string='Email', required=True)
|
|
user_name = fields.Char(string='Full Name', required=True)
|
|
company_name = fields.Char(string='Company Name', required=True)
|
|
phone = fields.Char(string='Phone')
|
|
country_id = fields.Many2one('res.country', string='Country')
|
|
|
|
# Subscription details
|
|
subscription_plan_id = fields.Many2one('subscription.plan', string='Subscription Plan')
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('trial', 'Trial'),
|
|
('active', 'Active'),
|
|
('expired', 'Expired'),
|
|
('cancelled', 'Cancelled'),
|
|
], string='Status', default='draft', tracking=True)
|
|
|
|
# Trial period
|
|
trial_start_date = fields.Datetime(string='Trial Start Date')
|
|
trial_end_date = fields.Datetime(string='Trial End Date')
|
|
|
|
# Subscription period
|
|
subscription_start_date = fields.Datetime(string='Subscription Start Date')
|
|
subscription_end_date = fields.Datetime(string='Subscription End Date')
|
|
|
|
# Flags
|
|
is_trial = fields.Boolean(string='Is Trial', compute='_compute_is_trial')
|
|
is_premium = fields.Boolean(string='Is Premium', default=False)
|
|
days_remaining = fields.Integer(string='Days Remaining', compute='_compute_days_remaining')
|
|
|
|
# Payment
|
|
payment_reference = fields.Char(string='Payment Reference')
|
|
payment_state = fields.Selection([
|
|
('pending', 'Pending'),
|
|
('paid', 'Paid'),
|
|
('failed', 'Failed'),
|
|
], string='Payment Status', default='pending')
|
|
|
|
# Database instance
|
|
database_instance_id = fields.One2many('database.instance', 'subscription_id',
|
|
string='Database Instances')
|
|
active_database_id = fields.Many2one('database.instance', string='Active Database')
|
|
|
|
# Selected apps
|
|
selected_app_ids = fields.One2many('selected.apps', 'subscription_id', string='Selected Apps')
|
|
max_apps_allowed = fields.Integer(related='subscription_plan_id.max_apps',
|
|
string='Max Apps Allowed')
|
|
|
|
@api.model
|
|
def create(self, vals):
|
|
"""Create subscription with automatic trial setup"""
|
|
subscription = super().create(vals)
|
|
|
|
if subscription.state == 'trial' and not subscription.trial_start_date:
|
|
trial_plan = self.env['subscription.plan'].get_trial_plan()
|
|
trial_days = trial_plan.trial_days if trial_plan else 15
|
|
|
|
subscription.write({
|
|
'subscription_plan_id': trial_plan.id if trial_plan else False,
|
|
'trial_start_date': fields.Datetime.now(),
|
|
'trial_end_date': fields.Datetime.now() + timedelta(days=trial_days),
|
|
})
|
|
|
|
# Send verification email
|
|
subscription._send_verification_email()
|
|
|
|
return subscription
|
|
|
|
def _compute_is_trial(self):
|
|
for record in self:
|
|
record.is_trial = record.state == 'trial'
|
|
|
|
def _compute_days_remaining(self):
|
|
now = fields.Datetime.now()
|
|
for record in self:
|
|
if record.state == 'trial' and record.trial_end_date:
|
|
delta = record.trial_end_date - now
|
|
record.days_remaining = max(0, delta.days)
|
|
elif record.state == 'active' and record.subscription_end_date:
|
|
delta = record.subscription_end_date - now
|
|
record.days_remaining = max(0, delta.days)
|
|
else:
|
|
record.days_remaining = 0
|
|
|
|
def _send_verification_email(self):
|
|
"""Send email verification to user"""
|
|
self.ensure_one()
|
|
template = self.env.ref('odoo_subscription.email_verification_template',
|
|
raise_if_not_found=False)
|
|
if template:
|
|
template.send_mail(self.id, force_send=True)
|
|
|
|
def _send_credentials_email(self):
|
|
"""Send admin credentials to user"""
|
|
self.ensure_one()
|
|
template = self.env.ref('odoo_subscription.email_credentials_template',
|
|
raise_if_not_found=False)
|
|
if template:
|
|
template.send_mail(self.id, force_send=True)
|
|
|
|
def check_trial_expired(self):
|
|
"""Check if trial has expired"""
|
|
self.ensure_one()
|
|
if self.state == 'trial' and self.trial_end_date:
|
|
if fields.Datetime.now() > self.trial_end_date:
|
|
self.state = 'expired'
|
|
return True
|
|
return False
|
|
|
|
def is_subscription_valid(self):
|
|
"""Check if subscription is valid"""
|
|
self.ensure_one()
|
|
|
|
if self.state == 'active':
|
|
if self.subscription_end_date and fields.Datetime.now() <= self.subscription_end_date:
|
|
return True
|
|
elif self.state == 'trial':
|
|
if not self.check_trial_expired():
|
|
return True
|
|
return False
|
|
|
|
def provision_database(self, app_list):
|
|
"""Provision database and install apps"""
|
|
self.ensure_one()
|
|
|
|
try:
|
|
# Create database instance record
|
|
db_instance_obj = self.env['database.instance']
|
|
|
|
# Generate unique subdomain
|
|
subdomain = db_instance_obj.generate_unique_subdomain(self.company_name)
|
|
database_name = subdomain.replace('-', '_')
|
|
|
|
# Create database instance
|
|
db_instance = db_instance_obj.create({
|
|
'subscription_id': self.id,
|
|
'database_name': database_name,
|
|
'subdomain': subdomain,
|
|
'admin_email': self.user_email,
|
|
'db_state': 'pending',
|
|
})
|
|
|
|
self.active_database_id = db_instance.id
|
|
self.state = 'trial'
|
|
self._cr.commit()
|
|
|
|
# Create database (this may take time)
|
|
if db_instance.create_database():
|
|
# Install selected apps
|
|
if db_instance.install_apps(app_list):
|
|
# Configure instance
|
|
db_instance.configure_instance()
|
|
|
|
# Send credentials
|
|
self._send_credentials_email()
|
|
|
|
return {
|
|
'success': True,
|
|
'database_url': db_instance.full_domain,
|
|
'admin_login': db_instance.admin_login,
|
|
'admin_password': db_instance.admin_password,
|
|
}
|
|
|
|
return {
|
|
'success': False,
|
|
'error': 'Database provisioning failed',
|
|
}
|
|
|
|
except Exception as e:
|
|
_logger.error(f"Database provisioning error: {e}")
|
|
return {
|
|
'success': False,
|
|
'error': str(e),
|
|
}
|
|
|
|
def activate_subscription(self, plan_id, payment_ref=None):
|
|
"""Activate paid subscription"""
|
|
self.ensure_one()
|
|
plan = self.env['subscription.plan'].browse(plan_id)
|
|
|
|
self.write({
|
|
'state': 'active',
|
|
'subscription_plan_id': plan.id,
|
|
'is_premium': True,
|
|
'subscription_start_date': fields.Datetime.now(),
|
|
'payment_reference': payment_ref,
|
|
'payment_state': 'paid',
|
|
})
|
|
|
|
# Calculate end date based on plan duration
|
|
if plan.plan_code == '3_months':
|
|
self.subscription_end_date = fields.Datetime.now() + timedelta(days=90)
|
|
elif plan.plan_code == '6_months':
|
|
self.subscription_end_date = fields.Datetime.now() + timedelta(days=180)
|
|
elif plan.plan_code == '1_year':
|
|
self.subscription_end_date = fields.Datetime.now() + timedelta(days=365)
|
|
|
|
# Update database instance limits
|
|
if self.active_database_id:
|
|
self.active_database_id.write({
|
|
'workers': 4,
|
|
'memory_limit_mb': 1024,
|
|
'max_connections': 50,
|
|
}) |