Merge pull request 'warmfix: New payment from ticket' (!1801) from warmfix_ticket_newPayment into test
gitea/salix-front/pipeline/head This commit looks good
Details
gitea/salix-front/pipeline/head This commit looks good
Details
Reviewed-on: #1801 Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
This commit is contained in:
commit
0b5cc7d00f
|
@ -55,7 +55,6 @@ const filterBanks = {
|
|||
fields: ['id', 'bank', 'accountingTypeFk'],
|
||||
include: { relation: 'accountingType' },
|
||||
order: 'id',
|
||||
limit: 30,
|
||||
};
|
||||
|
||||
const filterClientFindOne = {
|
||||
|
@ -200,7 +199,6 @@ async function getAmountPaid() {
|
|||
option-label="bank"
|
||||
:include="{ relation: 'accountingType' }"
|
||||
sort-by="id"
|
||||
:limit="0"
|
||||
@update:model-value="
|
||||
(value, options) => setPaymentType(data, value, options)
|
||||
"
|
||||
|
|
|
@ -14,8 +14,6 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
|||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnRow from 'src/components/ui/VnRow.vue';
|
||||
import TicketFilter from './TicketFilter.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
|
||||
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
|
||||
|
@ -25,6 +23,7 @@ import TicketProblems from 'src/components/TicketProblems.vue';
|
|||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
|
||||
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
|
||||
import TicketNewPayment from './components/TicketNewPayment.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
@ -73,11 +72,6 @@ const initializeFromQuery = () => {
|
|||
|
||||
const selectedRows = ref([]);
|
||||
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
|
||||
const showForm = ref(false);
|
||||
const dialogData = ref();
|
||||
const companiesOptions = ref([]);
|
||||
const accountingOptions = ref([]);
|
||||
const amountToReturn = ref();
|
||||
const dataKey = 'TicketList';
|
||||
const formInitialData = ref({});
|
||||
|
||||
|
@ -381,101 +375,22 @@ function openBalanceDialog(ticket) {
|
|||
description.value.push(ticketData.id);
|
||||
}
|
||||
|
||||
const balanceCreateDialog = ref({
|
||||
const dialogData = ref({
|
||||
amountPaid: amountPaid.value,
|
||||
clientFk: clientFk.value,
|
||||
description: `Albaran: ${description.value.join(', ')}`,
|
||||
});
|
||||
dialogData.value = balanceCreateDialog;
|
||||
showForm.value = true;
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
const { data: email } = await axios.get('Clients', {
|
||||
params: {
|
||||
filter: JSON.stringify({ where: { id: dialogData.value.value.clientFk } }),
|
||||
quasar.dialog({
|
||||
component: TicketNewPayment,
|
||||
componentProps: {
|
||||
clientId: clientFk.value,
|
||||
formData: dialogData.value,
|
||||
},
|
||||
});
|
||||
|
||||
const { data } = await axios.post(
|
||||
`Clients/${dialogData.value.value.clientFk}/createReceipt`,
|
||||
{
|
||||
payed: dialogData.value.payed,
|
||||
companyFk: dialogData.value.companyFk,
|
||||
bankFk: dialogData.value.bankFk,
|
||||
amountPaid: dialogData.value.value.amountPaid,
|
||||
description: dialogData.value.value.description,
|
||||
clientFk: dialogData.value.value.clientFk,
|
||||
email: email[0].email,
|
||||
},
|
||||
);
|
||||
|
||||
if (data) notify('globals.dataSaved', 'positive');
|
||||
showForm.value = false;
|
||||
}
|
||||
|
||||
const setAmountToReturn = (newAmountGiven) => {
|
||||
const amountPaid = dialogData.value.value.amountPaid;
|
||||
|
||||
amountToReturn.value = newAmountGiven - amountPaid;
|
||||
};
|
||||
|
||||
function setReference(data) {
|
||||
let newDescription = '';
|
||||
|
||||
switch (data) {
|
||||
case 1:
|
||||
newDescription = `${t(
|
||||
'ticketList.creditCard',
|
||||
)}, ${dialogData.value.value.description.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
'',
|
||||
)}`;
|
||||
break;
|
||||
case 2:
|
||||
newDescription = `${t(
|
||||
'ticketList.cash',
|
||||
)}, ${dialogData.value.value.description.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
'',
|
||||
)}`;
|
||||
break;
|
||||
case 3:
|
||||
newDescription = `${newDescription.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
'',
|
||||
)}`;
|
||||
break;
|
||||
case 4:
|
||||
newDescription = `${t(
|
||||
'ticketList.transfers',
|
||||
)}, ${dialogData.value.value.description.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
'',
|
||||
)}`;
|
||||
break;
|
||||
case 3317:
|
||||
newDescription = '';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dialogData.value.value.description = newDescription;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Companies"
|
||||
@on-fetch="(data) => (companiesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Accountings"
|
||||
@on-fetch="(data) => (accountingOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<VnSection
|
||||
:data-key="dataKey"
|
||||
:columns="columns"
|
||||
|
@ -722,99 +637,6 @@ function setReference(data) {
|
|||
{{ t('ticketList.accountPayment') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
<QDialog ref="dialogRef" v-model="showForm">
|
||||
<QCard class="q-pa-md q-mb-md">
|
||||
<QForm @submit="onSubmit()" class="q-pa-sm">
|
||||
{{ t('ticketList.addPayment') }}
|
||||
<VnRow>
|
||||
<VnInputDate
|
||||
:label="t('ticketList.date')"
|
||||
v-model="dialogData.payed"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('ticketList.company')"
|
||||
v-model="dialogData.companyFk"
|
||||
:options="companiesOptions"
|
||||
option-label="code"
|
||||
hide-selected
|
||||
>
|
||||
</VnSelect>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('ticketList.bank')"
|
||||
v-model="dialogData.bankFk"
|
||||
:options="accountingOptions"
|
||||
option-label="bank"
|
||||
hide-selected
|
||||
@update:model-value="setReference"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('ticketList.amount')"
|
||||
v-model="dialogData.value.amountPaid"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 2">
|
||||
<span>
|
||||
{{ t('ticketList.cash') }}
|
||||
</span>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 2">
|
||||
<VnInput
|
||||
:label="t('ticketList.deliveredAmount')"
|
||||
v-model="dialogData.value.amountGiven"
|
||||
@update:model-value="setAmountToReturn"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('ticketList.amountToReturn')"
|
||||
:model-value="amountToReturn"
|
||||
type="number"
|
||||
readonly
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 3 || dialogData.bankFk === 3117">
|
||||
<VnInput
|
||||
:label="t('ticketList.compensation')"
|
||||
v-model="dialogData.value.compensation"
|
||||
type="text"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('ticketList.reference')"
|
||||
v-model="dialogData.value.description"
|
||||
type="text"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 2">
|
||||
<QCheckbox
|
||||
:label="t('ticketList.viewReceipt')"
|
||||
v-model="dialogData.value.viewReceipt"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('ticketList.sendEmail')"
|
||||
v-model="dialogData.value.senEmail"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</VnRow>
|
||||
<div class="q-mt-lg row justify-end">
|
||||
<QBtn
|
||||
:label="t('globals.save')"
|
||||
color="primary"
|
||||
@click="onSubmit()"
|
||||
/>
|
||||
<QBtn
|
||||
flat
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
/>
|
||||
</div>
|
||||
</QForm>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
<QPageSticky v-if="hasSelectedRows" :offset="[20, 200]" style="z-index: 2">
|
||||
<QBtn
|
||||
@click="sendDocuware(selectedRows)"
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import axios from 'axios';
|
||||
import { useDialogPluginComponent } from 'quasar';
|
||||
|
||||
import { usePrintService } from 'src/composables/usePrintService';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
||||
import FormModelPopup from 'src/components/FormModelPopup.vue';
|
||||
import VnRow from 'src/components/ui/VnRow.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';
|
||||
import { useState } from 'src/composables/useState';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
const { sendEmail, openReport } = usePrintService();
|
||||
const { dialogRef } = useDialogPluginComponent();
|
||||
|
||||
const $props = defineProps({
|
||||
formData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
clientId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
promise: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const closeButton = ref(null);
|
||||
const viewReceipt = ref();
|
||||
const shouldSendEmail = ref(false);
|
||||
const maxAmount = ref();
|
||||
const accountingType = ref({});
|
||||
const isCash = ref(false);
|
||||
const formModelRef = ref(false);
|
||||
const amountToReturn = ref();
|
||||
const filterBanks = {
|
||||
fields: ['id', 'bank', 'accountingTypeFk'],
|
||||
include: { relation: 'accountingType' },
|
||||
order: 'id',
|
||||
};
|
||||
|
||||
const state = useState();
|
||||
const user = state.getUser();
|
||||
const initialData = ref({
|
||||
...$props.formData.value,
|
||||
companyFk: user.value.companyFk,
|
||||
payed: Date.vnNew(),
|
||||
});
|
||||
|
||||
function setPaymentType(data, accounting) {
|
||||
data.bankFk = accounting.id;
|
||||
if (!accounting) return;
|
||||
accountingType.value = accounting.accountingType;
|
||||
data.description = [];
|
||||
data.payed = Date.vnNew();
|
||||
isCash.value = accountingType.value.code == 'cash';
|
||||
viewReceipt.value = isCash.value;
|
||||
if (accountingType.value.daysInFuture)
|
||||
data.payed.setDate(data.payed.getDate() + accountingType.value.daysInFuture);
|
||||
maxAmount.value = accountingType.value && accountingType.value.maxAmount;
|
||||
if (accountingType.value.code == 'compensation') return (data.description = '');
|
||||
|
||||
let descriptions = [];
|
||||
if (accountingType.value.receiptDescription)
|
||||
descriptions.push(accountingType.value.receiptDescription);
|
||||
if (data.description > 0) descriptions.push(data.description);
|
||||
data.description = descriptions.join(', ');
|
||||
}
|
||||
|
||||
const calculateFromAmount = (event) => {
|
||||
initialData.value.amountToReturn = Number(
|
||||
(parseFloat(initialData.value.deliveredAmount) + parseFloat(event) * -1).toFixed(
|
||||
2,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
const calculateFromDeliveredAmount = (event) => {
|
||||
amountToReturn.value = Number((event - initialData.value.amountPaid).toFixed(2));
|
||||
};
|
||||
|
||||
function onBeforeSave(data) {
|
||||
const exceededAmount = data.amountPaid > maxAmount.value;
|
||||
if (isCash.value && exceededAmount)
|
||||
return notify(t('Amount exceeded', { maxAmount: maxAmount.value }), 'negative');
|
||||
|
||||
if (isCash.value && shouldSendEmail.value && !data.email)
|
||||
return notify(t('There is no assigned email for this client'), 'negative');
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function onDataSaved({ email, id }) {
|
||||
try {
|
||||
if (shouldSendEmail.value && isCash.value)
|
||||
await sendEmail(`Receipts/${id}/receipt-email`, {
|
||||
recipient: email,
|
||||
});
|
||||
|
||||
if (viewReceipt.value) openReport(`Receipts/${id}/receipt-pdf`, {}, '_blank');
|
||||
} finally {
|
||||
if ($props.promise) $props.promise();
|
||||
if (closeButton.value) closeButton.value.click();
|
||||
}
|
||||
}
|
||||
|
||||
async function getSupplierClientReferences(data) {
|
||||
if (!data) return (initialData.value.description = '');
|
||||
const params = { bankAccount: data.compensationAccount };
|
||||
const { data: reference } = await axios(`Clients/getClientOrSupplierReference`, {
|
||||
params,
|
||||
});
|
||||
if (reference.supplierId) {
|
||||
data.description = t('Supplier Compensation Reference', {
|
||||
supplierId: reference.supplierId,
|
||||
supplierName: reference.supplierName,
|
||||
});
|
||||
return;
|
||||
}
|
||||
data.description = t('Client Compensation Reference', {
|
||||
clientId: reference.clientId,
|
||||
clientName: reference.clientName,
|
||||
});
|
||||
}
|
||||
|
||||
async function getAmountPaid() {
|
||||
const filter = {
|
||||
where: {
|
||||
clientFk: $props.clientId,
|
||||
companyFk: initialData.value.companyFk,
|
||||
},
|
||||
};
|
||||
|
||||
const { data } = await getClientRisk(filter);
|
||||
initialData.value.amountPaid = (data?.length && data[0].amount) || undefined;
|
||||
}
|
||||
|
||||
async function onSubmit(formData) {
|
||||
const {
|
||||
data: [{ email }],
|
||||
} = await axios.get('Clients', {
|
||||
params: {
|
||||
filter: JSON.stringify({ where: { id: $props.clientFk } }),
|
||||
},
|
||||
});
|
||||
|
||||
const { data } = await axios.post(`Clients/${formData.clientFk}/createReceipt`, {
|
||||
payed: formData.payed,
|
||||
companyFk: formData.companyFk,
|
||||
bankFk: formData.bankFk,
|
||||
amountPaid: formData.amountPaid,
|
||||
description: formData.description,
|
||||
clientFk: $props.clientFk,
|
||||
email,
|
||||
});
|
||||
|
||||
if (data) notify('globals.dataSaved', 'positive');
|
||||
await onDataSaved(data);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QDialog ref="dialogRef" persistent>
|
||||
<FormModelPopup
|
||||
ref="formModelRef"
|
||||
:form-initial-data="initialData"
|
||||
:save-fn="onSubmit"
|
||||
:prevent-submit="true"
|
||||
:mapper="onBeforeSave"
|
||||
>
|
||||
<template #form-inputs="{ data, validate }">
|
||||
<h5 class="q-mt-none">{{ t('New payment') }}</h5>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
autofocus
|
||||
:label="t('Bank')"
|
||||
v-model="data.bankFk"
|
||||
url="Accountings"
|
||||
:filter="filterBanks"
|
||||
option-label="bank"
|
||||
:include="{ relation: 'accountingType' }"
|
||||
sort-by="id"
|
||||
@update:model-value="
|
||||
(value, options) => setPaymentType(data, value, options)
|
||||
"
|
||||
:emit-value="false"
|
||||
data-cy="paymentBank"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>
|
||||
{{ scope.opt.id }}: {{ scope.opt.bank }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnInputNumber
|
||||
:label="t('Amount')"
|
||||
:required="true"
|
||||
@update:model-value="calculateFromAmount($event)"
|
||||
clearable
|
||||
v-model.number="data.amountPaid"
|
||||
data-cy="paymentAmount"
|
||||
:positive="false"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInputDate
|
||||
:label="t('Date')"
|
||||
v-model="data.payed"
|
||||
:required="true"
|
||||
/>
|
||||
<VnSelect
|
||||
url="Companies"
|
||||
:label="t('Company')"
|
||||
:required="true"
|
||||
:rules="validate('entry.companyFk')"
|
||||
hide-selected
|
||||
option-label="code"
|
||||
v-model="data.companyFk"
|
||||
@update:model-value="getAmountPaid()"
|
||||
/>
|
||||
</VnRow>
|
||||
<div v-if="accountingType.code == 'compensation'">
|
||||
<div class="text-h6">
|
||||
{{ t('Compensation') }}
|
||||
</div>
|
||||
<VnRow>
|
||||
<VnAccountNumber
|
||||
:label="t('Compensation account')"
|
||||
clearable
|
||||
v-model="data.compensationAccount"
|
||||
@blur="getSupplierClientReferences(data)"
|
||||
/>
|
||||
</VnRow>
|
||||
</div>
|
||||
<VnInput
|
||||
:label="t('Reference')"
|
||||
:required="true"
|
||||
clearable
|
||||
v-model="data.description"
|
||||
/>
|
||||
<div v-if="accountingType.code == 'cash'">
|
||||
<div class="text-h6">{{ t('Cash') }}</div>
|
||||
<VnRow>
|
||||
<VnInputNumber
|
||||
:label="t('Delivered amount')"
|
||||
@update:model-value="calculateFromDeliveredAmount($event)"
|
||||
clearable
|
||||
v-model="data.deliveredAmount"
|
||||
/>
|
||||
<VnInputNumber
|
||||
:label="t('Amount to return')"
|
||||
disable
|
||||
v-model="amountToReturn"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<QCheckbox v-model="viewReceipt" :label="t('View recipt')" />
|
||||
<QCheckbox v-model="shouldSendEmail" :label="t('Send email')" />
|
||||
</VnRow>
|
||||
</div>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
</QDialog>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
en:
|
||||
Supplier Compensation Reference: ({supplierId}) Ntro Proveedor {supplierName}
|
||||
Client Compensation Reference: ({clientId}) Ntro Cliente {clientName}
|
||||
es:
|
||||
New payment: Añadir pago
|
||||
Date: Fecha
|
||||
Company: Empresa
|
||||
Bank: Caja
|
||||
Amount: Importe
|
||||
Reference: Referencia
|
||||
Cash: Efectivo
|
||||
Delivered amount: Cantidad entregada
|
||||
Amount to return: Cantidad a devolver
|
||||
View recipt: Ver recibido
|
||||
Send email: Enviar correo
|
||||
Compensation: Compensación
|
||||
Compensation account: Cuenta para compensar
|
||||
Supplier Compensation Reference: ({supplierId}) Ntro Proveedor {supplierName}
|
||||
Client Compensation Reference: ({clientId}) Ntro Cliente {clientName}
|
||||
There is no assigned email for this client: No hay correo asignado para este cliente
|
||||
Amount exceeded: Según ley contra el fraude no se puede recibir cobros por importe igual o superior a {maxAmount}
|
||||
</i18n>
|
Loading…
Reference in New Issue