146 lines
4.9 KiB
Python
146 lines
4.9 KiB
Python
from flask import Blueprint, Response, jsonify, request
|
|
|
|
from app.routes.auth_decorators import require_auth
|
|
from app.services.analytics.export_sections import export_filename_base, parse_export_sections
|
|
from app.services.analytics.finance_summary import build_finance_summary
|
|
from app.services.analytics.pdf_export import build_analytics_pdf
|
|
from app.services.analytics.plan_fact_layers import build_plan_fact_rows
|
|
from app.services.analytics.stock_forecast import build_stock_forecast
|
|
from app.services.analytics.xlsx_summary import build_finance_summary_xlsx
|
|
|
|
bp = Blueprint("analytics", __name__, url_prefix="/api/analytics")
|
|
|
|
|
|
def _error(message: str, status_code: int = 400):
|
|
return jsonify({"error": True, "message": message}), status_code
|
|
|
|
|
|
def _export_params():
|
|
date_from = (request.args.get("date_from") or "").strip()
|
|
date_to = (request.args.get("date_to") or "").strip()
|
|
if not date_from or not date_to:
|
|
return None, None, None, None, _error("Укажите date_from и date_to (YYYY-MM-DD)", 400)
|
|
recipe_id = (request.args.get("recipe_id") or "").strip() or None
|
|
recipe_ids = (request.args.get("recipe_ids") or "").strip() or None
|
|
return date_from, date_to, recipe_id, recipe_ids, None
|
|
|
|
|
|
@bp.get("/finance")
|
|
@require_auth
|
|
def finance_summary():
|
|
return jsonify(
|
|
build_finance_summary(
|
|
date_from=request.args.get("date_from"),
|
|
date_to=request.args.get("date_to"),
|
|
recipe_id=(request.args.get("recipe_id") or "").strip() or None,
|
|
recipe_ids=(request.args.get("recipe_ids") or "").strip() or None,
|
|
)
|
|
)
|
|
|
|
|
|
@bp.get("/plan-fact")
|
|
@require_auth
|
|
def plan_fact():
|
|
return jsonify(
|
|
build_plan_fact_rows(
|
|
date_from=request.args.get("date_from"),
|
|
date_to=request.args.get("date_to"),
|
|
recipe_id=(request.args.get("recipe_id") or "").strip() or None,
|
|
recipe_ids=(request.args.get("recipe_ids") or "").strip() or None,
|
|
client_id=(request.args.get("client_id") or "").strip() or None,
|
|
)
|
|
)
|
|
|
|
|
|
@bp.get("/stock-forecast")
|
|
@require_auth
|
|
def stock_forecast():
|
|
from app.models import Component
|
|
|
|
return jsonify(
|
|
build_stock_forecast(
|
|
plan_date=request.args.get("plan_date"),
|
|
Component=Component,
|
|
)
|
|
)
|
|
|
|
|
|
def _filter_context_kwargs():
|
|
return {
|
|
"filter_farms": (request.args.get("filter_farms") or "").strip() or None,
|
|
"filter_dispensers": (request.args.get("filter_dispensers") or "").strip() or None,
|
|
"filter_recipes": (request.args.get("filter_recipes") or "").strip() or None,
|
|
}
|
|
|
|
|
|
@bp.get("/export")
|
|
@require_auth
|
|
def analytics_export():
|
|
date_from, date_to, recipe_id, recipe_ids, err = _export_params()
|
|
if err:
|
|
return err
|
|
fmt = (request.args.get("format") or "xlsx").strip().lower()
|
|
section = (request.args.get("section") or "all").strip().lower()
|
|
sections = parse_export_sections(section)
|
|
base_name = export_filename_base(
|
|
date_from=date_from, date_to=date_to, sections=sections
|
|
)
|
|
ctx = _filter_context_kwargs()
|
|
if fmt == "pdf":
|
|
data = build_analytics_pdf(
|
|
date_from=date_from,
|
|
date_to=date_to,
|
|
recipe_id=recipe_id,
|
|
recipe_ids=recipe_ids,
|
|
section=section,
|
|
**ctx,
|
|
)
|
|
return Response(
|
|
data,
|
|
mimetype="application/pdf",
|
|
headers={
|
|
"Content-Disposition": f'attachment; filename="{base_name}.pdf"'
|
|
},
|
|
)
|
|
if fmt in ("xlsx", "excel"):
|
|
data = build_finance_summary_xlsx(
|
|
date_from=date_from,
|
|
date_to=date_to,
|
|
recipe_id=recipe_id,
|
|
recipe_ids=recipe_ids,
|
|
section=section,
|
|
**ctx,
|
|
)
|
|
return Response(
|
|
data,
|
|
mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
headers={
|
|
"Content-Disposition": f'attachment; filename="{base_name}.xlsx"'
|
|
},
|
|
)
|
|
return _error("format должен быть xlsx или pdf", 400)
|
|
|
|
|
|
@bp.get("/finance/export")
|
|
@require_auth
|
|
def finance_export():
|
|
date_from, date_to, recipe_id, recipe_ids, err = _export_params()
|
|
if err:
|
|
return err
|
|
section = (request.args.get("section") or "all").strip().lower()
|
|
sections = parse_export_sections(section)
|
|
data = build_finance_summary_xlsx(
|
|
date_from=date_from,
|
|
date_to=date_to,
|
|
recipe_id=recipe_id,
|
|
recipe_ids=recipe_ids,
|
|
section=section,
|
|
**_filter_context_kwargs(),
|
|
)
|
|
filename = f"{export_filename_base(date_from=date_from, date_to=date_to, sections=sections)}.xlsx"
|
|
return Response(
|
|
data,
|
|
mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
|
)
|