diff --git a/backend/app/services/quote_service.py b/backend/app/services/quote_service.py index f428df3..e7fa272 100644 --- a/backend/app/services/quote_service.py +++ b/backend/app/services/quote_service.py @@ -416,6 +416,9 @@ async def accept_quote(db: AsyncSession, quote_id: UUID, payload: AcceptQuoteIn, # --- process item decisions (UPSERT) --- chosen_ts_ids: set[UUID] = set() + # پروژه‌های ارسالی در payload.item_projects — منبع اصلی برای + # decision.project_id (مدیر تدارکات برای هر قلم یک پروژه انتخاب می‌کند) + proj_by_line: dict[UUID, list[UUID]] = {e.line_item_id: list(e.project_ids) for e in payload.item_projects} for decision_in in payload.item_decisions: decision = await db.scalar( select(ItemDecision).where(ItemDecision.line_item_id == decision_in.line_item_id).with_for_update() @@ -460,22 +463,31 @@ async def accept_quote(db: AsyncSession, quote_id: UUID, payload: AcceptQuoteIn, decision.adjusted_unit_price = decision_in.adjusted_unit_price decision.adjusted_notes = decision_in.adjusted_notes decision.decided_at = utcnow() - # v2.6: the SINGLE purchased project (proc manager picks it; - # auto-filled when the offer had exactly one project). + # v2.6: the SINGLE purchased project (proc manager picks it). + # Derivation order: + # 1) explicit decision_in.project_id + # 2) payload.item_projects for this line item (exactly one) + # 3) existing line_item_projects (exactly one) + # otherwise NULL — the item stays visible only to the office + # until a project is assigned (never wrongly visible to a PM). if decision_in.project_id is not None: decision.project_id = decision_in.project_id else: - line_projs = ( - (await db.execute( - select(LineItemProjects.project_id).where( - LineItemProjects.line_item_id == decision_in.line_item_id - ) - )) - .scalars() - .all() - ) - if len(line_projs) == 1: - decision.project_id = line_projs[0] + accept_projs = proj_by_line.get(decision_in.line_item_id) or [] + if len(accept_projs) == 1: + decision.project_id = accept_projs[0] + else: + line_projs = ( + (await db.execute( + select(LineItemProjects.project_id).where( + LineItemProjects.line_item_id == decision_in.line_item_id + ) + )) + .scalars() + .all() + ) + if len(line_projs) == 1: + decision.project_id = line_projs[0] if decision.project_id is not None: if await db.get(Project, decision.project_id) is None: raise NotFoundError("پروژه یافت نشد", field="item_decisions.project_id")