feat(Order): refs #7984 add currency in sections

This commit is contained in:
Alex Moreno 2025-01-15 14:59:44 +01:00
parent c6d7008ed5
commit f3f0c0e88c
14 changed files with 257 additions and 35 deletions

View File

@ -12,6 +12,7 @@ import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputTime from 'components/common/VnInputTime.vue';
import VnComponent from 'components/common/VnComponent.vue';
import VnUserLink from 'components/ui/VnUserLink.vue';
import VnCurrency from '../ui/VnCurrency.vue';
const model = defineModel(undefined, { required: true });
const $props = defineProps({
@ -131,6 +132,9 @@ const defaultComponents = {
userLink: {
component: markRaw(VnUserLink),
},
currency: {
component: markRaw(VnCurrency),
},
};
const value = computed(() => {

View File

@ -12,6 +12,7 @@ const props = defineProps({
baseUrl: { type: String, default: undefined },
customUrl: { type: String, default: undefined },
filter: { type: Object, default: () => {} },
userFilter: { type: Object, default: () => {} },
descriptor: { type: Object, required: true },
filterPanel: { type: Object, default: undefined },
searchDataKey: { type: String, default: undefined },
@ -32,6 +33,7 @@ const url = computed(() => {
const arrayData = useArrayData(props.dataKey, {
url: url.value,
filter: props.filter,
userFilter: props.userFilter,
});
onBeforeMount(async () => {

View File

@ -0,0 +1,43 @@
<script setup>
import VnSelect from 'components/common/VnSelect.vue';
import axios from 'axios';
import { onMounted } from 'vue';
import { ref } from 'vue';
import { watch } from 'vue';
const model = defineModel({
type: [String, Number, Object],
default: null,
});
const clientId = defineModel('clientId', {
type: Number,
default: null,
});
const companyList = ref([]);
onMounted(async () => {
companyList.value = (await axios.get('Companies')).data;
});
watch(
() => clientId.value,
async (newId) => {
if (!newId) return;
const { data } = await axios.get(`Clients/${newId}`, {
fields: ['defaultCompanyFk'],
});
model.value = data.defaultCompanyFk;
}
);
</script>
<template>
<VnSelect
:label="$t('globals.company')"
v-bind="$attrs"
v-model="model"
:options="companyList"
option-label="code"
/>
</template>

View File

@ -0,0 +1,44 @@
<script setup>
import VnSelect from 'components/common/VnSelect.vue';
import axios from 'axios';
import { onMounted } from 'vue';
import { ref } from 'vue';
import { watch } from 'vue';
const model = defineModel({
type: [String, Number, Object],
default: null,
});
const clientId = defineModel('clientId', {
type: Number,
default: null,
});
const currencyList = ref([]);
onMounted(async () => {
currencyList.value = (await axios.get('Currencies')).data;
});
watch(
() => clientId.value,
async (newId) => {
if (!newId) return;
const { data } = await axios.get(`Clients/${newId}`, {
fields: ['defaultCurrencyFk'],
});
model.value = data.defaultCurrencyFk;
}
);
</script>
<template>
<VnSelect
:label="$t('globals.currency')"
v-bind="$attrs"
v-model="model"
:options="currencyList"
option-label="name"
option-caption="code"
/>
</template>

View File

@ -6,8 +6,7 @@ import VnLv from 'components/ui/VnLv.vue';
import VnImg from 'src/components/ui/VnImg.vue';
import OrderCatalogItemDialog from 'pages/Order/Card/OrderCatalogItemDialog.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import { toCurrency } from 'filters/index';
import VnCurrency from './VnCurrency.vue';
const DEFAULT_PRICE_KG = 0;
@ -61,7 +60,7 @@ const card = toRef(props, 'item');
<div class="price">
<p v-if="isCatalog">
{{ card.available }} {{ t('to') }}
{{ toCurrency(card.price) }}
<VnCurrency :model="card" array-data-model="Order" />
</p>
<slot name="price" />
<QIcon v-if="isCatalog" name="add_circle" class="icon">
@ -81,7 +80,12 @@ const card = toRef(props, 'item');
</div>
<p v-if="card.priceKg" class="price-kg">
{{ t('price-kg') }}
{{ toCurrency(card.priceKg) || DEFAULT_PRICE_KG }}
<VnCurrency
v-model="card"
array-data-model="Order"
local-field="priceKg"
foreign-field="foreignPriceKg"
/>
</p>
</div>
</div>

View File

@ -0,0 +1,52 @@
<script setup>
import { toCurrency } from 'src/filters';
import { computed, onMounted, ref } from 'vue';
import { useArrayData } from 'src/composables/useArrayData';
const $props = defineProps({
model: {
type: Object,
required: true,
description: 'object to use foreignField and localField',
},
currencyCode: {
type: String,
default: undefined,
},
foreignField: {
type: String,
default: 'foreignPrice',
},
localField: {
type: String,
default: 'price',
},
arrayDataModel: {
type: String,
default: undefined,
description: 'find currency code in array data model',
},
});
const foreignValue = computed(() => $props.model?.[$props.foreignField]);
const localValue = computed(() => $props.model?.[$props.localField]);
const currency = computed(() => $props.currencyCode ?? currencyCodeModel.value);
const toCurrencyLabel = computed(() =>
toCurrency(foreignValue.value ?? localValue.value, currency.value)
);
const currencyCodeModel = ref();
onMounted(() => {
if ($props.arrayDataModel) {
const arrayData = useArrayData($props.arrayDataModel);
currencyCodeModel.value = arrayData.store.data?.currency?.code;
}
});
</script>
<template>
<span :title="toCurrencyLabel">
<span v-if="foreignValue">{{ toCurrency(localValue) }} /</span>
{{ toCurrencyLabel }}
</span>
</template>

View File

@ -130,6 +130,7 @@ globals:
medium: Medium
big: Big
email: Email
currency: Currency
pageTitles:
logIn: Login
addressEdit: Update address

View File

@ -132,6 +132,7 @@ globals:
medium: Mediano/a
big: Grande
email: Correo
currency: Moneda
pageTitles:
logIn: Inicio de sesión
addressEdit: Modificar consignatario

View File

@ -10,6 +10,8 @@ import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnSelectCompany from 'src/components/common/VnSelectCompany.vue';
import VnSelectCurrency from 'src/components/common/VnSelectCurrency.vue';
const { t } = useI18n();
const route = useRoute();
@ -176,6 +178,10 @@ const onClientChange = async (clientId) => {
"
/>
</VnRow>
<VnRow>
<VnSelectCompany v-model="data.companyFk" />
<VnSelectCurrency v-model="data.currencyFk" />
</VnRow>
<VnRow>
<VnInput
:label="t('globals.notes')"

View File

@ -8,5 +8,10 @@ import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
data-key="Order"
base-url="Orders"
:descriptor="OrderDescriptor"
:user-filter="{
include: {
relation: 'currency',
},
}"
/>
</template>

View File

@ -7,6 +7,7 @@ import { useRoute } from 'vue-router';
import useNotify from 'composables/useNotify';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import { useState } from 'src/composables/useState';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const { t } = useI18n();
const { notify } = useNotify();
@ -73,10 +74,10 @@ const canAddToOrder = () => {
<QMarkupTable class="shadow-0">
<tbody>
<tr v-for="price in prices" :key="price.warehouse">
<td class="text-bold q-pr-md td" style="width: 35%">
<td class="text-bold q-pr-md" style="width: 10%">
{{ price.warehouse }}
</td>
<td class="text-right" style="width: 35%">
<td class="text-right" style="width: 60%">
<span
class="link"
@click.shift="
@ -92,12 +93,18 @@ const canAddToOrder = () => {
>
{{ price.grouping }}
</span>
x {{ toCurrency(price.price) }}
x
<VnCurrency
:model="price"
array-data-model="Order"
class="q-pr-sm"
/>
</td>
<td class="text-right">
<td style="width: 30%">
<VnInputNumber
v-model.number="price.quantity"
:step="price.grouping"
input-class="text-right"
min="0"
/>
</td>
@ -117,12 +124,6 @@ const canAddToOrder = () => {
</div>
</template>
<style lang="scss" scoped>
.td {
width: 200px;
}
</style>
<i18n>
es:
noAmount: La cantidad no puede ser 0

View File

@ -10,6 +10,7 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchData from 'components/FetchData.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const DEFAULT_ITEMS = 0;
@ -69,19 +70,19 @@ const getConfirmationValue = (isConfirmed) => {
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
};
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
const total = ref(0);
function setTotal(response) {
total.value = response;
state.set('orderTotal', response);
}
const orderTotal = computed(() => state.get('orderTotal'));
const total = ref();
</script>
<template>
<FetchData
ref="getTotalRef"
:url="`Orders/${entityId}/getTotal`"
@on-fetch="
(response) => {
total = response;
}
"
@on-fetch="(response) => setTotal(response)"
/>
<CardDescriptor
ref="descriptor"
@ -113,7 +114,16 @@ const total = ref(0);
:label="t('order.summary.items')"
:value="(entity?.rows?.length || DEFAULT_ITEMS).toString()"
/>
<VnLv :label="t('order.summary.total')" :value="toCurrency(orderTotal)" />
<VnLv :label="t('order.summary.total')">
<template #value>
<VnCurrency
:model="orderTotal"
array-data-model="Order"
local-field="total"
foreign-field="foreignTotal"
/>
</template>
</VnLv>
</template>
<template #actions="{ entity }">
<QCardActions>

View File

@ -16,6 +16,7 @@ import VnImg from 'src/components/ui/VnImg.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchedTags from 'src/components/ui/FetchedTags.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const router = useRouter();
const stateStore = useStateStore();
@ -28,7 +29,9 @@ const tableLinesRef = ref();
const order = ref();
const orderSummary = ref({
total: null,
foreignTotal: null,
vat: null,
foreignVat: null,
});
const getTotalRef = ref();
const getVATRef = ref();
@ -91,16 +94,14 @@ const columns = computed(() => [
},
},
columnFilter: false,
cardVisible: true,
},
{
align: 'left',
name: 'id',
label: t('lines.item'),
chip: {
condition: () => true,
},
isId: true,
format: (row) => row?.item?.id,
cardVisible: true,
},
{
align: 'left',
@ -156,12 +157,12 @@ const columns = computed(() => [
name: 'price',
label: t('lines.price'),
cardVisible: true,
format: (row) => toCurrency(row.price),
},
{
align: 'left',
name: 'amount',
label: t('lines.amount'),
cardVisible: true,
},
{
align: 'right',
@ -241,14 +242,14 @@ watch(
ref="getTotalRef"
:key="componentKey"
:url="`Orders/${route.params.id}/getTotal`"
@on-fetch="(data) => (orderSummary.total = data)"
@on-fetch="(data) => (orderSummary = { ...orderSummary, ...data })"
auto-load
/>
<FetchData
ref="getVATRef"
:key="componentKey"
:url="`Orders/${route.params.id}/getVAT`"
@on-fetch="(data) => (orderSummary.vat = data)"
@on-fetch="(data) => (orderSummary = { ...orderSummary, ...data })"
auto-load
/>
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
@ -262,9 +263,38 @@ watch(
<VnLv
:label="t('subtotal') + ': '"
:value="toCurrency(orderSummary.total - orderSummary.vat)"
/>
<VnLv :label="t('VAT') + ': '" :value="toCurrency(orderSummary?.vat)" />
<VnLv :label="t('total') + ': '" :value="toCurrency(orderSummary?.total)" />
>
<template #value>
<VnCurrency
:model="{
price: orderSummary.total - orderSummary.vat,
foreignPrice:
orderSummary.foreignTotal - orderSummary.foreignVat,
}"
array-data-model="Order"
/>
</template>
</VnLv>
<VnLv :label="t('VAT') + ': '">
<template #value>
<VnCurrency
:model="orderSummary"
array-data-model="Order"
local-field="vat"
foreign-field="foreignVat"
/>
</template>
</VnLv>
<VnLv :label="t('total') + ': '">
<template #value>
<VnCurrency
:model="orderSummary"
array-data-model="Order"
local-field="total"
foreign-field="foreignTotal"
/>
</template>
</VnLv>
</QCard>
</Teleport>
@ -300,10 +330,19 @@ watch(
{{ row?.item?.subName.toUpperCase() }}
</div>
</div>
<FetchedTags :item="row?.item" />
<FetchedTags :item="row?.item" :columns="3" />
</template>
<template #column-amount="{ row }">
{{ toCurrency(row.quantity * row.price) }}
<template #column-price="{ row }">
<VnCurrency :model="row" array-data-model="Order" />
</template>
<template #column-amount="{ row: { price, quantity, foreignPrice } }">
<VnCurrency
:model="{
price: price * quantity,
foreignPrice: foreignPrice * quantity,
}"
array-data-model="Order"
/>
</template>
<template #column-tableActions="{ row }">
<QIcon

View File

@ -16,6 +16,8 @@ import VnTable from 'src/components/VnTable/VnTable.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSection from 'src/components/common/VnSection.vue';
import VnSelectCurrency from 'src/components/common/VnSelectCurrency.vue';
import VnSelectCompany from 'src/components/common/VnSelectCompany.vue';
const { t } = useI18n();
const { viewSummary } = useSummaryDialog();
@ -297,6 +299,14 @@ const getDateColor = (date) => {
option-value="agencyModeFk"
option-label="agencyMode"
/>
<VnSelectCompany
v-model="data.defaultCompanyFk"
v-model:client-id="data.clientFk"
/>
<VnSelectCurrency
v-model="data.defaultCurrencyFk"
v-model:client-id="data.clientFk"
/>
</template>
</VnTable>
</template>