"""Image Blueprint: part image upload and management. Prefix: /pos/api/inventory """ from flask import Blueprint, request, jsonify, g, send_from_directory from middleware import require_auth from tenant_db import get_tenant_conn from services.image_service import save_image, delete_image, get_image_info import os image_bp = Blueprint('images', __name__, url_prefix='/pos/api/inventory') @image_bp.route('/items//image', methods=['POST']) @require_auth() def upload_item_image(item_id): """Upload an image for an inventory item. Supports multipart/form-data with 'image' file, or JSON with 'image_url'. """ tenant_id = g.tenant_id # Check if item exists conn = get_tenant_conn(tenant_id) try: cur = conn.cursor() cur.execute("SELECT id FROM inventory WHERE id = %s", (item_id,)) if not cur.fetchone(): cur.close() return jsonify({'error': 'Inventory item not found'}), 404 cur.close() file_obj = None image_url = None filename_hint = None if 'image' in request.files: file = request.files['image'] if file.filename: file_obj = file.stream filename_hint = file.filename elif request.is_json: data = request.get_json() or {} image_url = data.get('image_url') if not file_obj and not image_url: return jsonify({'error': 'No image provided. Upload via multipart "image" field or JSON "image_url"'}), 400 result = save_image(tenant_id, item_id, file_obj=file_obj, image_url=image_url, filename_hint=filename_hint) # Update inventory.image_url cur = conn.cursor() cur.execute(""" UPDATE inventory SET image_url = %s WHERE id = %s """, (result['image_url'], item_id)) conn.commit() cur.close() return jsonify(result), 201 finally: conn.close() @image_bp.route('/items//image', methods=['GET']) @require_auth() def get_item_image(item_id): """Get image info for an inventory item.""" tenant_id = g.tenant_id info = get_image_info(tenant_id, item_id) return jsonify(info) @image_bp.route('/items//image', methods=['DELETE']) @require_auth() def delete_item_image(item_id): """Delete the image for an inventory item.""" tenant_id = g.tenant_id result = delete_image(tenant_id, item_id) conn = get_tenant_conn(tenant_id) try: cur = conn.cursor() cur.execute("UPDATE inventory SET image_url = NULL WHERE id = %s", (item_id,)) conn.commit() cur.close() return jsonify({'message': 'Image deleted', 'deleted': result['deleted']}) finally: conn.close() @image_bp.route('/images/bulk', methods=['POST']) @require_auth() def bulk_import_images(): """Bulk import images from a list of {item_id, image_url} objects. Body: {"items": [{"item_id": 1, "image_url": "https://..."}, ...]} """ data = request.get_json() or {} items = data.get('items', []) if not items: return jsonify({'error': 'items array is required'}), 400 tenant_id = g.tenant_id results = {'successful': [], 'failed': []} conn = get_tenant_conn(tenant_id) try: cur = conn.cursor() for item in items: item_id = item.get('item_id') image_url = item.get('image_url') if not item_id or not image_url: results['failed'].append({'item_id': item_id, 'error': 'Missing item_id or image_url'}) continue # Verify item exists cur.execute("SELECT id FROM inventory WHERE id = %s", (item_id,)) if not cur.fetchone(): results['failed'].append({'item_id': item_id, 'error': 'Item not found'}) continue try: result = save_image(tenant_id, item_id, image_url=image_url) cur.execute("UPDATE inventory SET image_url = %s WHERE id = %s", (result['image_url'], item_id)) results['successful'].append({'item_id': item_id, 'image_url': result['image_url']}) except Exception as e: results['failed'].append({'item_id': item_id, 'error': str(e)}) conn.commit() cur.close() return jsonify(results) finally: conn.close()