2025-04-09 20:34:32 +08:00

115 lines
4.6 KiB
Python

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('/<int:batch_id>', 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