Merge branch 'dev' into 7235-InvoiceOutBySerial
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
ac4e0f9b07
|
@ -1,6 +1,5 @@
|
||||||
function focusFirstInput(input) {
|
function focusFirstInput(input) {
|
||||||
input.focus();
|
input.focus();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
|
|
|
@ -293,6 +293,7 @@ defineExpose({
|
||||||
class="q-pa-md"
|
class="q-pa-md"
|
||||||
:style="maxWidth ? 'max-width: ' + maxWidth : ''"
|
:style="maxWidth ? 'max-width: ' + maxWidth : ''"
|
||||||
id="formModel"
|
id="formModel"
|
||||||
|
:prevent-submit="$attrs['prevent-submit']"
|
||||||
>
|
>
|
||||||
<QCard>
|
<QCard>
|
||||||
<slot
|
<slot
|
||||||
|
|
|
@ -162,7 +162,9 @@ onMounted(() => {
|
||||||
: $props.defaultMode;
|
: $props.defaultMode;
|
||||||
stateStore.rightDrawer = quasar.screen.gt.xs;
|
stateStore.rightDrawer = quasar.screen.gt.xs;
|
||||||
columnsVisibilitySkipped.value = [
|
columnsVisibilitySkipped.value = [
|
||||||
...splittedColumns.value.columns.filter((c) => !c.visible).map((c) => c.name),
|
...splittedColumns.value.columns
|
||||||
|
.filter((c) => c.visible === false)
|
||||||
|
.map((c) => c.name),
|
||||||
...['tableActions'],
|
...['tableActions'],
|
||||||
];
|
];
|
||||||
createForm.value = $props.create;
|
createForm.value = $props.create;
|
||||||
|
|
|
@ -152,7 +152,7 @@ onMounted(async () => {
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
v-for="col in localColumns"
|
v-for="col in localColumns"
|
||||||
:key="col.name"
|
:key="col.name"
|
||||||
:label="col.label"
|
:label="col.label ?? col.name"
|
||||||
v-model="col.visible"
|
v-model="col.visible"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, toRef } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
|
@ -13,7 +13,7 @@ const DEFAULT_PRICE_KG = 0;
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -25,57 +25,63 @@ defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const dialog = ref(null);
|
const dialog = ref(null);
|
||||||
|
const card = toRef(props, 'item');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container order-catalog-item overflow-hidden">
|
<div class="container order-catalog-item overflow-hidden">
|
||||||
<QCard class="card shadow-6">
|
<QCard class="card shadow-6">
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
<VnImg :id="item.id" class="image" zoom-resolution="1600x900" />
|
<VnImg :id="card.id" class="image" zoom-resolution="1600x900" />
|
||||||
<div v-if="item.hex && isCatalog" class="item-color-container">
|
<div v-if="card.hex && isCatalog" class="item-color-container">
|
||||||
<div
|
<div
|
||||||
class="item-color"
|
class="item-color"
|
||||||
:style="{ backgroundColor: `#${item.hex}` }"
|
:style="{ backgroundColor: `#${card.hex}` }"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<span class="link">
|
<span class="link">
|
||||||
{{ item.name }}
|
{{ card.name }}
|
||||||
<ItemDescriptorProxy :id="item.id" />
|
<ItemDescriptorProxy :id="card.id" />
|
||||||
</span>
|
</span>
|
||||||
<p class="subName">{{ item.subName }}</p>
|
<p class="subName">{{ card.subName }}</p>
|
||||||
<template v-for="index in 4" :key="`tag-${index}`">
|
<template v-for="index in 4" :key="`tag-${index}`">
|
||||||
<VnLv
|
<VnLv
|
||||||
v-if="item?.[`tag${index + 4}`]"
|
v-if="card?.[`tag${index + 4}`]"
|
||||||
:label="item?.[`tag${index + 4}`] + ':'"
|
:label="card?.[`tag${index + 4}`] + ':'"
|
||||||
:value="item?.[`value${index + 4}`]"
|
:value="card?.[`value${index + 4}`]"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="item.minQuantity" class="min-quantity">
|
<div v-if="card.minQuantity" class="min-quantity">
|
||||||
<QIcon name="production_quantity_limits" size="xs" />
|
<QIcon name="production_quantity_limits" size="xs" />
|
||||||
{{ item.minQuantity }}
|
{{ card.minQuantity }}
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="price">
|
<div class="price">
|
||||||
<p v-if="isCatalog">
|
<p v-if="isCatalog">
|
||||||
{{ item.available }} {{ t('to') }}
|
{{ card.available }} {{ t('to') }}
|
||||||
{{ toCurrency(item.price) }}
|
{{ toCurrency(card.price) }}
|
||||||
</p>
|
</p>
|
||||||
<slot name="price" />
|
<slot name="price" />
|
||||||
<QIcon v-if="isCatalog" name="add_circle" class="icon">
|
<QIcon v-if="isCatalog" name="add_circle" class="icon">
|
||||||
<QTooltip>{{ t('globals.add') }}</QTooltip>
|
<QTooltip>{{ t('globals.add') }}</QTooltip>
|
||||||
<QPopupProxy ref="dialog">
|
<QPopupProxy ref="dialog">
|
||||||
<OrderCatalogItemDialog
|
<OrderCatalogItemDialog
|
||||||
:item="item"
|
:item="card"
|
||||||
@added="() => dialog.hide()"
|
@added="
|
||||||
|
(quantityAdded) => {
|
||||||
|
card.available += quantityAdded;
|
||||||
|
dialog.hide();
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</QPopupProxy>
|
</QPopupProxy>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="item.priceKg" class="price-kg">
|
<p v-if="card.priceKg" class="price-kg">
|
||||||
{{ t('price-kg') }}
|
{{ t('price-kg') }}
|
||||||
{{ toCurrency(item.priceKg) || DEFAULT_PRICE_KG }}
|
{{ toCurrency(card.priceKg) || DEFAULT_PRICE_KG }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,10 +51,6 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
staticParams: {
|
|
||||||
type: Array,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
exprBuilder: {
|
exprBuilder: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: null,
|
default: null,
|
||||||
|
|
|
@ -264,6 +264,10 @@ input::-webkit-inner-spin-button {
|
||||||
.shrink {
|
.shrink {
|
||||||
max-width: 75px;
|
max-width: 75px;
|
||||||
}
|
}
|
||||||
|
.number {
|
||||||
|
text-align: right;
|
||||||
|
width: 96px;
|
||||||
|
}
|
||||||
.expand {
|
.expand {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,7 +499,7 @@ invoiceOut:
|
||||||
ticketList: Listado de tickets
|
ticketList: Listado de tickets
|
||||||
summary:
|
summary:
|
||||||
issued: Fecha
|
issued: Fecha
|
||||||
dued: Vencimiento
|
dued: Fecha límite
|
||||||
booked: Contabilizada
|
booked: Contabilizada
|
||||||
taxBreakdown: Desglose impositivo
|
taxBreakdown: Desglose impositivo
|
||||||
taxableBase: Base imp.
|
taxableBase: Base imp.
|
||||||
|
|
|
@ -6,6 +6,7 @@ import CrudModel from 'components/CrudModel.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import { tMobile } from 'composables/tMobile';
|
import { tMobile } from 'composables/tMobile';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
@ -157,19 +158,14 @@ const columns = computed(() => [
|
||||||
auto-width
|
auto-width
|
||||||
@keyup.ctrl.enter.stop="claimDevelopmentForm.saveChanges()"
|
@keyup.ctrl.enter.stop="claimDevelopmentForm.saveChanges()"
|
||||||
>
|
>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
|
v-if="col.name == 'worker'"
|
||||||
v-model="row[col.model]"
|
v-model="row[col.model]"
|
||||||
:url="col.url"
|
|
||||||
:where="col.where"
|
|
||||||
:sort-by="col.sortBy"
|
|
||||||
:options="col.options"
|
|
||||||
:option-value="col.optionValue"
|
|
||||||
:option-label="col.optionLabel"
|
|
||||||
:autofocus="col.tabIndex == 1"
|
:autofocus="col.tabIndex == 1"
|
||||||
input-debounce="0"
|
input-debounce="0"
|
||||||
hide-selected
|
hide-selected
|
||||||
>
|
>
|
||||||
<template #option="scope" v-if="col.name == 'worker'">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||||
|
@ -180,7 +176,20 @@ const columns = computed(() => [
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelectWorker>
|
||||||
|
<VnSelect
|
||||||
|
v-else
|
||||||
|
v-model="row[col.model]"
|
||||||
|
:url="col.url"
|
||||||
|
:where="col.where"
|
||||||
|
:sort-by="col.sortBy"
|
||||||
|
:options="col.options"
|
||||||
|
:option-value="col.optionValue"
|
||||||
|
:option-label="col.optionLabel"
|
||||||
|
:autofocus="col.tabIndex == 1"
|
||||||
|
input-debounce="0"
|
||||||
|
hide-selected
|
||||||
|
/>
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #item="props">
|
<template #item="props">
|
||||||
|
|
|
@ -120,13 +120,13 @@ const developmentColumns = ref([
|
||||||
{
|
{
|
||||||
name: 'claimReason',
|
name: 'claimReason',
|
||||||
label: 'claim.reason',
|
label: 'claim.reason',
|
||||||
field: (row) => row.claimReason.description,
|
field: (row) => row.claimReason?.description,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'claimResult',
|
name: 'claimResult',
|
||||||
label: 'claim.result',
|
label: 'claim.result',
|
||||||
field: (row) => row.claimResult.description,
|
field: (row) => row.claimResult?.description,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,7 @@ import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||||
import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue';
|
import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue';
|
||||||
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -144,7 +145,6 @@ function handleLocation(data, location) {
|
||||||
:url="`Addresses/${route.params.addressId}`"
|
:url="`Addresses/${route.params.addressId}`"
|
||||||
@on-data-saved="onDataSaved()"
|
@on-data-saved="onDataSaved()"
|
||||||
auto-load
|
auto-load
|
||||||
model="customer"
|
|
||||||
>
|
>
|
||||||
<template #moreActions>
|
<template #moreActions>
|
||||||
<QBtn
|
<QBtn
|
||||||
|
@ -220,31 +220,35 @@ function handleLocation(data, location) {
|
||||||
</div>
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<div class="col">
|
<VnSelect
|
||||||
<VnSelect
|
:label="t('Incoterms')"
|
||||||
:label="t('Incoterms')"
|
:options="incoterms"
|
||||||
:options="incoterms"
|
hide-selected
|
||||||
hide-selected
|
option-label="name"
|
||||||
option-label="name"
|
option-value="code"
|
||||||
option-value="code"
|
v-model="data.incotermsFk"
|
||||||
v-model="data.incotermsFk"
|
/>
|
||||||
/>
|
<VnSelectDialog
|
||||||
</div>
|
:label="t('Customs agent')"
|
||||||
<div class="col">
|
:options="customsAgents"
|
||||||
<VnSelectDialog
|
hide-selected
|
||||||
:label="t('Customs agent')"
|
option-label="fiscalName"
|
||||||
:options="customsAgents"
|
option-value="id"
|
||||||
hide-selected
|
v-model="data.customsAgentFk"
|
||||||
option-label="fiscalName"
|
:tooltip="t('New customs agent')"
|
||||||
option-value="id"
|
>
|
||||||
v-model="data.customsAgentFk"
|
<template #form>
|
||||||
:tooltip="t('New customs agent')"
|
<CustomerNewCustomsAgent />
|
||||||
>
|
</template>
|
||||||
<template #form>
|
</VnSelectDialog>
|
||||||
<CustomerNewCustomsAgent />
|
</VnRow>
|
||||||
</template>
|
<VnRow>
|
||||||
</VnSelectDialog>
|
<VnInputNumber
|
||||||
</div>
|
:label="t('Longitude')"
|
||||||
|
clearable
|
||||||
|
v-model="data.longitude"
|
||||||
|
/>
|
||||||
|
<VnInputNumber :label="t('Latitude')" clearable v-model="data.latitude" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<h4 class="q-mb-xs">{{ t('Notes') }}</h4>
|
<h4 class="q-mb-xs">{{ t('Notes') }}</h4>
|
||||||
<VnRow
|
<VnRow
|
||||||
|
@ -322,4 +326,6 @@ es:
|
||||||
Description: Descripción
|
Description: Descripción
|
||||||
Add note: Añadir nota
|
Add note: Añadir nota
|
||||||
Remove note: Eliminar nota
|
Remove note: Eliminar nota
|
||||||
|
Longitude: Longitud
|
||||||
|
Latitude: Latitud
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -189,6 +189,7 @@ async function getAmountPaid() {
|
||||||
:url-create="urlCreate"
|
:url-create="urlCreate"
|
||||||
:mapper="onBeforeSave"
|
:mapper="onBeforeSave"
|
||||||
@on-data-saved="onDataSaved"
|
@on-data-saved="onDataSaved"
|
||||||
|
:prevent-submit="true"
|
||||||
>
|
>
|
||||||
<template #form="{ data, validate }">
|
<template #form="{ data, validate }">
|
||||||
<span ref="closeButton" class="row justify-end close-icon" v-close-popup>
|
<span ref="closeButton" class="row justify-end close-icon" v-close-popup>
|
||||||
|
@ -303,7 +304,7 @@ async function getAmountPaid() {
|
||||||
:label="t('globals.save')"
|
:label="t('globals.save')"
|
||||||
:loading="formModelRef.isLoading"
|
:loading="formModelRef.isLoading"
|
||||||
color="primary"
|
color="primary"
|
||||||
type="submit"
|
@click="formModelRef.save()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, watch } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
|
||||||
import { toCurrency } from 'filters/index';
|
import { toCurrency } from 'filters/index';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -15,31 +14,22 @@ import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
import ItemRequestFilter from './ItemRequestFilter.vue';
|
import ItemRequestFilter from './ItemRequestFilter.vue';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
let filterParams = ref({});
|
|
||||||
const denyFormRef = ref(null);
|
const denyFormRef = ref(null);
|
||||||
const denyRequestId = ref(null);
|
const denyRequestId = ref(null);
|
||||||
const denyRequestIndex = ref(null);
|
const denyRequestIndex = ref(null);
|
||||||
const itemRequestsOptions = ref([]);
|
const itemRequestsOptions = ref([]);
|
||||||
const arrayData = useArrayData('ItemRequests', {
|
|
||||||
url: 'TicketRequests/filter',
|
|
||||||
userParams: filterParams,
|
|
||||||
order: ['shippedDate ASC', 'isOk ASC'],
|
|
||||||
});
|
|
||||||
const store = arrayData.store;
|
|
||||||
|
|
||||||
const userParams = {
|
const userParams = {
|
||||||
state: 'pending',
|
state: 'pending',
|
||||||
daysOnward: 7,
|
daysOnward: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
watch(
|
onMounted(async () => {
|
||||||
() => store.data,
|
stateStore.rightDrawer = true;
|
||||||
(value) => (itemRequestsOptions.value = value)
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
|
@ -223,11 +213,6 @@ const onDenyAccept = (_, responseData) => {
|
||||||
denyRequestIndex.value = null;
|
denyRequestIndex.value = null;
|
||||||
tableRef.value.reload();
|
tableRef.value.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await arrayData.fetch({ append: false });
|
|
||||||
stateStore.rightDrawer = true;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -244,10 +229,10 @@ onMounted(async () => {
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:user-params="userParams"
|
:user-params="userParams"
|
||||||
:is-editable="true"
|
:is-editable="true"
|
||||||
|
:right-search="false"
|
||||||
auto-load
|
auto-load
|
||||||
:disable-option="{ card: true }"
|
:disable-option="{ card: true }"
|
||||||
chip-locale="item.params"
|
chip-locale="item.params"
|
||||||
:right-search="false"
|
|
||||||
>
|
>
|
||||||
<template #column-ticketFk="{ row }">
|
<template #column-ticketFk="{ row }">
|
||||||
<span class="link">
|
<span class="link">
|
||||||
|
@ -306,14 +291,17 @@ onMounted(async () => {
|
||||||
<template #moreFilterPanel="{ params }">
|
<template #moreFilterPanel="{ params }">
|
||||||
<VnInputNumber
|
<VnInputNumber
|
||||||
:label="t('params.scopeDays')"
|
:label="t('params.scopeDays')"
|
||||||
v-model.number="params.scopeDays"
|
v-model.number="params.daysOnward"
|
||||||
@keyup.enter="(evt) => handleScopeDays(evt.target.value)"
|
@keyup.enter="(evt) => handleScopeDays(evt.target.value)"
|
||||||
@remove="handleScopeDays()"
|
@remove="handleScopeDays()"
|
||||||
class="q-px-xs q-pr-lg"
|
class="q-px-xs q-pr-lg"
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
|
lazy-rules
|
||||||
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #column-denyOptions="{ row, rowIndex }">
|
<template #column-denyOptions="{ row, rowIndex }">
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="row.response?.length"
|
v-if="row.response?.length"
|
||||||
|
|
|
@ -6,7 +6,6 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
|
@ -46,20 +45,6 @@ const exprBuilder = (param, value) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const add = (paramsObj, key) => {
|
|
||||||
if (paramsObj[key] === undefined) {
|
|
||||||
paramsObj[key] = 1;
|
|
||||||
} else {
|
|
||||||
paramsObj[key]++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const decrement = (paramsObj, key) => {
|
|
||||||
if (paramsObj[key] === 0) return;
|
|
||||||
|
|
||||||
paramsObj[key]--;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (arrayData.store?.userParams) {
|
if (arrayData.store?.userParams) {
|
||||||
fieldFiltersValues.value = Object.entries(arrayData.store.userParams).map(
|
fieldFiltersValues.value = Object.entries(arrayData.store.userParams).map(
|
||||||
|
@ -95,8 +80,7 @@ onMounted(async () => {
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
<div class="q-gutter-x-xs">
|
<div class="q-gutter-x-xs">
|
||||||
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
<span v-if="tag.label !== 'state'">{{ formatFn(tag.value) }}</span>
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
<span v-else>{{ t(`${tag.value}`) }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ params, searchFn }">
|
<template #body="{ params, searchFn }">
|
||||||
|
@ -174,83 +158,6 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
|
||||||
v-model="params.myTeam"
|
|
||||||
:label="t('params.myTeam')"
|
|
||||||
@update:model-value="searchFn()"
|
|
||||||
toggle-indeterminate
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QCard bordered>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInputDate
|
|
||||||
:label="t('params.from')"
|
|
||||||
v-model="params.from"
|
|
||||||
@update:model-value="searchFn()"
|
|
||||||
is-outlined
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInputDate
|
|
||||||
:label="t('params.to')"
|
|
||||||
v-model="params.to"
|
|
||||||
@update:model-value="searchFn()"
|
|
||||||
is-outlined
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
|
||||||
v-model="params.scopeDays"
|
|
||||||
:label="t('globals.daysOnward')"
|
|
||||||
type="number"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
:min="0"
|
|
||||||
>
|
|
||||||
<template #append>
|
|
||||||
<QBtn
|
|
||||||
icon="add"
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
size="12px"
|
|
||||||
shortcut="+"
|
|
||||||
@click="add(params, 'scopeDays')"
|
|
||||||
/>
|
|
||||||
<QBtn
|
|
||||||
icon="remove"
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
size="12px"
|
|
||||||
@click="decrement(params, 'scopeDays')"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</VnInput>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QIcon name="info" style="position: absolute; top: 4px; right: 4px">
|
|
||||||
<QTooltip max-width="300px">
|
|
||||||
{{ t('dateFiltersTooltip') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</QCard>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('params.mine')"
|
|
||||||
v-model="params.mine"
|
|
||||||
toggle-indeterminate
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
@ -267,6 +174,16 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
:label="t('params.daysOnward')"
|
||||||
|
v-model="params.daysOnward"
|
||||||
|
lazy-rules
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnFilterPanel>
|
</VnFilterPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -78,29 +78,32 @@ async function setItemTypeData(data) {
|
||||||
{{ t('globals.summary.basicData') }}
|
{{ t('globals.summary.basicData') }}
|
||||||
<QIcon name="open_in_new" />
|
<QIcon name="open_in_new" />
|
||||||
</router-link>
|
</router-link>
|
||||||
<VnLv :label="t('summary.id')" :value="itemType.id" />
|
<VnLv :label="t('itemType.summary.id')" :value="itemType.id" />
|
||||||
<VnLv :label="t('shared.code')" :value="itemType.code" />
|
<VnLv :label="t('itemType.shared.code')" :value="itemType.code" />
|
||||||
<VnLv :label="t('shared.name')" :value="itemType.name" />
|
<VnLv :label="t('itemType.shared.name')" :value="itemType.name" />
|
||||||
<VnLv :label="t('shared.worker')">
|
<VnLv :label="t('itemType.shared.worker')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">{{ itemType.worker?.firstName }}</span>
|
<span class="link">{{ itemType.worker?.firstName }}</span>
|
||||||
<WorkerDescriptorProxy :id="itemType.worker?.id" />
|
<WorkerDescriptorProxy :id="itemType.worker?.id" />
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv :label="t('shared.category')" :value="itemType.category?.name" />
|
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('shared.temperature')"
|
:label="t('itemType.shared.category')"
|
||||||
|
:value="itemType.category?.name"
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('itemType.shared.temperature')"
|
||||||
:value="itemType.temperature?.name"
|
:value="itemType.temperature?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('summary.life')" :value="itemType.life" />
|
<VnLv :label="t('itemType.summary.life')" :value="itemType.life" />
|
||||||
<VnLv :label="t('summary.promo')" :value="itemType.promo" />
|
<VnLv :label="t('itemType.summary.promo')" :value="itemType.promo" />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('summary.itemPackingType')"
|
:label="t('itemType.summary.itemPackingType')"
|
||||||
:value="itemType.itemPackingType?.description"
|
:value="itemType.itemPackingType?.description"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
class="large-label"
|
class="large-label"
|
||||||
:label="t('summary.isUnconventionalSize')"
|
:label="t('itemType.summary.isUnconventionalSize')"
|
||||||
:value="itemType.isUnconventionalSize"
|
:value="itemType.isUnconventionalSize"
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
shared:
|
itemType:
|
||||||
code: Code
|
shared:
|
||||||
name: Name
|
code: Code
|
||||||
worker: Worker
|
name: Name
|
||||||
category: Category
|
worker: Worker
|
||||||
temperature: Temperature
|
category: Category
|
||||||
life: Life
|
temperature: Temperature
|
||||||
itemPackingType: Item packing type
|
life: Life
|
||||||
maxRefs: Maximum references
|
itemPackingType: Item packing type
|
||||||
fragile: Fragile
|
maxRefs: Maximum references
|
||||||
summary:
|
fragile: Fragile
|
||||||
id: id
|
summary:
|
||||||
life: Life
|
id: id
|
||||||
promo: Promo
|
life: Life
|
||||||
itemPackingType: Item packing type
|
promo: Promo
|
||||||
isUnconventionalSize: Is unconventional size
|
itemPackingType: Item packing type
|
||||||
|
isUnconventionalSize: Is unconventional size
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
shared:
|
itemType:
|
||||||
code: Código
|
shared:
|
||||||
name: Nombre
|
code: Código
|
||||||
worker: Trabajador
|
name: Nombre
|
||||||
category: Reino
|
worker: Trabajador
|
||||||
temperature: Temperatura
|
category: Reino
|
||||||
life: Vida
|
temperature: Temperatura
|
||||||
itemPackingType: Tipo de embalaje
|
life: Vida
|
||||||
maxRefs: Referencias máximas
|
itemPackingType: Tipo de embalaje
|
||||||
fragile: Frágil
|
maxRefs: Referencias máximas
|
||||||
summary:
|
fragile: Frágil
|
||||||
id: id
|
summary:
|
||||||
life: Vida
|
id: id
|
||||||
promo: Promoción
|
life: Vida
|
||||||
itemPackingType: Tipo de embalaje
|
promo: Promoción
|
||||||
isUnconventionalSize: Es de tamaño poco convencional
|
itemPackingType: Tipo de embalaje
|
||||||
|
isUnconventionalSize: Es de tamaño poco convencional
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
@ -16,6 +16,7 @@ import MonitorTicketSearchbar from './MonitorTicketSearchbar.vue';
|
||||||
import MonitorTicketFilter from './MonitorTicketFilter.vue';
|
import MonitorTicketFilter from './MonitorTicketFilter.vue';
|
||||||
import TicketProblems from 'src/components/TicketProblems.vue';
|
import TicketProblems from 'src/components/TicketProblems.vue';
|
||||||
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
|
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
|
||||||
|
import { useStateStore } from 'src/stores/useStateStore';
|
||||||
|
|
||||||
const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000;
|
const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000;
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -25,8 +26,9 @@ const provinceOpts = ref([]);
|
||||||
const stateOpts = ref([]);
|
const stateOpts = ref([]);
|
||||||
const zoneOpts = ref([]);
|
const zoneOpts = ref([]);
|
||||||
const DepartmentOpts = ref([]);
|
const DepartmentOpts = ref([]);
|
||||||
|
const PayMethodOpts = ref([]);
|
||||||
const ItemPackingTypeOpts = ref([]);
|
const ItemPackingTypeOpts = ref([]);
|
||||||
const visibleColumns = ref([]);
|
const stateStore = useStateStore();
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
|
||||||
const [from, to] = dateRange(Date.vnNew());
|
const [from, to] = dateRange(Date.vnNew());
|
||||||
|
@ -37,6 +39,11 @@ const stateColors = {
|
||||||
alert: 'negative',
|
alert: 'negative',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
stateStore.leftDrawer = false;
|
||||||
|
stateStore.rightDrawer = false;
|
||||||
|
});
|
||||||
|
|
||||||
function exprBuilder(param, value) {
|
function exprBuilder(param, value) {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 'stateFk':
|
case 'stateFk':
|
||||||
|
@ -217,7 +224,16 @@ const columns = computed(() => [
|
||||||
label: t('salesTicketsTable.payMethod'),
|
label: t('salesTicketsTable.payMethod'),
|
||||||
name: 'payMethod',
|
name: 'payMethod',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
columnFilter: false,
|
columnFilter: {
|
||||||
|
component: 'select',
|
||||||
|
url: 'PayMethods',
|
||||||
|
attrs: {
|
||||||
|
options: PayMethodOpts.value,
|
||||||
|
optionValue: 'id',
|
||||||
|
optionLabel: 'name',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('salesTicketsTable.total'),
|
label: t('salesTicketsTable.total'),
|
||||||
|
@ -238,11 +254,8 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
component: 'select',
|
component: 'select',
|
||||||
url: 'Departments',
|
|
||||||
attrs: {
|
attrs: {
|
||||||
options: DepartmentOpts.value,
|
options: DepartmentOpts.value,
|
||||||
optionValue: 'name',
|
|
||||||
optionLabel: 'name',
|
|
||||||
dense: true,
|
dense: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -358,6 +371,15 @@ const openTab = (id) =>
|
||||||
auto-load
|
auto-load
|
||||||
@on-fetch="(data) => (DepartmentOpts = data)"
|
@on-fetch="(data) => (DepartmentOpts = data)"
|
||||||
/>
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="PayMethods"
|
||||||
|
:filter="{
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
order: 'id ASC',
|
||||||
|
}"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (PayMethodOpts = data)"
|
||||||
|
/>
|
||||||
<MonitorTicketSearchbar />
|
<MonitorTicketSearchbar />
|
||||||
<RightMenu>
|
<RightMenu>
|
||||||
<template #right-panel>
|
<template #right-panel>
|
||||||
|
@ -377,7 +399,7 @@ const openTab = (id) =>
|
||||||
auto-load
|
auto-load
|
||||||
:row-click="({ id }) => openTab(id)"
|
:row-click="({ id }) => openTab(id)"
|
||||||
:disable-option="{ card: true }"
|
:disable-option="{ card: true }"
|
||||||
:user-params="{ from, to, scopeDays: 0, packing }"
|
:user-params="{ from, to, scopeDays: 0 }"
|
||||||
>
|
>
|
||||||
<template #top-left>
|
<template #top-left>
|
||||||
<QBtn
|
<QBtn
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { onMounted, ref, computed, watch, provide } from 'vue';
|
import { onMounted, ref, computed, watch } from 'vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||||
|
@ -75,19 +75,6 @@ watch(
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
const onItemSaved = (updatedItem) => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
scrollToItem(updatedItem.items[0].itemFk);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const scrollToItem = async (id) => {
|
|
||||||
const element = itemRefs.value[id]?.$el;
|
|
||||||
if (element) {
|
|
||||||
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
provide('onItemSaved', onItemSaved);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -100,16 +87,14 @@ provide('onItemSaved', onItemSaved);
|
||||||
:label="t('Search items')"
|
:label="t('Search items')"
|
||||||
:info="t('You can search items by name or id')"
|
:info="t('You can search items by name or id')"
|
||||||
/>
|
/>
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QScrollArea class="fit text-grey-8">
|
<OrderCatalogFilter
|
||||||
<OrderCatalogFilter
|
:data-key="dataKey"
|
||||||
:data-key="dataKey"
|
:tag-value="tagValue"
|
||||||
:tag-value="tagValue"
|
:tags="tags"
|
||||||
:tags="tags"
|
:initial-catalog-params="catalogParams"
|
||||||
:initial-catalog-params="catalogParams"
|
/>
|
||||||
/>
|
</Teleport>
|
||||||
</QScrollArea>
|
|
||||||
</QDrawer>
|
|
||||||
<QPage class="column items-center q-pa-md" data-cy="orderCatalogPage">
|
<QPage class="column items-center q-pa-md" data-cy="orderCatalogPage">
|
||||||
<div class="full-width">
|
<div class="full-width">
|
||||||
<VnPaginate
|
<VnPaginate
|
||||||
|
|
|
@ -65,7 +65,6 @@ const selectCategory = async (params, category, search) => {
|
||||||
params.typeFk = null;
|
params.typeFk = null;
|
||||||
params.categoryFk = category.id;
|
params.categoryFk = category.id;
|
||||||
await loadTypes(category?.id);
|
await loadTypes(category?.id);
|
||||||
await search();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadTypes = async (id) => {
|
const loadTypes = async (id) => {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import toCurrency from 'src/filters/toCurrency';
|
import toCurrency from 'src/filters/toCurrency';
|
||||||
import { inject, ref } from 'vue';
|
import { computed, inject, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import useNotify from 'composables/useNotify';
|
import useNotify from 'composables/useNotify';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
|
||||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
@ -18,10 +18,17 @@ const props = defineProps({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const onItemSaved = inject('onItemSaved');
|
const state = useState();
|
||||||
|
|
||||||
|
const orderData = computed(() => state.get('orderData'));
|
||||||
|
|
||||||
const prices = ref((props.item.prices || []).map((item) => ({ ...item, quantity: 0 })));
|
const prices = ref((props.item.prices || []).map((item) => ({ ...item, quantity: 0 })));
|
||||||
const descriptorData = useArrayData('orderData');
|
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
const totalQuantity = (items) =>
|
||||||
|
items.reduce((acc, item) => {
|
||||||
|
return acc + item.quantity;
|
||||||
|
}, 0);
|
||||||
const addToOrder = async () => {
|
const addToOrder = async () => {
|
||||||
if (isLoading.value) return;
|
if (isLoading.value) return;
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
@ -30,10 +37,19 @@ const addToOrder = async () => {
|
||||||
items,
|
items,
|
||||||
orderFk: Number(route.params.id),
|
orderFk: Number(route.params.id),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: orderTotal } = await axios.get(
|
||||||
|
`Orders/${Number(route.params.id)}/getTotal`
|
||||||
|
);
|
||||||
|
|
||||||
|
state.set('orderTotal', orderTotal);
|
||||||
|
const rows = orderData.value.rows.push(...items) || [];
|
||||||
|
state.set('orderData', {
|
||||||
|
...orderData.value,
|
||||||
|
rows,
|
||||||
|
});
|
||||||
notify(t('globals.dataSaved'), 'positive');
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
await descriptorData.fetch({});
|
emit('added', -totalQuantity(items));
|
||||||
onItemSaved({ ...props, items, saved: true });
|
|
||||||
emit('added', items);
|
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
};
|
};
|
||||||
const canAddToOrder = () => {
|
const canAddToOrder = () => {
|
||||||
|
|
|
@ -63,21 +63,26 @@ const setData = (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
getTotalRef.value && getTotalRef.value.fetch();
|
getTotalRef.value && getTotalRef.value.fetch();
|
||||||
data.value = useCardDescription(entity?.client?.name, entity?.id);
|
data.value = useCardDescription(entity?.client?.name, entity?.id);
|
||||||
state.set('orderData', entity);
|
state.set('orderTotal', total);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConfirmationValue = (isConfirmed) => {
|
const getConfirmationValue = (isConfirmed) => {
|
||||||
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
|
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
|
||||||
};
|
};
|
||||||
|
|
||||||
const total = ref(null);
|
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
|
||||||
|
const total = ref(0);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
ref="getTotalRef"
|
ref="getTotalRef"
|
||||||
:url="`Orders/${entityId}/getTotal`"
|
:url="`Orders/${entityId}/getTotal`"
|
||||||
@on-fetch="(response) => (total = response)"
|
@on-fetch="
|
||||||
|
(response) => {
|
||||||
|
total = response;
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
|
@ -112,7 +117,7 @@ const total = ref(null);
|
||||||
:label="t('order.summary.items')"
|
:label="t('order.summary.items')"
|
||||||
:value="(entity?.rows?.length || DEFAULT_ITEMS).toString()"
|
:value="(entity?.rows?.length || DEFAULT_ITEMS).toString()"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('order.summary.total')" :value="toCurrency(total)" />
|
<VnLv :label="t('order.summary.total')" :value="toCurrency(orderTotal)" />
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{ entity }">
|
<template #actions="{ entity }">
|
||||||
<QCardActions>
|
<QCardActions>
|
||||||
|
|
|
@ -251,7 +251,7 @@ watch(
|
||||||
@on-fetch="(data) => (orderSummary.vat = data)"
|
@on-fetch="(data) => (orderSummary.vat = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<QDrawer side="right" :width="265" v-model="stateStore.rightDrawer">
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QCard
|
<QCard
|
||||||
class="order-lines-summary q-pa-lg"
|
class="order-lines-summary q-pa-lg"
|
||||||
v-if="orderSummary.vat && orderSummary.total"
|
v-if="orderSummary.vat && orderSummary.total"
|
||||||
|
@ -266,7 +266,7 @@ watch(
|
||||||
<VnLv :label="t('VAT') + ': '" :value="toCurrency(orderSummary?.vat)" />
|
<VnLv :label="t('VAT') + ': '" :value="toCurrency(orderSummary?.vat)" />
|
||||||
<VnLv :label="t('total') + ': '" :value="toCurrency(orderSummary?.total)" />
|
<VnLv :label="t('total') + ': '" :value="toCurrency(orderSummary?.total)" />
|
||||||
</QCard>
|
</QCard>
|
||||||
</QDrawer>
|
</Teleport>
|
||||||
|
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableLinesRef"
|
ref="tableLinesRef"
|
||||||
|
|
|
@ -8,7 +8,7 @@ import SendEmailDialog from 'components/common/SendEmailDialog.vue';
|
||||||
import SupplierConsumptionFilter from './SupplierConsumptionFilter.vue';
|
import SupplierConsumptionFilter from './SupplierConsumptionFilter.vue';
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
|
||||||
import { toDate } from 'src/filters';
|
import { dateRange, toDate } from 'src/filters';
|
||||||
import { dashIfEmpty } from 'src/filters';
|
import { dashIfEmpty } from 'src/filters';
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
import { usePrintService } from 'composables/usePrintService';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
@ -35,14 +35,17 @@ const store = arrayData.store;
|
||||||
|
|
||||||
onUnmounted(() => state.unset('SupplierConsumption'));
|
onUnmounted(() => state.unset('SupplierConsumption'));
|
||||||
const dateRanges = computed(() => {
|
const dateRanges = computed(() => {
|
||||||
const { from, to } = arrayData.store?.userParams || {};
|
let { from, to } = arrayData.store?.userParams || {};
|
||||||
return { from, to };
|
return { from, to };
|
||||||
});
|
});
|
||||||
|
|
||||||
const reportParams = computed(() => ({
|
const reportParams = computed(() => {
|
||||||
recipientId: Number(route.params.id),
|
return {
|
||||||
...dateRanges.value,
|
recipientId: Number(route.params.id),
|
||||||
}));
|
to: dateRange(dateRanges.value.to)[1],
|
||||||
|
from: dateRange(dateRanges.value.from)[1],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
async function getSupplierConsumptionData() {
|
async function getSupplierConsumptionData() {
|
||||||
await arrayData.fetch({ append: false });
|
await arrayData.fetch({ append: false });
|
||||||
|
@ -171,11 +174,9 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<QPage class="column items-center q-pa-md">
|
<QPage class="column items-center q-pa-md">
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QScrollArea class="fit text-grey-8">
|
<SupplierConsumptionFilter data-key="SupplierConsumption" />
|
||||||
<SupplierConsumptionFilter data-key="SupplierConsumption" />
|
</Teleport>
|
||||||
</QScrollArea>
|
|
||||||
</QDrawer>
|
|
||||||
<QTable
|
<QTable
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, watch } from 'vue';
|
import { ref, computed, onMounted, nextTick } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
@ -10,37 +10,15 @@ import { useStateStore } from 'stores/useStateStore';
|
||||||
import { toCurrency } from 'filters/index';
|
import { toCurrency } from 'filters/index';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useRole } from 'src/composables/useRole';
|
||||||
|
|
||||||
const $props = defineProps({
|
const haveNegatives = defineModel('haveNegatives', { type: Boolean, required: true });
|
||||||
formData: {
|
const formData = defineModel({ type: Object, required: true });
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
haveNegatives: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(['updateForm', 'update:haveNegatives']);
|
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { hasAny } = useRole();
|
const { hasAny } = useRole();
|
||||||
|
|
||||||
const _ticketData = ref($props.formData);
|
|
||||||
const ticketUpdateActions = ref(null);
|
const ticketUpdateActions = ref(null);
|
||||||
const haveNegatives = computed({
|
const rows = computed(() => formData.value?.sale?.items || []);
|
||||||
get: () => $props.haveNegatives,
|
|
||||||
set: (val) => emit('update:haveNegatives', val),
|
|
||||||
});
|
|
||||||
const rows = computed(() => _ticketData.value?.sale?.items || []);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => _ticketData.value,
|
|
||||||
(val) => emit('updateForm', val),
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
|
@ -57,24 +35,28 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
hidden: true,
|
hidden: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'subName',
|
||||||
|
align: 'left',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: t('basicData.movable'),
|
label: t('basicData.movable'),
|
||||||
name: 'movable',
|
name: 'movable',
|
||||||
align: 'left',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
label: t('basicData.quantity'),
|
label: t('basicData.quantity'),
|
||||||
name: 'quantity',
|
name: 'quantity',
|
||||||
field: 'quantity',
|
field: 'quantity',
|
||||||
align: 'left',
|
classes: 'number',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
label: t('basicData.pricePPU'),
|
label: t('basicData.pricePPU'),
|
||||||
name: 'price',
|
name: 'price',
|
||||||
field: 'price',
|
field: 'price',
|
||||||
align: 'left',
|
classes: 'number',
|
||||||
format: (val) => toCurrency(val),
|
format: (val) => toCurrency(val),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -82,7 +64,7 @@ const columns = computed(() => [
|
||||||
label: t('basicData.newPricePPU'),
|
label: t('basicData.newPricePPU'),
|
||||||
name: 'newPrice',
|
name: 'newPrice',
|
||||||
field: (row) => row.component.newPrice,
|
field: (row) => row.component.newPrice,
|
||||||
align: 'left',
|
classes: 'number',
|
||||||
format: (val) => toCurrency(val),
|
format: (val) => toCurrency(val),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -90,14 +72,15 @@ const columns = computed(() => [
|
||||||
label: t('basicData.difference'),
|
label: t('basicData.difference'),
|
||||||
name: 'difference',
|
name: 'difference',
|
||||||
field: (row) => row.component.difference,
|
field: (row) => row.component.difference,
|
||||||
align: 'left',
|
classes: 'number',
|
||||||
format: (val) => toCurrency(val),
|
format: (val) => toCurrency(val),
|
||||||
|
autoWidth: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const loadDefaultTicketAction = () => {
|
const loadDefaultTicketAction = () => {
|
||||||
const isSalesAssistant = hasAny(['salesAssistant']);
|
const isSalesAssistant = hasAny(['salesAssistant']);
|
||||||
_ticketData.value.option = isSalesAssistant ? 'mana' : 'renewPrices';
|
formData.value.option = isSalesAssistant ? 'mana' : 'renewPrices';
|
||||||
};
|
};
|
||||||
|
|
||||||
const totalPrice = computed(() => {
|
const totalPrice = computed(() => {
|
||||||
|
@ -115,24 +98,25 @@ const totalDifference = computed(() => {
|
||||||
return rows.value.reduce((acc, item) => acc + item.component?.difference || 0, 0);
|
return rows.value.reduce((acc, item) => acc + item.component?.difference || 0, 0);
|
||||||
});
|
});
|
||||||
const showMovableColumn = computed(() => (haveDifferences.value > 0 ? ['movable'] : []));
|
const showMovableColumn = computed(() => (haveDifferences.value > 0 ? ['movable'] : []));
|
||||||
const haveDifferences = computed(() => _ticketData.value.sale?.haveDifferences);
|
const haveDifferences = computed(() => formData.value.sale?.haveDifferences);
|
||||||
const ticketHaveNegatives = () => {
|
async function ticketHaveNegatives() {
|
||||||
let _haveNegatives = false;
|
let _haveNegatives = false;
|
||||||
let haveNotNegatives = false;
|
let haveNotNegatives = false;
|
||||||
_ticketData.value.withoutNegatives = false;
|
formData.value.withoutNegatives = false;
|
||||||
_ticketData.value?.sale?.items.forEach((item) => {
|
formData.value?.sale?.items.forEach((item) => {
|
||||||
if (item.quantity > item.movable) _haveNegatives = true;
|
if (item.quantity > item.movable) _haveNegatives = true;
|
||||||
else haveNotNegatives = true;
|
else haveNotNegatives = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
haveNegatives.value = _haveNegatives && haveNotNegatives && haveDifferences.value;
|
haveNegatives.value = _haveNegatives && haveNotNegatives && haveDifferences.value;
|
||||||
if (haveNegatives.value) _ticketData.value.withoutNegatives = true;
|
await nextTick();
|
||||||
};
|
if (haveNegatives.value) formData.value.withoutNegatives = true;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
loadDefaultTicketAction();
|
loadDefaultTicketAction();
|
||||||
ticketHaveNegatives();
|
await ticketHaveNegatives();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -189,7 +173,7 @@ onMounted(() => {
|
||||||
horizontal
|
horizontal
|
||||||
>
|
>
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="_ticketData.option"
|
v-model="formData.option"
|
||||||
:val="action.code"
|
:val="action.code"
|
||||||
:label="action.description"
|
:label="action.description"
|
||||||
dense
|
dense
|
||||||
|
@ -206,7 +190,7 @@ onMounted(() => {
|
||||||
<QCardSection horizontal class="flex row items-center">
|
<QCardSection horizontal class="flex row items-center">
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="t('basicData.withoutNegatives')"
|
:label="t('basicData.withoutNegatives')"
|
||||||
v-model="_ticketData.withoutNegatives"
|
v-model="formData.withoutNegatives"
|
||||||
:toggle-indeterminate="false"
|
:toggle-indeterminate="false"
|
||||||
/>
|
/>
|
||||||
<QIcon name="info" size="xs" class="q-ml-sm">
|
<QIcon name="info" size="xs" class="q-ml-sm">
|
||||||
|
@ -223,7 +207,7 @@ onMounted(() => {
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
:pagination="{ rowsPerPage: 0 }"
|
:pagination="{ rowsPerPage: 0 }"
|
||||||
class="full-width q-mt-md"
|
class="full-width"
|
||||||
:no-data-label="t('globals.noResults')"
|
:no-data-label="t('globals.noResults')"
|
||||||
flat
|
flat
|
||||||
>
|
>
|
||||||
|
@ -236,21 +220,27 @@ onMounted(() => {
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-description="{ row }">
|
<template #body-cell-description="{ row }">
|
||||||
<QTd style="display: contents">
|
<QTd style="min-width: 120px; max-width: 120px">
|
||||||
<div class="column">
|
<div class="column q-pb-xs" style="min-width: 120px">
|
||||||
<span>{{ row.item.name }}</span>
|
<span>{{ row.item.name }}</span>
|
||||||
<span class="color-vn-label">{{ row.item.subName }}</span>
|
<FetchedTags :item="row.item" class="full-width" />
|
||||||
<FetchedTags :item="row.item" />
|
|
||||||
</div>
|
</div>
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-movable="{ row }">
|
<template #body-cell-subName="{ row }">
|
||||||
<QTd>
|
<QTd>
|
||||||
<QBadge
|
<span class="color-vn-label">{{ row.item.subName }}</span>
|
||||||
v-if="_ticketData?.sale?.haveDifferences"
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-movable="{ row }">
|
||||||
|
<QTd class="number">
|
||||||
|
<QChip
|
||||||
|
v-if="formData?.sale?.haveDifferences"
|
||||||
:text-color="row.quantity > row.movable ? 'black' : 'white'"
|
:text-color="row.quantity > row.movable ? 'black' : 'white'"
|
||||||
:color="row.quantity > row.movable ? 'negative' : 'transparent'"
|
:color="row.quantity > row.movable ? 'negative' : 'transparent'"
|
||||||
:label="row.movable"
|
:label="row.movable"
|
||||||
|
dense
|
||||||
|
square
|
||||||
/>
|
/>
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -21,7 +21,6 @@ const formData = defineModel({
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['updateForm']);
|
|
||||||
const { validate } = useValidator();
|
const { validate } = useValidator();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -33,18 +32,11 @@ const canEditZone = useAcl().hasAny([
|
||||||
const agencyFetchRef = ref();
|
const agencyFetchRef = ref();
|
||||||
const warehousesOptions = ref([]);
|
const warehousesOptions = ref([]);
|
||||||
const companiesOptions = ref([]);
|
const companiesOptions = ref([]);
|
||||||
const currenciesOptions = ref([]);
|
|
||||||
const agenciesOptions = ref([]);
|
const agenciesOptions = ref([]);
|
||||||
const zonesOptions = ref([]);
|
const zonesOptions = ref([]);
|
||||||
const addresses = ref([]);
|
const addresses = ref([]);
|
||||||
const zoneSelectRef = ref();
|
const zoneSelectRef = ref();
|
||||||
|
|
||||||
watch(
|
|
||||||
() => formData.value,
|
|
||||||
(val) => emit('updateForm', val),
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => onFormModelInit());
|
onMounted(() => onFormModelInit());
|
||||||
|
|
||||||
const agencyByWarehouseFilter = computed(() => ({
|
const agencyByWarehouseFilter = computed(() => ({
|
||||||
|
|
|
@ -155,18 +155,10 @@ onBeforeMount(async () => await getTicketData());
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
|
<QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
|
||||||
<TicketBasicDataForm
|
<TicketBasicDataForm v-if="initialDataLoaded" v-model="formData" />
|
||||||
v-if="initialDataLoaded"
|
|
||||||
@update-form="($event) => (formData = $event)"
|
|
||||||
v-model="formData"
|
|
||||||
/>
|
|
||||||
</QStep>
|
</QStep>
|
||||||
<QStep :name="2" :title="t('basicData.priceDifference')">
|
<QStep :name="2" :title="t('basicData.priceDifference')">
|
||||||
<TicketBasicData
|
<TicketBasicData v-model="formData" v-model:have-negatives="haveNegatives" />
|
||||||
:form-data="formData"
|
|
||||||
v-model:haveNegatives="haveNegatives"
|
|
||||||
@update-form="($event) => (formData = $event)"
|
|
||||||
/>
|
|
||||||
</QStep>
|
</QStep>
|
||||||
<template #navigation>
|
<template #navigation>
|
||||||
<QStepperNavigation class="flex justify-between">
|
<QStepperNavigation class="flex justify-between">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { date, useQuasar } from 'quasar';
|
import { date, useQuasar } from 'quasar';
|
||||||
|
import { useStateStore } from 'src/stores/useStateStore';
|
||||||
import { computed, onMounted, reactive, ref } from 'vue';
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
@ -8,7 +9,7 @@ import { useRouter } from 'vue-router';
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const stateStore = useStateStore();
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetch();
|
await fetch();
|
||||||
});
|
});
|
||||||
|
@ -84,7 +85,7 @@ async function getVideoList(expeditionId, timed) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QDrawer show-if-above side="right">
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QScrollArea class="fit">
|
<QScrollArea class="fit">
|
||||||
<QList bordered separator style="max-width: 318px">
|
<QList bordered separator style="max-width: 318px">
|
||||||
<QItem v-if="lastExpedition && videoList.length">
|
<QItem v-if="lastExpedition && videoList.length">
|
||||||
|
@ -150,7 +151,7 @@ async function getVideoList(expeditionId, timed) {
|
||||||
</QItem>
|
</QItem>
|
||||||
</QList>
|
</QList>
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</Teleport>
|
||||||
|
|
||||||
<QCard>
|
<QCard>
|
||||||
<QCarousel animated v-model="slide" height="max-content">
|
<QCarousel animated v-model="slide" height="max-content">
|
||||||
|
|
|
@ -178,7 +178,7 @@ onMounted(() => {
|
||||||
@on-fetch="(data) => (components = data)"
|
@on-fetch="(data) => (components = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<QDrawer side="right" :width="265" v-model="stateStore.rightDrawer">
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black">
|
<QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black">
|
||||||
<QCardSection horizontal>
|
<QCardSection horizontal>
|
||||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||||
|
@ -264,7 +264,7 @@ onMounted(() => {
|
||||||
<span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span>
|
<span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
</QCard>
|
</QCard>
|
||||||
</QDrawer>
|
</Teleport>
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="TicketComponents"
|
data-key="TicketComponents"
|
||||||
|
|
|
@ -17,6 +17,7 @@ import axios from 'axios';
|
||||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import VnBtnSelect from 'src/components/common/VnBtnSelect.vue';
|
import VnBtnSelect from 'src/components/common/VnBtnSelect.vue';
|
||||||
import FetchData from 'src/components/FetchData.vue';
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
|
import useOpenURL from 'src/composables/useOpenURL';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
|
@ -123,6 +124,12 @@ const columns = computed(() => [
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
action: (row) => showLog(row),
|
action: (row) => showLog(row),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('Grafana'),
|
||||||
|
icon: 'vn:grafana',
|
||||||
|
isPrimary: true,
|
||||||
|
action: ({ id }) => openGrafana(id),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -192,10 +199,16 @@ const getExpeditionState = async (expedition) => {
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openGrafana = (expeditionFk) => {
|
||||||
|
useOpenURL(
|
||||||
|
`https://grafana.verdnatura.es/d/d552ab74-85b4-4e7f-a279-fab7cd9c6124/control-de-expediciones?orgId=1&var-expeditionFk=${expeditionFk}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
const filteredColumns = columns.value.filter((col) => col.name !== 'history');
|
const filteredColumns = columns.value.filter(({ name }) => name !== 'history');
|
||||||
allColumnNames.value = filteredColumns.map((col) => col.name);
|
allColumnNames.value = filteredColumns.map(({ name }) => name);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -617,7 +617,7 @@ watch(
|
||||||
</QBtnGroup>
|
</QBtnGroup>
|
||||||
</template>
|
</template>
|
||||||
</VnSubToolbar>
|
</VnSubToolbar>
|
||||||
<QDrawer side="right" :width="265" v-model="stateStore.rightDrawer">
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<div
|
<div
|
||||||
class="q-pa-md q-mb-md q-ma-md color-vn-text"
|
class="q-pa-md q-mb-md q-ma-md color-vn-text"
|
||||||
style="border: 2px solid black"
|
style="border: 2px solid black"
|
||||||
|
@ -638,8 +638,8 @@ watch(
|
||||||
<span class="q-mr-xs color-vn-label"> {{ t('basicData.total') }}: </span>
|
<span class="q-mr-xs color-vn-label"> {{ t('basicData.total') }}: </span>
|
||||||
<span>{{ toCurrency(store.data?.totalWithVat) }}</span>
|
<span>{{ toCurrency(store.data?.totalWithVat) }}</span>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
</div></QDrawer
|
</div>
|
||||||
>
|
</Teleport>
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="TicketSales"
|
data-key="TicketSales"
|
||||||
|
|
|
@ -100,11 +100,9 @@ onMounted(() => (stateStore.rightDrawer = true));
|
||||||
@on-fetch="(data) => applyVolumes(data)"
|
@on-fetch="(data) => applyVolumes(data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<QDrawer
|
<Teleport
|
||||||
v-if="packingTypeVolume.length"
|
to="#right-panel"
|
||||||
side="right"
|
v-if="stateStore.isHeaderMounted() && packingTypeVolume.length"
|
||||||
:width="265"
|
|
||||||
v-model="stateStore.rightDrawer"
|
|
||||||
>
|
>
|
||||||
<QCard
|
<QCard
|
||||||
v-for="(packingType, index) in packingTypeVolume"
|
v-for="(packingType, index) in packingTypeVolume"
|
||||||
|
@ -124,8 +122,7 @@ onMounted(() => (stateStore.rightDrawer = true));
|
||||||
<span> {{ t('volume.volume') }}: {{ packingType.volume }} </span>
|
<span> {{ t('volume.volume') }}: {{ packingType.volume }} </span>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
</QCard>
|
</QCard>
|
||||||
</QDrawer>
|
</Teleport>
|
||||||
|
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="TicketVolume"
|
data-key="TicketVolume"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { computed, ref, onMounted } from 'vue';
|
import { computed, ref, onBeforeMount } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
@ -46,7 +46,7 @@ const userParams = {
|
||||||
from: null,
|
from: null,
|
||||||
to: null,
|
to: null,
|
||||||
};
|
};
|
||||||
onMounted(() => {
|
onBeforeMount(() => {
|
||||||
initializeFromQuery();
|
initializeFromQuery();
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
if (!route.query.createForm) return;
|
if (!route.query.createForm) return;
|
||||||
|
|
|
@ -15,9 +15,6 @@ const columns = computed(() => [
|
||||||
name: 'paymentDate',
|
name: 'paymentDate',
|
||||||
label: t('worker.balance.tableVisibleColumns.paymentDate'),
|
label: t('worker.balance.tableVisibleColumns.paymentDate'),
|
||||||
create: true,
|
create: true,
|
||||||
columnCreate: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
component: 'date',
|
component: 'date',
|
||||||
field: 'paymentDate',
|
field: 'paymentDate',
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
|
@ -27,9 +24,6 @@ const columns = computed(() => [
|
||||||
name: 'incomeTypeFk',
|
name: 'incomeTypeFk',
|
||||||
label: t('worker.balance.tableVisibleColumns.incomeType'),
|
label: t('worker.balance.tableVisibleColumns.incomeType'),
|
||||||
create: true,
|
create: true,
|
||||||
columnCreate: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
component: 'select',
|
component: 'select',
|
||||||
attrs: {
|
attrs: {
|
||||||
options: payrollComponents,
|
options: payrollComponents,
|
||||||
|
@ -43,9 +37,6 @@ const columns = computed(() => [
|
||||||
name: 'debit',
|
name: 'debit',
|
||||||
label: t('worker.balance.tableVisibleColumns.debit'),
|
label: t('worker.balance.tableVisibleColumns.debit'),
|
||||||
create: true,
|
create: true,
|
||||||
columnCreate: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
component: 'input',
|
component: 'input',
|
||||||
field: 'debit',
|
field: 'debit',
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
|
@ -55,9 +46,6 @@ const columns = computed(() => [
|
||||||
name: 'credit',
|
name: 'credit',
|
||||||
label: t('worker.balance.tableVisibleColumns.credit'),
|
label: t('worker.balance.tableVisibleColumns.credit'),
|
||||||
create: true,
|
create: true,
|
||||||
columnCreate: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
component: 'input',
|
component: 'input',
|
||||||
field: 'credit',
|
field: 'credit',
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
|
|
|
@ -23,6 +23,7 @@ const insertTag = () => {
|
||||||
workerPitCrudRef.value.insert();
|
workerPitCrudRef.value.insert();
|
||||||
};
|
};
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
|
||||||
const deleteRelative = async (id) => {
|
const deleteRelative = async (id) => {
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
quasar
|
quasar
|
||||||
|
@ -62,7 +63,6 @@ const deleteRelative = async (id) => {
|
||||||
>
|
>
|
||||||
<template #form="{ data }">
|
<template #form="{ data }">
|
||||||
<QCard class="q-px-lg q-py-lg">
|
<QCard class="q-px-lg q-py-lg">
|
||||||
<VnTitle :text="t('IRPF')" />
|
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('familySituation')"
|
:label="t('familySituation')"
|
||||||
|
@ -100,8 +100,12 @@ const deleteRelative = async (id) => {
|
||||||
:label="t(`spousePension`)"
|
:label="t(`spousePension`)"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow wrap>
|
||||||
<QCheckbox v-model="data.isDependend" :label="t(`isDependend`)" />
|
<QCheckbox
|
||||||
|
clearable
|
||||||
|
v-model="data.isDependend"
|
||||||
|
:label="t(`isDependend`)"
|
||||||
|
/>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
v-model="data.hasHousingPaymentBefore"
|
v-model="data.hasHousingPaymentBefore"
|
||||||
:label="t(`hasHousingPaymentBefore`)"
|
:label="t(`hasHousingPaymentBefore`)"
|
||||||
|
@ -127,7 +131,11 @@ const deleteRelative = async (id) => {
|
||||||
:filter="{
|
:filter="{
|
||||||
where: { workerFk: route.params.id },
|
where: { workerFk: route.params.id },
|
||||||
}"
|
}"
|
||||||
:data-required="{ workerFk: route.params.id }"
|
:data-required="{
|
||||||
|
workerFk: route.params.id,
|
||||||
|
isJointCustody: false,
|
||||||
|
isDependend: false,
|
||||||
|
}"
|
||||||
:has-sub-toolbar="false"
|
:has-sub-toolbar="false"
|
||||||
>
|
>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
|
|
|
@ -108,7 +108,20 @@ const agencyOptions = ref([]);
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
<VnRow>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('Distribution point')"
|
||||||
|
v-model="data.addressFk"
|
||||||
|
option-value="id"
|
||||||
|
option-label="nickname"
|
||||||
|
url="Addresses"
|
||||||
|
:fields="['id', 'nickname']"
|
||||||
|
sort-by="id"
|
||||||
|
hide-selected
|
||||||
|
map-options
|
||||||
|
:rules="validate('data.addressFk')"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="data.inflation"
|
v-model="data.inflation"
|
||||||
|
@ -143,4 +156,5 @@ es:
|
||||||
Inflation: Inflación
|
Inflation: Inflación
|
||||||
Volumetric: Volumétrico
|
Volumetric: Volumétrico
|
||||||
Max length m³: Medida máxima tumbado
|
Max length m³: Medida máxima tumbado
|
||||||
|
Distribution point: Punto de distribución
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -16,24 +16,14 @@ const actions = {
|
||||||
clone: async () => {
|
clone: async () => {
|
||||||
const opts = { message: t('Zone cloned'), type: 'positive' };
|
const opts = { message: t('Zone cloned'), type: 'positive' };
|
||||||
|
|
||||||
try {
|
const { data } = await axios.post(`Zones/${zoneId}/clone`, {});
|
||||||
const { data } = await axios.post(`Zones/${zoneId}/clone`, {});
|
notify(opts);
|
||||||
notify(opts);
|
push(`/zone/${data.id}/basic-data`);
|
||||||
push(`/zone/${data.id}/basic-data`);
|
|
||||||
} catch (e) {
|
|
||||||
opts.message = t('It was not able to clone the zone');
|
|
||||||
opts.type = 'negative';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
remove: async () => {
|
remove: async () => {
|
||||||
try {
|
await axios.post(`Zones/${zoneId}/deleteZone`);
|
||||||
await axios.post(`Zones/${zoneId}/deleteZone`);
|
notify({ message: t('Zone deleted'), type: 'positive' });
|
||||||
|
push({ name: 'ZoneList' });
|
||||||
notify({ message: t('Zone deleted'), type: 'positive' });
|
|
||||||
push({ name: 'ZoneList' });
|
|
||||||
} catch (e) {
|
|
||||||
notify({ message: e.message, type: 'negative' });
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
function openConfirmDialog(callback) {
|
function openConfirmDialog(callback) {
|
||||||
|
|
|
@ -43,16 +43,14 @@ const onZoneEventFormClose = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QScrollArea class="fit text-grey-8">
|
<ZoneEventsPanel
|
||||||
<ZoneEventsPanel
|
:first-day="firstDay"
|
||||||
:first-day="firstDay"
|
:last-day="lastDay"
|
||||||
:last-day="lastDay"
|
:events="events"
|
||||||
:events="events"
|
v-model:formModeName="formModeName"
|
||||||
v-model:formModeName="formModeName"
|
/>
|
||||||
/>
|
</Teleport>
|
||||||
</QScrollArea>
|
|
||||||
</QDrawer>
|
|
||||||
<QPage class="q-pa-md flex justify-center">
|
<QPage class="q-pa-md flex justify-center">
|
||||||
<ZoneCalendarGrid
|
<ZoneCalendarGrid
|
||||||
v-model:events="events"
|
v-model:events="events"
|
||||||
|
|
|
@ -11,10 +11,6 @@ import { dashIfEmpty } from 'src/filters';
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
|
|
||||||
const formModeName = defineModel('formModeName', {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
});
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
firstDay: {
|
firstDay: {
|
||||||
type: Date,
|
type: Date,
|
||||||
|
@ -31,8 +27,18 @@ const props = defineProps({
|
||||||
required: true,
|
required: true,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
formModeName: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: 'include',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formName = computed({
|
||||||
|
get: () => props.formModeName,
|
||||||
|
set: (value) => emit('update:formModeName', value),
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['openZoneForm', 'update:formModeName']);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const weekdayStore = useWeekdayStore();
|
const weekdayStore = useWeekdayStore();
|
||||||
|
@ -80,6 +86,15 @@ const deleteEvent = async (id) => {
|
||||||
await fetchData();
|
await fetchData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openInclusionForm = (event) => {
|
||||||
|
formName.value = 'include';
|
||||||
|
emit('openZoneForm', {
|
||||||
|
date: event.dated,
|
||||||
|
event,
|
||||||
|
isNewMode: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
weekdayStore.initStore();
|
weekdayStore.initStore();
|
||||||
});
|
});
|
||||||
|
@ -92,13 +107,13 @@ onMounted(async () => {
|
||||||
t('eventsPanel.editMode')
|
t('eventsPanel.editMode')
|
||||||
}}</span>
|
}}</span>
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="formModeName"
|
v-model="formName"
|
||||||
dense
|
dense
|
||||||
val="include"
|
val="include"
|
||||||
:label="t('eventsPanel.include')"
|
:label="t('eventsPanel.include')"
|
||||||
/>
|
/>
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="formModeName"
|
v-model="formName"
|
||||||
dense
|
dense
|
||||||
val="exclude"
|
val="exclude"
|
||||||
:label="t('eventsPanel.exclude')"
|
:label="t('eventsPanel.exclude')"
|
||||||
|
|
|
@ -20,6 +20,7 @@ export default {
|
||||||
path: '',
|
path: '',
|
||||||
name: 'MonitorMain',
|
name: 'MonitorMain',
|
||||||
component: () => import('src/components/common/VnSectionMain.vue'),
|
component: () => import('src/components/common/VnSectionMain.vue'),
|
||||||
|
props: (route) => ({ leftDrawer: route.name === 'MonitorClientsActions' }),
|
||||||
redirect: { name: 'MonitorTickets' },
|
redirect: { name: 'MonitorTickets' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
|
||||||
|
import { createWrapper } from 'app/test/vitest/helper';
|
||||||
|
import VnDiscount from 'components/common/vnDiscount.vue';
|
||||||
|
|
||||||
|
describe('VnDiscount', () => {
|
||||||
|
let vm;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
vm = createWrapper(VnDiscount, {
|
||||||
|
props: {
|
||||||
|
data: {},
|
||||||
|
price: 100,
|
||||||
|
quantity: 2,
|
||||||
|
discount: 10,
|
||||||
|
}
|
||||||
|
}).vm;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('total', () => {
|
||||||
|
it('should calculate total correctly', () => {
|
||||||
|
expect(vm.total).toBe(180);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue