fix update bulk master data

main
MrWaradana 2 months ago
parent 8a3833b32a
commit 72f913e308

@ -36,7 +36,7 @@ async def get_all(
*, db_session: DbSession, items_per_page: int, search: str = None, common
) -> list[MasterData]:
"""Returns all documents."""
query = Select(MasterData)
query = Select(MasterData).order_by(MasterData.description.asc())
if search:
query = query.filter(MasterData.name.ilike(f"%{search}%"))
@ -138,45 +138,81 @@ async def bulk_update(
result = await db_session.execute(query)
records = result.scalars().all()
# Create a mapping of id to record for easier access
records_map = {record.id: record for record in records}
# Create a mapping of id (string) to record and name to record for easier access
# IDs coming from the router are strings, so normalize keys to strings to match lookups
records_map = {str(record.id): record for record in records}
records_by_name = {record.name: record for record in records}
# Process updates in batches
updated_records = []
for masterdata_id, masterdata_in in zip(ids, updates):
masterdata = records_map.get(masterdata_id)
print("Processing update for ID:", masterdata)
if not masterdata:
continue
data = masterdata_in.model_dump()
update_data = masterdata_in.model_dump(exclude_defaults=True)
def get_value(obj, name):
return next((m.value_num for m in obj if m.name == name), 0)
# Update direct values
for field in update_data:
setattr(masterdata, field, update_data[field])
async def get_value(name):
# Prefer values from the current batch (records_by_name)
rd = records_by_name.get(name)
if rd is not None and rd.value_num is not None:
return rd.value_num
# If not found in batch, try to fetch from DB
query_val = Select(MasterData).where(MasterData.name == name)
res_val = await db_session.execute(query_val)
row = res_val.scalars().one_or_none()
return row.value_num if row and row.value_num is not None else 0
# Update direct values (attributes present on MasterData)
# Recognised attribute fields on MasterData
attr_fields = {
"name",
"description",
"unit_of_measurement",
"value_num",
"value_str",
"created_by",
"updated_by",
}
for field, val in update_data.items():
if field in attr_fields:
setattr(masterdata, field, val)
else:
# Field is not a direct attribute: treat it as a named masterdata
# e.g. payload included {"discount_rate": 5.0}
query_other = Select(MasterData).where(MasterData.name == field)
res_other = await db_session.execute(query_other)
other = res_other.scalars().one_or_none()
if other:
# Update numeric or string value depending on payload
if isinstance(val, (int, float)):
other.value_num = val
else:
other.value_str = str(val)
# keep updated record available for batch calculations
records_by_name[other.name] = other
# Handle interdependent calculations
if "loan_portion" in update_data:
equity_portion = 100 - get_value(masterdata, "loan_portion")
equity_portion = 100 - await get_value("loan_portion")
setattr(masterdata, "equity_portion", equity_portion)
total_project_cost = get_value(masterdata, "total_project_cost")
loan = total_project_cost * (get_value(masterdata, "loan_portion") / 100)
total_project_cost = await get_value("total_project_cost")
loan = total_project_cost * (await get_value("loan_portion") / 100)
setattr(masterdata, "loan", loan)
equity = total_project_cost * (equity_portion / 100)
setattr(masterdata, "equity", equity)
if any(
field in update_data for field in ["loan", "interest_rate", "loan_tenor"]
):
if any(field in update_data for field in ["loan", "interest_rate", "loan_tenor"]):
pmt = calculate_pmt(
rate=get_value(masterdata, "interest_rate"),
nper=get_value(masterdata, "loan_tenor"),
pv=get_value(masterdata, "loan"),
rate=await get_value("interest_rate"),
nper=await get_value("loan_tenor"),
pv=await get_value("loan"),
)
setattr(masterdata, "principal_interest_payment", pmt)
@ -191,19 +227,18 @@ async def bulk_update(
]
):
wacc = (
get_value(masterdata, "loan_portion")
await get_value("loan_portion")
* (
get_value(masterdata, "interest_rate")
* (1 - get_value(masterdata, "corporate_tax_rate"))
await get_value("interest_rate")
* (1 - await get_value("corporate_tax_rate"))
)
) + (
get_value(masterdata, "wacc_on_equity")
* get_value(masterdata, "equity_portion")
await get_value("wacc_on_equity") * await get_value("equity_portion")
)
setattr(masterdata, "wacc_on_project", wacc)
updated_records.append(masterdata)
print("Updated masterdata:", updated_records)
# Commit all changes in a single transaction
await db_session.commit()

Loading…
Cancel
Save