feat: add treasury audit, attachment download, and installment SMS
Let cheque clearance pick a cash account and export income, expense, and installment lists to Excel. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,6 +27,10 @@ const items = ref<ChequeDto[]>([]);
|
||||
const status = ref('');
|
||||
const q = ref('');
|
||||
const savingId = ref('');
|
||||
const clearOpen = ref(false);
|
||||
const clearRow = ref<ChequeDto | null>(null);
|
||||
const clearAccountId = ref('');
|
||||
const clearAccounts = ref<Array<{ id: string; name: string }>>([]);
|
||||
const tab = ref<ChequeDirection>('in');
|
||||
|
||||
const formOpen = ref(false);
|
||||
@@ -95,9 +99,26 @@ async function load() {
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmClear() {
|
||||
if (!clearRow.value || !clearAccountId.value) return;
|
||||
savingId.value = clearRow.value.id;
|
||||
error.value = '';
|
||||
try {
|
||||
const { data } = await api.patch<ChequeDto>(`/cheques/${clearRow.value.id}`, {
|
||||
status: 'cleared',
|
||||
financialAccountId: clearAccountId.value,
|
||||
});
|
||||
items.value = items.value.map((item) => (item.id === data.id ? data : item));
|
||||
clearOpen.value = false;
|
||||
} catch {
|
||||
error.value = 'وصول چک ناموفق بود.';
|
||||
} finally {
|
||||
savingId.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
async function setStatus(row: ChequeDto, next: ChequeStatus) {
|
||||
if (row.status === next) return;
|
||||
let financialAccountId: string | undefined;
|
||||
if (next === 'cleared' && row.status !== 'cleared') {
|
||||
const accountsRes = await api
|
||||
.get<Array<{ id: string; name: string; isActive: boolean }>>('/treasury/accounts')
|
||||
@@ -114,30 +135,20 @@ async function setStatus(row: ChequeDto, next: ChequeStatus) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
const accounts = accountsRes.data;
|
||||
const active = accounts.filter((item) => item.isActive);
|
||||
const active = accountsRes.data.filter((item) => item.isActive);
|
||||
if (!active.length) {
|
||||
error.value = 'برای وصول چک ابتدا یک حساب صندوق بسازید.';
|
||||
return;
|
||||
}
|
||||
if (active.length === 1) {
|
||||
financialAccountId = active[0]!.id;
|
||||
} else {
|
||||
const picked = window.prompt(`نام حساب صندوق را بنویسید: ${active.map((item) => item.name).join('، ')}`);
|
||||
const match = active.find((item) => item.name.trim() === picked?.trim());
|
||||
if (!match) {
|
||||
error.value = 'حساب صندوق انتخاب نشد.';
|
||||
return;
|
||||
}
|
||||
financialAccountId = match.id;
|
||||
}
|
||||
clearAccounts.value = active.map((item) => ({ id: item.id, name: item.name }));
|
||||
clearAccountId.value = active[0]!.id;
|
||||
clearRow.value = row;
|
||||
clearOpen.value = true;
|
||||
return;
|
||||
}
|
||||
savingId.value = row.id;
|
||||
try {
|
||||
const { data } = await api.patch<ChequeDto>(`/cheques/${row.id}`, {
|
||||
status: next,
|
||||
...(financialAccountId ? { financialAccountId } : {}),
|
||||
});
|
||||
const { data } = await api.patch<ChequeDto>(`/cheques/${row.id}`, { status: next });
|
||||
items.value = items.value.map((item) => (item.id === row.id ? data : item));
|
||||
} catch {
|
||||
error.value = 'تغییر وضعیت چک ناموفق بود.';
|
||||
@@ -326,6 +337,24 @@ onMounted(load);
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<UiModal :open="clearOpen" title="حساب وصول چک" @close="clearOpen = false">
|
||||
<p class="hint">چک {{ clearRow?.number }} در کدام حساب صندوق بنشیند؟</p>
|
||||
<label class="field">
|
||||
<span>حساب</span>
|
||||
<select v-model="clearAccountId">
|
||||
<option v-for="account in clearAccounts" :key="account.id" :value="account.id">
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
<UiButton
|
||||
:loading="savingId === clearRow?.id"
|
||||
@click="confirmClear"
|
||||
>
|
||||
ثبت وصول
|
||||
</UiButton>
|
||||
</UiModal>
|
||||
|
||||
<UiModal
|
||||
:open="formOpen"
|
||||
:title="isIncomingForm ? 'دریافت چک' : 'پرداخت چک'"
|
||||
|
||||
Reference in New Issue
Block a user