[C28-33][@ant] feat: СЗ 2010 по канону вёрстки реестра + назначение платежа отдельным полем после реквизитов — фиксируется в снимке для кассира; «оплата по счету», «Организация/ИП», алерт «передано в совет», хинт механики убран
This commit is contained in:
@@ -97,7 +97,7 @@ void expense::createexp(name coopname, name username,
|
||||
// прямую оплату по выставленным реквизитам, аванс ей не выдаётся.
|
||||
if (it.recipient_type == static_cast<uint8_t>(D::RecipientType::ORG)) {
|
||||
eosio::check(it.mechanics == static_cast<uint8_t>(D::Mechanics::DIRECT),
|
||||
"Организации доступна только прямая оплата (DIRECT)");
|
||||
"Организации/ИП доступна только оплата по счёту (DIRECT)");
|
||||
} else {
|
||||
eosio::check(it.mechanics == static_cast<uint8_t>(D::Mechanics::ADVANCE),
|
||||
"Пайщику средства выдаются только авансом под отчёт (ADVANCE)");
|
||||
|
||||
+5
@@ -42,6 +42,11 @@ class ExpenseProposalItemInputDTO implements ItemAction {
|
||||
@IsString()
|
||||
requisites?: string;
|
||||
|
||||
@Field({ description: 'Назначение платежа — отдельной строкой после реквизитов', nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
payment_purpose?: string;
|
||||
|
||||
@Field({
|
||||
description:
|
||||
'Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ.',
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ export class CreateProgramExpenseInputDTO {
|
||||
@IsString()
|
||||
creator!: string;
|
||||
|
||||
@Field(() => [ExpenseItemInputDTO], { description: 'Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно.' })
|
||||
@Field(() => [ExpenseItemInputDTO], { description: 'Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно.' })
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@ValidateNested({ each: true })
|
||||
|
||||
+1
@@ -61,6 +61,7 @@ export class ProgramExpensesManagementService {
|
||||
mechanics: it.mechanics === ExpenseMechanics.DIRECT ? 'DIRECT' : 'ADVANCE',
|
||||
paymentMethodId: it.payment_method_id,
|
||||
requisites: it.requisites,
|
||||
paymentPurpose: it.payment_purpose,
|
||||
}));
|
||||
await this.expenseChassis.validateRequisites(data.coopname, requisiteItems);
|
||||
|
||||
|
||||
@@ -51,4 +51,12 @@ export class ExpenseItemInputDTO {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
requisites?: string;
|
||||
|
||||
@Field(() => String, {
|
||||
nullable: true,
|
||||
description: 'Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира.',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
payment_purpose?: string;
|
||||
}
|
||||
|
||||
+3
-2
@@ -60,12 +60,12 @@ export class ExpenseRequisiteSnapshotsService {
|
||||
// прямая оплата по выставленным реквизитам.
|
||||
if (it.isOrganization && it.mechanics !== 'DIRECT') {
|
||||
throw new BadRequestException(
|
||||
'Организации доступна только прямая оплата по реквизитам (DIRECT) — аванс под отчёт ей не выдаётся'
|
||||
'Организации/ИП доступна только оплата по счёту (DIRECT) — аванс под отчёт ей не выдаётся'
|
||||
)
|
||||
}
|
||||
if (!it.isOrganization && it.mechanics !== 'ADVANCE') {
|
||||
throw new BadRequestException(
|
||||
`Пайщику ${it.recipient} средства передаются только авансом под отчёт (ADVANCE) — прямая оплата доступна только организации`
|
||||
`Пайщику ${it.recipient} средства передаются только авансом под отчёт (ADVANCE) — оплата по счёту доступна только организации/ИП`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ export class ExpenseRequisiteSnapshotsService {
|
||||
method_type: null,
|
||||
data: null,
|
||||
requisites: it.requisites ?? '',
|
||||
payment_purpose: it.paymentPurpose ?? null,
|
||||
})
|
||||
|
||||
if (it.isOrganization) {
|
||||
|
||||
+2
@@ -67,6 +67,7 @@ export class ExpensesMutationsService {
|
||||
mechanics: item.mechanics,
|
||||
recipient_name: item.recipient_name,
|
||||
requisites,
|
||||
payment_purpose: item.payment_purpose,
|
||||
}
|
||||
})
|
||||
)
|
||||
@@ -184,5 +185,6 @@ function toRequisiteItems(proposalHash: string, items: ExpenseItemInputDTO[]): I
|
||||
mechanics: it.mechanics === ExpenseMechanics.DIRECT ? 'DIRECT' : 'ADVANCE',
|
||||
paymentMethodId: it.payment_method_id,
|
||||
requisites: it.requisites,
|
||||
paymentPurpose: it.payment_purpose,
|
||||
}))
|
||||
}
|
||||
|
||||
+3
@@ -43,6 +43,9 @@ export class ExpenseRequisiteSnapshotTypeormEntity {
|
||||
@Column({ type: 'text', comment: 'Реквизиты строкой — как в документе СЗ' })
|
||||
requisites!: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true, comment: 'Назначение платежа (оплата по счёту) — для поручения кассиру' })
|
||||
payment_purpose!: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
created_at!: Date;
|
||||
}
|
||||
|
||||
@@ -2644,7 +2644,7 @@ export type ValueTypes = {
|
||||
description: string | Variable<any, string>,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string | Variable<any, string>,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<ValueTypes["ExpenseItemInput"]> | Variable<any, string>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: ValueTypes["ExpenseProposalStatementSignedDocumentInput"] | Variable<any, string>
|
||||
@@ -5282,6 +5282,8 @@ export type ValueTypes = {
|
||||
mechanics: ValueTypes["ExpenseMechanics"] | Variable<any, string>,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null | Variable<any, string>,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null | Variable<any, string>,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string | Variable<any, string>,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -5418,6 +5420,8 @@ export type ValueTypes = {
|
||||
number: string | Variable<any, string>,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null | Variable<any, string>,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null | Variable<any, string>,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null | Variable<any, string>,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
@@ -11737,7 +11741,7 @@ export type ResolverInputTypes = {
|
||||
description: string,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<ResolverInputTypes["ExpenseItemInput"]>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: ResolverInputTypes["ExpenseProposalStatementSignedDocumentInput"]
|
||||
@@ -14312,6 +14316,8 @@ export type ResolverInputTypes = {
|
||||
mechanics: ResolverInputTypes["ExpenseMechanics"],
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -14447,6 +14453,8 @@ export type ResolverInputTypes = {
|
||||
number: string,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
@@ -20579,7 +20587,7 @@ export type ModelTypes = {
|
||||
description: string,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<ModelTypes["ExpenseItemInput"]>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: ModelTypes["ExpenseProposalStatementSignedDocumentInput"]
|
||||
@@ -23083,6 +23091,8 @@ export type ModelTypes = {
|
||||
mechanics: ModelTypes["ExpenseMechanics"],
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -23215,6 +23225,8 @@ export type ModelTypes = {
|
||||
number: string,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
@@ -30003,7 +30015,7 @@ export type GraphQLTypes = {
|
||||
description: string,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<GraphQLTypes["ExpenseItemInput"]>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: GraphQLTypes["ExpenseProposalStatementSignedDocumentInput"]
|
||||
@@ -32641,6 +32653,8 @@ export type GraphQLTypes = {
|
||||
mechanics: GraphQLTypes["ExpenseMechanics"],
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -32777,6 +32791,8 @@ export type GraphQLTypes = {
|
||||
number: string,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
|
||||
+12
-6
@@ -14,6 +14,8 @@ export interface IExpenseItem {
|
||||
mechanics: ExpenseItemPaymentMechanics
|
||||
recipient_name?: string
|
||||
requisites?: string
|
||||
/** Назначение платежа — отдельной строкой после реквизитов (для оплаты по счёту) */
|
||||
payment_purpose?: string
|
||||
}
|
||||
|
||||
export interface IExpenseProposalHeader {
|
||||
@@ -48,11 +50,13 @@ export interface Model {
|
||||
export const title = 'Служебная записка-смета о расходах'
|
||||
export const description = 'Заявка-смета председателю кооператива на финансирование расходов по программе. Содержит описание цели и массив позиций расхода.'
|
||||
|
||||
// Вёрстка по бумажному образцу служебной записки: шапка-адресат справа,
|
||||
// дата слева, центрированный заголовок с идентификатором (= proposal_hash,
|
||||
// по нему записку можно найти), позиции — нумерованным списком с полными
|
||||
// реквизитами получателей. Кошелёк-источник в документе не указывается.
|
||||
export const context = `<style>h1{margin:0;text-align:center;}.digital-document{padding:20px;}.doc-header{text-align:right;padding-bottom:25px;}.doc-header p{margin:2px 0;}.doc-id{text-align:center;font-size:12px;word-break:break-all;padding-top:6px;padding-bottom:25px;}ol.items{padding-left:25px;margin:10px 0;}ol.items li{padding-bottom:10px;}.signature{padding-top:40px;}</style><div class="digital-document"><div class="doc-header"><p>{% trans 'TO_COUNCIL' %} {{vars.full_abbr_genitive}} «{{vars.name}}»</p><p>{% trans 'FROM_MEMBER' %} {{ user.full_name_or_short_name }}</p></div><p>{% trans 'DATE' %}: {{ meta.created_at }}</p><h1 style="padding-top:25px;">{% trans 'PROPOSAL_TITLE' %}</h1><p class="doc-id">№ {{ proposal_hash }}</p><p>{% trans 'BODY_INTRO' %}{% if proposal.fund_name %} {% trans 'BY_FUND' %} {{ proposal.fund_name }}{% endif %} {% trans 'IN_TOTAL' %} {{ proposal.total_amount }}{% if proposal.deadline %} {% trans 'DUE_BY' %} {{ proposal.deadline }}{% endif %}, {% trans 'BODY_NAMELY' %}:</p><ol class="items">{% for item in items %}<li>{{ item.description }} — {{ item.amount }} ({% if item.mechanics == 'ADVANCE' %}{% trans 'MECH_ADVANCE' %}{% else %}{% trans 'MECH_DIRECT' %}{% endif %}). {% trans 'ITEM_RECIPIENT' %}: {% if item.recipient_type == 'SELF' %}{{ user.full_name_or_short_name }}{% else %}{{ item.recipient_name }}{% endif %}{% if item.requisites %}. {% trans 'ITEM_REQUISITES' %}: {{ item.requisites }}{% endif %}</li>{% endfor %}</ol><p>{% trans 'PURPOSE' %}: {{ proposal.description }}</p><div class="signature"><p>{{ user.full_name_or_short_name }}</p><p>{% trans 'SIGNED_DIGITALLY' %}</p></div></div>`
|
||||
// Вёрстка по канону документов реестра (см. 1040): без <style>-блока — превью
|
||||
// его не применяет; только inline text-align на div-обёртках. Шапка-адресат
|
||||
// справа, центрированный заголовок с идентификатором (= proposal_hash, по нему
|
||||
// записку можно найти), позиции — нумерованным списком: описание и сумма,
|
||||
// затем построчно получатель, реквизиты и назначение платежа (для кассира).
|
||||
// Кошелёк-источник в документе не указывается.
|
||||
export const context = `<div class="digital-document"><div style="text-align: right"><p>{% trans 'TO_COUNCIL' %} {{vars.full_abbr_genitive}} «{{vars.name}}»</p><p>{% trans 'FROM_MEMBER' %} {{ user.full_name_or_short_name }}</p></div><p>{% trans 'DATE' %}: {{ meta.created_at }}</p><div style="text-align: center"><h2>{% trans 'PROPOSAL_TITLE' %}</h2><p style="word-break: break-all">№ {{ proposal_hash }}</p></div><p>{% trans 'BODY_INTRO' %}{% if proposal.fund_name %} {% trans 'BY_FUND' %} {{ proposal.fund_name }}{% endif %} {% trans 'IN_TOTAL' %} {{ proposal.total_amount }}{% if proposal.deadline %} {% trans 'DUE_BY' %} {{ proposal.deadline }}{% endif %}, {% trans 'BODY_NAMELY' %}:</p><ol>{% for item in items %}<li><p>{{ item.description }} — {{ item.amount }} ({% if item.mechanics == 'ADVANCE' %}{% trans 'MECH_ADVANCE' %}{% else %}{% trans 'MECH_DIRECT' %}{% endif %})</p><p>{% trans 'ITEM_RECIPIENT' %}: {% if item.recipient_type == 'SELF' %}{{ user.full_name_or_short_name }}{% else %}{{ item.recipient_name }}{% endif %}</p>{% if item.requisites %}<p>{% trans 'ITEM_REQUISITES' %}: {{ item.requisites }}</p>{% endif %}{% if item.payment_purpose %}<p>{% trans 'ITEM_PAYMENT_PURPOSE' %}: {{ item.payment_purpose }}</p>{% endif %}</li>{% endfor %}</ol><p>{% trans 'PURPOSE' %}: {{ proposal.description }}</p><p>{{ user.full_name_or_short_name }}</p><p>{% trans 'SIGNED_DIGITALLY' %}</p></div>`
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
@@ -66,9 +70,10 @@ export const translations = {
|
||||
DUE_BY: 'в срок до',
|
||||
BODY_NAMELY: 'а именно',
|
||||
MECH_ADVANCE: 'аванс под отчёт',
|
||||
MECH_DIRECT: 'прямая оплата',
|
||||
MECH_DIRECT: 'оплата по счёту',
|
||||
ITEM_RECIPIENT: 'Получатель',
|
||||
ITEM_REQUISITES: 'Реквизиты',
|
||||
ITEM_PAYMENT_PURPOSE: 'Назначение платежа',
|
||||
PURPOSE: 'Цель расходов',
|
||||
SIGNED_DIGITALLY: 'подписано электронной подписью',
|
||||
},
|
||||
@@ -97,6 +102,7 @@ export const exampleData = {
|
||||
mechanics: 'DIRECT',
|
||||
recipient_name: 'ООО «Яндекс.Облако»',
|
||||
requisites: 'ИНН 7704414297, р/с 40702810000000000000, БИК 044525000',
|
||||
payment_purpose: 'Оплата по счёту № 814 от 01.06.2026 за аренду серверов',
|
||||
},
|
||||
{
|
||||
number: '2',
|
||||
|
||||
+4
@@ -19,6 +19,8 @@ export interface ICreateProgramExpenseDraftItem {
|
||||
recipient_type: Zeus.ExpenseRecipientType;
|
||||
recipient_name?: string;
|
||||
requisites?: string;
|
||||
/** Назначение платежа (оплата по счёту организации/ИП). */
|
||||
payment_purpose?: string;
|
||||
recipient_account?: string;
|
||||
item_hash?: string;
|
||||
/** Идентификатор платёжного метода получателя-пайщика (SELF/MEMBER). */
|
||||
@@ -77,6 +79,7 @@ export function useCreateProgramExpense() {
|
||||
mechanics: it.mechanics,
|
||||
recipient_name: it.recipient_name ?? '',
|
||||
requisites: it.requisites ?? '',
|
||||
payment_purpose: it.payment_purpose || undefined,
|
||||
payment_method_id: it.payment_method_id ?? undefined,
|
||||
recipient_username:
|
||||
it.recipient_type === Zeus.ExpenseRecipientType.MEMBER
|
||||
@@ -116,6 +119,7 @@ export function useCreateProgramExpense() {
|
||||
planned_amount: formatToAsset(it.amount, symbol, precision),
|
||||
payment_method_id: it.payment_method_id ?? undefined,
|
||||
requisites: it.requisites || undefined,
|
||||
payment_purpose: it.payment_purpose || undefined,
|
||||
}));
|
||||
|
||||
const result = await createProgramExpense({
|
||||
|
||||
+13
-6
@@ -57,8 +57,7 @@ BaseDialog(
|
||||
v-model='item.mechanics',
|
||||
:options='mechanicsOptions',
|
||||
label='Способ оплаты',
|
||||
disabled,
|
||||
hint='Пайщику — только аванс под отчёт; организации — только прямая оплата'
|
||||
disabled
|
||||
)
|
||||
.col-12.col-md-6(v-if='item.recipient_type === Zeus.ExpenseRecipientType.MEMBER')
|
||||
BaseInput(
|
||||
@@ -109,6 +108,13 @@ BaseDialog(
|
||||
placeholder='ИНН, р/с, БИК',
|
||||
required
|
||||
)
|
||||
.col-12(v-if='item.recipient_type === Zeus.ExpenseRecipientType.ORG')
|
||||
BaseInput(
|
||||
v-model='item.payment_purpose',
|
||||
label='Назначение платежа',
|
||||
placeholder='Например: «Оплата по счёту № 814 от 01.06.2026 за аренду серверов»',
|
||||
required
|
||||
)
|
||||
|
||||
template(#footer)
|
||||
.footer-bar
|
||||
@@ -163,13 +169,13 @@ const submitting = ref(false);
|
||||
|
||||
const mechanicsOptions = [
|
||||
{ label: 'Аванс под отчёт', value: Zeus.ExpenseMechanics.ADVANCE },
|
||||
{ label: 'Прямая оплата', value: Zeus.ExpenseMechanics.DIRECT },
|
||||
{ label: 'Оплата по счету', value: Zeus.ExpenseMechanics.DIRECT },
|
||||
];
|
||||
|
||||
const recipientTypeOptions = [
|
||||
{ label: 'Я сам', value: Zeus.ExpenseRecipientType.SELF },
|
||||
{ label: 'Пайщик', value: Zeus.ExpenseRecipientType.MEMBER },
|
||||
{ label: 'Организация', value: Zeus.ExpenseRecipientType.ORG },
|
||||
{ label: 'Организация/ИП', value: Zeus.ExpenseRecipientType.ORG },
|
||||
];
|
||||
|
||||
// Пайщик получает только аванс под отчёт (личные реквизиты, отчитается чеком);
|
||||
@@ -196,7 +202,7 @@ const canSubmit = computed(
|
||||
i.description.trim() &&
|
||||
(i.recipient_type !== Zeus.ExpenseRecipientType.MEMBER || i.recipient_account?.trim()) &&
|
||||
(i.recipient_type === Zeus.ExpenseRecipientType.ORG
|
||||
? Boolean(i.recipient_name?.trim() && i.requisites?.trim())
|
||||
? Boolean(i.recipient_name?.trim() && i.requisites?.trim() && i.payment_purpose?.trim())
|
||||
: Boolean(i.payment_method_id)),
|
||||
),
|
||||
);
|
||||
@@ -210,6 +216,7 @@ function addItem(): void {
|
||||
recipient_type: Zeus.ExpenseRecipientType.SELF,
|
||||
recipient_name: '',
|
||||
requisites: '',
|
||||
payment_purpose: '',
|
||||
recipient_account: '',
|
||||
payment_method_id: null,
|
||||
});
|
||||
@@ -231,7 +238,7 @@ async function submit(): Promise<void> {
|
||||
deadline: form.deadline,
|
||||
items: form.items,
|
||||
});
|
||||
SuccessAlert('Программный расход подан — заявление подписано и передано в шасси расходов');
|
||||
SuccessAlert('Программный расход подан — заявление подписано и передано в совет');
|
||||
emit('created');
|
||||
close();
|
||||
} catch (e) {
|
||||
|
||||
@@ -16,6 +16,8 @@ export interface ICreateProposalDraftItem {
|
||||
mechanics: 'ADVANCE' | 'DIRECT';
|
||||
recipient_name?: string;
|
||||
requisites?: string;
|
||||
/** Назначение платежа (оплата по счёту организации/ИП). */
|
||||
payment_purpose?: string;
|
||||
item_hash?: string;
|
||||
recipient_account?: string;
|
||||
}
|
||||
@@ -46,6 +48,7 @@ export function useExpenseProposalActions() {
|
||||
mechanics: it.mechanics,
|
||||
recipient_name: it.recipient_name ?? '',
|
||||
requisites: it.requisites ?? '',
|
||||
payment_purpose: it.payment_purpose || undefined,
|
||||
}));
|
||||
|
||||
const proposalHeader = {
|
||||
@@ -80,6 +83,7 @@ export function useExpenseProposalActions() {
|
||||
recipient: it.recipient_account ?? it.recipient_name ?? session.username,
|
||||
description: it.description,
|
||||
planned_amount: it.amount,
|
||||
payment_purpose: it.payment_purpose || undefined,
|
||||
}));
|
||||
|
||||
return createExpenseProposal({
|
||||
|
||||
@@ -76,8 +76,7 @@ BaseDialog(
|
||||
dense,
|
||||
emit-value,
|
||||
map-options,
|
||||
disable,
|
||||
hint='Пайщику — только аванс под отчёт; организации — только прямая оплата'
|
||||
disable
|
||||
)
|
||||
.col-12.col-md-6
|
||||
BaseInput(
|
||||
@@ -110,6 +109,12 @@ BaseDialog(
|
||||
label='Реквизиты получателя',
|
||||
placeholder='ИНН, р/с, БИК'
|
||||
)
|
||||
.col-12(v-if='item.recipient_type === "ORG"')
|
||||
BaseInput(
|
||||
v-model='item.payment_purpose',
|
||||
label='Назначение платежа',
|
||||
placeholder='Например: «Оплата по счёту № 814 от 01.06.2026 за аренду серверов»'
|
||||
)
|
||||
|
||||
template(#footer)
|
||||
.footer-bar
|
||||
@@ -151,12 +156,12 @@ const submitting = ref(false);
|
||||
const recipientTypeOptions = [
|
||||
{ label: 'Я сам', value: 'SELF' as const },
|
||||
{ label: 'Пайщик', value: 'MEMBER' as const },
|
||||
{ label: 'Организация', value: 'ORG' as const },
|
||||
{ label: 'Организация/ИП', value: 'ORG' as const },
|
||||
];
|
||||
|
||||
const mechanicsOptions = [
|
||||
{ label: 'Аванс под отчёт', value: 'ADVANCE' as const },
|
||||
{ label: 'Прямая оплата', value: 'DIRECT' as const },
|
||||
{ label: 'Оплата по счету', value: 'DIRECT' as const },
|
||||
];
|
||||
|
||||
// Пайщик получает только аванс под отчёт; организация — только прямую оплату.
|
||||
@@ -182,6 +187,7 @@ function addItem(): void {
|
||||
mechanics: 'ADVANCE',
|
||||
recipient_name: '',
|
||||
requisites: '',
|
||||
payment_purpose: '',
|
||||
recipient_account: '',
|
||||
});
|
||||
}
|
||||
@@ -203,7 +209,7 @@ async function submit(): Promise<void> {
|
||||
deadline: form.deadline,
|
||||
items: form.items,
|
||||
});
|
||||
SuccessAlert('Служебная записка подана — заявление подписано и отправлено в блокчейн');
|
||||
SuccessAlert('Служебная записка подана — заявление подписано и передано в совет');
|
||||
emit('created');
|
||||
close();
|
||||
} catch (e) {
|
||||
|
||||
@@ -100,6 +100,8 @@ export interface InterExpenseRequisiteItemInput {
|
||||
paymentMethodId?: string;
|
||||
/** Реквизиты строкой (организации — ручной ввод из формы). */
|
||||
requisites?: string;
|
||||
/** Назначение платежа (оплата по счёту) — фиксируется в снимке для кассира. */
|
||||
paymentPurpose?: string;
|
||||
}
|
||||
|
||||
export interface InterExpenseChassisPort {
|
||||
|
||||
@@ -2644,7 +2644,7 @@ export type ValueTypes = {
|
||||
description: string | Variable<any, string>,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string | Variable<any, string>,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<ValueTypes["ExpenseItemInput"]> | Variable<any, string>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: ValueTypes["ExpenseProposalStatementSignedDocumentInput"] | Variable<any, string>
|
||||
@@ -5282,6 +5282,8 @@ export type ValueTypes = {
|
||||
mechanics: ValueTypes["ExpenseMechanics"] | Variable<any, string>,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null | Variable<any, string>,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null | Variable<any, string>,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string | Variable<any, string>,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -5418,6 +5420,8 @@ export type ValueTypes = {
|
||||
number: string | Variable<any, string>,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null | Variable<any, string>,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null | Variable<any, string>,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null | Variable<any, string>,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
@@ -11737,7 +11741,7 @@ export type ResolverInputTypes = {
|
||||
description: string,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<ResolverInputTypes["ExpenseItemInput"]>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: ResolverInputTypes["ExpenseProposalStatementSignedDocumentInput"]
|
||||
@@ -14312,6 +14316,8 @@ export type ResolverInputTypes = {
|
||||
mechanics: ResolverInputTypes["ExpenseMechanics"],
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -14447,6 +14453,8 @@ export type ResolverInputTypes = {
|
||||
number: string,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
@@ -20579,7 +20587,7 @@ export type ModelTypes = {
|
||||
description: string,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<ModelTypes["ExpenseItemInput"]>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: ModelTypes["ExpenseProposalStatementSignedDocumentInput"]
|
||||
@@ -23083,6 +23091,8 @@ export type ModelTypes = {
|
||||
mechanics: ModelTypes["ExpenseMechanics"],
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -23215,6 +23225,8 @@ export type ModelTypes = {
|
||||
number: string,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
@@ -30003,7 +30015,7 @@ export type GraphQLTypes = {
|
||||
description: string,
|
||||
/** Хэш СЗ-расхода (детерминированный, из UI). Он же станет proposal_hash в шасси. */
|
||||
expense_hash: string,
|
||||
/** Строки расхода. Способ оплаты (аванс / прямая оплата) задаётся на каждой строке отдельно. */
|
||||
/** Строки расхода. Способ оплаты (аванс под отчёт / оплата по счёту) задаётся на каждой строке отдельно. */
|
||||
items: Array<GraphQLTypes["ExpenseItemInput"]>,
|
||||
/** Подписанная СЗ-смета (document2, registry 2010). */
|
||||
statement: GraphQLTypes["ExpenseProposalStatementSignedDocumentInput"]
|
||||
@@ -32641,6 +32653,8 @@ export type GraphQLTypes = {
|
||||
mechanics: GraphQLTypes["ExpenseMechanics"],
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — реквизиты снимаются в момент создания и прикладываются к платежу. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа (для оплаты по счёту) — фиксируется в снимке для кассира. */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Планируемая сумма (asset, eg "1000.0000 RUB"). */
|
||||
planned_amount: string,
|
||||
/** Получатель: username пайщика; для организации — пустая строка (аккаунта в кооперативе нет). */
|
||||
@@ -32777,6 +32791,8 @@ export type GraphQLTypes = {
|
||||
number: string,
|
||||
/** Идентификатор сохранённых реквизитов получателя-пайщика — сервер подставит полные реквизиты в документ. */
|
||||
payment_method_id?: string | undefined | null,
|
||||
/** Назначение платежа — отдельной строкой после реквизитов */
|
||||
payment_purpose?: string | undefined | null,
|
||||
/** Имя получателя */
|
||||
recipient_name?: string | undefined | null,
|
||||
/** Тип получателя (SELF / MEMBER / ORG) */
|
||||
|
||||
Reference in New Issue
Block a user