Files
site/WESP_REL/tests/test_sklad_metrics.py
2026-07-17 12:57:18 +03:00

200 lines
6.5 KiB
Python

"""Тесты sklad_metrics (общие расчёты склада)."""
from __future__ import annotations
import os
import tempfile
import unittest
import uuid
from datetime import datetime
from app import create_app, db
from app.models import Component, ComponentStock, LoadingReport, LoadingReportComponent
from app.services.sklad_metrics import (
consumed_by_component_id,
effective_consumed_kg,
list_stock_balance_items,
month_consumption_by_component,
)
from config import TestingConfig
class SkladMetricsTestConfig(TestingConfig):
_TMP_DIR = tempfile.mkdtemp(prefix="wesp-sklad-metrics-")
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(_TMP_DIR, 'recipes_test.db')}"
SQLALCHEMY_BINDS = {"reports": f"sqlite:///{os.path.join(_TMP_DIR, 'reports_test.db')}"}
class SkladMetricsTests(unittest.TestCase):
def setUp(self) -> None:
self.app = create_app(SkladMetricsTestConfig)
self.ctx = self.app.app_context()
self.ctx.push()
db.create_all()
self._seed()
def tearDown(self) -> None:
db.session.remove()
db.drop_all()
self.ctx.pop()
def _seed(self) -> None:
comp = Component(name="Сено", type="roughage")
db.session.add(comp)
db.session.flush()
db.session.add(
ComponentStock(
component_id=comp.id,
component_name=comp.name,
total_kg=500.0,
stocktake_at=datetime.now(),
updated_at=datetime.now(),
)
)
report = LoadingReport(
id=str(uuid.uuid4()),
recipe_id=str(uuid.uuid4()),
recipe_name="R1",
start_time=datetime.now(),
dispenser_type="dispenser",
)
db.session.add(report)
db.session.flush()
db.session.add(
LoadingReportComponent(
report_id=report.id,
component_id=comp.id,
component_name=comp.name,
target_weight=10.0,
actual_weight=7.5,
loading_order=1,
)
)
db.session.commit()
self.comp_id = comp.id
def test_consumed_by_component_id(self) -> None:
with self.app.app_context():
data = consumed_by_component_id(
db, LoadingReport, LoadingReportComponent
)
self.assertAlmostEqual(data.get(self.comp_id, 0), 7.5)
def test_list_stock_balance_items(self) -> None:
today = datetime.now().date()
start = today.replace(day=1).isoformat()
end = today.isoformat()
with self.app.app_context():
items = list_stock_balance_items(
db,
LoadingReport,
LoadingReportComponent,
None,
None,
date_from=start,
date_to=end,
)
self.assertEqual(len(items), 1)
self.assertEqual(items[0]["name"], "Сено")
self.assertAlmostEqual(items[0]["consumed_total_kg"], 7.5)
def test_effective_consumed_kg_zero_actual_uses_target(self) -> None:
self.assertAlmostEqual(effective_consumed_kg(0, 0, 12.5), 12.5)
self.assertAlmostEqual(effective_consumed_kg(0, -2, 12.5), 12.5)
self.assertAlmostEqual(effective_consumed_kg(8, 1.5, 10), 9.5)
self.assertAlmostEqual(effective_consumed_kg(8, -1, 10), 8.0)
def test_consumed_zero_actual_with_target(self) -> None:
report = LoadingReport(
id=str(uuid.uuid4()),
recipe_id=str(uuid.uuid4()),
recipe_name="R2",
start_time=datetime.now(),
dispenser_type="dispenser",
)
db.session.add(report)
db.session.flush()
db.session.add(
LoadingReportComponent(
report_id=report.id,
component_id=self.comp_id,
component_name="Сено",
target_weight=15.0,
actual_weight=0.0,
loading_order=1,
)
)
db.session.commit()
with self.app.app_context():
data = consumed_by_component_id(db, LoadingReport, LoadingReportComponent)
self.assertAlmostEqual(data.get(self.comp_id, 0), 22.5)
def test_consumed_matches_by_name_when_id_differs(self) -> None:
report = LoadingReport(
id=str(uuid.uuid4()),
recipe_id=str(uuid.uuid4()),
recipe_name="R-name",
start_time=datetime.now(),
dispenser_type="dispenser",
)
db.session.add(report)
db.session.flush()
db.session.add(
LoadingReportComponent(
report_id=report.id,
component_id="other-id-123",
component_name="Сено",
target_weight=10.0,
actual_weight=4.0,
loading_order=1,
)
)
db.session.commit()
today = datetime.now().date()
start = today.replace(day=1).isoformat()
end = today.isoformat()
with self.app.app_context():
items = list_stock_balance_items(
db,
LoadingReport,
LoadingReportComponent,
None,
None,
date_from=start,
date_to=end,
)
stock_item = next(i for i in items if i.get("has_stock"))
self.assertAlmostEqual(stock_item["consumed_total_kg"], 11.5)
def test_month_consumption_without_stock_row(self) -> None:
now = datetime.now()
report = LoadingReport(
id=str(uuid.uuid4()),
recipe_id=str(uuid.uuid4()),
recipe_name="R3",
start_time=now,
dispenser_type="dispenser",
)
db.session.add(report)
db.session.flush()
db.session.add(
LoadingReportComponent(
report_id=report.id,
component_id=None,
component_name="Силос",
target_weight=20.0,
actual_weight=0.0,
loading_order=1,
)
)
db.session.commit()
with self.app.app_context():
agg = month_consumption_by_component(
db, LoadingReport, LoadingReportComponent, now.year, now.month
)
self.assertTrue(any("Силос" in (m.get("name") or "") for m in agg.values()))
if __name__ == "__main__":
unittest.main()