import datetime from flask import Blueprint, request, jsonify from flask_jwt_extended import jwt_required, get_jwt_identity from .database import db, MilkBatch, User from .utils import calculate_expiry_date, convert_volume milk_bp = Blueprint('milk', __name__, url_prefix='/api/milk') @milk_bp.route('', methods=['POST']) @jwt_required() def add_milk(): current_user_id = get_jwt_identity() data = request.get_json() if not data: return jsonify({"error": "Request must be JSON"}), 400 expiry_date_str = data.get('expiryDate') production_date_str = data.get('productionDate') shelf_life = data.get('shelfLife') shelf_unit = data.get('shelfUnit', 'days') initial_quantity_items = data.get('quantity') volume_per_item = data.get('volumePerItem') volume_unit = data.get('unit') # 'ml' or 'L' note = data.get('note') # --- Validation --- if not initial_quantity_items or volume_per_item is None or not volume_unit: return jsonify({"error": "Missing required fields: quantity, volumePerItem, unit"}), 400 if volume_unit not in ['ml', 'L']: return jsonify({"error": "Invalid volume unit. Use 'ml' or 'L'."}), 400 try: initial_quantity_items = int(initial_quantity_items) volume_per_item = float(volume_per_item) if initial_quantity_items <= 0 or volume_per_item <= 0: raise ValueError("Quantity and volume must be positive.") except (ValueError, TypeError): return jsonify({"error": "Invalid number format for quantity or volumePerItem."}), 400 # --- Determine Expiry Date --- expiry_date = None if expiry_date_str: try: expiry_date = datetime.date.fromisoformat(expiry_date_str) except ValueError: return jsonify({"error": "Invalid expiryDate format. Use YYYY-MM-DD."}), 400 elif production_date_str and shelf_life: expiry_date = calculate_expiry_date(production_date_str, shelf_life, shelf_unit) if not expiry_date: return jsonify({"error": "Invalid productionDate or shelfLife for expiry calculation."}), 400 else: return jsonify({"error": "Either expiryDate or (productionDate and shelfLife) is required."}), 400 # --- Production Date (Optional) --- prod_date = None if production_date_str: try: prod_date = datetime.date.fromisoformat(production_date_str) except ValueError: # Allow if only expiry date was provided, otherwise error if not expiry_date_str: return jsonify({"error": "Invalid productionDate format. Use YYYY-MM-DD."}), 400 # --- Create Batch --- initial_remaining_volume = initial_quantity_items * volume_per_item new_batch = MilkBatch( user_id=current_user_id, production_date=prod_date, expiry_date=expiry_date, initial_quantity_items=initial_quantity_items, volume_per_item=volume_per_item, volume_unit=volume_unit, note=note, remaining_volume=initial_remaining_volume, is_deleted=False ) db.session.add(new_batch) try: db.session.commit() return jsonify(new_batch.to_dict()), 201 except Exception as e: db.session.rollback() print(f"Error adding milk batch: {e}") return jsonify({"error": "Database error occurred."}), 500 @milk_bp.route('', methods=['GET']) @jwt_required() def get_milk_batches(): current_user_id = get_jwt_identity() include_deleted = request.args.get('includeDeleted', 'false').lower() == 'true' only_active = request.args.get('onlyActive', 'true').lower() == 'true' # Only not empty and not expired query = MilkBatch.query.filter_by(user_id=current_user_id) if not include_deleted: query = query.filter_by(is_deleted=False) if only_active: query = query.filter(MilkBatch.remaining_volume > 0.001) # Check remaining volume with tolerance query = query.filter(MilkBatch.expiry_date >= datetime.date.today()) # Sort by expiry date (soonest first) batches = query.order_by(MilkBatch.expiry_date.asc()).all() return jsonify([batch.to_dict() for batch in batches]), 200 @milk_bp.route('/', methods=['DELETE']) @jwt_required() def delete_milk_batch(batch_id): current_user_id = get_jwt_identity() batch = MilkBatch.query.filter_by(id=batch_id, user_id=current_user_id).first() if not batch: return jsonify({"error": "Milk batch not found or access denied."}), 404 if batch.is_deleted: return jsonify({"message": "Batch already deleted."}), 200 batch.is_deleted = True # Soft delete db.session.commit() return '', 204