feat(Ticket): refs #7984 add currency
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Alex Moreno 2025-01-22 15:04:50 +01:00
parent 1ac0672f1e
commit 583a774d7d
13 changed files with 162 additions and 82 deletions

View File

@ -14,8 +14,8 @@ const $props = defineProps({
default: undefined,
},
foreignField: {
type: String,
default: 'foreignPrice',
type: [String, undefined],
default: undefined,
},
localField: {
type: String,
@ -27,22 +27,36 @@ const $props = defineProps({
description: 'find currency code in array data model',
},
});
const foreignFieldComputed = ref();
const arrayData = $props.arrayDataModel && useArrayData($props.arrayDataModel);
const foreignValue = computed(() => $props.model?.[$props.foreignField]);
const foreignValue = ref();
const localValue = computed(() => $props.model?.[$props.localField]);
const currency = computed(
() => $props.currencyCode ?? arrayData.store.data?.currency?.code
);
const toCurrencyLabel = computed(() =>
toCurrency(foreignValue.value ?? localValue.value, currency.value)
() => $props.currencyCode ?? arrayData.store.data?.currency?.code,
);
const toCurrencyLabel = ref();
const currencyCodeModel = ref();
// onMounted(() => {
// if ($props.arrayDataModel) {
// currencyCodeModel.value = arrayData.store.data?.currency?.code;
// }
// });
onMounted(() => {
// if ($props.arrayDataModel) {
// currencyCodeModel.value = arrayData.store.data?.currency?.code;
// }
foreignFieldComputed.value =
$props.foreignField ??
'foreign' +
$props.localField.charAt(0).toUpperCase() +
$props.localField.slice(1);
foreignValue.value = $props.model[foreignFieldComputed.value];
getLabel();
});
function getLabel() {
toCurrencyLabel.value = toCurrency(
foreignValue.value ?? localValue.value,
currency.value,
);
}
</script>
<template>

View File

@ -1,5 +1,5 @@
<script setup>
import { defineProps, ref } from 'vue';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();

View File

@ -10,6 +10,8 @@ import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import { getDifferences, getUpdatedValues } from 'src/filters';
import VnSelectCompany from 'src/components/common/VnSelectCompany.vue';
import VnSelectCurrency from 'src/components/common/VnSelectCurrency.vue';
const route = useRoute();
const { t } = useI18n();
@ -37,7 +39,7 @@ const exprBuilder = (param, value) => {
function onBeforeSave(formData, originalData) {
return getUpdatedValues(
Object.keys(getDifferences(formData, originalData)),
formData
formData,
);
}
</script>
@ -142,6 +144,10 @@ function onBeforeSave(formData, originalData) {
:input-debounce="0"
/>
</VnRow>
<VnRow>
<VnSelectCompany v-model="data.defaultCompanyFk" />
<VnSelectCurrency v-model="data.defaultCurrencyFk" />
</VnRow>
<VnRow>
<VnSelect
url="Clients"
@ -160,7 +166,7 @@ function onBeforeSave(formData, originalData) {
<QIcon name="info" class="cursor-pointer">
<QTooltip>{{
t(
'In case of a company succession, specify the grantor company'
'In case of a company succession, specify the grantor company',
)
}}</QTooltip>
</QIcon>

View File

@ -15,6 +15,7 @@ import InvoiceOutDescriptorProxy from 'pages/InvoiceOut/Card/InvoiceOutDescripto
import RouteDescriptorProxy from 'src/pages/Route/Card/RouteDescriptorProxy.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import CustomerDescriptorProxy from '../Card/CustomerDescriptorProxy.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const { t } = useI18n();
const route = useRoute();
@ -42,6 +43,7 @@ const filter = {
},
},
},
{ relation: 'currency' },
],
where: { clientFk: route.params.id },
order: ['shipped DESC', 'id'],
@ -114,7 +116,7 @@ const columns = computed(() => [
action: ({ id }) =>
window.open(
router.resolve({ params: { id }, name: 'TicketSale' }).href,
'_blank'
'_blank',
),
isPrimary: true,
},
@ -213,9 +215,19 @@ const getItemPackagingType = (ticketSales) => {
:color="setTotalPriceColor(row)"
text-color="black"
>
{{ toCurrency(row.totalWithVat) }}
<VnCurrency
:model="row"
local-field="totalWithVat"
:currency-code="row.currency.code"
/>
</QBadge>
<span v-else> {{ toCurrency(row.totalWithVat) }}</span>
<span v-else>
<VnCurrency
:model="row"
local-field="totalWithVat"
:currency-code="row.currency.code"
/>
</span>
</template>
<template #column-state="{ row }">
<span v-if="row.invoiceOut" @click.stop>

View File

@ -149,7 +149,7 @@ function sendPdfInvoice({ address }) {
const createInvoiceInCorrection = async () => {
const { data: correctingId } = await axios.post(
'InvoiceIns/corrective',
Object.assign(correctionFormData, { id: entityId.value })
Object.assign(correctionFormData, { id: entityId.value }),
);
push({ path: `/invoice-in/${correctingId}/summary` });
};
@ -272,7 +272,6 @@ const createInvoiceInCorrection = async () => {
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
{{ console.log('opt: ', opt) }}
<QItemSection>
<QItemLabel
>{{ opt.id }} -
@ -311,11 +310,11 @@ const createInvoiceInCorrection = async () => {
<i18n>
en:
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
isLinked: The entry has been linked to Sage. Please contact administration for further information
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
isLinked: The entry has been linked to Sage. Please contact administration for further information
assertAction: Are you sure you want to {action} this invoice?
es:
isNotLinked: Se ha eliminado el asiento {bookEntry} con {accountingEntries} apuntes
isLinked: El asiento fue enlazado a Sage, por favor contacta con administración
isNotLinked: Se ha eliminado el asiento {bookEntry} con {accountingEntries} apuntes
isLinked: El asiento fue enlazado a Sage, por favor contacta con administración
assertAction: Estas seguro de querer {action} esta factura?
</i18n>

View File

@ -74,7 +74,7 @@ function setTotal(response) {
total.value = response;
state.set('orderTotal', response);
}
const orderTotal = computed(() => state.get('orderTotal'));
const orderTotal = computed(() => state.get('orderTotal') ?? {});
const total = ref();
</script>

View File

@ -155,7 +155,7 @@ onMounted(() => {
async function fetchClientAddress(id, formData = {}) {
const { data } = await axios.get(
`Clients/${id}/addresses?filter[order]=isActive DESC`
`Clients/${id}/addresses?filter[order]=isActive DESC`,
);
addressOptions.value = data;
formData.addressId = data.defaultAddressFk;
@ -300,11 +300,11 @@ const getDateColor = (date) => {
option-label="agencyMode"
/>
<VnSelectCompany
v-model="data.defaultCompanyFk"
v-model="data.companyId"
v-model:client-id="data.clientFk"
/>
<VnSelectCurrency
v-model="data.defaultCurrencyFk"
v-model="data.currencyId"
v-model:client-id="data.clientFk"
/>
</template>

View File

@ -250,10 +250,7 @@ onMounted(async () => {
</template>
<template #body-cell-price="{ row }">
<QTd class="number">
<VnCurrency
:model="row.component"
:currency-code="formData.currency.code"
/>
<VnCurrency :model="row.component" array-data-model="ticketData" />
</QTd>
</template>
<template #body-cell-newPrice="{ row }">

View File

@ -43,7 +43,7 @@ const cancel = () => {
<template>
<QPopupProxy ref="QPopupProxyRef">
<div class="container">
<QSpinner v-if="!mana" color="primary" size="md" />
<QSpinner v-if="!mana && mana !== 0" color="primary" size="md" />
<div v-else>
<div class="header">Mana: {{ toCurrency(mana) }}</div>
<div class="q-pa-md">

View File

@ -5,11 +5,13 @@ import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import CatalogItem from 'components/ui/CatalogItem.vue';
import { toCurrency } from 'filters/index';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
import { useArrayData } from 'composables/useArrayData';
const { t } = useI18n();
const route = useRoute();
const arrayData = useArrayData('ticketData');
const { store } = arrayData;
const salesFilter = {
include: {
@ -37,7 +39,12 @@ const sales = ref([]);
<div class="q-mt-md full-width row justify-between items-center">
<span class="text-h6">{{ sale.quantity }}</span>
<span>{{ t('by') }}</span>
<span class="text-h6">{{ toCurrency(sale?.price) }}</span>
<span class="text-h6">
<VnCurrency
:model="sale"
:currency-code="store.data.currency.code"
/>
</span>
</div>
</template>
</CatalogItem>

View File

@ -58,7 +58,7 @@ const canProceed = ref();
watch(
() => route.params.id,
() => tableRef.value.reload()
() => tableRef.value.reload(),
);
const columns = computed(() => [
@ -201,7 +201,7 @@ const changeQuantity = async (sale) => {
await updateQuantity(sale);
} catch (e) {
const { quantity } = tableRef.value.CrudModelRef.originalData.find(
(s) => s.id === sale.id
(s) => s.id === sale.id,
);
sale.quantity = quantity;
throw e;
@ -506,7 +506,7 @@ async function isSalePrepared(item) {
componentProps: {
title: t('Item prepared'),
message: t(
'This item is already prepared. Do you want to continue?'
'This item is already prepared. Do you want to continue?',
),
data: item,
},
@ -528,7 +528,7 @@ watch(
if (newItemFk) {
updateItem(newRow.value);
}
}
},
);
</script>
@ -598,7 +598,7 @@ watch(
openConfirmationModal(
t('Continue anyway?'),
t('You are going to delete lines of the ticket'),
removeSales
removeSales,
)
"
>

View File

@ -21,6 +21,7 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const route = useRoute();
const { notify } = useNotify();
@ -277,19 +278,38 @@ function toTicketUrl(section) {
<QCard class="vn-one">
<VnTitle :text="t('ticket.summary.summaryAmount')" />
<div class="bodyCard">
<VnLv
:label="t('globals.subtotal')"
:value="toCurrency(entity.totalWithoutVat)"
/>
<VnLv
:label="t('globals.vat')"
:value="toCurrency(entity.totalWithVat - entity.totalWithoutVat)"
/>
<VnLv
:label="t('ticket.summary.total')"
:value="toCurrency(ticket.totalWithVat)"
style="font-weight: bold"
/>
<VnLv :label="t('globals.subtotal')">
<template #value>
<VnCurrency
:model="entity"
:currency-code="entity.currency.code"
local-field="totalWithoutVat"
/>
</template>
</VnLv>
<VnLv :label="t('globals.vat')">
<template #value>
<VnCurrency
:model="{
vat: entity.totalWithVat - entity.totalWithoutVat,
foreignVat:
entity.foreignTotalWithVat -
entity.foreignTotalWithoutVat,
}"
:currency-code="entity.currency.code"
local-field="vat"
/>
</template>
</VnLv>
<VnLv :label="t('ticket.summary.total')" style="font-weight: bold">
<template #value>
<VnCurrency
:model="entity"
:currency-code="entity.currency.code"
local-field="totalWithVat"
/>
</template>
</VnLv>
</div>
</QCard>
<QCard class="vn-max">
@ -447,16 +467,28 @@ function toTicketUrl(section) {
:item="props.row.item"
></FetchedTags>
</QTd>
<QTd>{{ props.row.price }} </QTd>
<QTd>
<VnCurrency
:model="props.row"
:currency-code="entity.currency.code"
/>
</QTd>
<QTd>{{ props.row.discount }} %</QTd>
<QTd
>{{
toCurrency(
props.row.quantity *
<QTd>
<VnCurrency
:model="{
amount:
props.row.quantity *
props.row.price *
((100 - props.row.discount) / 100)
)
}}
((100 - props.row.discount) / 100),
foreignAmount:
props.row.quantity *
props.row.foreignPrice *
((100 - props.row.discount) / 100),
}"
local-field="amount"
:currency-code="entity.currency.code"
/>
</QTd>
<QTd>{{ dashIfEmpty(props.row.item.itemPackingTypeFk) }}</QTd>
</QTr>
@ -501,7 +533,12 @@ function toTicketUrl(section) {
<QTr :props="props">
<QTd>{{ props.row.quantity }}</QTd>
<QTd>{{ props.row.description }}</QTd>
<QTd>{{ toCurrency(props.row.price) }}</QTd>
<QTd>
<VnCurrency
:model="props.row"
:currency-code="entity.currency.code"
/>
</QTd>
<QTd>{{ props.row.taxClass.description }}</QTd>
<QTd>{{
toCurrency(props.row.quantity * props.row.price)

View File

@ -1,11 +1,11 @@
<script setup>
import axios from 'axios';
import { computed, ref, onBeforeMount } from 'vue';
import { computed, ref, onBeforeMount, markRaw } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useStateStore } from 'stores/useStateStore';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { toDate, toCurrency, dashIfEmpty } from 'src/filters/index';
import { QChip, useQuasar } from 'quasar';
import { toDate, dashIfEmpty } from 'src/filters/index';
import useNotify from 'src/composables/useNotify';
import TicketSummary from './Card/TicketSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
@ -24,6 +24,7 @@ import TicketProblems from 'src/components/TicketProblems.vue';
import VnSection from 'src/components/common/VnSection.vue';
import VnSelectCompany from 'src/components/common/VnSelectCompany.vue';
import VnSelectCurrency from 'src/components/common/VnSelectCurrency.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const route = useRoute();
const router = useRouter();
@ -194,7 +195,6 @@ const columns = computed(() => [
component: 'number',
inWhere: true,
},
format: (row) => toCurrency(row.totalWithVat),
},
{
align: 'left',
@ -252,7 +252,7 @@ const fetchAvailableAgencies = async (formData) => {
const defaultAgency = agenciesOptions.value.find(
(agency) =>
agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk
agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk,
);
if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk;
@ -349,7 +349,7 @@ function openBalanceDialog(ticket) {
const description = ref([]);
const firstTicketClientId = checkedTickets[0].clientFk;
const isSameClient = checkedTickets.every(
(ticket) => ticket.clientFk === firstTicketClientId
(ticket) => ticket.clientFk === firstTicketClientId,
);
if (!isSameClient) {
@ -388,7 +388,7 @@ async function onSubmit() {
description: dialogData.value.value.description,
clientFk: dialogData.value.value.clientFk,
email: email[0].email,
}
},
);
if (data) notify('globals.dataSaved', 'positive');
@ -407,32 +407,32 @@ function setReference(data) {
switch (data) {
case 1:
newDescription = `${t(
'ticketList.creditCard'
'ticketList.creditCard',
)}, ${dialogData.value.value.description.replace(
/^(Credit Card, |Cash, |Transfers, )/,
''
'',
)}`;
break;
case 2:
newDescription = `${t(
'ticketList.cash'
'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'
'ticketList.transfers',
)}, ${dialogData.value.value.description.replace(
/^(Credit Card, |Cash, |Transfers, )/,
''
'',
)}`;
break;
case 3317:
@ -444,6 +444,10 @@ function setReference(data) {
dialogData.value.value.description = newDescription;
}
function isLittle(row) {
return row.totalWithVat > 0 && row.totalWithVat < 50;
}
</script>
<template>
@ -543,14 +547,18 @@ function setReference(data) {
</span>
</template>
<template #column-totalWithVat="{ row }">
<QChip
v-if="row.totalWithVat > 0 && row.totalWithVat < 50"
class="bg-warning"
<component
:is="isLittle(row) ? markRaw(QChip) : 'span'"
:class="{ 'bg-warning': isLittle(row) }"
dense
square
>
{{ row.totalWithVat }}
</QChip>
<VnCurrency
:model="row"
:currency-code="row.currencyCode"
local-field="totalWithVat"
/>
</component>
</template>
<template #more-create-dialog="{ data }">
<VnRow>