131 lines
6.3 KiB
Python
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) |