diff --git a/src/app.py b/src/app.py index 7228860..8cc4e4f 100644 --- a/src/app.py +++ b/src/app.py @@ -98,20 +98,39 @@ def update_tenant_credentials(tenant_id): tenant = database.get_tenant(tenant_id) if tenant is None: return jsonify({"error": "Tenant not found"}), 404 - + username = request.form.get('username', '').strip() password = request.form.get('password', '').strip() - + if not username: flash('Username is required.', 'error') return redirect(f'/{tenant_id}/settings') - + # Update credentials database.update_tenant_credentials(tenant_id, username, password if password else None) - + flash('Credentials updated successfully.', 'success') return redirect(f'/{tenant_id}/settings') +@app.route('//settings/barcode', methods=['POST']) +def update_tenant_barcode_type(tenant_id): + # Get tenant + tenant = database.get_tenant(tenant_id) + if tenant is None: + return jsonify({"error": "Tenant not found"}), 404 + + barcode_type = request.form.get('barcode_type', '').strip() + + if not barcode_type: + flash('Barcode type is required.', 'error') + return redirect(f'/{tenant_id}/settings') + + # Update barcode type + database.update_tenant_barcode_type(tenant_id, barcode_type) + + flash('Barcode type updated successfully.', 'success') + return redirect(f'/{tenant_id}/settings') + def check_basic_auth(auth_header, tenant_id): """Validate Basic authentication credentials for a tenant""" if not auth_header or not auth_header.startswith('Basic '): @@ -381,14 +400,13 @@ def serve_barcode(tenant_id, filename): # Import product management routes from routes.admin import (add_product, edit_product, delete_product, - generate_barcode, generate_barcode_page, manage_ar_fields) + generate_barcode, manage_ar_fields) # Register product management routes (remove /admin/ from paths) app.add_url_rule('//add', 'admin.add_product', add_product, methods=['GET', 'POST']) app.add_url_rule('//edit/', 'admin.edit_product', edit_product, methods=['GET', 'POST']) app.add_url_rule('//delete/', 'admin.delete_product', delete_product, methods=['POST']) app.add_url_rule('//generate_barcode//', 'admin.generate_barcode', generate_barcode) -app.add_url_rule('//generate_barcode_page/', 'admin.generate_barcode_page', generate_barcode_page) app.add_url_rule('//ar_fields', 'admin.manage_ar_fields', manage_ar_fields, methods=['GET', 'POST']) # Register API routes with tenant prefix diff --git a/src/database.py b/src/database.py index 13dbc63..33a60ef 100644 --- a/src/database.py +++ b/src/database.py @@ -116,7 +116,15 @@ def init_database(): updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') - + + # Add barcode_type column to tenants table if it doesn't exist + try: + cursor.execute('ALTER TABLE tenants ADD COLUMN barcode_type TEXT DEFAULT "code128"') + conn.commit() + except sqlite3.OperationalError: + # Column already exists + pass + conn.commit() def migrate_from_json(): @@ -372,20 +380,22 @@ def get_tenant(tenant_id: str) -> Optional[Dict[str, Any]]: """Get a tenant without creating it""" # Normalize tenant_id to lowercase tenant_id = tenant_id.lower() - + with get_db() as conn: cursor = conn.cursor() - + # Check if tenant exists - cursor.execute('SELECT id, name, username, password FROM tenants WHERE id = ?', (tenant_id,)) + cursor.execute('SELECT id, name, username, password, created_at, barcode_type FROM tenants WHERE id = ?', (tenant_id,)) row = cursor.fetchone() - + if row: return { 'id': row['id'], 'name': row['name'], 'username': row['username'], - 'password': row['password'] + 'password': row['password'], + 'created_at': row['created_at'], + 'barcode_type': row['barcode_type'] or 'code128' } return None @@ -393,24 +403,26 @@ def get_or_create_tenant(tenant_id: str, username: str = None, password: str = N """Get or create a tenant""" # Normalize tenant_id to lowercase tenant_id = tenant_id.lower() - + # Check if tenant_id is reserved if tenant_id in RESERVED_TENANT_IDS: return None - + with get_db() as conn: cursor = conn.cursor() - + # Check if tenant exists - cursor.execute('SELECT id, name, username, password FROM tenants WHERE id = ?', (tenant_id,)) + cursor.execute('SELECT id, name, username, password, created_at, barcode_type FROM tenants WHERE id = ?', (tenant_id,)) row = cursor.fetchone() - + if row: return { 'id': row['id'], 'name': row['name'], 'username': row['username'], - 'password': row['password'] + 'password': row['password'], + 'created_at': row['created_at'], + 'barcode_type': row['barcode_type'] or 'code128' } else: # Create new tenant with default credentials @@ -426,28 +438,48 @@ def get_or_create_tenant(tenant_id: str, username: str = None, password: str = N # Initialize default AR fields for the new tenant init_default_ar_fields(tenant_id) - + + # Get the created_at timestamp and barcode_type from the database + cursor.execute('SELECT created_at, barcode_type FROM tenants WHERE id = ?', (tenant_id,)) + created_row = cursor.fetchone() + return { 'id': tenant_id, 'name': display_name, 'username': default_username, - 'password': default_password + 'password': default_password, + 'created_at': created_row['created_at'] if created_row else None, + 'barcode_type': created_row['barcode_type'] if created_row else 'code128' } def update_tenant_credentials(tenant_id: str, username: str, password: str): """Update tenant credentials""" # Normalize tenant_id to lowercase tenant_id = tenant_id.lower() - + with get_db() as conn: cursor = conn.cursor() cursor.execute(''' - UPDATE tenants + UPDATE tenants SET username = ?, password = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? ''', (username, password, tenant_id)) conn.commit() +def update_tenant_barcode_type(tenant_id: str, barcode_type: str): + """Update tenant barcode type""" + # Normalize tenant_id to lowercase + tenant_id = tenant_id.lower() + + with get_db() as conn: + cursor = conn.cursor() + cursor.execute(''' + UPDATE tenants + SET barcode_type = ?, updated_at = CURRENT_TIMESTAMP + WHERE id = ? + ''', (barcode_type, tenant_id)) + conn.commit() + def get_all_tenants() -> List[Dict[str, Any]]: """Get all tenants""" with get_db() as conn: diff --git a/src/routes/admin.py b/src/routes/admin.py index 1b24498..6bea8d4 100644 --- a/src/routes/admin.py +++ b/src/routes/admin.py @@ -1,24 +1,9 @@ -from flask import render_template, request, redirect, url_for, flash, jsonify, send_file +from flask import render_template, request, redirect, url_for, flash, jsonify import os -import json -import uuid -import io -from werkzeug.utils import secure_filename import sys sys.path.append(os.path.dirname(os.path.dirname(__file__))) import database -# Import barcode generator class, but handle the case if it fails -try: - from utils.barcode_generator import BarcodeGenerator - BARCODE_GENERATOR_AVAILABLE = True -except ImportError: - BARCODE_GENERATOR_AVAILABLE = False - class BarcodeGenerator: - @staticmethod - def check_dependencies(): - return {'qrcode': False, 'barcode': False, 'pillow': False} - DATA_FOLDER = os.path.join(os.path.dirname(__file__), '../data') PRODUCTS_FILE = os.path.join(DATA_FOLDER, 'products.json') UPLOAD_FOLDER = os.path.join(DATA_FOLDER, 'images') @@ -344,40 +329,6 @@ def generate_barcode(tenant_id, product_id, code_type): # Redirect to the main barcode endpoint which generates dynamically return redirect(f'/{tenant_id}/barcodes/{product_id}_{barcode_type}.png') -def generate_barcode_page(tenant_id, product_id): - """Show a page with different barcode options for a product""" - products = load_products(tenant_id) - - if product_id not in products: - flash('Product not found.') - return redirect(f'/{tenant_id}/') - - # Extract product data - product_data = {} - for field in products[product_id]: - field_name = field["fieldName"][1:] if field["fieldName"].startswith('_') else field["fieldName"] - product_data[field_name] = field["value"] - - # Add product ID - product_data['id'] = product_id - - # Check if barcode generation is available - dependency_status = {} - if BARCODE_GENERATOR_AVAILABLE: - dependency_status = BarcodeGenerator.check_dependencies() - else: - dependency_status = { - 'qrcode': False, - 'barcode': False, - 'pillow': False - } - - return render_template('admin/generate_barcode.html', - product_id=product_id, - product=product_data, - dependencies=dependency_status, - tenant_id=tenant_id) - def manage_credentials(tenant_id): """Manage tenant login credentials""" tenant = database.get_or_create_tenant(tenant_id) diff --git a/src/templates/admin/generate_barcode.html b/src/templates/admin/generate_barcode.html deleted file mode 100644 index dd94df4..0000000 --- a/src/templates/admin/generate_barcode.html +++ /dev/null @@ -1,150 +0,0 @@ -{% extends "layout.html" %} - -{% block title %}Generate Barcodes - KCAP Demo Server{% endblock %} - -{% block content %} -
-
-
-
-

Generate Barcodes for Product: {{ product_id }}

- Back to Products -
-
- {% if not dependencies.qrcode or not dependencies.barcode or not dependencies.pillow %} -
-

Missing Dependencies

-

Some barcode generation features are unavailable because required packages are not installed:

-
    - {% if not dependencies.qrcode %} -
  • QR Code: The 'qrcode' package is required for QR code generation
  • - {% endif %} - {% if not dependencies.barcode %} -
  • Barcodes: The 'python-barcode' package is required for EAN-13 and Code 128 generation
  • - {% endif %} - {% if not dependencies.pillow %} -
  • Image Processing: The 'Pillow' package is required for image processing
  • - {% endif %} -
-
-

To install the required dependencies, run: pip install -r requirements.txt

-
- {% endif %} - -
-
-
-
-

QR Code

-
-
- QR Code -

QR Code contains a link to the product AR info.

- Download QR Code -
-
-
- -
-
-
-

EAN-13 Barcode

-
-
- EAN-13 Barcode -

Standard EAN-13 barcode format.

- Download EAN-13 -
-
-
- -
-
-
-

Code 128 Barcode

-
-
- Code 128 Barcode -

High-density alphanumeric barcode.

- Download Code 128 -
-
-
-
- -
-
-
-
-

Product Information

-
-
-
-
-

Product ID: {{ product_id }}

-

Price: {{ product.price }}

-
- -
- {% if product.image %} - Product Image - {% else %} -

No product image available

- {% endif %} -
-
-
-
-
-
- -
-
-
-
-

Print All Codes

-
-
-

Use the button below to open a printable version of all barcodes for this product.

- -
-
-
-
-
-
-
-
-{% endblock %} - -{% block extra_css %} - -{% endblock %} diff --git a/src/templates/index.html b/src/templates/index.html index 7f394b3..65e1a0f 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -61,9 +61,12 @@ Edit - - Barcodes - + + + + + + + +