Files
Aislo/B08_wf5_Quantity/B08_wf5_Quantity_Repository_Basis.py
T
2026-07-25 19:41:05 +09:00

131 lines
6.3 KiB
Python

import json
from B08_wf5_Quantity.B08_wf5_Quantity_Repository_Stale import StaleRepository
from B08_wf5_Quantity.B08_wf5_Quantity_Schema_Basis import (
BasisWorkspace,
ExchangeRate,
PriceSource,
RatePolicy,
)
class BasisRepository:
def __init__(self, connection):
self.db = connection
async def load(self, project_id: str, version: str) -> BasisWorkspace | None:
async with self.db.cursor() as cursor:
await cursor.execute(
"SELECT * FROM b08_basis_versions WHERE project_id=%s AND version=%s",
(project_id, version),
)
head = await cursor.fetchone()
if not head:
return None
await cursor.execute(
"""SELECT * FROM b08_price_sources
WHERE project_id=%s AND status='ACTIVE' ORDER BY priority_no""",
(project_id,),
)
sources = list(await cursor.fetchall())
await cursor.execute(
"SELECT * FROM b08_exchange_rates WHERE project_id=%s AND basis_version=%s",
(project_id, version),
)
rates = list(await cursor.fetchall())
await cursor.execute(
"""SELECT * FROM b08_rate_policies
WHERE project_id=%s AND basis_version=%s ORDER BY sort_order""",
(project_id, version),
)
policies = list(await cursor.fetchall())
return BasisWorkspace(
project_id=project_id,
version=version,
base_date=head["base_date"],
region=head["region"],
currency=head["currency"],
status=head["status"],
price_sources=[PriceSource.model_validate(row) for row in sources],
exchange_rates=[ExchangeRate.model_validate(row) for row in rates],
rate_policies=[self._policy(row) for row in policies],
)
async def save(self, data: BasisWorkspace, user_id: int | None) -> None:
async with self.db.cursor() as cursor:
await cursor.execute(
"""INSERT INTO b08_basis_versions(
project_id,version,base_date,region,currency,status,confirmed_by,confirmed_at
) VALUES(%s,%s,%s,%s,%s,%s,%s,
IF(%s='CONFIRMED',CURRENT_TIMESTAMP,NULL))
ON DUPLICATE KEY UPDATE
base_date=VALUES(base_date),region=VALUES(region),currency=VALUES(currency),
status=VALUES(status),confirmed_by=VALUES(confirmed_by),
confirmed_at=VALUES(confirmed_at)""",
(data.project_id, data.version, data.base_date, data.region, data.currency,
data.status, user_id if data.status == "CONFIRMED" else None, data.status),
)
await self._invalidate_dependents(cursor, data.project_id, data.version)
await cursor.execute(
"UPDATE b08_price_sources SET status='INACTIVE' WHERE project_id=%s",
(data.project_id,),
)
for source in data.price_sources:
await cursor.execute(
"""INSERT INTO b08_price_sources(
id,project_id,source_code,source_name,priority_no,publisher,
reference_date,status
) VALUES(%s,%s,%s,%s,%s,%s,%s,'ACTIVE')
ON DUPLICATE KEY UPDATE source_name=VALUES(source_name),
priority_no=VALUES(priority_no),publisher=VALUES(publisher),
reference_date=VALUES(reference_date),status='ACTIVE'""",
(source.id, data.project_id, source.source_code, source.source_name,
source.priority_no, source.publisher, source.reference_date),
)
await cursor.execute(
"DELETE FROM b08_exchange_rates WHERE project_id=%s AND basis_version=%s",
(data.project_id, data.version),
)
for rate in data.exchange_rates:
await cursor.execute(
"""INSERT INTO b08_exchange_rates(
project_id,basis_version,currency,rate_to_krw,source_id,
effective_from,effective_to
) VALUES(%s,%s,%s,%s,%s,%s,%s)""",
(data.project_id, data.version, rate.currency, rate.rate_to_krw,
rate.source_id, rate.effective_from, rate.effective_to),
)
await cursor.execute(
"DELETE FROM b08_rate_policies WHERE project_id=%s AND basis_version=%s",
(data.project_id, data.version),
)
for policy in data.rate_policies:
await cursor.execute(
"""INSERT INTO b08_rate_policies(
project_id,basis_version,rule_code,rule_name,base_expression,
rate_value,minimum_amount,maximum_amount,rounding_mode,
rounding_unit,condition_json,source_reference,status,sort_order
) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""",
(data.project_id, data.version, policy.rule_code, policy.rule_name,
policy.base_expression, policy.rate_value, policy.minimum_amount,
policy.maximum_amount, policy.rounding_mode, policy.rounding_unit,
json.dumps(policy.condition_json, ensure_ascii=False),
policy.source_reference, policy.status, policy.sort_order),
)
await self.db.commit()
@staticmethod
def _policy(row: dict) -> RatePolicy:
values = dict(row)
condition = values.get("condition_json")
values["condition_json"] = json.loads(condition) if isinstance(condition, str) else (condition or {})
return RatePolicy.model_validate(values)
@staticmethod
async def _invalidate_dependents(cursor, project_id: str, version: str) -> None:
await cursor.execute(
"""UPDATE b08_price_books SET status='STALE'
WHERE project_id=%s AND basis_version=%s AND status='CONFIRMED'""",
(project_id, version),
)
await StaleRepository.mark_all(cursor, project_id)