Files

218 lines
8.1 KiB
Python
Raw Permalink Normal View History

2026-07-01 14:41:49 +07:00
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,
})