fix(materials): remove nested db.begin — material PATCH was 500

The router loads the material row (starting a transaction) before calling
material_service.update_material, which then opened its own
async with db.begin() → SQLAlchemy 'A transaction is already begun on
this Session' → INTERNAL_ERROR on every PATCH (incl. changing the
reference unit from ضرایب تبدیل). Mutations now run inside the request
transaction committed by the get_db dependency.
This commit is contained in:
2026-09-08 14:41:57 +03:30
parent 468ce64d29
commit 7f31fb5105
+23 -19
View File
@@ -160,27 +160,31 @@ async def update_material(db: AsyncSession, material: Material, payload: Materia
v2.5/2.6: category is DERIVED (from the first linked supplier) — it is v2.5/2.6: category is DERIVED (from the first linked supplier) — it is
no longer part of the update payload. no longer part of the update payload.
NOTE: no ``db.begin()`` here — the router already starts the transaction
(it loads the row first), and a nested begin raises
"A transaction is already begun on this Session" (500). The request
session commits via the get_db dependency.
""" """
async with db.begin(): if payload.name is not None:
if payload.name is not None: duplicate = await db.scalar(
duplicate = await db.scalar( select(Material.id).where(
select(Material.id).where( Material.name == payload.name,
Material.name == payload.name, Material.id != material.id,
Material.id != material.id,
)
) )
if duplicate is not None: )
raise ConflictError("متریالی با این نام در کل کاتالوگ قبلاً ثبت شده است", field="name") if duplicate is not None:
if payload.name is not None: raise ConflictError("متریالی با این نام در کل کاتالوگ قبلاً ثبت شده است", field="name")
material.name = payload.name if payload.name is not None:
if payload.topic is not None: material.name = payload.name
material.topic = payload.topic if payload.topic is not None:
if payload.canonical_unit_id is not None and payload.canonical_unit_id != material.canonical_unit_id: material.topic = payload.topic
if not await db.get(Unit, payload.canonical_unit_id): if payload.canonical_unit_id is not None and payload.canonical_unit_id != material.canonical_unit_id:
raise NotFoundError("واحد مرجع یافت نشد", field="canonical_unit_id") if not await db.get(Unit, payload.canonical_unit_id):
material.canonical_unit_id = payload.canonical_unit_id raise NotFoundError("واحد مرجع یافت نشد", field="canonical_unit_id")
if payload.status is not None: material.canonical_unit_id = payload.canonical_unit_id
material.status = payload.status if payload.status is not None:
material.status = payload.status
return material return material