diff --git a/src/webparts/ctFormsPortal/forms/ct/components/CtCreateForm.tsx b/src/webparts/ctFormsPortal/forms/ct/components/CtCreateForm.tsx index d6a01d3..e60e8c1 100644 --- a/src/webparts/ctFormsPortal/forms/ct/components/CtCreateForm.tsx +++ b/src/webparts/ctFormsPortal/forms/ct/components/CtCreateForm.tsx @@ -65,7 +65,8 @@ const CtCreateForm: React.FC = ({ context, userDisplayName, const rawOffers = await service.loadFullOffersForPositions(positionSpIds); // Build supplierSpId → offerId map from session uploadedKpFiles. - // offerId cannot be read back via SP REST (500), so we restore it from session. + // Лукап offerId через REST не читается (500), поэтому сначала берём из сессии, а без сессии — + // из числового дубля offerFileId (см. CtService.loadKpFilesForOffers). // formData here is the initial mount value (session state before this update). const offerIdBySupplierSpId = new Map(); for (const kpFile of (formData.uploadedKpFiles ?? [])) { @@ -120,7 +121,7 @@ const CtCreateForm: React.FC = ({ context, userDisplayName, // Build offers in domain format, restoring offerId from session const offers = rawOffers.map(o => { - const offerIdNum = offerIdBySupplierSpId.get(o.supplierSpId); + const offerIdNum = offerIdBySupplierSpId.get(o.supplierSpId) ?? o.offerFileSpId; const currencyCode = o.valutaSpId ? (rateById.get(o.valutaSpId)?.code ?? 'KZT') : 'KZT'; return { id: '', diff --git a/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts b/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts index d18750e..31a46d6 100644 --- a/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts +++ b/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts @@ -543,7 +543,11 @@ export class CtService { if (!isNaN(valId)) body.valutaId = valId; } const resolvedOfferId = o.offerId ? parseInt(o.offerId, 10) : undefined; - if (resolvedOfferId && !isNaN(resolvedOfferId)) body.offerId = resolvedOfferId; + if (resolvedOfferId && !isNaN(resolvedOfferId)) { + body.offerId = resolvedOfferId; + // Дубль лукапа числом — только его можно прочитать обратно (см. loadKpFilesForOffers). + body.offerFileId = resolvedOfferId; + } const res = await this.http.post(this._li(LISTS.OFFERS), SPHttpClient.configurations.v1, { headers: { "Content-Type": "application/json;odata=nometadata" }, @@ -777,6 +781,7 @@ export class CtService { currencyCode: string; valutaSpId?: number; deliveryDistanceKm?: number; + offerFileSpId?: number; }> > { if (positionSpIds.length === 0) return []; @@ -787,7 +792,7 @@ export class CtService { // valutaId is selected directly; caller enriches currencyCode via loadCurrencyRatesByIds. const url = `${this._li(LISTS.OFFERS)}` + - `?$select=positionId,supplierId,price,quantity,unit,priceTenge,summaTenge,valutaId,deliveryDistanceKm,supplier/Id,supplier/Title` + + `?$select=positionId,supplierId,price,quantity,unit,priceTenge,summaTenge,valutaId,deliveryDistanceKm,offerFileId,supplier/Id,supplier/Title` + `&$expand=supplier` + `&$filter=${filter}` + `&$top=2000`; @@ -810,6 +815,7 @@ export class CtService { currencyCode: "KZT", // enriched by caller via loadCurrencyRatesByIds valutaSpId: valutaSpId && !isNaN(valutaSpId) ? valutaSpId : undefined, deliveryDistanceKm: item["deliveryDistanceKm"] != null ? Number(item["deliveryDistanceKm"]) : undefined, + offerFileSpId: item["offerFileId"] ? Number(item["offerFileId"]) : undefined, }; }); } @@ -826,11 +832,13 @@ export class CtService { const filter = positionSpIds .map((id) => `positionId eq ${id}`) .join(" or "); - // offerId — обычное числовое поле (SP-Id строки файла КП), НЕ лукап. Раньше в $select - // ошибочно был offerIdId (raw-ID суффикс лукапа) — такого поля нет, и SP валил запрос 400. + // Лукап offer (КП) смотрит на FileLeafRef библиотеки — SP не отдаёт такой лукап через REST + // ни $select=offerId, ни $expand (500 «типы полей установлены неправильно»), и список КП + // всегда был пустым для всех, кроме автора в его сессии. Поэтому id файла дублируется + // в числовое поле offerFileId при записи и читается отсюда. const url = `${this._li(LISTS.OFFERS)}` + - `?$select=supplierId,offerId` + + `?$select=supplierId,offerFileId` + `&$filter=${filter}` + `&$top=2000`; const res = await this.http.get(url, SPHttpClient.configurations.v1); @@ -841,7 +849,7 @@ export class CtService { const pairs: Array<{ supplierSpId: number; offerSpId: number }> = []; for (const item of data.value ?? []) { const supplierSpId = Number(item["supplierId"]); - const offerSpId = Number(item["offerId"] ?? 0); + const offerSpId = Number(item["offerFileId"] ?? 0); if (!offerSpId || !supplierSpId || seen.has(supplierSpId)) continue; seen.add(supplierSpId); pairs.push({ supplierSpId, offerSpId }); @@ -1566,6 +1574,7 @@ export class CtService { positionId: params.positionSpId, supplierId: params.supplierSpId, offerId: params.offerSpId, + offerFileId: params.offerSpId, supplierPosition: params.supplierPosition, unit: params.unit, quantity: Number(params.quantity) || 0,