- Add a default make to the tenant
- Add a make to the SpecialistMagicLink
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from sqlalchemy.dialects.postgresql import JSONB
|
from sqlalchemy.dialects.postgresql import JSONB
|
||||||
|
|
||||||
from ..extensions import db
|
from ..extensions import db
|
||||||
from .user import User, Tenant
|
from .user import User, Tenant, TenantMake
|
||||||
from .document import Embedding, Retriever
|
from .document import Embedding, Retriever
|
||||||
|
|
||||||
|
|
||||||
@@ -223,6 +223,7 @@ class SpecialistMagicLink(db.Model):
|
|||||||
name = db.Column(db.String(50), nullable=False)
|
name = db.Column(db.String(50), nullable=False)
|
||||||
description = db.Column(db.Text, nullable=True)
|
description = db.Column(db.Text, nullable=True)
|
||||||
specialist_id = db.Column(db.Integer, db.ForeignKey(Specialist.id, ondelete='CASCADE'), nullable=False)
|
specialist_id = db.Column(db.Integer, db.ForeignKey(Specialist.id, ondelete='CASCADE'), nullable=False)
|
||||||
|
tenant_make_id = db.Column(db.Integer, db.ForeignKey(TenantMake.id, ondelete='CASCADE'), nullable=True)
|
||||||
magic_link_code = db.Column(db.String(55), nullable=False, unique=True)
|
magic_link_code = db.Column(db.String(55), nullable=False, unique=True)
|
||||||
|
|
||||||
valid_from = db.Column(db.DateTime, nullable=True)
|
valid_from = db.Column(db.DateTime, nullable=True)
|
||||||
|
|||||||
@@ -33,13 +33,15 @@ class Tenant(db.Model):
|
|||||||
# Entitlements
|
# Entitlements
|
||||||
currency = db.Column(db.String(20), nullable=True)
|
currency = db.Column(db.String(20), nullable=True)
|
||||||
storage_dirty = db.Column(db.Boolean, nullable=True, default=False)
|
storage_dirty = db.Column(db.Boolean, nullable=True, default=False)
|
||||||
|
default_tenant_make_id = db.Column(db.Integer, db.ForeignKey('public.tenant_make.id'), nullable=True)
|
||||||
|
|
||||||
# Relations
|
# Relations
|
||||||
users = db.relationship('User', backref='tenant')
|
users = db.relationship('User', backref='tenant')
|
||||||
domains = db.relationship('TenantDomain', backref='tenant')
|
domains = db.relationship('TenantDomain', backref='tenant')
|
||||||
licenses = db.relationship('License', back_populates='tenant')
|
licenses = db.relationship('License', back_populates='tenant')
|
||||||
license_usages = db.relationship('LicenseUsage', backref='tenant')
|
license_usages = db.relationship('LicenseUsage', backref='tenant')
|
||||||
makes = db.relationship('TenantMake', backref='tenant')
|
tenant_makes = db.relationship('TenantMake', backref='tenant', foreign_keys='TenantMake.tenant_id')
|
||||||
|
default_tenant_make = db.relationship('TenantMake', foreign_keys=[default_tenant_make_id], uselist=False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_license(self):
|
def current_license(self):
|
||||||
@@ -63,6 +65,7 @@ class Tenant(db.Model):
|
|||||||
'default_language': self.default_language,
|
'default_language': self.default_language,
|
||||||
'allowed_languages': self.allowed_languages,
|
'allowed_languages': self.allowed_languages,
|
||||||
'currency': self.currency,
|
'currency': self.currency,
|
||||||
|
'default_tenant_make_id': self.default_tenant_make_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from wtforms_sqlalchemy.fields import QuerySelectMultipleField
|
|||||||
|
|
||||||
from common.models.document import Retriever
|
from common.models.document import Retriever
|
||||||
from common.models.interaction import EveAITool, Specialist
|
from common.models.interaction import EveAITool, Specialist
|
||||||
|
from common.models.user import TenantMake
|
||||||
from common.extensions import cache_manager
|
from common.extensions import cache_manager
|
||||||
from common.utils.form_assistants import validate_json
|
from common.utils.form_assistants import validate_json
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ class SpecialistMagicLinkForm(FlaskForm):
|
|||||||
description = TextAreaField('Description', validators=[Optional()])
|
description = TextAreaField('Description', validators=[Optional()])
|
||||||
magic_link_code = StringField('Magic Link Code', validators=[DataRequired(), Length(max=55)], render_kw={'readonly': True})
|
magic_link_code = StringField('Magic Link Code', validators=[DataRequired(), Length(max=55)], render_kw={'readonly': True})
|
||||||
specialist_id = SelectField('Specialist', validators=[DataRequired()])
|
specialist_id = SelectField('Specialist', validators=[DataRequired()])
|
||||||
|
tenant_make_id = SelectField('Tenant Make', validators=[Optional()], coerce=int)
|
||||||
valid_from = DateField('Valid From', id='form-control datepicker', validators=[Optional()])
|
valid_from = DateField('Valid From', id='form-control datepicker', validators=[Optional()])
|
||||||
valid_to = DateField('Valid To', id='form-control datepicker', validators=[Optional()])
|
valid_to = DateField('Valid To', id='form-control datepicker', validators=[Optional()])
|
||||||
|
|
||||||
@@ -150,9 +152,13 @@ class SpecialistMagicLinkForm(FlaskForm):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
specialists = Specialist.query.all()
|
specialists = Specialist.query.all()
|
||||||
# Dynamically populate the 'type' field using the constructor
|
# Dynamically populate the specialist field
|
||||||
self.specialist_id.choices = [(specialist.id, specialist.name) for specialist in specialists]
|
self.specialist_id.choices = [(specialist.id, specialist.name) for specialist in specialists]
|
||||||
|
|
||||||
|
# Dynamically populate the tenant_make field with None as first option
|
||||||
|
tenant_makes = TenantMake.query.all()
|
||||||
|
self.tenant_make_id.choices = [(0, 'None')] + [(make.id, make.name) for make in tenant_makes]
|
||||||
|
|
||||||
|
|
||||||
class EditSpecialistMagicLinkForm(DynamicFormBase):
|
class EditSpecialistMagicLinkForm(DynamicFormBase):
|
||||||
name = StringField('Name', validators=[DataRequired(), Length(max=50)])
|
name = StringField('Name', validators=[DataRequired(), Length(max=50)])
|
||||||
@@ -161,6 +167,8 @@ class EditSpecialistMagicLinkForm(DynamicFormBase):
|
|||||||
render_kw={'readonly': True})
|
render_kw={'readonly': True})
|
||||||
specialist_id = IntegerField('Specialist', validators=[DataRequired()], render_kw={'readonly': True})
|
specialist_id = IntegerField('Specialist', validators=[DataRequired()], render_kw={'readonly': True})
|
||||||
specialist_name = StringField('Specialist Name', validators=[DataRequired()], render_kw={'readonly': True})
|
specialist_name = StringField('Specialist Name', validators=[DataRequired()], render_kw={'readonly': True})
|
||||||
|
tenant_make_id = SelectField('Tenant Make', validators=[Optional()], coerce=int)
|
||||||
|
tenant_make_name = StringField('Tenant Make Name', validators=[Optional()], render_kw={'readonly': True})
|
||||||
valid_from = DateField('Valid From', id='form-control datepicker', validators=[Optional()])
|
valid_from = DateField('Valid From', id='form-control datepicker', validators=[Optional()])
|
||||||
valid_to = DateField('Valid To', id='form-control datepicker', validators=[Optional()])
|
valid_to = DateField('Valid To', id='form-control datepicker', validators=[Optional()])
|
||||||
|
|
||||||
@@ -176,5 +184,15 @@ class EditSpecialistMagicLinkForm(DynamicFormBase):
|
|||||||
else:
|
else:
|
||||||
self.specialist_name.data = ''
|
self.specialist_name.data = ''
|
||||||
|
|
||||||
|
# Dynamically populate the tenant_make field with None as first option
|
||||||
|
tenant_makes = TenantMake.query.all()
|
||||||
|
self.tenant_make_id.choices = [(0, 'None')] + [(make.id, make.name) for make in tenant_makes]
|
||||||
|
|
||||||
|
# If the form has a tenant_make_id that's not zero, set the tenant_make_name
|
||||||
|
if hasattr(self, 'tenant_make_id') and self.tenant_make_id.data and self.tenant_make_id.data > 0:
|
||||||
|
tenant_make = TenantMake.query.get(self.tenant_make_id.data)
|
||||||
|
if tenant_make:
|
||||||
|
self.tenant_make_name.data = tenant_make.name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -691,9 +691,13 @@ def specialist_magic_link():
|
|||||||
try:
|
try:
|
||||||
new_specialist_magic_link = SpecialistMagicLink()
|
new_specialist_magic_link = SpecialistMagicLink()
|
||||||
|
|
||||||
# Populate fields individually instead of using populate_obj (gives problem with QueryMultipleSelectField)
|
# Populate fields individually instead of using populate_obj
|
||||||
form.populate_obj(new_specialist_magic_link)
|
form.populate_obj(new_specialist_magic_link)
|
||||||
|
|
||||||
|
# Handle the tenant_make_id special case (0 = None)
|
||||||
|
if form.tenant_make_id.data == 0:
|
||||||
|
new_specialist_magic_link.tenant_make_id = None
|
||||||
|
|
||||||
set_logging_information(new_specialist_magic_link, dt.now(tz.utc))
|
set_logging_information(new_specialist_magic_link, dt.now(tz.utc))
|
||||||
|
|
||||||
# Create 'public' SpecialistMagicLinkTenant
|
# Create 'public' SpecialistMagicLinkTenant
|
||||||
@@ -733,12 +737,23 @@ def edit_specialist_magic_link(specialist_magic_link_id):
|
|||||||
|
|
||||||
form.add_dynamic_fields("arguments", specialist_config, specialist_ml.specialist_args)
|
form.add_dynamic_fields("arguments", specialist_config, specialist_ml.specialist_args)
|
||||||
|
|
||||||
|
# Set the tenant_make_id default value
|
||||||
|
if request.method == 'GET':
|
||||||
|
if specialist_ml.tenant_make_id is None:
|
||||||
|
form.tenant_make_id.data = 0
|
||||||
|
else:
|
||||||
|
form.tenant_make_id.data = specialist_ml.tenant_make_id
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
# Update the basic fields
|
# Update the basic fields
|
||||||
form.populate_obj(specialist_ml)
|
form.populate_obj(specialist_ml)
|
||||||
# Update the arguments dynamic fields
|
# Update the arguments dynamic fields
|
||||||
specialist_ml.specialist_args = form.get_dynamic_data("arguments")
|
specialist_ml.specialist_args = form.get_dynamic_data("arguments")
|
||||||
|
|
||||||
|
# Handle the tenant_make_id special case (0 = None)
|
||||||
|
if form.tenant_make_id.data == 0:
|
||||||
|
specialist_ml.tenant_make_id = None
|
||||||
|
|
||||||
# Update logging information
|
# Update logging information
|
||||||
update_logging_information(specialist_ml, dt.now(tz.utc))
|
update_logging_information(specialist_ml, dt.now(tz.utc))
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class TenantForm(FlaskForm):
|
|||||||
currency = SelectField('Currency', choices=[], validators=[DataRequired()])
|
currency = SelectField('Currency', choices=[], validators=[DataRequired()])
|
||||||
# Timezone
|
# Timezone
|
||||||
timezone = SelectField('Timezone', choices=[], validators=[DataRequired()])
|
timezone = SelectField('Timezone', choices=[], validators=[DataRequired()])
|
||||||
|
# Default tenant make
|
||||||
|
default_tenant_make_id = SelectField('Default Tenant Make', choices=[], validators=[Optional()])
|
||||||
|
|
||||||
# For Super Users only - Allow to assign the tenant to the partner
|
# For Super Users only - Allow to assign the tenant to the partner
|
||||||
assign_to_partner = BooleanField('Assign to Partner', default=False)
|
assign_to_partner = BooleanField('Assign to Partner', default=False)
|
||||||
@@ -42,6 +44,13 @@ class TenantForm(FlaskForm):
|
|||||||
self.timezone.choices = [(tz, tz) for tz in pytz.common_timezones]
|
self.timezone.choices = [(tz, tz) for tz in pytz.common_timezones]
|
||||||
# Initialize fallback algorithms
|
# Initialize fallback algorithms
|
||||||
self.type.choices = [(t, t) for t in current_app.config['TENANT_TYPES']]
|
self.type.choices = [(t, t) for t in current_app.config['TENANT_TYPES']]
|
||||||
|
# Initialize default tenant make choices
|
||||||
|
tenant_id = session.get('tenant', {}).get('id') if 'tenant' in session else None
|
||||||
|
if tenant_id:
|
||||||
|
tenant_makes = TenantMake.query.filter_by(tenant_id=tenant_id, active=True).all()
|
||||||
|
self.default_tenant_make_id.choices = [(str(make.id), make.name) for make in tenant_makes]
|
||||||
|
# Add empty choice
|
||||||
|
self.default_tenant_make_id.choices.insert(0, ('', 'Geen'))
|
||||||
# Show field only for Super Users with partner in session
|
# Show field only for Super Users with partner in session
|
||||||
if not current_user.has_roles('Super User') or 'partner' not in session:
|
if not current_user.has_roles('Super User') or 'partner' not in session:
|
||||||
self._fields.pop('assign_to_partner', None)
|
self._fields.pop('assign_to_partner', None)
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ def tenant():
|
|||||||
new_tenant = Tenant()
|
new_tenant = Tenant()
|
||||||
form.populate_obj(new_tenant)
|
form.populate_obj(new_tenant)
|
||||||
|
|
||||||
|
# Convert default_tenant_make_id to integer if not empty
|
||||||
|
if form.default_tenant_make_id.data:
|
||||||
|
new_tenant.default_tenant_make_id = int(form.default_tenant_make_id.data)
|
||||||
|
|
||||||
timestamp = dt.now(tz.utc)
|
timestamp = dt.now(tz.utc)
|
||||||
new_tenant.created_at = timestamp
|
new_tenant.created_at = timestamp
|
||||||
new_tenant.updated_at = timestamp
|
new_tenant.updated_at = timestamp
|
||||||
@@ -118,6 +122,12 @@ def edit_tenant(tenant_id):
|
|||||||
# Populate the tenant with form data
|
# Populate the tenant with form data
|
||||||
form.populate_obj(tenant)
|
form.populate_obj(tenant)
|
||||||
|
|
||||||
|
# Convert default_tenant_make_id to integer if not empty
|
||||||
|
if form.default_tenant_make_id.data:
|
||||||
|
tenant.default_tenant_make_id = int(form.default_tenant_make_id.data)
|
||||||
|
else:
|
||||||
|
tenant.default_tenant_make_id = None
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash('Tenant updated successfully.', 'success')
|
flash('Tenant updated successfully.', 'success')
|
||||||
if session.get('tenant'):
|
if session.get('tenant'):
|
||||||
@@ -462,7 +472,17 @@ def tenant_overview():
|
|||||||
tenant_id = session['tenant']['id']
|
tenant_id = session['tenant']['id']
|
||||||
tenant = Tenant.query.get_or_404(tenant_id)
|
tenant = Tenant.query.get_or_404(tenant_id)
|
||||||
form = TenantForm(obj=tenant)
|
form = TenantForm(obj=tenant)
|
||||||
return render_template('user/tenant_overview.html', form=form)
|
|
||||||
|
# Zet de waarde van default_tenant_make_id
|
||||||
|
if tenant.default_tenant_make_id:
|
||||||
|
form.default_tenant_make_id.data = str(tenant.default_tenant_make_id)
|
||||||
|
|
||||||
|
# Haal de naam van de default make op als deze bestaat
|
||||||
|
default_make_name = None
|
||||||
|
if tenant.default_tenant_make:
|
||||||
|
default_make_name = tenant.default_tenant_make.name
|
||||||
|
|
||||||
|
return render_template('user/tenant_overview.html', form=form, default_make_name=default_make_name)
|
||||||
|
|
||||||
|
|
||||||
@user_bp.route('/tenant_project', methods=['GET', 'POST'])
|
@user_bp.route('/tenant_project', methods=['GET', 'POST'])
|
||||||
@@ -727,6 +747,23 @@ def handle_tenant_make_selection():
|
|||||||
|
|
||||||
if action == 'edit_tenant_make':
|
if action == 'edit_tenant_make':
|
||||||
return redirect(prefixed_url_for('user_bp.edit_tenant_make', tenant_make_id=tenant_make_id))
|
return redirect(prefixed_url_for('user_bp.edit_tenant_make', tenant_make_id=tenant_make_id))
|
||||||
|
elif action == 'set_as_default':
|
||||||
|
# Set this make as the default for the tenant
|
||||||
|
tenant_id = session['tenant']['id']
|
||||||
|
tenant = Tenant.query.get(tenant_id)
|
||||||
|
tenant.default_tenant_make_id = tenant_make_id
|
||||||
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
flash(f'Default tenant make updated successfully.', 'success')
|
||||||
|
# Update session data if necessary
|
||||||
|
if 'tenant' in session:
|
||||||
|
session['tenant'] = tenant.to_dict()
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.session.rollback()
|
||||||
|
flash(f'Failed to update default tenant make. Error: {str(e)}', 'danger')
|
||||||
|
current_app.logger.error(f'Failed to update default tenant make. Error: {str(e)}')
|
||||||
|
|
||||||
|
return redirect(prefixed_url_for('user_bp.tenant_makes'))
|
||||||
|
|
||||||
def reset_uniquifier(user):
|
def reset_uniquifier(user):
|
||||||
security.datastore.set_uniquifier(user)
|
security.datastore.set_uniquifier(user)
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""Add default TenantMake to Tenant model
|
||||||
|
|
||||||
|
Revision ID: 83d4e90f87c6
|
||||||
|
Revises: f40d16a0965a
|
||||||
|
Create Date: 2025-06-09 15:42:51.503696
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '83d4e90f87c6'
|
||||||
|
down_revision = 'f40d16a0965a'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
|
||||||
|
with op.batch_alter_table('tenant', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('default_tenant_make_id', sa.Integer(), nullable=True))
|
||||||
|
batch_op.create_foreign_key(None, 'tenant_make', ['default_tenant_make_id'], ['id'], referent_schema='public')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('tenant', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(None, type_='foreignkey')
|
||||||
|
batch_op.drop_column('default_tenant_make_id')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
"""Add tenant_make reference to SpecialistMagicLink
|
||||||
|
|
||||||
|
Revision ID: 2b6ae6cc923e
|
||||||
|
Revises: a179785e5362
|
||||||
|
Create Date: 2025-06-09 15:59:39.157066
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
import pgvector
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '2b6ae6cc923e'
|
||||||
|
down_revision = 'a179785e5362'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('specialist_magic_link', sa.Column('tenant_make_id', sa.Integer(), nullable=True))
|
||||||
|
op.create_foreign_key(None, 'specialist_magic_link', 'tenant_make', ['tenant_make_id'], ['id'], referent_schema='public', ondelete='CASCADE')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
pass
|
||||||
|
# ### end Alembic commands ###
|
||||||
Reference in New Issue
Block a user