[598-50][@ant] feat: единый путь выдачи через бандл — обычные заказы и докладка одним пропозалом
Оператор подписывает signiss1 и кладёт всё (существующие заказы + докладку со склада) в один оффчейн-бандл; на цепи до подписи пайщика ничего нет, поэтому отмена пайщиком = отказ от бандла без он-чейн отката (никакого reopeniss и второй ветки немедленного signiss1). Пайщик одной кнопкой контрподписывает получение — backend проводит convert?→stockorder?→signiss1→signiss2. Снесён мёртвый member-путь ordererTasks/listMyReadyToReceive в гейте. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+43
-7
@@ -145,26 +145,62 @@ export class MarketplaceCreateStockProposalLineInputDTO {
|
||||
signiss1_act!: MarketplaceIssueActSignedDocumentInputDTO;
|
||||
}
|
||||
|
||||
@InputType('MarketplaceCreateOrderProposalLineInput')
|
||||
export class MarketplaceCreateOrderProposalLineInputDTO {
|
||||
@Field(() => ID, { description: 'Существующий заказ пайщика к выдаче этим бандлом.' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
order_id!: string;
|
||||
|
||||
@Field(() => Int, { description: 'Фактическое количество к выдаче (сверено оператором).' })
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
actual_quantity!: number;
|
||||
|
||||
@Field(() => String, { description: 'Фактическая цена за единицу (оператор мог скорректировать).' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
actual_unit_price!: string;
|
||||
|
||||
@Field(() => MarketplaceIssueActSignedDocumentInputDTO, {
|
||||
description: 'Акт приёма-передачи, подписанный оператором КУ первой подписью.',
|
||||
})
|
||||
@ValidateNested()
|
||||
@Type(() => MarketplaceIssueActSignedDocumentInputDTO)
|
||||
signiss1_act!: MarketplaceIssueActSignedDocumentInputDTO;
|
||||
}
|
||||
|
||||
@InputType('MarketplaceCreateStockProposalInput')
|
||||
export class MarketplaceCreateStockProposalInputDTO {
|
||||
@Field(() => String, { description: 'Кооперативный участок, со склада которого идёт докладка.' })
|
||||
@Field(() => String, { description: 'Кооперативный участок, со склада которого идёт выдача.' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
braname!: string;
|
||||
|
||||
@Field(() => String, { description: 'Пайщик-адресат докладки.' })
|
||||
@Field(() => String, { description: 'Пайщик-адресат бандла.' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
member_account!: string;
|
||||
|
||||
@Field(() => [MarketplaceCreateStockProposalLineInputDTO], {
|
||||
description: 'Строки докладки с order_hash и подписью оператора (signiss1).',
|
||||
nullable: true,
|
||||
description: 'Строки докладки со склада: order_hash и подпись оператора (signiss1).',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ArrayNotEmpty()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => MarketplaceCreateStockProposalLineInputDTO)
|
||||
items!: MarketplaceCreateStockProposalLineInputDTO[];
|
||||
items?: MarketplaceCreateStockProposalLineInputDTO[];
|
||||
|
||||
@Field(() => [MarketplaceCreateOrderProposalLineInputDTO], {
|
||||
nullable: true,
|
||||
description: 'Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1).',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => MarketplaceCreateOrderProposalLineInputDTO)
|
||||
order_items?: MarketplaceCreateOrderProposalLineInputDTO[];
|
||||
}
|
||||
|
||||
@InputType('MarketplaceResolveStockProposalInput')
|
||||
@@ -223,10 +259,10 @@ export class MarketplaceStockAcceptPayloadDTO {
|
||||
|
||||
@InputType('MarketplaceStockFinalizeLineInput')
|
||||
export class MarketplaceStockFinalizeLineInputDTO {
|
||||
@Field(() => String, { description: 'Идентификатор предложения позиции (из payloads).' })
|
||||
@Field(() => String, { description: 'order_hash строки бандла (из payloads).' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public readonly offer_id!: string;
|
||||
public readonly order_hash!: string;
|
||||
|
||||
@Field(() => MarketplaceIssueActSignedDocumentInputDTO, {
|
||||
description: 'Акт приёма-передачи, контрподписанный пайщиком (подпись получения).',
|
||||
|
||||
+8
-2
@@ -159,7 +159,7 @@ export class MarketplaceStockResolver {
|
||||
@Mutation(() => MarketplaceStockProposalDTO, {
|
||||
name: 'marketplaceCreateStockProposal',
|
||||
description:
|
||||
'Оператор у стойки формирует докладку пайщику со склада кооператива (с уже подписанными им актами передачи) — пайщику немедленно приходит акт на подпись получения.',
|
||||
'Оператор у стойки формирует бандл выдачи пайщику (существующие заказы и/или докладка со склада), с уже подписанными им актами передачи — пайщику немедленно приходит акт на подпись получения. До его подписи ничего в блокчейне не происходит.',
|
||||
})
|
||||
@UseGuards(GqlJwtAuthGuard, MarketplaceMembershipGuard, MarketplaceRoleGuard)
|
||||
@RequireMarketplaceAccess('StockProposal', 'create:own-KU')
|
||||
@@ -173,12 +173,18 @@ export class MarketplaceStockResolver {
|
||||
operator_account: member.username,
|
||||
braname: data.braname,
|
||||
member_account: data.member_account,
|
||||
items: data.items.map((i) => ({
|
||||
items: (data.items ?? []).map((i) => ({
|
||||
offer_id: i.offer_id,
|
||||
quantity: i.quantity,
|
||||
order_hash: i.order_hash,
|
||||
signiss1_act: i.signiss1_act as unknown as ISignedDocumentDomainInterface,
|
||||
})),
|
||||
order_items: (data.order_items ?? []).map((i) => ({
|
||||
order_id: i.order_id,
|
||||
actual_quantity: i.actual_quantity,
|
||||
actual_unit_price: i.actual_unit_price,
|
||||
signiss1_act: i.signiss1_act as unknown as ISignedDocumentDomainInterface,
|
||||
})),
|
||||
});
|
||||
return toMarketplaceStockProposalDTO(proposal);
|
||||
}
|
||||
|
||||
+139
-28
@@ -42,6 +42,10 @@ import {
|
||||
MARKETPLACE_OFFER_REPOSITORY,
|
||||
type MarketplaceOfferDomainRepository,
|
||||
} from '../../domain/repositories/marketplace-offer.repository';
|
||||
import {
|
||||
MARKETPLACE_ORDER_REPOSITORY,
|
||||
type MarketplaceOrderDomainRepository,
|
||||
} from '../../domain/repositories/marketplace-order.repository';
|
||||
import { MarketplaceStockService, MARKETPLACE_STOCK_SERVICE } from './marketplace-stock.service';
|
||||
import { MarketplaceOfferStatuses } from '../../domain/entities/marketplace-offer.types';
|
||||
import type { MarketplaceOfferDomainEntity } from '../../domain/entities/marketplace-offer.entity';
|
||||
@@ -68,12 +72,30 @@ export interface MarketplaceStockProposalCreateLine {
|
||||
signiss1_act: ISignedDocumentDomainInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Строка обычного заказа в бандле: заказ уже существует (ACCEPTED_TO_COOP),
|
||||
* оператор сверил факт (кол-во/цену) и подписал signiss1-акт. На финализации
|
||||
* заказ не создаётся — сразу выдача (openIssuance+signiss2).
|
||||
*/
|
||||
export interface MarketplaceOrderProposalCreateLine {
|
||||
order_id: string;
|
||||
/** Фактическое количество к выдаче (оператор сверил при открытии). */
|
||||
actual_quantity: number;
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string;
|
||||
/** АПП-выдачи, подписанный оператором первой подписью (signiss1). */
|
||||
signiss1_act: ISignedDocumentDomainInterface;
|
||||
}
|
||||
|
||||
export interface MarketplaceStockProposalCreateInput {
|
||||
coopname: string;
|
||||
operator_account: string;
|
||||
braname: string;
|
||||
member_account: string;
|
||||
/** Строки докладки со склада (заказ родится на финализации). */
|
||||
items: MarketplaceStockProposalCreateLine[];
|
||||
/** Строки уже существующих обычных заказов пайщика к выдаче. */
|
||||
order_items?: MarketplaceOrderProposalCreateLine[];
|
||||
}
|
||||
|
||||
export interface MarketplaceStockProposalAcceptResult {
|
||||
@@ -131,9 +153,9 @@ export interface MarketplaceStockAcceptPayload {
|
||||
} | null;
|
||||
}
|
||||
|
||||
/** Строка финализации: offer + контрподписанный пайщиком АПП-выдачи (signiss2). */
|
||||
/** Строка финализации: order_hash + контрподписанный пайщиком АПП-выдачи (signiss2). */
|
||||
export interface MarketplaceStockFinalizeLine {
|
||||
offer_id: string;
|
||||
order_hash: string;
|
||||
signed_signiss2_act: MarketplaceIssueActSignedDocumentInputDTO;
|
||||
}
|
||||
|
||||
@@ -163,6 +185,8 @@ export class MarketplaceStockProposalService {
|
||||
private readonly proposalRepo: MarketplaceStockProposalDomainRepository,
|
||||
@Inject(MARKETPLACE_OFFER_REPOSITORY)
|
||||
private readonly offerRepo: MarketplaceOfferDomainRepository,
|
||||
@Inject(MARKETPLACE_ORDER_REPOSITORY)
|
||||
private readonly orderRepo: MarketplaceOrderDomainRepository,
|
||||
@Inject(MARKETPLACE_STOCK_SERVICE)
|
||||
private readonly stockService: MarketplaceStockService,
|
||||
@Inject(MARKETPLACE_ISSUANCE_SERVICE)
|
||||
@@ -224,7 +248,13 @@ export class MarketplaceStockProposalService {
|
||||
order_hash: item.order_hash,
|
||||
signiss1_aggregate,
|
||||
});
|
||||
neededUnits += this.economyService.lineUnits(item.unit_price, item.quantity, feePercent);
|
||||
// Конвертация паевого нужна ТОЛЬКО под докладку (строка без order_id):
|
||||
// её полная стоимость блокируется с членского на stockorder. Обычный
|
||||
// заказ уже профондирован с паевого на createorder — доплату по факту
|
||||
// (overage) signiss2 берёт с членского сам и фейлится при нехватке.
|
||||
if (!item.order_id) {
|
||||
neededUnits += this.economyService.lineUnits(item.unit_price, item.quantity, feePercent);
|
||||
}
|
||||
}
|
||||
|
||||
// Дефицит = потребность − уже внесённые членские средства. Конвертируем
|
||||
@@ -294,6 +324,60 @@ export class MarketplaceStockProposalService {
|
||||
return offer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Валидация строки обычного заказа в бандле + снапшот для показа пайщику.
|
||||
* Заказ обязан быть ACCEPTED_TO_COOP без открытой выдачи, принадлежать
|
||||
* адресату бандла и выдаваться ИМЕННО с этого КУ. order_hash берётся из
|
||||
* заказа (бэкенд авторитетен), product_name — из оффера заказа.
|
||||
*/
|
||||
private async buildOrderItem(
|
||||
coopname: string,
|
||||
braname: string,
|
||||
member_account: string,
|
||||
line: MarketplaceOrderProposalCreateLine
|
||||
): Promise<MarketplaceStockProposalItem> {
|
||||
if (!Number.isInteger(line.actual_quantity) || line.actual_quantity <= 0) {
|
||||
throw new BadRequestException('Количество в строке заказа должно быть целым больше нуля.');
|
||||
}
|
||||
if (Number.parseFloat(line.actual_unit_price) <= 0) {
|
||||
throw new BadRequestException('Цена в строке заказа должна быть больше нуля.');
|
||||
}
|
||||
if (!line.signiss1_act?.signatures?.length) {
|
||||
throw new BadRequestException(
|
||||
'Строка заказа без подписи оператора (signiss1) — переподпишите выдачу.'
|
||||
);
|
||||
}
|
||||
const order = await this.orderRepo.findById(line.order_id);
|
||||
if (!order || order.coopname !== coopname) {
|
||||
throw new NotFoundException(`Заказ ${line.order_id} не найден.`);
|
||||
}
|
||||
if (order.orderer_account !== member_account) {
|
||||
throw new BadRequestException(
|
||||
'Заказ принадлежит другому пайщику — нельзя включить его в бандл этого получателя.'
|
||||
);
|
||||
}
|
||||
if (order.delivery_braname !== braname) {
|
||||
throw new BadRequestException(
|
||||
`Заказ выдаётся на другом КУ (${order.delivery_braname}), со стойки ${braname} не выдаётся.`
|
||||
);
|
||||
}
|
||||
if (!order.awaits_chairman_issue_open) {
|
||||
throw new ConflictException(
|
||||
`Заказ ${order.id} (статус «${order.status}») не готов к открытию выдачи.`
|
||||
);
|
||||
}
|
||||
const offer = await this.offerRepo.findById(order.offer_id);
|
||||
return {
|
||||
order_id: order.id,
|
||||
offer_id: order.offer_id,
|
||||
quantity: line.actual_quantity,
|
||||
unit_price: line.actual_unit_price,
|
||||
product_name: offer?.product_name ?? 'Товар по предложению',
|
||||
order_hash: order.order_hash,
|
||||
signiss1_act: line.signiss1_act,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Нагрузка оператору для подписи signiss1 при формировании бандла докладки.
|
||||
* По строке: детерминированный order_hash (он же уйдёт в будущий stockorder) +
|
||||
@@ -350,16 +434,21 @@ export class MarketplaceStockProposalService {
|
||||
async createProposal(
|
||||
input: MarketplaceStockProposalCreateInput
|
||||
): Promise<MarketplaceStockProposalDomainEntity> {
|
||||
if (input.items.length === 0) {
|
||||
throw new BadRequestException('Предложение пустое — добавьте позиции из остатка.');
|
||||
const orderLines = input.order_items ?? [];
|
||||
if (input.items.length === 0 && orderLines.length === 0) {
|
||||
throw new BadRequestException('Бандл пуст — добавьте позиции заказа или докладку со склада.');
|
||||
}
|
||||
if (input.member_account === input.operator_account) {
|
||||
throw new BadRequestException('Нельзя отправить предложение самому себе.');
|
||||
}
|
||||
|
||||
// Снапшоты строк: только активные офферы кооператива ИМЕННО этого КУ,
|
||||
// количество в пределах остатка. Каждая строка несёт order_hash и
|
||||
// подписанный оператором signiss1-акт — пайщику останется одна подпись.
|
||||
// Единый бандл несёт строки двух видов:
|
||||
// • докладка — активные офферы остатка ИМЕННО этого КУ, кол-во в пределах
|
||||
// остатка; заказ родится на финализации.
|
||||
// • обычный заказ — уже существующий ACCEPTED_TO_COOP заказ пайщика
|
||||
// (профондирован с паевого), сразу к выдаче.
|
||||
// Каждая строка несёт order_hash и подписанный оператором signiss1-акт —
|
||||
// пайщику останется одна подпись.
|
||||
const items: MarketplaceStockProposalItem[] = [];
|
||||
for (const line of input.items) {
|
||||
const offer = await this.validateStockLine(
|
||||
@@ -385,6 +474,11 @@ export class MarketplaceStockProposalService {
|
||||
signiss1_act: line.signiss1_act,
|
||||
});
|
||||
}
|
||||
for (const line of orderLines) {
|
||||
items.push(
|
||||
await this.buildOrderItem(input.coopname, input.braname, input.member_account, line)
|
||||
);
|
||||
}
|
||||
|
||||
const proposal = await this.proposalRepo.create({
|
||||
coopname: input.coopname,
|
||||
@@ -433,9 +527,10 @@ export class MarketplaceStockProposalService {
|
||||
|
||||
const feePercent = await this.economyService.getMembershipFeeContractPercent(coopname);
|
||||
|
||||
// signiss2-акт по offer_id из подписанной пайщиком нагрузки.
|
||||
const signiss2ByOffer = new Map(
|
||||
(input.order_lines ?? []).map((l) => [l.offer_id, l.signed_signiss2_act])
|
||||
// signiss2-акт по order_hash строки (уникален в бандле; offer_id мог бы
|
||||
// совпасть у двух обычных заказов одного оффера).
|
||||
const signiss2ByHash = new Map(
|
||||
(input.order_lines ?? []).map((l) => [l.order_hash, l.signed_signiss2_act])
|
||||
);
|
||||
|
||||
// ── 0) Контрольная сверка: пайщик подписал РОВНО тот акт, что мы выдали ──
|
||||
@@ -446,23 +541,26 @@ export class MarketplaceStockProposalService {
|
||||
for (const item of proposal.items) {
|
||||
if (!item.order_hash || !item.signiss1_act) {
|
||||
throw new ConflictException(
|
||||
'Докладка в устаревшем формате (без подписи оператора) — переформируйте её у стойки.'
|
||||
'Бандл в устаревшем формате (без подписи оператора) — переформируйте его у стойки.'
|
||||
);
|
||||
}
|
||||
const submitted = signiss2ByOffer.get(item.offer_id);
|
||||
const submitted = signiss2ByHash.get(item.order_hash);
|
||||
if (!submitted) {
|
||||
throw new BadRequestException(
|
||||
'Состав подписания не совпадает с докладкой — обновите подписание.'
|
||||
'Состав подписания не совпадает с бандлом — обновите подписание.'
|
||||
);
|
||||
}
|
||||
await this.assertCountersignMatchesStored(item, submitted, member_account);
|
||||
}
|
||||
|
||||
// Потребность и дефицит сверх членских (как в getAcceptSignablePayloads —
|
||||
// суммы обязаны совпасть с подписанным Заявлением).
|
||||
// Потребность и дефицит сверх членских — ТОЛЬКО по докладке (как в
|
||||
// getAcceptSignablePayloads; суммы обязаны совпасть с подписанным Заявлением).
|
||||
// Обычный заказ профондирован с паевого ранее и в дефицит не входит.
|
||||
let neededUnits = 0n;
|
||||
for (const item of proposal.items) {
|
||||
neededUnits += this.economyService.lineUnits(item.unit_price, item.quantity, feePercent);
|
||||
if (!item.order_id) {
|
||||
neededUnits += this.economyService.lineUnits(item.unit_price, item.quantity, feePercent);
|
||||
}
|
||||
}
|
||||
const memberUnits = await this.readMemberUnits(coopname, member_account);
|
||||
const deficitUnits = neededUnits > memberUnits ? neededUnits - memberUnits : 0n;
|
||||
@@ -497,21 +595,33 @@ export class MarketplaceStockProposalService {
|
||||
});
|
||||
}
|
||||
|
||||
// ── 2) Создание заказов из остатка (атомарно: на фейле — отмена всех) ────
|
||||
const created: Array<{ order_id: string; item: MarketplaceStockProposalItem }> = [];
|
||||
// ── 2) Заказы к выдаче: докладка → создаём из остатка (атомарно, на фейле —
|
||||
// отмена созданных); обычный заказ → уже существует, берём его order_id.
|
||||
const issuables: Array<{
|
||||
order_id: string;
|
||||
item: MarketplaceStockProposalItem;
|
||||
signiss2: MarketplaceIssueActSignedDocumentInputDTO;
|
||||
}> = [];
|
||||
const createdStock: Array<{ order_id: string }> = [];
|
||||
try {
|
||||
for (const item of proposal.items) {
|
||||
if (!item.order_hash || !item.signiss1_act) {
|
||||
throw new ConflictException(
|
||||
'Докладка в устаревшем формате (без подписи оператора) — переформируйте её у стойки.'
|
||||
'Бандл в устаревшем формате (без подписи оператора) — переформируйте его у стойки.'
|
||||
);
|
||||
}
|
||||
if (!signiss2ByOffer.get(item.offer_id)) {
|
||||
const signiss2 = signiss2ByHash.get(item.order_hash);
|
||||
if (!signiss2) {
|
||||
throw new BadRequestException(
|
||||
'Состав подписания не совпадает с докладкой — обновите подписание.'
|
||||
'Состав подписания не совпадает с бандлом — обновите подписание.'
|
||||
);
|
||||
}
|
||||
// Средства уже в членском (конвертация выше при дефиците) — без Заявления.
|
||||
if (item.order_id) {
|
||||
// Обычный заказ — уже ACCEPTED_TO_COOP, создавать нечего.
|
||||
issuables.push({ order_id: item.order_id, item, signiss2 });
|
||||
continue;
|
||||
}
|
||||
// Докладка: средства уже в членском (конвертация выше при дефиците) — без Заявления.
|
||||
const { order } = await this.stockService.createStockOrder({
|
||||
coopname,
|
||||
orderer_account: member_account,
|
||||
@@ -520,16 +630,17 @@ export class MarketplaceStockProposalService {
|
||||
checkout_id: proposal.id,
|
||||
order_hash: item.order_hash,
|
||||
});
|
||||
created.push({ order_id: order.id, item });
|
||||
createdStock.push({ order_id: order.id });
|
||||
issuables.push({ order_id: order.id, item, signiss2 });
|
||||
}
|
||||
} catch (error) {
|
||||
for (const { order_id } of created) {
|
||||
for (const { order_id } of createdStock) {
|
||||
try {
|
||||
await this.stockService.cancelStockOrder(
|
||||
coopname,
|
||||
order_id,
|
||||
member_account,
|
||||
'Подписание докладки не завершилось — строка отменена'
|
||||
'Подписание бандла не завершилось — строка отменена'
|
||||
);
|
||||
} catch (compErr: any) {
|
||||
this.logger.error(
|
||||
@@ -542,7 +653,7 @@ export class MarketplaceStockProposalService {
|
||||
|
||||
// ── 3) Выдача: signiss1 оператора → signiss2 пайщика (заказ RECEIVED) ────
|
||||
const order_ids: string[] = [];
|
||||
for (const { order_id, item } of created) {
|
||||
for (const { order_id, item, signiss2 } of issuables) {
|
||||
await this.issuanceService.openIssuance({
|
||||
coopname,
|
||||
chairman_account: proposal.operator_account,
|
||||
@@ -555,7 +666,7 @@ export class MarketplaceStockProposalService {
|
||||
coopname,
|
||||
orderer_account: member_account,
|
||||
order_id,
|
||||
signed_document: signiss2ByOffer.get(item.offer_id)!,
|
||||
signed_document: signiss2,
|
||||
});
|
||||
order_ids.push(order_id);
|
||||
}
|
||||
|
||||
+19
-3
@@ -23,7 +23,17 @@ export const MarketplaceStockProposalStatuses = {
|
||||
CANCELLED: 'CANCELLED',
|
||||
} as const satisfies Record<string, MarketplaceStockProposalStatus>;
|
||||
|
||||
/** Строка предложения: опубликованный оффер кооператива + количество. */
|
||||
/**
|
||||
* Строка бандла выдачи. Единый путь: бандл несёт И докладку со склада, И уже
|
||||
* существующие обычные заказы пайщика — отличает их `order_id`:
|
||||
* - `order_id` отсутствует → ДОКЛАДКА: заказ из остатка родится на финализации
|
||||
* (stockorder по `order_hash`), средства блокируются с членского.
|
||||
* - `order_id` задан → ОБЫЧНЫЙ ЗАКАЗ: он уже ACCEPTED_TO_COOP (профондирован с
|
||||
* паевого на createorder); на финализации создавать нечего — сразу выдача.
|
||||
* В обоих случаях signiss1 оператора отложен в бандл (оффчейн) и уходит на цепь
|
||||
* только вместе с signiss2 пайщика при подписи — поэтому отмена = отказ от
|
||||
* бандла, без он-чейн отката.
|
||||
*/
|
||||
export interface MarketplaceStockProposalItem {
|
||||
offer_id: string;
|
||||
quantity: number;
|
||||
@@ -32,9 +42,15 @@ export interface MarketplaceStockProposalItem {
|
||||
/** Снапшот наименования — для показа пайщику без дозапросов. */
|
||||
product_name: string;
|
||||
/**
|
||||
* Детерминированный order_hash будущего заказа из остатка — рождается при
|
||||
* Существующий обычный заказ пайщика (ACCEPTED_TO_COOP), выдаваемый этим
|
||||
* бандлом. Пусто → строка докладки со склада (заказ родится на финализации).
|
||||
*/
|
||||
order_id?: string;
|
||||
/**
|
||||
* Детерминированный order_hash заказа из остатка (докладка) — рождается при
|
||||
* формировании бандла (оператором у стойки), чтобы и signiss1-акт оператора,
|
||||
* и заказ создавались по одному и тому же хэшу.
|
||||
* и заказ создавались по одному и тому же хэшу. Для строки обычного заказа —
|
||||
* order_hash самого заказа (берётся бэкендом из заказа).
|
||||
*/
|
||||
order_hash?: string;
|
||||
/**
|
||||
|
||||
@@ -736,6 +736,9 @@ export const AllTypesProps: Record<string,any> = {
|
||||
delivery_points:"MarketplaceOfferDeliveryPointInput",
|
||||
images:"MarketplaceOfferImageUploadInput"
|
||||
},
|
||||
MarketplaceCreateOrderProposalLineInput:{
|
||||
signiss1_act:"MarketplaceIssueActSignedDocumentInput"
|
||||
},
|
||||
MarketplaceCreateReturnClaimInput:{
|
||||
defect_category:"MarketplaceReturnClaimDefectCategory",
|
||||
photos:"MarketplaceReturnClaimPhotoUploadInput",
|
||||
@@ -745,7 +748,8 @@ export const AllTypesProps: Record<string,any> = {
|
||||
groups:"MarketplaceShipmentGroupInput"
|
||||
},
|
||||
MarketplaceCreateStockProposalInput:{
|
||||
items:"MarketplaceCreateStockProposalLineInput"
|
||||
items:"MarketplaceCreateStockProposalLineInput",
|
||||
order_items:"MarketplaceCreateOrderProposalLineInput"
|
||||
},
|
||||
MarketplaceCreateStockProposalLineInput:{
|
||||
signiss1_act:"MarketplaceIssueActSignedDocumentInput"
|
||||
|
||||
@@ -6833,6 +6833,16 @@ export type ValueTypes = {
|
||||
unit_of_measure: string | Variable<any, string>,
|
||||
unlimited_flag: boolean | Variable<any, string>,
|
||||
warranty_days: number | Variable<any, string>
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number | Variable<any, string>,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string | Variable<any, string>,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: ValueTypes["ID"] | Variable<any, string>,
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: ValueTypes["MarketplaceIssueActSignedDocumentInput"] | Variable<any, string>
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -6861,12 +6871,14 @@ export type ValueTypes = {
|
||||
['...on MarketplaceCreateShipmentResult']?: Omit<ValueTypes["MarketplaceCreateShipmentResult"], "...on MarketplaceCreateShipmentResult">
|
||||
}>;
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string | Variable<any, string>,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<ValueTypes["MarketplaceCreateStockProposalLineInput"]> | Variable<any, string>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string | Variable<any, string>
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<ValueTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null | Variable<any, string>,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string | Variable<any, string>,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<ValueTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null | Variable<any, string>
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -8316,8 +8328,8 @@ export type ValueTypes = {
|
||||
['...on MarketplaceStockAcceptPayload']?: Omit<ValueTypes["MarketplaceStockAcceptPayload"], "...on MarketplaceStockAcceptPayload">
|
||||
}>;
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string | Variable<any, string>,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string | Variable<any, string>,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: ValueTypes["MarketplaceIssueActSignedDocumentInput"] | Variable<any, string>
|
||||
};
|
||||
@@ -17766,6 +17778,16 @@ export type ResolverInputTypes = {
|
||||
unit_of_measure: string,
|
||||
unlimited_flag: boolean,
|
||||
warranty_days: number
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: ResolverInputTypes["ID"],
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: ResolverInputTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -17793,12 +17815,14 @@ export type ResolverInputTypes = {
|
||||
__typename?: boolean | `@${string}`
|
||||
}>;
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<ResolverInputTypes["MarketplaceCreateStockProposalLineInput"]>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<ResolverInputTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<ResolverInputTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -19202,8 +19226,8 @@ export type ResolverInputTypes = {
|
||||
__typename?: boolean | `@${string}`
|
||||
}>;
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: ResolverInputTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
@@ -28340,6 +28364,16 @@ export type ModelTypes = {
|
||||
unit_of_measure: string,
|
||||
unlimited_flag: boolean,
|
||||
warranty_days: number
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: ModelTypes["ID"],
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: ModelTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -28366,12 +28400,14 @@ export type ModelTypes = {
|
||||
shipments: Array<ModelTypes["MarketplaceShipment"]>
|
||||
};
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<ModelTypes["MarketplaceCreateStockProposalLineInput"]>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<ModelTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<ModelTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -29701,8 +29737,8 @@ export type ModelTypes = {
|
||||
order_lines: Array<ModelTypes["MarketplaceStockAcceptOrderLine"]>
|
||||
};
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: ModelTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
@@ -30828,7 +30864,7 @@ export type ModelTypes = {
|
||||
marketplaceCreateReturnClaim: ModelTypes["MarketplaceReturnClaimResult"],
|
||||
/** Сформировать партии поставки из акцептованной заявки. Каждая группа = одна партия (КУ + вариант доставки + опционально подмножество заказов). Покрытие всех КУ не обязательно — допустима частичная отгрузка и догрузка остатка отдельными партиями. */
|
||||
marketplaceCreateShipment: ModelTypes["MarketplaceCreateShipmentResult"],
|
||||
/** Оператор у стойки формирует докладку пайщику со склада кооператива (с уже подписанными им актами передачи) — пайщику немедленно приходит акт на подпись получения. */
|
||||
/** Оператор у стойки формирует бандл выдачи пайщику (существующие заказы и/или докладка со склада), с уже подписанными им актами передачи — пайщику немедленно приходит акт на подпись получения. До его подписи ничего в блокчейне не происходит. */
|
||||
marketplaceCreateStockProposal: ModelTypes["MarketplaceStockProposal"],
|
||||
/** Создаёт ручной черновик проекта списания. На кооператив может быть только один открытый черновик и один проект, отправленный в совет. */
|
||||
marketplaceCreateWriteoffDraft: ModelTypes["MarketplaceWriteoffProposal"],
|
||||
@@ -39829,6 +39865,16 @@ export type GraphQLTypes = {
|
||||
unit_of_measure: string,
|
||||
unlimited_flag: boolean,
|
||||
warranty_days: number
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: GraphQLTypes["ID"],
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: GraphQLTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -39857,12 +39903,14 @@ export type GraphQLTypes = {
|
||||
['...on MarketplaceCreateShipmentResult']: Omit<GraphQLTypes["MarketplaceCreateShipmentResult"], "...on MarketplaceCreateShipmentResult">
|
||||
};
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<GraphQLTypes["MarketplaceCreateStockProposalLineInput"]>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<GraphQLTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<GraphQLTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -41313,8 +41361,8 @@ export type GraphQLTypes = {
|
||||
['...on MarketplaceStockAcceptPayload']: Omit<GraphQLTypes["MarketplaceStockAcceptPayload"], "...on MarketplaceStockAcceptPayload">
|
||||
};
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: GraphQLTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
@@ -42500,7 +42548,7 @@ export type GraphQLTypes = {
|
||||
marketplaceCreateReturnClaim: GraphQLTypes["MarketplaceReturnClaimResult"],
|
||||
/** Сформировать партии поставки из акцептованной заявки. Каждая группа = одна партия (КУ + вариант доставки + опционально подмножество заказов). Покрытие всех КУ не обязательно — допустима частичная отгрузка и догрузка остатка отдельными партиями. */
|
||||
marketplaceCreateShipment: GraphQLTypes["MarketplaceCreateShipmentResult"],
|
||||
/** Оператор у стойки формирует докладку пайщику со склада кооператива (с уже подписанными им актами передачи) — пайщику немедленно приходит акт на подпись получения. */
|
||||
/** Оператор у стойки формирует бандл выдачи пайщику (существующие заказы и/или докладка со склада), с уже подписанными им актами передачи — пайщику немедленно приходит акт на подпись получения. До его подписи ничего в блокчейне не происходит. */
|
||||
marketplaceCreateStockProposal: GraphQLTypes["MarketplaceStockProposal"],
|
||||
/** Создаёт ручной черновик проекта списания. На кооператив может быть только один открытый черновик и один проект, отправленный в совет. */
|
||||
marketplaceCreateWriteoffDraft: GraphQLTypes["MarketplaceWriteoffProposal"],
|
||||
@@ -46879,6 +46927,7 @@ type ZEUS_VARIABLES = {
|
||||
["MarketplaceCreateAplReceptionInput"]: ValueTypes["MarketplaceCreateAplReceptionInput"];
|
||||
["MarketplaceCreateExpressReceptionInput"]: ValueTypes["MarketplaceCreateExpressReceptionInput"];
|
||||
["MarketplaceCreateOfferInput"]: ValueTypes["MarketplaceCreateOfferInput"];
|
||||
["MarketplaceCreateOrderProposalLineInput"]: ValueTypes["MarketplaceCreateOrderProposalLineInput"];
|
||||
["MarketplaceCreateReturnClaimInput"]: ValueTypes["MarketplaceCreateReturnClaimInput"];
|
||||
["MarketplaceCreateShipmentInput"]: ValueTypes["MarketplaceCreateShipmentInput"];
|
||||
["MarketplaceCreateStockProposalInput"]: ValueTypes["MarketplaceCreateStockProposalInput"];
|
||||
|
||||
+68
-69
@@ -15,12 +15,15 @@ import { formatAsset2Digits } from 'src/shared/lib/utils/formatAsset2Digits';
|
||||
import { marketplaceUnitShort } from 'src/shared/lib/consts/marketplace-units';
|
||||
import {
|
||||
getChairmanSignablePayload,
|
||||
openIssuance,
|
||||
getStockIssuancePayloads,
|
||||
createStockProposal,
|
||||
type CreateStockProposalInput,
|
||||
type MarketplaceOrderIssuanceView,
|
||||
} from '../api';
|
||||
|
||||
// Подписанный signiss1-акт в строке бандла — тип берём прямо из SDK-входа.
|
||||
type StockBundleStockLine = NonNullable<CreateStockProposalInput['items']>[number];
|
||||
type StockBundleOrderLine = NonNullable<CreateStockProposalInput['order_items']>[number];
|
||||
import StockPickDialog, { type StockPickLine } from './StockPickDialog.vue';
|
||||
|
||||
/**
|
||||
@@ -34,14 +37,19 @@ import StockPickDialog, { type StockPickLine } from './StockPickDialog.vue';
|
||||
* позиции и сохраняется на заказе. Финальная подпись заказчика факт не
|
||||
* редактирует.
|
||||
*
|
||||
* ЕДИНЫЙ ПУТЬ ВЫДАЧИ: оператор подписывает АПП-выдачи первой подписью (signiss1)
|
||||
* по выдаваемым заказам И докладке со склада и складывает всё в ОДИН бандл
|
||||
* (оффчейн, через БД). На цепи до подписи пайщика НИЧЕГО не происходит, поэтому
|
||||
* отмена пайщиком = отказ от бандла без он-чейн отката, а выдача (signiss1+
|
||||
* signiss2) уходит на цепь только при контрподписи получения пайщиком у стойки.
|
||||
*
|
||||
* Поток:
|
||||
* 1. Оператор корректирует количество/цену в сводной таблице сверки (строка на
|
||||
* позицию, предзаполнена заказом).
|
||||
* 2. «Открыть выдачу» — UI ЦИКЛОМ по всем позициям: формирует акт на
|
||||
* фактическое количество, подписывает ключом председателя сессии
|
||||
* (signatureId=1) и отправляет в `openIssuance`. Каждая позиция = свой акт
|
||||
* (результаты могут различаться). Заказы переходят в «Готово к получению»,
|
||||
* заказчику — уведомление; финальную подпись он поставит сам.
|
||||
* позицию, предзаполнена заказом) и при желании добавляет докладку со склада.
|
||||
* 2. «Подписать и отправить пайщику» — UI по каждой позиции формирует акт на
|
||||
* фактическое количество, подписывает ключом оператора (signatureId=1) и
|
||||
* отправляет единым `createStockProposal`. Пайщику немедленно приходит один
|
||||
* акт на подпись получения (карточка в гейте «подпись на месте»).
|
||||
*/
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -322,52 +330,51 @@ async function confirm(): Promise<void> {
|
||||
FailAlert(new Error('Приватный ключ не найден. Войдите в кооператив.'));
|
||||
return;
|
||||
}
|
||||
if (!recipientAccount.value || !issueBraname.value) {
|
||||
FailAlert(new Error('Не определён получатель или пункт выдачи.'));
|
||||
return;
|
||||
}
|
||||
signing.value = true;
|
||||
const docSigner = new Classes.Document(wifKey);
|
||||
const failed: string[] = [];
|
||||
let ok = 0;
|
||||
// По выдаваемым позициям ПАРАЛЛЕЛЬНО: каждая — отдельный акт (председатель →
|
||||
// openIssuance, signiss1). Невыбранные позиции в выдачу не идут — остаются на
|
||||
// складе в текущем статусе (частичная выдача). У заказов разные хэши — на цепи
|
||||
// это разные документы, гонок подписи нет, и все позиции взводятся в
|
||||
// READY_TO_RECEIVE почти в один блок.
|
||||
await Promise.all(
|
||||
includedOrders.value.map(async (o) => {
|
||||
try {
|
||||
// ЕДИНЫЙ ПУТЬ: оператор подписывает АПП-выдачи первой подписью (signiss1) по
|
||||
// выдаваемым позициям И докладке, и кладёт всё в ОДИН бандл (оффчейн, в БД).
|
||||
// На цепи до подписи пайщика НИЧЕГО не происходит — поэтому отмена пайщиком
|
||||
// = отказ от бандла, без он-чейн отката. Выдача (signiss1+signiss2) уходит
|
||||
// в цепь только когда пайщик контрподписывает акт у стойки.
|
||||
|
||||
// 1) Обычные заказы пайщика → строки бандла order_items.
|
||||
const order_items: StockBundleOrderLine[] = [];
|
||||
for (const o of includedOrders.value) {
|
||||
const f = facts.value[o.id];
|
||||
const priceStr = String(f.price);
|
||||
try {
|
||||
const generated = await getChairmanSignablePayload({
|
||||
order_id: o.id,
|
||||
actual_quantity: f.qty,
|
||||
actual_unit_price: priceStr,
|
||||
});
|
||||
const signed = await docSigner.signDocument(generated, globalStore.username, 1);
|
||||
await openIssuance({
|
||||
order_id: o.id,
|
||||
actual_quantity: f.qty,
|
||||
actual_unit_price: priceStr,
|
||||
signed_document: signed,
|
||||
});
|
||||
ok += 1;
|
||||
} catch (e) {
|
||||
console.error('openIssuance failed for order', o.id, e);
|
||||
failed.push(o.product_name || o.id.slice(0, 8));
|
||||
}
|
||||
}),
|
||||
);
|
||||
const generated = await getChairmanSignablePayload({
|
||||
order_id: o.id,
|
||||
actual_quantity: f.qty,
|
||||
actual_unit_price: priceStr,
|
||||
});
|
||||
const signiss1_act = (await docSigner.signDocument(
|
||||
generated,
|
||||
globalStore.username,
|
||||
1,
|
||||
)) as StockBundleOrderLine['signiss1_act'];
|
||||
order_items.push({
|
||||
order_id: o.id,
|
||||
actual_quantity: f.qty,
|
||||
actual_unit_price: priceStr,
|
||||
signiss1_act,
|
||||
});
|
||||
}
|
||||
|
||||
// Докладка со склада: оператор формирует бандл и СРАЗУ подписывает акты
|
||||
// приёма-передачи первой подписью (signiss1) — пайщику докладка уйдёт в гейт
|
||||
// готовым актом с одной кнопкой «Подписать» (получение), без отдельного
|
||||
// «Принять». Заказ из остатка и сама выдача рождаются на подписи пайщика.
|
||||
if (restockLines.value.length && recipientAccount.value && issueBraname.value) {
|
||||
try {
|
||||
// 2) Докладка со склада → строки бандла items (заказ родится на подписи пайщика).
|
||||
let items: StockBundleStockLine[] = [];
|
||||
if (restockLines.value.length) {
|
||||
const payloads = await getStockIssuancePayloads({
|
||||
braname: issueBraname.value,
|
||||
member_account: recipientAccount.value,
|
||||
items: restockLines.value.map((l) => ({ offer_id: l.offer_id, quantity: l.quantity })),
|
||||
});
|
||||
const items = await Promise.all(
|
||||
items = await Promise.all(
|
||||
payloads.map(async (p) => ({
|
||||
offer_id: p.offer_id,
|
||||
quantity: p.quantity,
|
||||
@@ -376,37 +383,29 @@ async function confirm(): Promise<void> {
|
||||
p.signiss1_document,
|
||||
globalStore.username,
|
||||
1,
|
||||
)) as CreateStockProposalInput['items'][number]['signiss1_act'],
|
||||
)) as StockBundleStockLine['signiss1_act'],
|
||||
})),
|
||||
);
|
||||
await createStockProposal({
|
||||
braname: issueBraname.value,
|
||||
member_account: recipientAccount.value,
|
||||
items,
|
||||
});
|
||||
restockLines.value = [];
|
||||
} catch (e) {
|
||||
FailAlert(e, 'Не удалось доложить со склада');
|
||||
}
|
||||
}
|
||||
|
||||
signing.value = false;
|
||||
// 3) Один бандл — пайщику уйдёт один акт на подпись (получение).
|
||||
await createStockProposal({
|
||||
braname: issueBraname.value,
|
||||
member_account: recipientAccount.value,
|
||||
items,
|
||||
order_items,
|
||||
});
|
||||
restockLines.value = [];
|
||||
|
||||
if (ok > 0) emit('opened');
|
||||
if (failed.length === 0) {
|
||||
const tail = leftCount.value > 0
|
||||
? ` Осталось на складе позиц.: ${leftCount.value}.`
|
||||
: '';
|
||||
SuccessAlert(
|
||||
`Выдача открыта по ${ok} позиц. — ждём подтверждение заказчика.${tail}`,
|
||||
);
|
||||
signing.value = false;
|
||||
emit('opened');
|
||||
const total = order_items.length + items.length;
|
||||
const tail = leftCount.value > 0 ? ` Осталось на складе позиц.: ${leftCount.value}.` : '';
|
||||
SuccessAlert(`Акт отправлен пайщику на подпись (${total} позиц.) — ждём подтверждение получения.${tail}`);
|
||||
emit('update:modelValue', false);
|
||||
} else {
|
||||
FailAlert(
|
||||
new Error(
|
||||
`Открыто ${ok} из ${includedCount.value}. Не удалось: ${failed.join(', ')}. Повторите по оставшимся.`,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
signing.value = false;
|
||||
FailAlert(e, 'Не удалось отправить акт пайщику на подпись');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +505,7 @@ TakeoverDialog(
|
||||
)
|
||||
template(#icon-left)
|
||||
q-icon(name="draw" size="16px")
|
||||
| Подписать и открыть выдачу
|
||||
| Подписать и отправить пайщику
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './ui';
|
||||
export { useOnsiteSignatureGate, type OrdererPickupTask } from './model/useOnsiteSignatureGate';
|
||||
export { useOnsiteSignatureGate } from './model/useOnsiteSignatureGate';
|
||||
export { createMarketplaceEventsSubscription } from './model/marketplaceEventsSubscription';
|
||||
|
||||
+10
-84
@@ -9,13 +9,10 @@ import {
|
||||
} from 'src/pages/Marketplace/OffererPendingAplReceptions/api';
|
||||
import { Classes } from '@coopenomics/sdk';
|
||||
import {
|
||||
listMyReadyToReceive,
|
||||
finalizeOrdererIssuance,
|
||||
listStockProposals,
|
||||
finalizeStockIssuance,
|
||||
declineStockProposal,
|
||||
getStockProposalSignablePayloads,
|
||||
type MarketplaceOrderIssuanceView,
|
||||
type MarketplaceStockProposalView,
|
||||
type IStockConvertSigned,
|
||||
type IStockFinalizeOrderLine,
|
||||
@@ -48,16 +45,6 @@ import {
|
||||
* откатил — после ближайшей дочитки список пустеет. Поллинга нет.
|
||||
*/
|
||||
|
||||
interface OrdererPickupTask {
|
||||
/** Ключ группировки — braname пункта выдачи. */
|
||||
key: string;
|
||||
pointName: string;
|
||||
pointAddress: string;
|
||||
orders: MarketplaceOrderIssuanceView[];
|
||||
/** Совокупная сумма к получению по всем позициям пункта. */
|
||||
totalCost: string;
|
||||
}
|
||||
|
||||
const PENDING_SUPPLIER_SIGN = 'PENDING_SUPPLIER_SIGN';
|
||||
// Очная приёмка кодируется как 'A' / 'IN_PERSON' в зависимости от слоя — гейт
|
||||
// блокирует ТОЛЬКО её; экспедиторскую (B / EXPEDITOR) не трогает.
|
||||
@@ -65,9 +52,9 @@ const IN_PERSON_VARIANTS = new Set(['A', 'IN_PERSON']);
|
||||
|
||||
// Singleton-состояние (как у SelectBranchOverlay): один гейт на всё приложение.
|
||||
const supplierReceptions = ref<MarketplaceAplReceptionView[]>([]);
|
||||
const ordererOrders = ref<MarketplaceOrderIssuanceView[]>([]);
|
||||
// Входящие предложения имущества со склада кооператива (докладка): оператор
|
||||
// накинул у стойки — пайщик решает прямо в гейте (принять / отказаться).
|
||||
// Единый бандл выдачи: оператор у стойки подписал акты (signiss1) по заказам
|
||||
// и/или докладке и отправил пайщику — пайщик решает прямо в гейте (подписать
|
||||
// получение / отменить). До его подписи на цепи ничего нет.
|
||||
const stockProposals = ref<MarketplaceStockProposalView[]>([]);
|
||||
// Разложение стоимости докладки по предложению: сколько спишется с уже внесённых
|
||||
// членских и сколько уйдёт в конвертацию с паевого (по Заявлению). Предзагружается,
|
||||
@@ -85,40 +72,11 @@ const supplierTasks = computed<ReceptionGroup<MarketplaceAplReceptionView>[]>(()
|
||||
),
|
||||
);
|
||||
|
||||
const ordererTasks = computed<OrdererPickupTask[]>(() => {
|
||||
// listMyReadyToReceive отдаёт заказы со статусом READY_TO_RECEIVE; фильтруем
|
||||
// ещё не подписанные заказчиком и группируем по пункту выдачи — одна подпись
|
||||
// на пункт (как в карточке «Моих заказов», задача #53).
|
||||
const pending = ordererOrders.value.filter((o) => !o.orderer_signed_at);
|
||||
const byPoint = new Map<string, MarketplaceOrderIssuanceView[]>();
|
||||
for (const o of pending) {
|
||||
const key = o.delivery_braname || o.delivery_point_name || o.id;
|
||||
const arr = byPoint.get(key) ?? [];
|
||||
arr.push(o);
|
||||
byPoint.set(key, arr);
|
||||
}
|
||||
return [...byPoint.entries()].map(([key, orders]) => ({
|
||||
key,
|
||||
pointName: orders[0]?.delivery_point_name ?? '',
|
||||
pointAddress: orders[0]?.delivery_point_address ?? '',
|
||||
orders,
|
||||
totalCost: orders
|
||||
.reduce(
|
||||
(sum, o) => sum + Number.parseFloat(o.issuance_fact?.fact_cost ?? o.total_cost ?? '0'),
|
||||
0,
|
||||
)
|
||||
.toFixed(4),
|
||||
}));
|
||||
});
|
||||
|
||||
const proposalTasks = computed(() => stockProposals.value);
|
||||
|
||||
/** Гейт виден, пока есть хоть одна личная подпись/решение, которых ждут от пайщика. */
|
||||
const isVisible = computed(
|
||||
() =>
|
||||
supplierTasks.value.length > 0 ||
|
||||
ordererTasks.value.length > 0 ||
|
||||
proposalTasks.value.length > 0,
|
||||
() => supplierTasks.value.length > 0 || proposalTasks.value.length > 0,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -130,22 +88,19 @@ async function refresh(source = 'ручной'): Promise<void> {
|
||||
if (!global.wif) {
|
||||
// Не залогинен — гейта нет, очищаем возможный хвост.
|
||||
supplierReceptions.value = [];
|
||||
ordererOrders.value = [];
|
||||
stockProposals.value = [];
|
||||
return;
|
||||
}
|
||||
const wasVisible = isVisible.value;
|
||||
loading.value = true;
|
||||
try {
|
||||
const [receptions, orders, proposals] = await Promise.all([
|
||||
const [receptions, proposals] = await Promise.all([
|
||||
listAplReceptionsAsSupplier().catch(() => [] as MarketplaceAplReceptionView[]),
|
||||
listMyReadyToReceive().catch(() => [] as MarketplaceOrderIssuanceView[]),
|
||||
listStockProposals({ statuses: ['PROPOSED'] }).catch(
|
||||
() => [] as MarketplaceStockProposalView[],
|
||||
),
|
||||
]);
|
||||
supplierReceptions.value = receptions;
|
||||
ordererOrders.value = orders;
|
||||
stockProposals.value = proposals;
|
||||
// Подтягиваем разложение сумм (с членского / с паевого) для показа в карточке —
|
||||
// не блокирует дочитку; кэш по id, ушедшие предложения чистятся.
|
||||
@@ -158,7 +113,7 @@ async function refresh(source = 'ручной'): Promise<void> {
|
||||
// сокет; если перед этим был «POLL» — сработала страховочная дочитка.
|
||||
const appeared = !wasVisible && isVisible.value;
|
||||
console.info(
|
||||
`%c[OnsiteGate] refresh ← ${source}: поставщик=${supplierTasks.value.length}, заказчик=${ordererTasks.value.length}, предложений=${proposalTasks.value.length}, гейт виден=${isVisible.value}${appeared ? ' (ВСПЛЫЛ только что)' : ''}`,
|
||||
`%c[OnsiteGate] refresh ← ${source}: поставщик=${supplierTasks.value.length}, актов на подпись=${proposalTasks.value.length}, гейт виден=${isVisible.value}${appeared ? ' (ВСПЛЫЛ только что)' : ''}`,
|
||||
appeared ? 'color:#16a34a;font-weight:bold' : 'color:#64748b',
|
||||
);
|
||||
}
|
||||
@@ -214,34 +169,8 @@ async function signSupplier(group: ReceptionGroup<MarketplaceAplReceptionView>):
|
||||
}
|
||||
}
|
||||
|
||||
async function signOrderer(task: OrdererPickupTask): Promise<void> {
|
||||
const global = useGlobalStore();
|
||||
const wif = global.wif?.toString();
|
||||
if (!wif) {
|
||||
FailAlert(new Error('Приватный ключ не найден. Войдите в кооператив.'));
|
||||
return;
|
||||
}
|
||||
signingKey.value = task.key;
|
||||
try {
|
||||
const { ok, failed } = await finalizeOrdererIssuance(task.orders, wif, global.username);
|
||||
if (failed.length === 0) {
|
||||
SuccessAlert(`Имущество получено по ${ok} позиц. Заказы закрыты.`);
|
||||
} else {
|
||||
const names = failed.map((f) => f.order.product_name || f.order.id.slice(0, 8));
|
||||
FailAlert(
|
||||
new Error(
|
||||
`Получено ${ok} из ${task.orders.length}. Не удалось: ${names.join(', ')}. Повторите по оставшимся.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
await refresh();
|
||||
} finally {
|
||||
signingKey.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Пайщик ОДНОЙ подписью утверждает докладку как акт получения. Подписывает:
|
||||
* Пайщик ОДНОЙ подписью утверждает бандл как акт получения. Подписывает:
|
||||
* при дефиците членских — единое Заявление о конвертации (paевой → членский),
|
||||
* затем по каждой строке контрподписывает АПП-выдачи (signiss2) поверх подписи
|
||||
* оператора. Backend создаёт заказы из остатка и проводит выдачу — имущество
|
||||
@@ -275,7 +204,7 @@ async function signProposal(task: MarketplaceStockProposalView): Promise<void> {
|
||||
// document с подписью оператора (канон 2-подписи).
|
||||
const order_lines: IStockFinalizeOrderLine[] = await Promise.all(
|
||||
payload.order_lines.map(async (line) => ({
|
||||
offer_id: line.offer_id,
|
||||
order_hash: line.order_hash,
|
||||
signed_signiss2_act: (await signer.signDocument(
|
||||
line.signiss1_aggregate.rawDocument,
|
||||
global.username,
|
||||
@@ -286,7 +215,7 @@ async function signProposal(task: MarketplaceStockProposalView): Promise<void> {
|
||||
);
|
||||
|
||||
const { order_ids } = await finalizeStockIssuance(task.id, order_lines, signed_convert);
|
||||
SuccessAlert(`Имущество получено по ${order_ids.length} позиц. со склада. Акт подписан.`);
|
||||
SuccessAlert(`Имущество получено по ${order_ids.length} позиц. Акт подписан.`);
|
||||
} catch (error) {
|
||||
FailAlert(error);
|
||||
} finally {
|
||||
@@ -299,7 +228,7 @@ async function declineProposal(task: MarketplaceStockProposalView): Promise<void
|
||||
signingKey.value = task.id;
|
||||
try {
|
||||
await declineStockProposal(task.id);
|
||||
SuccessAlert('Предложение отклонено.');
|
||||
SuccessAlert('Получение отменено. Оператор сформирует акт заново.');
|
||||
} catch (error) {
|
||||
FailAlert(error);
|
||||
} finally {
|
||||
@@ -314,16 +243,13 @@ export function useOnsiteSignatureGate() {
|
||||
loading,
|
||||
signingKey,
|
||||
supplierTasks,
|
||||
ordererTasks,
|
||||
proposalTasks,
|
||||
proposalSums,
|
||||
refresh,
|
||||
signSupplier,
|
||||
signOrderer,
|
||||
signProposal,
|
||||
declineProposal,
|
||||
};
|
||||
}
|
||||
|
||||
export type { OrdererPickupTask };
|
||||
export type { MarketplaceStockProposalView };
|
||||
|
||||
+7
-58
@@ -7,7 +7,7 @@ import { type ReceptionGroup } from 'src/shared/lib/marketplace';
|
||||
import { marketplaceUnitShort } from 'src/shared/lib/consts/marketplace-units';
|
||||
import { formatAsset2Digits } from 'src/shared/lib/utils/formatAsset2Digits';
|
||||
import type { MarketplaceAplReceptionView } from 'src/pages/Marketplace/OffererPendingAplReceptions/api';
|
||||
import { useOnsiteSignatureGate, type OrdererPickupTask } from '../model/useOnsiteSignatureGate';
|
||||
import { useOnsiteSignatureGate } from '../model/useOnsiteSignatureGate';
|
||||
|
||||
/**
|
||||
* Глобальный оверлей подписи на месте — монтируется один раз в App.vue рядом с
|
||||
@@ -24,12 +24,10 @@ const {
|
||||
isVisible,
|
||||
signingKey,
|
||||
supplierTasks,
|
||||
ordererTasks,
|
||||
proposalTasks,
|
||||
proposalSums,
|
||||
refresh,
|
||||
signSupplier,
|
||||
signOrderer,
|
||||
signProposal,
|
||||
declineProposal,
|
||||
} = useOnsiteSignatureGate();
|
||||
@@ -57,21 +55,11 @@ function kuAddr(braname: string): string {
|
||||
return kuStore.details.find((d) => d.coreBraname === braname)?.addressFull ?? '';
|
||||
}
|
||||
|
||||
function ordererPointLabel(task: OrdererPickupTask): string {
|
||||
return [task.pointName, task.pointAddress].filter(Boolean).join(' · ') || task.key;
|
||||
}
|
||||
function factQty(o: OrdererPickupTask['orders'][number]): number {
|
||||
return o.issuance_fact?.actual_quantity ?? o.quantity ?? 0;
|
||||
}
|
||||
function factCost(o: OrdererPickupTask['orders'][number]): string {
|
||||
return o.issuance_fact?.fact_cost ?? o.total_cost ?? '0';
|
||||
}
|
||||
function proposalLineCost(i: { quantity: number; unit_price: string }): string {
|
||||
return (i.quantity * Number.parseFloat(i.unit_price)).toFixed(4);
|
||||
}
|
||||
|
||||
const supplierBusy = (g: ReceptionGroup<MarketplaceAplReceptionView>) => signingKey.value === g.key;
|
||||
const ordererBusy = (t: OrdererPickupTask) => signingKey.value === t.key;
|
||||
const proposalBusy = (id: string) => signingKey.value === id;
|
||||
const anySigning = computed(() => signingKey.value !== null);
|
||||
|
||||
@@ -140,54 +128,15 @@ BaseDialog(
|
||||
q-icon(name='draw', size='18px')
|
||||
| Подписать поставку
|
||||
|
||||
//- Заказчик: финальная (закрывающая) подпись получения, сводно по пункту.
|
||||
BaseCard.onsite-gate__card(v-for='t in ordererTasks', :key='t.key')
|
||||
template(#head)
|
||||
.onsite-gate__head
|
||||
q-icon(name='inventory_2', size='28px')
|
||||
.onsite-gate__ident
|
||||
span.onsite-gate__name Получение в пункте выдачи
|
||||
span.onsite-gate__addr
|
||||
q-icon(name='place', size='14px')
|
||||
| {{ ordererPointLabel(t) }}
|
||||
span.onsite-gate__sub Подтвердите получение имущества — финальная подпись заказчика
|
||||
|
||||
table.onsite-gate__table
|
||||
thead
|
||||
tr
|
||||
th Позиция
|
||||
th.num К получению
|
||||
th.num Сумма
|
||||
tbody
|
||||
tr(v-for='o in t.orders', :key='o.id')
|
||||
td {{ o.product_name || 'Товар по предложению' }}
|
||||
td.num {{ factQty(o) }} {{ marketplaceUnitShort(o.unit_of_measure) }}
|
||||
td.num {{ formatAsset2Digits(factCost(o)) }} ₽
|
||||
tfoot
|
||||
tr
|
||||
td Итого к получению
|
||||
td.num
|
||||
td.num {{ formatAsset2Digits(t.totalCost) }} ₽
|
||||
|
||||
.onsite-gate__foot
|
||||
BaseButton(
|
||||
variant='primary',
|
||||
:loading='ordererBusy(t)',
|
||||
:disabled='anySigning && !ordererBusy(t)',
|
||||
@click='signOrderer(t)'
|
||||
)
|
||||
template(#icon-left)
|
||||
q-icon(name='draw', size='18px')
|
||||
| Подписать и получить
|
||||
|
||||
//- Докладка со склада кооператива: оператор уже подписал акт передачи —
|
||||
//- пайщику остаётся одна подпись получения (принятие = подпись акта).
|
||||
//- Бандл выдачи: оператор уже подписал акт передачи (по заказам и/или
|
||||
//- докладке со склада) — пайщику остаётся одна подпись получения; до неё на
|
||||
//- цепи ничего нет, поэтому «Отменить» = отказ от бандла (оператор повторит).
|
||||
BaseCard.onsite-gate__card(v-for='p in proposalTasks', :key='p.id')
|
||||
template(#head)
|
||||
.onsite-gate__head
|
||||
q-icon(name='inventory_2', size='28px')
|
||||
.onsite-gate__ident
|
||||
span.onsite-gate__name Получение со склада кооператива
|
||||
span.onsite-gate__name Получение в пункте выдачи
|
||||
span.onsite-gate__sub Подтвердите получение имущества — ваша подпись акта
|
||||
|
||||
table.onsite-gate__table
|
||||
@@ -220,7 +169,7 @@ BaseDialog(
|
||||
variant='ghost',
|
||||
:disabled='anySigning',
|
||||
@click='declineProposal(p)'
|
||||
) Отказаться
|
||||
) Отменить
|
||||
BaseButton(
|
||||
variant='primary',
|
||||
:loading='proposalBusy(p.id)',
|
||||
@@ -229,7 +178,7 @@ BaseDialog(
|
||||
)
|
||||
template(#icon-left)
|
||||
q-icon(name='draw', size='18px')
|
||||
| Подписать
|
||||
| Подписать и получить
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -736,6 +736,9 @@ export const AllTypesProps: Record<string,any> = {
|
||||
delivery_points:"MarketplaceOfferDeliveryPointInput",
|
||||
images:"MarketplaceOfferImageUploadInput"
|
||||
},
|
||||
MarketplaceCreateOrderProposalLineInput:{
|
||||
signiss1_act:"MarketplaceIssueActSignedDocumentInput"
|
||||
},
|
||||
MarketplaceCreateReturnClaimInput:{
|
||||
defect_category:"MarketplaceReturnClaimDefectCategory",
|
||||
photos:"MarketplaceReturnClaimPhotoUploadInput",
|
||||
@@ -745,7 +748,8 @@ export const AllTypesProps: Record<string,any> = {
|
||||
groups:"MarketplaceShipmentGroupInput"
|
||||
},
|
||||
MarketplaceCreateStockProposalInput:{
|
||||
items:"MarketplaceCreateStockProposalLineInput"
|
||||
items:"MarketplaceCreateStockProposalLineInput",
|
||||
order_items:"MarketplaceCreateOrderProposalLineInput"
|
||||
},
|
||||
MarketplaceCreateStockProposalLineInput:{
|
||||
signiss1_act:"MarketplaceIssueActSignedDocumentInput"
|
||||
|
||||
@@ -6833,6 +6833,16 @@ export type ValueTypes = {
|
||||
unit_of_measure: string | Variable<any, string>,
|
||||
unlimited_flag: boolean | Variable<any, string>,
|
||||
warranty_days: number | Variable<any, string>
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number | Variable<any, string>,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string | Variable<any, string>,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: ValueTypes["ID"] | Variable<any, string>,
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: ValueTypes["MarketplaceIssueActSignedDocumentInput"] | Variable<any, string>
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -6861,12 +6871,14 @@ export type ValueTypes = {
|
||||
['...on MarketplaceCreateShipmentResult']?: Omit<ValueTypes["MarketplaceCreateShipmentResult"], "...on MarketplaceCreateShipmentResult">
|
||||
}>;
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string | Variable<any, string>,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<ValueTypes["MarketplaceCreateStockProposalLineInput"]> | Variable<any, string>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string | Variable<any, string>
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<ValueTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null | Variable<any, string>,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string | Variable<any, string>,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<ValueTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null | Variable<any, string>
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -8316,8 +8328,8 @@ export type ValueTypes = {
|
||||
['...on MarketplaceStockAcceptPayload']?: Omit<ValueTypes["MarketplaceStockAcceptPayload"], "...on MarketplaceStockAcceptPayload">
|
||||
}>;
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string | Variable<any, string>,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string | Variable<any, string>,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: ValueTypes["MarketplaceIssueActSignedDocumentInput"] | Variable<any, string>
|
||||
};
|
||||
@@ -17766,6 +17778,16 @@ export type ResolverInputTypes = {
|
||||
unit_of_measure: string,
|
||||
unlimited_flag: boolean,
|
||||
warranty_days: number
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: ResolverInputTypes["ID"],
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: ResolverInputTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -17793,12 +17815,14 @@ export type ResolverInputTypes = {
|
||||
__typename?: boolean | `@${string}`
|
||||
}>;
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<ResolverInputTypes["MarketplaceCreateStockProposalLineInput"]>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<ResolverInputTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<ResolverInputTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -19202,8 +19226,8 @@ export type ResolverInputTypes = {
|
||||
__typename?: boolean | `@${string}`
|
||||
}>;
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: ResolverInputTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
@@ -28340,6 +28364,16 @@ export type ModelTypes = {
|
||||
unit_of_measure: string,
|
||||
unlimited_flag: boolean,
|
||||
warranty_days: number
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: ModelTypes["ID"],
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: ModelTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -28366,12 +28400,14 @@ export type ModelTypes = {
|
||||
shipments: Array<ModelTypes["MarketplaceShipment"]>
|
||||
};
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<ModelTypes["MarketplaceCreateStockProposalLineInput"]>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<ModelTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<ModelTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -29701,8 +29737,8 @@ export type ModelTypes = {
|
||||
order_lines: Array<ModelTypes["MarketplaceStockAcceptOrderLine"]>
|
||||
};
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: ModelTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
@@ -30828,7 +30864,7 @@ export type ModelTypes = {
|
||||
marketplaceCreateReturnClaim: ModelTypes["MarketplaceReturnClaimResult"],
|
||||
/** Сформировать партии поставки из акцептованной заявки. Каждая группа = одна партия (КУ + вариант доставки + опционально подмножество заказов). Покрытие всех КУ не обязательно — допустима частичная отгрузка и догрузка остатка отдельными партиями. */
|
||||
marketplaceCreateShipment: ModelTypes["MarketplaceCreateShipmentResult"],
|
||||
/** Оператор у стойки формирует докладку пайщику со склада кооператива (с уже подписанными им актами передачи) — пайщику немедленно приходит акт на подпись получения. */
|
||||
/** Оператор у стойки формирует бандл выдачи пайщику (существующие заказы и/или докладка со склада), с уже подписанными им актами передачи — пайщику немедленно приходит акт на подпись получения. До его подписи ничего в блокчейне не происходит. */
|
||||
marketplaceCreateStockProposal: ModelTypes["MarketplaceStockProposal"],
|
||||
/** Создаёт ручной черновик проекта списания. На кооператив может быть только один открытый черновик и один проект, отправленный в совет. */
|
||||
marketplaceCreateWriteoffDraft: ModelTypes["MarketplaceWriteoffProposal"],
|
||||
@@ -39829,6 +39865,16 @@ export type GraphQLTypes = {
|
||||
unit_of_measure: string,
|
||||
unlimited_flag: boolean,
|
||||
warranty_days: number
|
||||
};
|
||||
["MarketplaceCreateOrderProposalLineInput"]: {
|
||||
/** Фактическое количество к выдаче (сверено оператором). */
|
||||
actual_quantity: number,
|
||||
/** Фактическая цена за единицу (оператор мог скорректировать). */
|
||||
actual_unit_price: string,
|
||||
/** Существующий заказ пайщика к выдаче этим бандлом. */
|
||||
order_id: GraphQLTypes["ID"],
|
||||
/** Акт приёма-передачи, подписанный оператором КУ первой подписью. */
|
||||
signiss1_act: GraphQLTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
["MarketplaceCreateReturnClaimInput"]: {
|
||||
/** Возвращаемое количество единиц (по умолчанию — выданное количество). */
|
||||
@@ -39857,12 +39903,14 @@ export type GraphQLTypes = {
|
||||
['...on MarketplaceCreateShipmentResult']: Omit<GraphQLTypes["MarketplaceCreateShipmentResult"], "...on MarketplaceCreateShipmentResult">
|
||||
};
|
||||
["MarketplaceCreateStockProposalInput"]: {
|
||||
/** Кооперативный участок, со склада которого идёт докладка. */
|
||||
/** Кооперативный участок, со склада которого идёт выдача. */
|
||||
braname: string,
|
||||
/** Строки докладки с order_hash и подписью оператора (signiss1). */
|
||||
items: Array<GraphQLTypes["MarketplaceCreateStockProposalLineInput"]>,
|
||||
/** Пайщик-адресат докладки. */
|
||||
member_account: string
|
||||
/** Строки докладки со склада: order_hash и подпись оператора (signiss1). */
|
||||
items?: Array<GraphQLTypes["MarketplaceCreateStockProposalLineInput"]> | undefined | null,
|
||||
/** Пайщик-адресат бандла. */
|
||||
member_account: string,
|
||||
/** Строки уже существующих заказов пайщика к выдаче (подпись оператора signiss1). */
|
||||
order_items?: Array<GraphQLTypes["MarketplaceCreateOrderProposalLineInput"]> | undefined | null
|
||||
};
|
||||
["MarketplaceCreateStockProposalLineInput"]: {
|
||||
/** Предложение кооператива из остатка. */
|
||||
@@ -41313,8 +41361,8 @@ export type GraphQLTypes = {
|
||||
['...on MarketplaceStockAcceptPayload']: Omit<GraphQLTypes["MarketplaceStockAcceptPayload"], "...on MarketplaceStockAcceptPayload">
|
||||
};
|
||||
["MarketplaceStockFinalizeLineInput"]: {
|
||||
/** Идентификатор предложения позиции (из payloads). */
|
||||
offer_id: string,
|
||||
/** order_hash строки бандла (из payloads). */
|
||||
order_hash: string,
|
||||
/** Акт приёма-передачи, контрподписанный пайщиком (подпись получения). */
|
||||
signed_signiss2_act: GraphQLTypes["MarketplaceIssueActSignedDocumentInput"]
|
||||
};
|
||||
@@ -42500,7 +42548,7 @@ export type GraphQLTypes = {
|
||||
marketplaceCreateReturnClaim: GraphQLTypes["MarketplaceReturnClaimResult"],
|
||||
/** Сформировать партии поставки из акцептованной заявки. Каждая группа = одна партия (КУ + вариант доставки + опционально подмножество заказов). Покрытие всех КУ не обязательно — допустима частичная отгрузка и догрузка остатка отдельными партиями. */
|
||||
marketplaceCreateShipment: GraphQLTypes["MarketplaceCreateShipmentResult"],
|
||||
/** Оператор у стойки формирует докладку пайщику со склада кооператива (с уже подписанными им актами передачи) — пайщику немедленно приходит акт на подпись получения. */
|
||||
/** Оператор у стойки формирует бандл выдачи пайщику (существующие заказы и/или докладка со склада), с уже подписанными им актами передачи — пайщику немедленно приходит акт на подпись получения. До его подписи ничего в блокчейне не происходит. */
|
||||
marketplaceCreateStockProposal: GraphQLTypes["MarketplaceStockProposal"],
|
||||
/** Создаёт ручной черновик проекта списания. На кооператив может быть только один открытый черновик и один проект, отправленный в совет. */
|
||||
marketplaceCreateWriteoffDraft: GraphQLTypes["MarketplaceWriteoffProposal"],
|
||||
@@ -46879,6 +46927,7 @@ type ZEUS_VARIABLES = {
|
||||
["MarketplaceCreateAplReceptionInput"]: ValueTypes["MarketplaceCreateAplReceptionInput"];
|
||||
["MarketplaceCreateExpressReceptionInput"]: ValueTypes["MarketplaceCreateExpressReceptionInput"];
|
||||
["MarketplaceCreateOfferInput"]: ValueTypes["MarketplaceCreateOfferInput"];
|
||||
["MarketplaceCreateOrderProposalLineInput"]: ValueTypes["MarketplaceCreateOrderProposalLineInput"];
|
||||
["MarketplaceCreateReturnClaimInput"]: ValueTypes["MarketplaceCreateReturnClaimInput"];
|
||||
["MarketplaceCreateShipmentInput"]: ValueTypes["MarketplaceCreateShipmentInput"];
|
||||
["MarketplaceCreateStockProposalInput"]: ValueTypes["MarketplaceCreateStockProposalInput"];
|
||||
|
||||
Reference in New Issue
Block a user