Compare commits

..

18 Commits

Author SHA1 Message Date
Alex Moreno 0e535663b1 fix: refs #7984 update currency display logic and set default currency code
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2025-04-03 15:07:33 +02:00
Alex Moreno 8593f1d760 Merge branch 'dev' of https: refs #7984//gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2025-04-03 13:19:48 +02:00
Alex Moreno 9ea4d785aa Merge branch 'dev' of https: refs #7984//gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency 2025-03-26 12:09:47 +01:00
Alex Moreno f309d21682 fix: refs #7984 currency merge in dev 2025-03-12 14:08:44 +01:00
Alex Moreno 84f2948f8b feat: refs #7984 add currency relation to ticket filter 2025-03-12 13:00:20 +01:00
Alex Moreno a9e01dd71e Merge branch 'dev' of https: refs #7984//gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency 2025-03-12 13:00:10 +01:00
Alex Moreno 1b2573bfc6 feat(TicketSale): refs #7984 add currency
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2025-01-29 15:27:08 +01:00
Alex Moreno 2e085c6b15 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency 2025-01-29 12:11:01 +01:00
Alex Moreno 05b35f8d29 fix: refs #7984 vnCurrency
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2025-01-28 15:07:07 +01:00
Alex Moreno b4e7ea1eac Merge branch 'dev' of https: refs #7984//gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2025-01-28 14:03:01 +01:00
Alex Moreno 65bbd0768c feat: refs #7984 add currency in userPanel
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2025-01-23 15:09:38 +01:00
Alex Moreno 552d05098c Merge branch 'dev' of https: refs #7984//gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2025-01-23 10:28:31 +01:00
Alex Moreno 583a774d7d feat(Ticket): refs #7984 add currency
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2025-01-22 15:04:50 +01:00
Alex Moreno 1ac0672f1e Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency 2025-01-22 12:12:57 +01:00
Alex Moreno 8626b99273 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 7984-addCurrency
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2025-01-22 12:04:07 +01:00
Alex Moreno f076c62bab feat: refs #7984 add currency in sale
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2025-01-21 15:09:40 +01:00
Alex Moreno 3c6a4c1e16 feat: refs #7984 add currency in ticket basic-data
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2025-01-20 14:07:05 +01:00
Alex Moreno f3f0c0e88c feat(Order): refs #7984 add currency in sections 2025-01-15 14:59:44 +01:00
46 changed files with 708 additions and 219 deletions

View File

@ -47,6 +47,8 @@ const darkMode = computed({
},
});
const foreignCurrency = ref();
const user = state.getUser();
const warehousesData = ref();
const companiesData = ref();
@ -58,6 +60,8 @@ onMounted(async () => {
});
function updatePreferences() {
foreignCurrency.value = user.value.foreignCurrency;
if (user.value.darkMode !== null) {
darkMode.value = user.value.darkMode;
}
@ -116,6 +120,11 @@ async function saveUserData(param, value) {
}
}
async function saveCurrency(value) {
user.value.foreignCurrency = value;
useState().setUser(user.value);
}
const onDataSaved = () => {
notify('globals.dataSaved', 'positive');
};
@ -169,6 +178,14 @@ const onDataError = () => {
color="primary"
unchecked-icon="light_mode"
/>
<QToggle
v-model="foreignCurrency"
:label="t(`globals.foreignCurrency`)"
@update:model-value="saveCurrency"
color="primary"
unchecked-icon="euro_symbol"
checked-icon="currency_exchange"
/>
</div>
<QSeparator vertical inset class="q-mx-lg" />

View File

@ -11,6 +11,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';
import VnSelectEnum from '../common/VnSelectEnum.vue';
import VnCheckbox from '../common/VnCheckbox.vue';
@ -152,6 +153,9 @@ const defaultComponents = {
userLink: {
component: markRaw(VnUserLink),
},
currency: {
component: markRaw(VnCurrency),
},
toggle: {
component: markRaw(QToggle),
},

View File

@ -60,7 +60,7 @@ async function confirm() {
v-model="address"
is-outlined
autofocus
data-cy="SendEmailNotificationDialogInput"
data-cy="SendEmailNotifiactionDialogInput"
/>
</QCardSection>
<QCardActions align="right">

View File

@ -10,7 +10,6 @@ import { useFilterParams } from 'src/composables/useFilterParams';
import FetchData from '../FetchData.vue';
import { useValidator } from 'src/composables/useValidator';
import { useCapitalize } from 'src/composables/useCapitalize';
import VnAvatar from '../ui/VnAvatar.vue';
const $props = defineProps({
dataKey: {
@ -100,6 +99,7 @@ function getActions() {
:columns="columns"
:redirect="false"
:hiddenTags="['originFk', 'creationDate']"
:exprBuilder
search-url="logs"
:showTagChips="false"
>

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,57 @@
<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: Number,
default: null,
});
const clientId = defineModel('clientId', {
type: Number,
default: null,
});
const currencyList = ref([]);
const emit = defineEmits(['newValue']);
onMounted(async () => {
currencyList.value = (await axios.get('Currencies')).data;
emitCurrency(model.value);
});
watch(
() => clientId.value,
async (newId) => {
if (!newId) return;
const { data } = await axios.get(`Clients/${newId}`, {
fields: ['defaultCurrencyFk'],
});
model.value = data.defaultCurrencyFk;
}
);
function emitCurrency(id) {
if (!id) return;
emit(
'newValue',
currencyList.value?.find((c) => c.id == id)
);
}
</script>
<template>
<VnSelect
:label="$t('globals.currency')"
v-bind="$attrs"
v-model="model"
:options="currencyList"
option-label="name"
option-caption="code"
@update:model-value="(id) => emitCurrency(id)"
/>
</template>

View File

@ -177,8 +177,6 @@ async function fetch() {
.value {
color: var(--vn-text-color);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.header {
@ -210,21 +208,27 @@ async function fetch() {
}
.vn-card-group {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 16px;
display: flex;
flex-direction: column;
}
.vn-card-content {
display: flex;
flex-direction: column;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
> div {
max-height: 70px;
}
}
@media (min-width: 1010px) {
.vn-card-group {
flex-direction: row;
}
.vn-card-content {
flex: 1;
}
}
</style>
<style lang="scss" scoped>
.summaryHeader .vn-label-value {

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,82 @@
<script setup>
import { toCurrency } from 'src/filters';
import { watch, ref } from 'vue';
import { useArrayData } from 'src/composables/useArrayData';
import { useState } from 'src/composables/useState';
const $props = defineProps({
model: {
type: Object,
required: true,
description: 'object to use foreignField and localField',
},
currencyCode: {
type: String,
default: undefined,
},
foreignField: {
type: [String, undefined],
default: undefined,
},
localField: {
type: String,
default: 'price',
},
arrayDataModel: {
type: String,
default: undefined,
description: 'find currency code in array data model',
},
});
const state = useState();
const user = state.getUser();
const toCurrencyLabel = ref();
const foreignValue = ref();
const localValue = ref();
const currency = ref();
watch(
() => $props.model,
() => calculate(),
{ immediate: true, deep: true },
);
function calculate() {
if (!$props.model) return;
currency.value = $props.currencyCode;
if ($props.arrayDataModel) {
const arrayData = $props.arrayDataModel && useArrayData($props.arrayDataModel);
currency.value = arrayData.store.data?.currency?.code;
}
foreignValue.value = $props.model[getForeignFieldComputed()];
localValue.value = $props.model?.[$props.localField];
toCurrencyLabel.value = toCurrency(
foreignValue.value ?? localValue.value,
currency.value,
);
}
function getForeignFieldComputed() {
return (
$props.foreignField ??
'foreign' + $props.localField.charAt(0).toUpperCase() + $props.localField.slice(1)
);
}
</script>
<template>
<span :title="toCurrencyLabel">
<template v-if="currency && (localValue || localValue === 0)">
{{
foreignValue && user.foreignCurrency && currency != user.currencyCode
? toCurrencyLabel
: toCurrency(localValue)
}}
</template>
<template v-else>-</template>
</span>
</template>

View File

@ -252,10 +252,6 @@ const toModule = computed(() => {
content: ':';
}
}
&.ellipsis > .value {
text-overflow: ellipsis;
white-space: pre;
}
.value {
color: var(--vn-text-color);
font-size: 14px;

View File

@ -13,7 +13,7 @@ export function useRole() {
name: data.user.name,
nickname: data.user.nickname,
lang: data.user.lang || 'es',
departmentFk: data.user?.worker?.department?.departmentFk,
departmentFk: data.user.worker.department.departmentFk,
};
state.setUser(userData);
state.setRoles(roles);

View File

@ -60,7 +60,7 @@ export function useSession() {
const { data: isValidToken } = await axios.get('VnUsers/validateToken');
if (isValidToken)
destroyTokenPromises = Object.entries(tokens).map(([key, url]) =>
destroyToken(url, storage, key)
destroyToken(url, storage, key),
);
}
} finally {
@ -75,6 +75,8 @@ export function useSession() {
nickname: '',
lang: '',
darkMode: null,
foreignCurrency: true,
currencyCode: 'EUR', //FIXME: use config
});
stopRenewer();

View File

@ -10,6 +10,7 @@ const user = ref({
darkMode: null,
companyFk: null,
warehouseFk: null,
foreignCurrency: true,
});
if (sessionStorage.getItem('user'))
user.value = JSON.parse(sessionStorage.getItem('user'));

View File

@ -22,7 +22,7 @@ export function useVnConfirm() {
{ customHTML: () => h(component, props) }
),
}).onOk(async () => {
if (successFn) successFn();
if (successFn) await successFn();
});
};

View File

@ -1,9 +1,9 @@
import { useI18n } from 'vue-i18n';
// import { useI18n } from 'vue-i18n';
export default function (value, symbol = 'EUR', fractionSize = 2) {
if (value == null || value === '') value = 0;
const { locale } = useI18n();
// const { locale } = useI18n(); // sacar en el boot, cuando se añade al user. Y aqui usarlo
const options = {
style: 'currency',
@ -12,7 +12,7 @@ export default function (value, symbol = 'EUR', fractionSize = 2) {
maximumFractionDigits: fractionSize,
};
const lang = locale.value == 'es' ? 'de' : locale.value;
const lang = 'de';
return new Intl.NumberFormat(lang, options).format(value);
}

View File

@ -2,8 +2,9 @@ globals:
lang:
es: Spanish
en: English
language: Language
foreignCurrency: Foreign currency
quantity: Quantity
language: Language
entity: Entity
preview: Preview
user: User
@ -136,6 +137,7 @@ globals:
medium: Medium
big: Big
email: Email
currency: Currency
supplier: Supplier
ticketList: Ticket List
created: Created

View File

@ -2,6 +2,7 @@ globals:
lang:
es: Español
en: Inglés
foreignCurrency: Moneda extranjera
language: Idioma
quantity: Cantidad
entity: Entidad
@ -140,6 +141,7 @@ globals:
medium: Mediano/a
big: Grande
email: Correo
currency: Moneda
supplier: Proveedor
ticketList: Listado de tickets
created: Fecha creación

View File

@ -9,6 +9,8 @@ import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.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();
@ -136,6 +138,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"

View File

@ -104,11 +104,8 @@ const sumRisk = ({ clientRisks }) => {
:value="entity.email"
class="ellipsis"
copy
>
<template #value>
<VnLinkMail :email="entity.email" />
</template>
</VnLv>
><template #value> <VnLinkMail :email="entity.email" /> </template
></VnLv>
<VnLv :label="t('globals.department')">
<template #value>
<span class="link" v-text="entity.department?.name" />

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();
@ -47,6 +48,7 @@ const filter = {
},
},
},
{ relation: 'currency' },
],
where: { clientFk: $props.id ?? route.params.id },
order: ['shipped DESC', 'id'],
@ -218,9 +220,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

@ -70,8 +70,8 @@ onMounted(async () => {
:url="`#/entry/${entityId}/basic-data`"
:text="t('globals.summary.basicData')"
/>
<div class="vn-card-group">
<div class="vn-card-content">
<div class="card-group">
<div class="card-content">
<VnLv
:label="t('entry.summary.commission')"
:value="entry?.commission"
@ -93,7 +93,7 @@ onMounted(async () => {
:value="entry?.invoiceNumber"
/>
</div>
<div class="vn-card-content">
<div class="card-content">
<VnCheckbox
:label="t('entry.list.tableVisibleColumns.isOrdered')"
v-model="entry.isOrdered"
@ -130,8 +130,8 @@ onMounted(async () => {
:url="`#/travel/${entry.travel.id}/summary`"
:text="t('Travel')"
/>
<div class="vn-card-group">
<div class="vn-card-content">
<div class="card-group">
<div class="card-content">
<VnLv :label="t('entry.summary.travelReference')">
<template #value>
<span class="link">
@ -161,7 +161,7 @@ onMounted(async () => {
:value="entry.travel.warehouseIn?.name"
/>
</div>
<div class="vn-card-content">
<div class="card-content">
<VnLv :label="t('travel.awbFk')" :value="entry.travel.awbFk" />
<VnCheckbox
:label="t('entry.summary.travelDelivered')"
@ -193,6 +193,31 @@ onMounted(async () => {
</template>
</CardSummary>
</template>
<style lang="scss" scoped>
.card-group {
display: flex;
flex-direction: column;
}
.card-content {
display: flex;
flex-direction: column;
text-overflow: ellipsis;
> div {
max-height: 24px;
}
}
@media (min-width: 1010px) {
.card-group {
flex-direction: row;
}
.card-content {
flex: 1;
margin-right: 16px;
}
}
</style>
<i18n>
es:
Travel: Envío

View File

@ -10,10 +10,13 @@ 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();
const state = useState();
const ORDER_MODEL = 'Order';
const isNew = Boolean(!route.params.id);
const clientList = ref([]);
@ -81,10 +84,9 @@ const onClientChange = async (clientId) => {
<div class="q-pa-md">
<FormModel
:url-update="`Orders/${route.params.id}/updateBasicData`"
model="Order"
:model="ORDER_MODEL"
:filter="orderFilter"
@on-fetch="fetchOrderDetails"
auto-load
>
<template #form="{ data }">
<VnRow>
@ -164,6 +166,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

@ -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();
@ -72,10 +73,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="
@ -91,12 +92,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>
@ -116,12 +123,6 @@ const canAddToOrder = () => {
</div>
</template>
<style lang="scss" scoped>
.td {
width: 200px;
}
</style>
<i18n>
es:
noAmount: La cantidad no puede ser 0

View File

@ -6,6 +6,7 @@ import { toCurrency, toDate } from 'src/filters';
import { useState } from 'src/composables/useState';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchData from 'components/FetchData.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
import OrderCard from './OrderCard.vue';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
@ -24,13 +25,13 @@ const route = useRoute();
const state = useState();
const { t } = useI18n();
const getTotalRef = ref();
const total = ref(0);
const entityId = computed(() => {
return $props.id || route.params.id;
});
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
const orderTotal = computed(() => state.get('orderTotal') ?? {});
const total = ref();
const setData = (entity) => {
if (!entity) return;
@ -41,17 +42,18 @@ const setData = (entity) => {
const getConfirmationValue = (isConfirmed) => {
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
};
function setTotal(response) {
total.value = response;
state.set('orderTotal', response);
}
</script>
<template>
<FetchData
ref="getTotalRef"
:url="`Orders/${entityId}/getTotal`"
@on-fetch="
(response) => {
total = response;
}
"
@on-fetch="(response) => setTotal(response)"
/>
<CardDescriptor
v-bind="$attrs"
@ -81,7 +83,16 @@ const getConfirmationValue = (isConfirmed) => {
: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

@ -22,5 +22,8 @@ export default {
},
},
},
{
relation: 'currency',
},
],
};

View File

@ -15,6 +15,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';
import RightMenu from 'src/components/common/RightMenu.vue';
const router = useRouter();
@ -27,7 +28,9 @@ const tableLinesRef = ref();
const order = ref();
const orderSummary = ref({
total: null,
foreignTotal: null,
vat: null,
foreignVat: null,
});
const getTotalRef = ref();
const getVATRef = ref();
@ -90,16 +93,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',
@ -155,12 +156,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',
@ -253,14 +254,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
/>
<RightMenu>
@ -275,12 +276,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>
</template>
</RightMenu>
@ -316,10 +343,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

@ -15,6 +15,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';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import { getAddresses } from '../Customer/composables/getAddresses';
@ -354,6 +356,14 @@ const isDefaultAddress = (opt, data) => {
option-value="agencyModeFk"
option-label="agencyMode"
/>
<VnSelectCompany
v-model="data.companyId"
v-model:client-id="data.clientFk"
/>
<VnSelectCurrency
v-model="data.currencyId"
v-model:client-id="data.clientFk"
/>
</template>
</VnTable>
</template>

View File

@ -9,6 +9,7 @@ import FetchData from 'components/FetchData.vue';
import { useStateStore } from 'stores/useStateStore';
import { toCurrency } from 'filters/index';
import { useRole } from 'src/composables/useRole';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
const haveNegatives = defineModel('have-negatives', { type: Boolean, required: true });
@ -19,7 +20,7 @@ const { t } = useI18n();
const { hasAny } = useRole();
const ticketUpdateActions = ref(null);
const rows = computed(() => formData.value?.sale?.items || []);
const rows = computed(() => formData.value?.sale?.sales || []);
const columns = computed(() => [
{
@ -84,27 +85,13 @@ const loadDefaultTicketAction = () => {
formData.value.option = isSalesAssistant ? 'mana' : 'renewPrices';
};
const totalPrice = computed(() => {
return rows.value.reduce((acc, item) => acc + item.price * item.quantity, 0);
});
const totalNewPrice = computed(() => {
return rows.value.reduce(
(acc, item) => acc + item.component.newPrice * item.quantity,
0
);
});
const totalDifference = computed(() => {
return rows.value.reduce((acc, item) => acc + item.component?.difference || 0, 0);
});
const showMovableColumn = computed(() => (haveDifferences.value > 0 ? ['movable'] : []));
const haveDifferences = computed(() => formData.value.sale?.haveDifferences);
async function ticketHaveNegatives() {
let _haveNegatives = false;
let haveNotNegatives = false;
formData.value.withoutNegatives = false;
formData.value?.sale?.items.forEach((item) => {
formData.value?.sale?.sales.forEach((item) => {
if (item.quantity > item.movable) _haveNegatives = true;
else haveNotNegatives = true;
});
@ -142,17 +129,34 @@ onMounted(async () => {
<QCardSection class="column items-left" horizontal>
<span>
{{ t('basicData.price') }}:
{{ toCurrency(totalPrice) }}
<VnCurrency
:model="formData.sale"
local-field="totalUnitPrice"
foreign-field="totalForeignUnitPrice"
:currency-code="formData.currency.code"
/>
</span>
</QCardSection>
<QCardSection class="column items-left" horizontal>
<span>
{{ t('basicData.newPrice') }}: {{ toCurrency(totalNewPrice) }}
{{ t('basicData.newPrice') }}:
<VnCurrency
:model="formData.sale"
local-field="totalNewPrice"
foreign-field="totalForeignNewPrice"
:currency-code="formData.currency.code"
/>
</span>
</QCardSection>
<QCardSection class="column items-left" horizontal>
<span>
{{ t('basicData.difference') }}: {{ toCurrency(totalDifference) }}
{{ t('basicData.difference') }}:
<VnCurrency
:model="formData.sale"
local-field="totalDifference"
foreign-field="totalForeignDifference"
:currency-code="formData.currency.code"
/>
</span>
</QCardSection>
</QCard>
@ -242,5 +246,33 @@ onMounted(async () => {
/>
</QTd>
</template>
<template #body-cell-price="{ row }">
<QTd class="number">
<VnCurrency
:model="row.component"
:currency-code="formData.currency.code"
/>
</QTd>
</template>
<template #body-cell-newPrice="{ row }">
<QTd class="number">
<VnCurrency
:model="row.component"
:currency-code="formData.currency.code"
local-field="newPrice"
foreign-field="newForeignPrice"
/>
</QTd>
</template>
<template #body-cell-difference="{ row }">
<QTd class="number">
<VnCurrency
:model="row.component"
:currency-code="formData.currency.code"
local-field="difference"
foreign-field="foreignDifference"
/>
</QTd>
</template>
</QTable>
</template>

View File

@ -15,6 +15,7 @@ import useNotify from 'src/composables/useNotify.js';
import { useAcl } from 'src/composables/useAcl';
import { useValidator } from 'src/composables/useValidator';
import { toTimeFormat } from 'filters/date.js';
import VnSelectCurrency from 'src/components/common/VnSelectCurrency.vue';
const formData = defineModel({
type: Object,
@ -355,7 +356,7 @@ async function getZone(options) {
:rules="validate('basicData.alias')"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md no-wrap">
<VnRow>
<VnSelect
:label="t('ticketList.company')"
v-model="formData.companyFk"
@ -367,6 +368,12 @@ async function getZone(options) {
:required="true"
:rules="validate('ticketList.company')"
/>
<VnSelectCurrency
v-model="formData.currencyFk"
@new-value="(value) => (formData.currency = value)"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md no-wrap">
<VnSelect
:label="t('basicData.agency')"
v-model="agencyModeId"

View File

@ -6,10 +6,10 @@ import { useRouter } from 'vue-router';
import TicketBasicData from './TicketBasicData.vue';
import TicketBasicDataForm from './TicketBasicDataForm.vue';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useArrayData } from 'composables/useArrayData';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
import { useArrayData } from 'src/composables/useArrayData';
import useNotify from 'src/composables/useNotify';
const { notify } = useNotify();
const router = useRouter();
@ -42,6 +42,7 @@ const getPriceDifference = async () => {
zoneId: ticket.value.zoneFk,
warehouseId: ticket.value.warehouseFk,
shipped: ticket.value.shipped,
currencyId: ticket.value.currencyFk,
};
const { data } = await axios.post(
`tickets/${ticket.value.id}/priceDifference`,
@ -67,6 +68,7 @@ const submit = async () => {
option: ticket.value.option,
isWithoutNegatives: ticket.value.withoutNegatives,
withWarningAccept: ticket.value.withWarningAccept,
currencyFk: ticket.value.currencyFk,
keepPrice: false,
};
@ -78,6 +80,8 @@ const submit = async () => {
if (!data) return;
const ticketToMove = data.id;
const arrayData = useArrayData('ticketData');
arrayData.fetch({});
notify(t('basicData.unroutedTicket'), 'positive');
router.push({ name: 'TicketSummary', params: { id: ticketToMove } });
};
@ -101,7 +105,7 @@ const onNextStep = async () => {
t('basicData.negativesConfirmMessage'),
submitWithNegatives,
);
else submit();
else await submit();
}
};
</script>

View File

@ -9,9 +9,9 @@ import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toDateTimeFormat } from 'src/filters/date';
import filter from './TicketFilter.js';
import FetchData from 'src/components/FetchData.vue';
import TicketProblems from 'src/components/TicketProblems.vue';
import axios from 'axios';
import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({
id: {
@ -31,6 +31,8 @@ const { t } = useI18n();
const entityId = computed(() => {
return $props.id || route.params.id;
});
const data = ref(useCardDescription());
const problems = ref({});
const originalTicket = ref();

View File

@ -5,6 +5,7 @@ import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { toCurrency } from 'src/filters';
import VnUsesMana from 'components/ui/VnUsesMana.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const $props = defineProps({
newPrice: {
@ -58,7 +59,15 @@ defineExpose({ save });
data-cy="ticketEditManaProxy"
>
<div class="container">
<div class="header">Mana: {{ toCurrency(mana) }}</div>
<div class="header">
Mana:
<VnCurrency
:model="{ mana }"
local-field="mana"
foreign-field="mana"
arrayDataModel="ticketData"
/>
</div>
<QSpinner v-if="!hasMana" color="primary" size="md" />
<div class="q-pa-md" v-else>
<slot :popup="QPopupProxyRef" />

View File

@ -68,5 +68,6 @@ export default {
],
},
},
{ relation: 'currency' },
],
};

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

@ -0,0 +1,59 @@
<script setup>
import RightMenu from 'src/components/common/RightMenu.vue';
import { useArrayData } from 'composables/useArrayData';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
const arrayData = useArrayData('ticketData');
const store = arrayData.store;
</script>
<template>
<RightMenu>
<template #right-panel>
<div
class="q-pa-md q-mb-md q-ma-md color-vn-text"
style="border: 2px solid black"
>
<QCardSection class="justify-end text-subtitle1" horizontal>
<span class="q-mr-xs color-vn-label"
>{{ $t('ticketSale.subtotal') }}:
</span>
<VnCurrency
:model="store.data"
:currency-code="store.data?.currency?.code"
local-field="totalWithoutVat"
foreign-field="foreignTotalWithoutVat"
/>
</QCardSection>
<QCardSection class="justify-end text-subtitle1" horizontal>
<span class="q-mr-xs color-vn-label">
{{ $t('ticketSale.tax') }}:
</span>
<VnCurrency
:model="{
vat: store.data?.totalWithVat - store.data?.totalWithoutVat,
foreignVat:
store.data?.foreignTotalWithVat -
store.data?.foreignTotalWithoutVat,
}"
:currency-code="store.data?.currency?.code"
local-field="vat"
foreign-field="foreignVat"
/>
</QCardSection>
<QCardSection
class="justify-end text-weight-bold text-subtitle1"
horizontal
>
<span class="q-mr-xs color-vn-label">
{{ $t('basicData.total') }}:
</span>
<VnCurrency
:model="store.data"
:currency-code="store.data?.currency?.code"
local-field="totalWithVat"
foreign-field="foreignTotalWithVat"
/>
</QCardSection>
</div>
</template>
</RightMenu>
</template>

View File

@ -3,6 +3,7 @@ import { onMounted, ref, computed, watch, inject } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter, useRoute } from 'vue-router';
import { useQuasar } from 'quasar';
import { useState } from 'src/composables/useState';
import FetchData from 'components/FetchData.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
@ -23,12 +24,16 @@ import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import VnCurrency from 'src/components/ui/VnCurrency.vue';
import TicketRightTotals from './TicketRightTotals.vue';
import TicketProblems from 'src/components/TicketProblems.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
const app = inject('app');
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const state = useState();
const user = state.getUser();
const { notify } = useNotify();
const { openConfirmationModal } = useVnConfirm();
const editPriceProxyRef = ref(null);
@ -130,7 +135,7 @@ const columns = computed(() => [
{
align: 'left',
label: t('globals.amount'),
name: 'amount',
name: 'total',
},
{
align: 'left',
@ -160,11 +165,6 @@ const getConfig = async () => {
ticketConfig.value = data;
};
const onSalesFetched = (salesData) => {
sales.value = salesData;
for (let sale of salesData) sale.amount = getSaleTotal(sale);
};
const getSaleTotal = (sale) => {
if (sale.quantity == null || sale.price == null) return null;
@ -284,7 +284,9 @@ const selectedValidSales = computed(() => {
const onOpenEditPricePopover = async (sale) => {
edit.value = {
sale: JSON.parse(JSON.stringify(sale)),
price: sale.price,
price: user.value.foreignCurrency
? (sale.foreignPrice ?? sale.price)
: sale.price,
};
};
@ -312,7 +314,10 @@ const changePrice = async (sale) => {
};
const updatePrice = async (sale, newPrice) => {
try {
await axios.post(`Sales/${sale.id}/updatePrice`, { newPrice });
await axios.post(`Sales/${sale.id}/updatePrice`, {
newPrice,
isForeign: user.value.foreignCurrency,
});
sale.price = newPrice;
edit.value = { ...DEFAULT_EDIT };
notify('globals.dataSaved', 'positive');
@ -362,7 +367,10 @@ const getNewPrice = computed(() => {
if (edit.value?.sale) {
const sale = edit.value.sale;
let newDiscount = sale.discount;
let newPrice = edit.value.price || sale.price;
let newPrice = user.value.foreignCurrency
? (sale.foreignPrice ?? sale.price)
: sale.price;
// let newPrice = edit.value.price || sale.price;
if (edit.value.discount != null) newDiscount = edit.value.discount;
@ -476,7 +484,7 @@ const updateItem = async (row) => {
row.price = selectedItem.price;
row.discount = 0;
row.quantity = 0;
row.amount = row.price * row.quantity;
row.total = 0;
}
endNewRow(selectedItem);
};
@ -497,7 +505,7 @@ const addRow = (original = null) => {
quantity: original.quantity,
price: original.price,
discount: original.discount,
amount: original.amount,
total: original.total,
isNew: true,
};
}
@ -659,38 +667,7 @@ watch(
</QBtnGroup>
</template>
</VnSubToolbar>
<RightMenu>
<template #right-panel>
<div
class="q-pa-md q-mb-md q-ma-md color-vn-text"
style="border: 2px solid black"
>
<QCardSection class="justify-end text-subtitle1" horizontal>
<span class="q-mr-xs color-vn-label"
>{{ t('ticketSale.subtotal') }}:
</span>
<span>{{ toCurrency(store.data?.totalWithoutVat) }}</span>
</QCardSection>
<QCardSection class="justify-end text-subtitle1" horizontal>
<span class="q-mr-xs color-vn-label">
{{ t('ticketSale.tax') }}:
</span>
<span>{{
toCurrency(store.data?.totalWithVat - store.data?.totalWithoutVat)
}}</span>
</QCardSection>
<QCardSection
class="justify-end text-weight-bold text-subtitle1"
horizontal
>
<span class="q-mr-xs color-vn-label">
{{ t('basicData.total') }}:
</span>
<span>{{ toCurrency(store.data?.totalWithVat) }}</span>
</QCardSection>
</div>
</template>
</RightMenu>
<TicketRightTotals />
<VnTable
ref="tableRef"
data-key="TicketSales"
@ -707,7 +684,7 @@ watch(
:column-search="false"
:disable-option="{ card: true }"
auto-load
@on-fetch="onSalesFetched"
@on-fetch="(data) => (sales = data)"
:create="{
onDataSaved: handleOnDataSave,
}"
@ -814,7 +791,10 @@ watch(
<template #column-price="{ row }">
<template v-if="isTicketEditable && row.id">
<QBtn flat class="link" dense @click="onOpenEditPricePopover(row)">
{{ toCurrency(row.price) }}
<VnCurrency
:model="row"
:currency-code="store.data?.currency?.code"
/>
</QBtn>
<TicketEditManaProxy
ref="editPriceProxyRef"
@ -830,7 +810,9 @@ watch(
/>
</TicketEditManaProxy>
</template>
<span v-else>{{ toCurrency(row.price) }}</span>
<span v-else>
<VnCurrency :model="row" :currency-code="store.data?.currency?.code" />
</span>
</template>
<template #column-discount="{ row }">
<template v-if="!isLocked && row.id">
@ -850,14 +832,17 @@ watch(
@keyup.enter.stop="() => editManaProxyRef.save(row)"
v-model.number="edit.discount"
:label="t('ticketSale.discount')"
type="number"
/>
</TicketEditManaProxy>
</template>
<span v-else>{{ toPercentage(row.discount / 100) }}</span>
</template>
<template #column-amount="{ row }">
{{ toCurrency(getSaleTotal(row)) }}
<template #column-total="{ row }">
<VnCurrency
:model="row"
:currency-code="store.data?.currency?.code"
local-field="total"
/>
</template>
</VnTable>

View File

@ -12,10 +12,14 @@ import VnInput from 'src/components/common/VnInput.vue';
import { useArrayData } from 'src/composables/useArrayData';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import TicketRightTotals from './TicketRightTotals.vue';
import { useState } from 'src/composables/useState';
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const state = useState();
const user = state.getUser();
const ticketServiceTypeFetchRef = ref(null);
const ticketServiceCrudRef = ref(null);
const ticketServiceOptions = ref([]);
@ -174,6 +178,7 @@ function beforeSave(data) {
auto-load
url="TicketServiceTypes"
/>
<TicketRightTotals />
<CrudModel
ref="ticketServiceCrudRef"
data-key="TicketService"
@ -241,7 +246,9 @@ function beforeSave(data) {
<QTd auto-width>
<VnInput
:label="col.label"
v-model.number="row.price"
v-model.number="
row[user.foreignCurrency ? 'foreignPrice' : 'price']
"
type="number"
:required="true"
min="0"

View File

@ -20,6 +20,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';
import TicketProblems from 'src/components/TicketProblems.vue';
import VnDropdown from 'src/components/common/VnDropdown.vue';
@ -277,19 +278,38 @@ onMounted(async () => {
<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">
@ -371,16 +391,28 @@ onMounted(async () => {
: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),
)
}}
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>
@ -425,7 +457,12 @@ onMounted(async () => {
<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

@ -23,6 +23,9 @@ import { toTimeFormat } from 'src/filters/date';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
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';
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
@ -113,7 +116,7 @@ const columns = computed(() => [
},
{
align: 'left',
name: 'shippedDate',
name: 'shipped',
cardVisible: true,
label: t('ticketList.shipped'),
columnFilter: {
@ -123,7 +126,7 @@ const columns = computed(() => [
},
{
align: 'left',
name: 'shippedHour',
name: 'shipped',
component: 'time',
columnFilter: false,
label: t('ticketList.hour'),
@ -219,7 +222,6 @@ const columns = computed(() => [
component: 'number',
inWhere: true,
},
format: (row) => toCurrency(row.totalWithVat),
},
{
align: 'left',
@ -563,7 +565,11 @@ function setReference(data) {
dense
square
>
{{ row.totalWithVat }}
<VnCurrency
:model="row"
:currency-code="row.currencyCode"
local-field="totalWithVat"
/>
</QChip>
</template>
<template #more-create-dialog="{ data }">
@ -652,41 +658,43 @@ function setReference(data) {
</VnSelect>
</VnRow>
<VnRow>
<div class="col">
<VnInputDate
placeholder="dd-mm-aaa"
:label="t('globals.landed')"
v-model="data.landed"
@update:model-value="() => fetchAvailableAgencies(data)"
/>
</div>
<VnInputDate
placeholder="dd-mm-aaa"
:label="t('globals.landed')"
v-model="data.landed"
@update:model-value="() => fetchAvailableAgencies(data)"
/>
</VnRow>
<VnRow>
<div class="col">
<VnSelect
url="Warehouses"
:sort-by="['name']"
:label="t('globals.warehouse')"
v-model="data.warehouseId"
:options="warehousesOptions"
hide-selected
required
@update:model-value="() => fetchAvailableAgencies(data)"
/>
</div>
<VnSelect
url="Warehouses"
:sort-by="['name']"
:label="t('globals.warehouse')"
v-model="data.warehouseId"
:options="warehousesOptions"
hide-selected
required
@update:model-value="() => fetchAvailableAgencies(data)"
/>
</VnRow>
<VnRow>
<div class="col">
<VnSelect
:label="t('globals.agency')"
v-model="data.agencyModeId"
:options="agenciesOptions"
option-value="agencyModeFk"
option-label="agencyMode"
hide-selected
/>
</div>
<VnSelect
:label="t('globals.agency')"
v-model="data.agencyModeId"
:options="agenciesOptions"
option-value="agencyModeFk"
option-label="agencyMode"
hide-selected
/>
</VnRow>
<VnSelectCompany
v-model="data.companyId"
v-model:client-id="data.clientId"
/>
<VnSelectCurrency
v-model="data.currencyId"
v-model:client-id="data.clientId"
/>
</template>
</VnTable>
</template>

View File

@ -205,7 +205,6 @@ ticketList:
toLines: Go to lines
addressNickname: Address nickname
ref: Reference
hour: Hour
rounding: Rounding
noVerifiedData: No verified data
purchaseRequest: Purchase request

View File

@ -116,7 +116,7 @@ const handlePhotoUpdated = (evt = false) => {
<template #body="{ entity }">
<VnLv :label="t('globals.user')" :value="entity.user?.name" />
<VnLv
class="ellipsis"
class="ellipsis-text"
:label="t('globals.params.email')"
:value="entity.user?.emailUser?.email"
copy

View File

@ -132,7 +132,6 @@ onBeforeMount(async () => {
<VnTitle :text="t('worker.summary.userData')" />
<VnLv :label="t('globals.name')" :value="worker?.user?.nickname" />
<VnLv
class="ellipsis"
:label="t('globals.params.email')"
:value="worker.user?.emailUser?.email"
copy

View File

@ -75,13 +75,13 @@ onMounted(async () => {
<template #body="{ entity: zone }">
<QCard class="vn-one">
<VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
<div class="vn-card-group">
<div class="vn-card-content">
<div class="card-group">
<div class="card-content">
<VnLv :label="t('list.agency')" :value="zone.agencyMode?.name" />
<VnLv :label="t('list.price')" :value="toCurrency(zone.price)" />
<VnLv :label="t('zone.bonus')" :value="toCurrency(zone.bonus)" />
</div>
<div class="vn-card-content">
<div class="card-content">
<VnLv
:label="t('summary.closeHour')"
:value="toTimeFormat(zone.hour)"
@ -98,7 +98,7 @@ onMounted(async () => {
</div>
</div>
</QCard>
<QCard class="vn-max">
<QCard class="vn-one">
<VnTitle :url="zoneUrl + `warehouses`" :text="t('list.warehouse')" />
<QTable
:columns="columns"
@ -109,3 +109,15 @@ onMounted(async () => {
</template>
</CardSummary>
</template>
<style lang="scss" scoped>
.card-group {
display: flex;
flex-direction: column;
}
.card-content {
display: flex;
flex-direction: column;
}
</style>

View File

@ -9,6 +9,7 @@ const ticketCard = {
menu: [
'TicketBasicData',
'TicketSale',
'TicketService',
'TicketLog',
'TicketExpedition',
'TicketDms',
@ -19,7 +20,6 @@ const ticketCard = {
'TicketVolume',
'TicketComponents',
'TicketPackage',
'TicketService',
'TicketSaleTracking',
'TicketBoxing',
'TicketSms',

View File

@ -40,7 +40,7 @@ describe('InvoiceInDescriptor', () => {
cy.visit('/#/invoice-in/6/summary');
cy.selectDescriptorOption(5);
cy.dataCy('SendEmailNotificationDialogInput_input').type(
cy.dataCy('SendEmailNotifiactionDialogInput_input').type(
'{selectall}jorgito@gmail.mx',
);
cy.clickConfirm();

View File

@ -37,7 +37,7 @@ describe('InvoiceOut summary', () => {
});
});
it.skip('should transfer the invoice ', () => {
it('should transfer the invoice ', () => {
cy.typeSearchbar('T1111111{enter}');
cy.dataCy('descriptor-more-opts').click();
cy.get(selectMenuOption(1)).click();
@ -50,7 +50,7 @@ describe('InvoiceOut summary', () => {
cy.dataCy('descriptor-more-opts').click();
cy.get(selectMenuOption(3)).click();
cy.dataCy('InvoiceOutDescriptorMenuSendPdfOption').click();
cy.dataCy('SendEmailNotificationDialogInput').should('be.visible');
cy.dataCy('SendEmailNotifiactionDialogInput').should('be.visible');
cy.get(confirmSend).click();
cy.checkNotification('Notification sent');
});
@ -59,7 +59,7 @@ describe('InvoiceOut summary', () => {
cy.dataCy('descriptor-more-opts').click();
cy.get(selectMenuOption(3)).click();
cy.dataCy('InvoiceOutDescriptorMenuSendCsvOption').click();
cy.dataCy('SendEmailNotificationDialogInput').should('be.visible');
cy.dataCy('SendEmailNotifiactionDialogInput').should('be.visible');
cy.get(confirmSend).click();
cy.checkNotification('Notification sent');
});