Add optional default product fields on tenant creation

When creating a new tenant, users can now choose to initialize with default product fields (Product Name, Item ID, Sale Price, and Image). The option is presented via a checkbox in the tenant creation modal and is enabled by default.
This commit is contained in:
2025-10-20 21:13:05 -04:00
parent 25e3848710
commit a727796ed2
3 changed files with 80 additions and 2 deletions

View File

@@ -13,9 +13,20 @@ def index(tenant_id):
if tenant is None: if tenant is None:
return jsonify({"error": f"'{tenant_id}' is a reserved name and cannot be used as a tenant ID"}), 404 return jsonify({"error": f"'{tenant_id}' is a reserved name and cannot be used as a tenant ID"}), 404
products = ProductModel.get_all(tenant_id) # Check if we should create default fields for a new tenant
create_defaults = request.args.get('create_defaults', '0') == '1'
custom_fields = ARFieldModel.get_all(tenant_id) custom_fields = ARFieldModel.get_all(tenant_id)
# If no custom fields exist and user requested defaults, create them
if create_defaults and not custom_fields:
ARFieldModel.create_default_fields(tenant_id)
custom_fields = ARFieldModel.get_all(tenant_id)
flash('Tenant created with default product fields!', 'success')
# Redirect to remove the query parameter
return redirect(f'/{tenant_id}/')
products = ProductModel.get_all(tenant_id)
return render_template('index.html', tenant=tenant, products=products, custom_fields=custom_fields) return render_template('index.html', tenant=tenant, products=products, custom_fields=custom_fields)
@tenant_bp.route('/delete', methods=['POST']) @tenant_bp.route('/delete', methods=['POST'])

View File

@@ -82,3 +82,56 @@ class ARFieldModel:
cursor.execute('DELETE FROM custom_ar_fields WHERE id = ? AND tenant_id = ?', cursor.execute('DELETE FROM custom_ar_fields WHERE id = ? AND tenant_id = ?',
(field_id, tenant_id)) (field_id, tenant_id))
conn.commit() conn.commit()
@staticmethod
def create_default_fields(tenant_id: str):
"""Create default product fields for a new tenant"""
tenant_id = tenant_id.lower()
default_fields = [
{
'fieldName': '_name',
'label': 'Product Name',
'fieldType': 'TEXT',
'editable': 'true',
'displayOrder': 0
},
{
'fieldName': '_id',
'label': 'Item ID',
'fieldType': 'TEXT',
'editable': 'false',
'displayOrder': 1
},
{
'fieldName': '_price',
'label': 'Sale Price',
'fieldType': 'TEXT',
'editable': 'true',
'displayOrder': 2
},
{
'fieldName': '_image',
'label': 'Image',
'fieldType': 'IMAGE_URI',
'editable': 'true',
'displayOrder': 3
}
]
with get_db() as conn:
cursor = conn.cursor()
for field in default_fields:
cursor.execute('''
INSERT INTO custom_ar_fields
(tenant_id, field_name, label, field_type, editable, display_order)
VALUES (?, ?, ?, ?, ?, ?)
''', (
tenant_id,
field['fieldName'],
field['label'],
field['fieldType'],
field['editable'],
field['displayOrder']
))
conn.commit()

View File

@@ -160,6 +160,15 @@
<input type="text" class="form-control" id="tenantId" placeholder="e.g., demo-company" required pattern="[a-zA-Z0-9_-]+"> <input type="text" class="form-control" id="tenantId" placeholder="e.g., demo-company" required pattern="[a-zA-Z0-9_-]+">
<small class="form-text text-muted">Only letters, numbers, hyphens, and underscores allowed</small> <small class="form-text text-muted">Only letters, numbers, hyphens, and underscores allowed</small>
</div> </div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="createDefaultFields" checked>
<label class="form-check-label" for="createDefaultFields">
Create products with default fields
</label>
</div>
<small class="form-text text-muted">Adds: Product Name, Item ID, Sale Price, and Image fields</small>
</div>
<div class="alert alert-info"> <div class="alert alert-info">
<i class="bi bi-info-circle"></i> <i class="bi bi-info-circle"></i>
<small>Default credentials: <strong>admin</strong> / <strong>admin</strong></small> <small>Default credentials: <strong>admin</strong> / <strong>admin</strong></small>
@@ -237,13 +246,18 @@
document.getElementById('newTenantForm').addEventListener('submit', function(e) { document.getElementById('newTenantForm').addEventListener('submit', function(e) {
e.preventDefault(); e.preventDefault();
const tenantId = document.getElementById('tenantId').value; const tenantId = document.getElementById('tenantId').value;
const createDefaults = document.getElementById('createDefaultFields').checked;
if (tenantId) { if (tenantId) {
const normalizedId = tenantId.toLowerCase(); const normalizedId = tenantId.toLowerCase();
if (reservedIds.includes(normalizedId)) { if (reservedIds.includes(normalizedId)) {
alert(`"${tenantId}" is a reserved name and cannot be used as a tenant ID.`); alert(`"${tenantId}" is a reserved name and cannot be used as a tenant ID.`);
return; return;
} }
window.location.href = '/' + normalizedId + '/';
// Redirect with query parameter for default fields
const url = '/' + normalizedId + '/' + (createDefaults ? '?create_defaults=1' : '');
window.location.href = url;
} }
}); });