96 lines
4.2 KiB
Python
96 lines
4.2 KiB
Python
import datetime
|
|
from flask import Blueprint, request, jsonify
|
|
from flask_jwt_extended import jwt_required, get_jwt_identity
|
|
from .database import db, ConsumptionRecord, MilkBatch, User
|
|
from .utils import convert_volume
|
|
|
|
consumption_bp = Blueprint('consumption', __name__, url_prefix='/api/consumption')
|
|
|
|
@consumption_bp.route('', methods=['POST'])
|
|
@jwt_required()
|
|
def record_consumption():
|
|
current_user_id = get_jwt_identity()
|
|
data = request.get_json()
|
|
if not data: return jsonify({"error": "Request must be JSON"}), 400
|
|
|
|
batch_id = data.get('milkBatchId')
|
|
amount_str = data.get('amountConsumed')
|
|
unit = data.get('unitConsumed') # 'ml', 'L', 'items'
|
|
consumed_at_str = data.get('dateConsumed', datetime.datetime.utcnow().isoformat())
|
|
|
|
# --- Validation ---
|
|
if not batch_id or amount_str is None or not unit:
|
|
return jsonify({"error": "Missing fields: milkBatchId, amountConsumed, unitConsumed"}), 400
|
|
if unit not in ['ml', 'L', 'items']:
|
|
return jsonify({"error": "Invalid unitConsumed."}), 400
|
|
try:
|
|
amount = float(amount_str)
|
|
if amount <= 0: raise ValueError("Amount must be positive.")
|
|
except (ValueError, TypeError):
|
|
return jsonify({"error": "Invalid number format for amountConsumed."}), 400
|
|
try:
|
|
# Attempt to parse date, fallback to now if invalid format
|
|
consumed_time = datetime.datetime.fromisoformat(consumed_at_str.replace('Z', '+00:00'))
|
|
except ValueError:
|
|
consumed_time = datetime.datetime.utcnow()
|
|
|
|
# --- Find Batch & Check Status ---
|
|
batch = MilkBatch.query.filter_by(id=batch_id, user_id=current_user_id, is_deleted=False).first()
|
|
if not batch: return jsonify({"error": "Milk batch not found or invalid."}), 404
|
|
if batch.remaining_volume < 0.001: return jsonify({"error": "Selected milk batch is empty."}), 400
|
|
if batch.expiry_date < datetime.date.today():
|
|
# Optionally warn or prevent consuming expired? For now, allow but maybe log.
|
|
print(f"Warning: Consuming from expired batch {batch_id}")
|
|
|
|
# --- Calculate Consumed Volume in Batch's Unit ---
|
|
try:
|
|
consumed_volume_in_batch_unit = 0
|
|
if unit == 'items':
|
|
consumed_volume_in_batch_unit = amount * batch.volume_per_item
|
|
elif unit == batch.volume_unit:
|
|
consumed_volume_in_batch_unit = amount
|
|
else: # Convert (e.g., L consumed from ml batch)
|
|
consumed_volume_in_batch_unit = convert_volume(amount, unit, batch.volume_unit)
|
|
|
|
# --- Check Availability & Update ---
|
|
# Use tolerance for float comparison
|
|
if consumed_volume_in_batch_unit > (batch.remaining_volume + 0.001):
|
|
return jsonify({"error": f"Not enough milk. Only {batch.remaining_volume:.2f} {batch.volume_unit} left."}), 400
|
|
|
|
batch.remaining_volume -= consumed_volume_in_batch_unit
|
|
batch.remaining_volume = max(0, batch.remaining_volume) # Prevent going negative
|
|
|
|
# --- Record Consumption ---
|
|
new_record = ConsumptionRecord(
|
|
user_id=current_user_id,
|
|
milk_batch_id=batch_id,
|
|
amount_consumed=amount, # Log the originally entered amount/unit
|
|
unit_consumed=unit,
|
|
consumed_at=consumed_time
|
|
)
|
|
db.session.add(new_record)
|
|
db.session.commit()
|
|
# Return updated batch state
|
|
return jsonify(batch.to_dict()), 201
|
|
|
|
except (ValueError, TypeError) as e:
|
|
db.session.rollback()
|
|
return jsonify({"error": f"Invalid input or calculation error: {e}"}), 400
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
print(f"Error recording consumption: {e}")
|
|
return jsonify({"error": "Database error occurred."}), 500
|
|
|
|
@consumption_bp.route('', methods=['GET'])
|
|
@jwt_required()
|
|
def get_consumption_history():
|
|
current_user_id = get_jwt_identity()
|
|
# Add pagination later if needed
|
|
limit = request.args.get('limit', 50, type=int)
|
|
offset = request.args.get('offset', 0, type=int)
|
|
|
|
records = ConsumptionRecord.query.filter_by(user_id=current_user_id)\
|
|
.order_by(ConsumptionRecord.consumed_at.desc())\
|
|
.limit(limit).offset(offset).all()
|
|
|
|
return jsonify([record.to_dict() for record in records]), 200 |