feat(desktop): гейт реквизитов в выходе из кооператива
Typecheck / desktop (pull_request) Failing after 8m35s
Typecheck / controller (pull_request) Successful in 13m35s

Перед подписанием заявления о выходе проверяем наличие реквизитов пайщика
(getPaymentMethods). Если их нет — вместо формы показываем баннер «установите
реквизиты для получения возврата паевого взноса» + кнопку перехода на страницу
реквизитов (payment-methods). Бэкенд проверяет то же при подаче (страховка).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
coopops
2026-06-15 17:17:46 +00:00
parent 56cd422440
commit 72a8a3d0c3
2 changed files with 64 additions and 1 deletions
@@ -74,6 +74,21 @@ export function useMembershipExit() {
return result;
}
/**
* Есть ли у пайщика реквизиты для получения возврата паевого взноса.
* Выход блокируется, пока их нет (бэкенд это же проверяет при подаче) — без
* реквизитов исходящий платёж возврата некуда будет создать.
*/
async function hasRequisites(): Promise<boolean> {
const { [Queries.PaymentMethods.GetPaymentMethods.name]: result } =
await client.Query(Queries.PaymentMethods.GetPaymentMethods.query, {
variables: {
data: { username: session.username, limit: 1, page: 1 },
},
});
return (result?.items?.length ?? 0) > 0;
}
/**
* Предварительный расчёт суммы возврата паевого взноса при выходе.
*/
@@ -145,5 +160,6 @@ export function useMembershipExit() {
createMembershipExit,
confirmExit,
getReturnPreview,
hasRequisites,
};
}
@@ -18,7 +18,28 @@ div
size='lg',
@update:model-value='(v) => !v && clear()'
)
//- Проверка реквизитов
div.q-pa-md.flex.items-center(v-if='checkingRequisites')
q-spinner(size='24px', color='primary')
span.q-ml-sm.text-grey-7 Проверка реквизитов
//- Нет реквизитов — выход заблокирован, ведём на страницу реквизитов
div(v-else-if='requisitesOk === false')
BaseBanner(variant='warn')
template(#icon)
q-icon(name='warning')
div
p.q-mb-sm Для выхода из кооператива установите реквизиты для получения возврата паевого взноса.
p.q-mb-none Без реквизитов кооператив не сможет вернуть вам паевой взнос.
div.q-mt-md.flex.justify-end
BaseButton(variant='primary', @click='goToRequisites')
template(#icon-left)
q-icon(name='account_balance', size='18px')
span.q-ml-sm Установить реквизиты
//- Реквизиты есть — показываем заявление и форму подписи
Form(
v-else,
:handler-submit='handlerSubmit',
:is-submitting='isSubmitting',
:disabled='!document || loadingDoc',
@@ -50,6 +71,7 @@ div
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { BaseButton } from 'src/shared/ui/base/BaseButton';
import { BaseDialog } from 'src/shared/ui/base/BaseDialog';
import { BaseBanner } from 'src/shared/ui/base/BaseBanner';
@@ -73,12 +95,16 @@ withDefaults(defineProps<Props>(), {
micro: false,
});
const route = useRoute();
const router = useRouter();
const walletStore = useWalletStore();
const { showDialog, open } = useExitDialog();
const { generateApplication, submitSignedApplication, getReturnPreview } = useMembershipExit();
const { generateApplication, submitSignedApplication, getReturnPreview, hasRequisites } = useMembershipExit();
const { loadExitStatus } = useExitGate();
const isSubmitting = ref(false);
const checkingRequisites = ref(false);
const requisitesOk = ref<boolean | null>(null);
const loadingDoc = ref(false);
const loadingPreview = ref(false);
const document = ref<IGenerateMembershipExitApplicationResult | null>(null);
@@ -86,6 +112,20 @@ const preview = ref<IMembershipExitReturnPreview | null>(null);
watch(showDialog, async (opened) => {
if (!opened) return;
// Гейт реквизитов — без них выход не запускаем.
checkingRequisites.value = true;
try {
requisitesOk.value = await hasRequisites();
} catch (error) {
// Не блокируем проактивно при сбое проверки — бэкенд всё равно отклонит подачу.
console.error('Не удалось проверить реквизиты пайщика:', error);
requisitesOk.value = true;
} finally {
checkingRequisites.value = false;
}
if (!requisitesOk.value) return;
loadingDoc.value = true;
loadingPreview.value = true;
try {
@@ -108,10 +148,17 @@ watch(showDialog, async (opened) => {
const clear = (): void => {
showDialog.value = false;
isSubmitting.value = false;
checkingRequisites.value = false;
requisitesOk.value = null;
document.value = null;
preview.value = null;
};
const goToRequisites = (): void => {
showDialog.value = false;
void router.push({ name: 'payment-methods', params: { coopname: route.params.coopname } });
};
const handlerSubmit = async (): Promise<void> => {
if (!document.value) return;
isSubmitting.value = true;