Merge branch 'dev' into 7129-finishMigration
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Pablo Natek 2024-07-15 09:25:52 +00:00
commit 35a165b9f3
13 changed files with 661 additions and 319 deletions

View File

@ -46,6 +46,7 @@ globals:
noPinnedModules: You don't have any pinned modules noPinnedModules: You don't have any pinned modules
summary: summary:
basicData: Basic data basicData: Basic data
daysOnward: Days onward
today: Today today: Today
yesterday: Yesterday yesterday: Yesterday
dateFormat: en-GB dateFormat: en-GB
@ -232,6 +233,7 @@ globals:
formation: Formation formation: Formation
locations: Locations locations: Locations
warehouses: Warehouses warehouses: Warehouses
saleTracking: Sale tracking
roles: Roles roles: Roles
connections: Connections connections: Connections
acls: ACLs acls: ACLs
@ -553,6 +555,7 @@ ticket:
expedition: Expedition expedition: Expedition
purchaseRequest: Purchase request purchaseRequest: Purchase request
weeklyTickets: Weekly tickets weeklyTickets: Weekly tickets
saleTracking: Sale tracking
services: Service services: Service
tracking: Tracking tracking: Tracking
components: Components components: Components

View File

@ -45,6 +45,7 @@ globals:
noPinnedModules: No has fijado ningún módulo noPinnedModules: No has fijado ningún módulo
summary: summary:
basicData: Datos básicos basicData: Datos básicos
daysOnward: Días adelante
today: Hoy today: Hoy
yesterday: Ayer yesterday: Ayer
dateFormat: es-ES dateFormat: es-ES
@ -241,6 +242,7 @@ globals:
privileges: Privilegios privileges: Privilegios
observation: Notas observation: Notas
expedition: Expedición expedition: Expedición
saleTracking: Líneas preparadas
services: Servicios services: Servicios
tracking: Estados tracking: Estados
components: Componentes components: Componentes
@ -558,6 +560,7 @@ ticket:
expedition: Expedición expedition: Expedición
purchaseRequest: Petición de compra purchaseRequest: Petición de compra
weeklyTickets: Tickets programados weeklyTickets: Tickets programados
saleTracking: Líneas preparadas
services: Servicios services: Servicios
tracking: Estados tracking: Estados
components: Componentes components: Componentes

View File

@ -7,6 +7,7 @@ import { toDate } from 'src/filters/index';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import EntryBuysTableDialog from './EntryBuysTableDialog.vue'; import EntryBuysTableDialog from './EntryBuysTableDialog.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import VnInput from 'src/components/common/VnInput.vue';
const stateStore = useStateStore(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
@ -34,6 +35,10 @@ const columns = computed(() => [
isTitle: false, isTitle: false,
create: true, create: true,
cardVisible: true, cardVisible: true,
component: 'date',
columnField: {
component: null,
},
format: ({ shipped }) => toDate(shipped), format: ({ shipped }) => toDate(shipped),
}, },
{ {
@ -43,6 +48,10 @@ const columns = computed(() => [
isTitle: false, isTitle: false,
create: true, create: true,
cardVisible: false, cardVisible: false,
component: 'date',
columnField: {
component: null,
},
format: ({ landed }) => toDate(landed), format: ({ landed }) => toDate(landed),
}, },
{ {
@ -93,14 +102,23 @@ const printBuys = (rowId) => {
:columns="columns" :columns="columns"
default-mode="card" default-mode="card"
auto-load auto-load
:right-search="true"
> >
<template #moreFilterPanel="{ params }">
<VnInput
:label="t('globals.daysOnward')"
v-model="params.days"
class="q-px-xs row"
dense
filled
outlined
></VnInput>
</template>
</VnTable> </VnTable>
</div> </div>
</QPage> </QPage>
</template> </template>
<i18n> <i18n>
es:
Search entries: Buscar entradas
You can search by entry reference: Puedes buscar por referencia de la entrada You can search by entry reference: Puedes buscar por referencia de la entrada
</i18n> </i18n>

View File

@ -209,7 +209,7 @@ const decrement = (paramsObj, key) => {
<QItemSection> <QItemSection>
<VnInput <VnInput
v-model="params.scopeDays" v-model="params.scopeDays"
:label="t('params.scopeDays')" :label="t('globals.daysOnward')"
type="number" type="number"
dense dense
outlined outlined
@ -281,7 +281,6 @@ en:
requesterFk: Salesperson requesterFk: Salesperson
from: From from: From
to: To to: To
scopeDays: Days onward
mine: For me mine: For me
state: State state: State
dateFiltersTooltip: Cannot choose a range of dates and days onward at the same time dateFiltersTooltip: Cannot choose a range of dates and days onward at the same time
@ -299,7 +298,6 @@ es:
requesterFk: Comercial requesterFk: Comercial
from: Desde from: Desde
to: Hasta to: Hasta
scopeDays: Días adelante
mine: Para mi mine: Para mi
state: Estado state: Estado
dateFiltersTooltip: No se puede seleccionar un rango de fechas y días en adelante a la vez dateFiltersTooltip: No se puede seleccionar un rango de fechas y días en adelante a la vez

View File

@ -71,39 +71,39 @@ const salesFilter = computed(() => ({
const columns = computed(() => [ const columns = computed(() => [
{ {
label: t('components.item'), label: t('ticketComponents.item'),
name: 'item', name: 'item',
align: 'left', align: 'left',
}, },
{ {
label: t('components.description'), label: t('ticketComponents.description'),
name: 'description', name: 'description',
align: 'left', align: 'left',
}, },
{ {
label: t('components.quantity'), label: t('ticketComponents.quantity'),
name: 'quantity', name: 'quantity',
field: 'quantity', field: 'quantity',
align: 'left', align: 'left',
format: (val) => dashIfEmpty(val), format: (val) => dashIfEmpty(val),
}, },
{ {
label: t('components.serie'), label: t('ticketComponents.serie'),
name: 'serie', name: 'serie',
align: 'left', align: 'left',
}, },
{ {
label: t('components.components'), label: t('ticketComponents.components'),
name: 'components', name: 'components',
align: 'left', align: 'left',
}, },
{ {
label: t('components.import'), label: t('ticketComponents.import'),
name: 'import', name: 'import',
align: 'left', align: 'left',
}, },
{ {
label: t('components.total'), label: t('ticketComponents.total'),
name: 'total', name: 'total',
align: 'left', align: 'left',
}, },
@ -111,7 +111,7 @@ const columns = computed(() => [
const getBase = computed(() => { const getBase = computed(() => {
let sum = 0; let sum = 0;
for (let sale of components.value) { for (let sale of ticketComponents.value) {
for (let saleComponent of sale.components) { for (let saleComponent of sale.components) {
if (saleComponent.component.componentType.isBase) { if (saleComponent.component.componentType.isBase) {
sum += sale.quantity * saleComponent.value; sum += sale.quantity * saleComponent.value;
@ -123,7 +123,7 @@ const getBase = computed(() => {
const getTotal = computed(() => { const getTotal = computed(() => {
let total = 0; let total = 0;
for (let sale of components.value) { for (let sale of ticketComponents.value) {
for (let saleComponent of sale.components) { for (let saleComponent of sale.components) {
total += sale.quantity * saleComponent.value; total += sale.quantity * saleComponent.value;
} }
@ -184,18 +184,18 @@ onUnmounted(() => (stateStore.rightDrawer = false));
> >
<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">
{{ t('components.total') }} {{ t('ticketComponents.total') }}
</span> </span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label" <span class="q-mr-xs color-vn-label"
>{{ t('components.baseToCommission') }}: >{{ t('ticketComponents.baseToCommission') }}:
</span> </span>
<span>{{ toCurrency(getBase) }}</span> <span>{{ toCurrency(getBase) }}</span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label" <span class="q-mr-xs color-vn-label"
>{{ t('components.totalWithoutVat') }}: >{{ t('ticketComponents.totalWithoutVat') }}:
</span> </span>
<span>{{ toCurrency(getTotal) }}</span> <span>{{ toCurrency(getTotal) }}</span>
</QCardSection> </QCardSection>
@ -208,7 +208,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
> >
<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">
{{ t('components.components') }} {{ t('ticketComponents.components') }}
</span> </span>
</QCardSection> </QCardSection>
<QCardSection <QCardSection
@ -232,24 +232,24 @@ onUnmounted(() => (stateStore.rightDrawer = false));
> >
<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">
{{ t('components.zoneBreakdown') }} {{ t('ticketComponents.zoneBreakdown') }}
</span> </span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label"> <span class="q-mr-xs color-vn-label">
{{ t('components.price') }}: {{ t('ticketComponents.price') }}:
</span> </span>
<span>{{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}</span> <span>{{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}</span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label"> <span class="q-mr-xs color-vn-label">
{{ t('components.bonus') }}: {{ t('ticketComponents.bonus') }}:
</span> </span>
<span>{{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}</span> <span>{{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}</span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label"> <span class="q-mr-xs color-vn-label">
{{ t('components.zone') }}: {{ t('ticketComponents.zone') }}:
</span> </span>
<span class="link"> <span class="link">
{{ dashIfEmpty(ticketData?.zone?.name) }} {{ dashIfEmpty(ticketData?.zone?.name) }}
@ -258,13 +258,13 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QCardSection> </QCardSection>
<QCardSection v-if="ticketData?.zone?.isVolumetric" horizontal> <QCardSection v-if="ticketData?.zone?.isVolumetric" horizontal>
<span class="q-mr-xs color-vn-label"> <span class="q-mr-xs color-vn-label">
{{ t('components.volume') }}: {{ t('ticketComponents.volume') }}:
</span> </span>
<span>{{ ticketVolume }}</span> <span>{{ ticketVolume }}</span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label"> <span class="q-mr-xs color-vn-label">
{{ t('components.packages') }}: {{ t('ticketComponents.packages') }}:
</span> </span>
<span>{{ dashIfEmpty(ticketData?.packages) }}</span> <span>{{ dashIfEmpty(ticketData?.packages) }}</span>
</QCardSection> </QCardSection>
@ -277,12 +277,12 @@ onUnmounted(() => (stateStore.rightDrawer = false));
> >
<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">
{{ t('components.theoricalCost') }} {{ t('ticketComponents.theoricalCost') }}
</span> </span>
</QCardSection> </QCardSection>
<QCardSection horizontal> <QCardSection horizontal>
<span class="q-mr-xs color-vn-label"> <span class="q-mr-xs color-vn-label">
{{ t('components.totalPrice') }}: {{ t('ticketComponents.totalPrice') }}:
</span> </span>
<span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span> <span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span>
</QCardSection> </QCardSection>

View File

@ -0,0 +1,549 @@
<script setup>
import { ref, computed, nextTick, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import FetchData from 'components/FetchData.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import { dashIfEmpty } from 'src/filters';
import useNotify from 'src/composables/useNotify.js';
import { toDateTimeFormat } from 'src/filters/date';
import axios from 'axios';
const route = useRoute();
const { t } = useI18n();
const { notify } = useNotify();
const saleTrackingTableDialogRef = ref(null);
const itemShelvingSaleDialogRef = ref(null);
const saleTrackingFetchDataRef = ref(null);
const sales = ref([]);
const saleTrackings = ref([]);
const itemShelvignsSales = ref([]);
const shelvingsOptions = ref([]);
const parkingsOptions = ref([]);
const saleTrackingUrl = computed(() => `SaleTrackings/${route.params.id}/filter`);
const oldQuantity = ref(null);
watch(
() => route.params.id,
async () => nextTick(async () => await saleTrackingFetchDataRef.value.fetch())
);
const columns = computed(() => [
{
label: t('ticketSaleTracking.isChecked'),
name: 'isChecked',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.item'),
name: 'item',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.description'),
name: 'description',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.quantity'),
name: 'quantity',
field: 'quantity',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.parking'),
name: 'parking',
field: 'parkingCode',
align: 'left',
sortable: true,
format: (value) => dashIfEmpty(value),
},
{
label: '',
name: 'actions',
align: 'left',
sortable: true,
},
]);
const logTableColumns = computed(() => [
{
label: t('ticketSaleTracking.quantity'),
name: 'quantity',
field: 'quantity',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.original'),
name: 'original',
field: 'originalQuantity',
align: 'original',
sortable: true,
},
{
label: t('ticketSaleTracking.worker'),
name: 'worker',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.state'),
name: 'state',
field: 'state',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.created'),
name: 'created',
field: 'created',
align: 'left',
sortable: true,
format: (value) => toDateTimeFormat(value),
},
]);
const shelvingsTableColumns = computed(() => [
{
label: t('ticketSaleTracking.quantity'),
name: 'quantity',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.worker'),
name: 'worker',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.shelving'),
name: 'shelving',
align: 'original',
sortable: true,
},
{
label: t('ticketSaleTracking.parking'),
name: 'parking',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.created'),
name: 'created',
field: 'created',
align: 'left',
sortable: true,
format: (value) => toDateTimeFormat(value),
},
]);
const getSaleTrackings = async (sale) => {
try {
const filter = {
where: { saleFk: sale.saleFk },
order: ['itemFk DESC'],
};
const { data } = await axios.get(`SaleTrackings/listSaleTracking`, {
params: { filter: JSON.stringify(filter) },
});
saleTrackings.value = data;
} catch (error) {
console.error(error);
}
};
const showLog = async (sale) => {
await getSaleTrackings(sale);
saleTrackingTableDialogRef.value.show();
};
const getItemShelvingSales = async (sale) => {
try {
const filter = {
where: { saleFk: sale.saleFk },
};
const { data } = await axios.get(`ItemShelvingSales/filter`, {
params: { filter: JSON.stringify(filter) },
});
itemShelvignsSales.value = data;
} catch (error) {
console.error(error);
}
};
const showShelving = async (sale) => {
await getItemShelvingSales(sale);
itemShelvingSaleDialogRef.value.show();
};
const updateQuantity = async (sale) => {
try {
if (oldQuantity.value === sale.quantity) return;
const params = {
quantity: sale.quantity,
};
await axios.patch(`ItemShelvingSales/${sale.id}`, params);
oldQuantity.value = null;
} catch (error) {
console.error(error);
}
};
const updateParking = async (sale) => {
try {
const filter = {
fields: ['id'],
where: {
code: sale.shelvingFk,
},
};
const { data } = await axios.get(`Shelvings/findOne`, {
params: { filter: JSON.stringify(filter) },
});
const params = {
parkingFk: sale.parkingFk,
};
await axios.patch(`Shelvings/${data.id}`, params);
} catch (error) {
console.error(error);
}
};
const updateShelving = async (sale) => {
const params = {
shelvingFk: sale.shelvingFk,
};
const { data: patchResponseData } = await axios.patch(
`ItemShelvings/${sale.itemShelvingFk}`,
params
);
const filter = {
fields: ['parkingFk'],
where: {
code: patchResponseData.shelvingFk,
},
};
const { data: getResponseData } = await axios.get(`Shelvings/findOne`, { filter });
sale.parkingFk = getResponseData.parkingFk;
};
const saleTrackingNew = async (sale, stateCode, isChecked) => {
try {
const params = {
saleFk: sale.saleFk,
isChecked,
quantity: sale.quantity,
stateCode,
};
await axios.post(`SaleTrackings/new`, params);
notify(t('globals.dataSaved'), 'positive');
} catch (error) {
console.error(error);
}
};
const saleTrackingDel = async ({ saleFk }, stateCode) => {
try {
const params = {
saleFk,
stateCodes: [stateCode],
};
await axios.post(`SaleTrackings/delete`, params);
notify(t('globals.dataSaved'), 'positive');
} catch (error) {
console.error(error);
}
};
const clickSaleGroupDetail = async (sale) => {
try {
if (!sale.saleGroupDetailFk) return;
await axios.delete(`SaleGroupDetails/${sale.saleGroupDetailFk}`);
sale.hasSaleGroupDetail = false;
notify(t('globals.dataSaved'), 'positive');
} catch (error) {
console.error(error);
}
};
const clickPreviousSelected = (sale) => {
try {
qCheckBoxController(sale, 'isPreviousSelected');
if (!sale.isPreviousSelected) sale.isPrevious = false;
} catch (error) {
console.error(error);
}
};
const clickPrevious = (sale) => {
try {
qCheckBoxController(sale, 'isPrevious');
if (sale.isPrevious) sale.isPreviousSelected = true;
} catch (error) {
console.error(error);
}
};
const qCheckBoxController = (sale, action) => {
const STATE_CODES = {
isControled: 'CHECKED',
isPrepared: 'PREPARED',
isPrevious: 'PREVIOUS_PREPARATION',
isPreviousSelected: 'PREVIOUS_PREPARATION',
};
const stateCode = STATE_CODES[action];
try {
if (!sale[action]) {
saleTrackingNew(sale, stateCode, true);
sale[action] = true;
} else {
saleTrackingDel(sale, stateCode);
sale[action] = false;
}
} catch (error) {
console.error(error);
}
};
</script>
<template>
<FetchData
ref="saleTrackingFetchDataRef"
:url="saleTrackingUrl"
:filter="{ order: ['concept ASC', 'quantity DESC'] }"
auto-load
@on-fetch="(data) => (sales = data)"
/>
<FetchData
url="Shelvings"
auto-load
@on-fetch="(data) => (shelvingsOptions = data)"
/>
<FetchData url="Parkings" auto-load @on-fetch="(data) => (parkingsOptions = data)" />
<QTable
:rows="sales"
:columns="columns"
row-key="id"
:pagination="{ rowsPerPage: 0 }"
class="full-width q-mt-md"
:no-data-label="t('globals.noResults')"
>
<template #body-cell-isChecked="{ row }">
<QTd @click.stop>
<QCheckbox
:model-value="!!row.hasSaleGroupDetail"
color="pink"
class="pink"
:toggle-indeterminate="false"
@update:model-value="clickSaleGroupDetail(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.saleGroupDetail') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isPreviousSelected"
color="info"
class="info"
:toggle-indeterminate="false"
@update:model-value="clickPreviousSelected(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.previousSelected') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isPrevious"
color="cyan"
class="cyan"
:toggle-indeterminate="false"
@update:model-value="clickPrevious(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.previous') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isPrepared"
color="warning"
class="warning"
:toggle-indeterminate="false"
@update:model-value="qCheckBoxController(row, 'isPrepared')"
>
<QTooltip>
{{ t('ticketSaleTracking.prepared') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isControled"
color="yellow"
class="yellow"
:toggle-indeterminate="false"
@update:model-value="qCheckBoxController(row, 'isControled')"
>
<QTooltip>
{{ t('ticketSaleTracking.checked') }}
</QTooltip>
</QCheckbox>
</QTd>
</template>
<template #body-cell-item="{ row }">
<QTd @click.stop>
<div>
<QBtn flat color="primary">
{{ row.itemFk }}
</QBtn>
<ItemDescriptorProxy :id="row.itemFk" />
</div>
</QTd>
</template>
<template #body-cell-description="{ row }">
<QTd class="col">
<div class="column">
<span>{{ row.concept }}</span>
<span v-if="row.subName" class="color-vn-label">
{{ row.subName }}
</span>
<FetchedTags :item="row" :max-length="6" tag="value" />
</div>
</QTd>
</template>
<template #body-cell-actions="{ row }">
<QTd>
<QBtn
@click.stop="showLog(row)"
color="primary"
icon="history"
size="md"
flat
>
<QTooltip class="text-no-wrap">
{{ t('ticketSaleTracking.historyAction') }}
</QTooltip>
</QBtn>
<QBtn
@click.stop="showShelving(row)"
color="primary"
icon="vn:inventory"
size="md"
flat
>
<QTooltip class="text-no-wrap">
{{ t('ticketSaleTracking.shelvingAction') }}
</QTooltip>
</QBtn>
</QTd>
</template>
</QTable>
<QDialog
ref="saleTrackingTableDialogRef"
transition-show="scale"
transition-hide="scale"
>
<QTable
data-key="saleTrackingLog"
:rows="saleTrackings"
:columns="logTableColumns"
class="q-pa-sm"
>
<template #body-cell-worker="{ row }">
<QTd auto-width>
<QBtn flat dense color="primary">{{ row.name }}</QBtn>
<WorkerDescriptorProxy :id="row.workerFk" />
</QTd>
</template>
</QTable>
</QDialog>
<QDialog
ref="itemShelvingSaleDialogRef"
transition-show="scale"
transition-hide="scale"
>
<QTable
data-key="itemShelvingsSales"
:rows="itemShelvignsSales"
:columns="shelvingsTableColumns"
class="q-pa-sm"
>
<template #body-cell-quantity="{ row }">
<QTd auto-width>
<VnInput
v-model.number="row.quantity"
@keyup.enter="updateQuantity(row)"
@blur="updateQuantity(row)"
@focus="oldQuantity = row.quantity"
/>
</QTd>
</template>
<template #body-cell-worker="{ row }">
<QTd auto-width>
<QBtn flat dense color="primary">{{ row.name }}</QBtn>
<WorkerDescriptorProxy :id="row.userFk" />
</QTd>
</template>
<template #body-cell-shelving="{ row }">
<QTd auto-width>
<VnSelect
:options="shelvingsOptions"
hide-selected
option-label="code"
option-value="code"
v-model="row.shelvingFk"
@update:model-value="updateShelving(row)"
style="max-width: 120px"
/>
</QTd>
</template>
<template #body-cell-parking="{ row }">
<QTd auto-width>
<VnSelect
:options="parkingsOptions"
hide-selected
option-label="code"
option-value="id"
v-model="row.parkingFk"
@update:model-value="updateParking(row)"
style="max-width: 120px"
/>
</QTd>
</template>
</QTable>
</QDialog>
</template>
<style lang="scss">
$estados: (
'info': var(--q-info),
'warning': var(--q-warning),
'cyan': #00bcd4,
'pink': pink,
'yellow': #ffeb3b,
);
@each $estado, $color in $estados {
.q-checkbox.#{$estado} {
> .q-checkbox__inner > .q-checkbox__bg.absolute {
border-radius: 50% !important;
& .q-checkbox__svg > .q-checkbox__truthy {
stroke: $color;
}
}
}
}
</style>

View File

@ -12,6 +12,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
import CardList from 'src/components/ui/CardList.vue'; import CardList from 'src/components/ui/CardList.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import { toDate, toCurrency } from 'src/filters';
const router = useRouter(); const router = useRouter();
const { t } = useI18n(); const { t } = useI18n();

View File

@ -168,6 +168,24 @@ weeklyTickets:
salesperson: Salesperson salesperson: Salesperson
search: Search weekly tickets search: Search weekly tickets
searchInfo: Search weekly tickets by id or client id searchInfo: Search weekly tickets by id or client id
ticketSaleTracking:
isChecked: Is checked
item: Item
description: Description
quantity: Quantity
parking: Parking
historyAction: Log states
shelvingAction: Shelvings sale
original: Original
worker: Worker
state: State
created: Created
shelving: Shelving
saleGroupDetail: sale group detail
previousSelected: previous selected
previous: previous
prepared: prepared
checked: checked
service: service:
pay: Pay pay: Pay
description: Description description: Description
@ -178,7 +196,7 @@ service:
addService: Add service addService: Add service
quantityInfo: To create services with negative amounts mark the service on the source ticket and press the pay button. quantityInfo: To create services with negative amounts mark the service on the source ticket and press the pay button.
createRefundSuccess: 'The following refund ticket have been created: { ticketId }' createRefundSuccess: 'The following refund ticket have been created: { ticketId }'
components: ticketComponents:
item: Item item: Item
description: Description description: Description
quantity: Quantity quantity: Quantity

View File

@ -164,7 +164,7 @@ ticketSale:
shipped: F. Envío shipped: F. Envío
agency: Agencia agency: Agencia
address: Consignatario address: Consignatario
components: ticketComponents:
item: Artículo item: Artículo
description: Descripción description: Descripción
quantity: Cantidad quantity: Cantidad
@ -207,6 +207,24 @@ package:
added: Añadido added: Añadido
addPackage: Añadir embalaje addPackage: Añadir embalaje
removePackage: Quitar embalaje removePackage: Quitar embalaje
ticketSaleTracking:
isChecked: Comprobado
item: Artículo
description: Descripción
quantity: Cantidad
parking: Parking
historyAction: Historial estados
shelvingAction: Carros línea
original: Original
worker: Trabajador
state: Estado
created: Fecha creación
shelving: Matrícula
saleGroupDetail: detalle grupo líneas
previousSelected: previa seleccionado
previous: previa
prepared: preparado
checked: revisado
Search ticket: Buscar tickets Search ticket: Buscar tickets
You can search by ticket id or alias: Puedes buscar por id o alias del ticket You can search by ticket id or alias: Puedes buscar por id o alias del ticket
Select lines to see the options: Selecciona líneas para ver las opciones Select lines to see the options: Selecciona líneas para ver las opciones

View File

@ -1,225 +0,0 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
const { t } = useI18n();
const props = defineProps({
dataKey: {
type: String,
required: true,
},
});
const warehousesOptions = ref([]);
const continentsOptions = ref([]);
const agenciesOptions = ref([]);
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]--;
};
</script>
<template>
<FetchData
url="Warehouses"
@on-fetch="(data) => (warehousesOptions = data)"
auto-load
/>
<FetchData
url="Continents"
@on-fetch="(data) => (continentsOptions = data)"
auto-load
/>
<FetchData
url="AgencyModes"
@on-fetch="(data) => (agenciesOptions = data)"
auto-load
/>
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
<template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span>
</div>
</template>
<template #body="{ params, searchFn }">
<QItem>
<QItemSection>
<VnSelect
:label="t('travelFilter.filter.agencyModeFk')"
v-model="params.agencyModeFk"
@update:model-value="searchFn()"
:options="agenciesOptions"
option-value="agencyFk"
option-label="name"
hide-selected
dense
outlined
rounded
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
:label="t('travelFilter.filter.warehouseOutFk')"
v-model="params.warehouseOutFk"
@update:model-value="searchFn()"
:options="warehousesOptions"
option-value="id"
option-label="name"
hide-selected
dense
outlined
rounded
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
:label="t('travelFilter.filter.warehouseInFk')"
v-model="params.warehouseInFk"
@update:model-value="searchFn()"
:options="warehousesOptions"
option-value="id"
option-label="name"
hide-selected
dense
outlined
rounded
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QInput
v-model="params.scopeDays"
type="number"
:label="t('travelFilter.filter.scopeDays')"
dense
outlined
rounded
class="input-number"
>
<template #append>
<QBtn
icon="add"
flat
dense
size="12px"
@click="add(params, 'scopeDays')"
/>
<QBtn
icon="remove"
flat
dense
size="12px"
@click="decrement(params, 'scopeDays')"
/>
</template>
</QInput>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
v-model="params.landedFrom"
:label="t('params.landedFrom')"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
:label="t('params.landedTo')"
v-model="params.landedTo"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
:label="t('params.continent')"
v-model="params.continent"
@update:model-value="searchFn()"
:options="continentsOptions"
option-value="code"
option-label="name"
hide-selected
dense
outlined
rounded
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QInput
v-model="params.totalEntries"
type="number"
:label="t('params.totalEntries')"
dense
outlined
rounded
min="0"
class="input-number"
>
<template #append>
<QBtn
icon="add"
flat
dense
size="12px"
@click="add(params, 'totalEntries')"
/>
<QBtn
icon="remove"
flat
dense
size="12px"
@click="decrement(params, 'totalEntries')"
/>
</template>
</QInput>
</QItemSection>
</QItem>
</template>
</VnFilterPanel>
</template>
<i18n>
en:
params:
search: Id/Reference
landedFrom: Landed from
landedTo: Landed to
continent: Continent out
totalEntries: Total entries
es:
params:
search: Id/Referencia
landedFrom: Llegada desde
landedTo: Llegada hasta
continent: Cont. Salida
totalEntries: Ent. totales
</i18n>

View File

@ -1,6 +0,0 @@
travelFilter:
filter:
warehouseOutFk: Warehouse Out
warehouseInFk: Warehouse In
agencyModeFk: Agency
scopeDays: Days onward

View File

@ -1,6 +0,0 @@
travelFilter:
filter:
warehouseInFk: Alm. entrada
warehouseOutFk: Alm. salida
agencyModeFk: Agencia
scopeDays: Días adelante

View File

@ -14,19 +14,17 @@ export default {
main: ['TicketList', 'TicketAdvance', 'TicketWeekly', 'TicketFuture'], main: ['TicketList', 'TicketAdvance', 'TicketWeekly', 'TicketFuture'],
card: [ card: [
'TicketBasicData', 'TicketBasicData',
'TicketPurchaseRequest',
'TicketSale', 'TicketSale',
'TicketLog', 'TicketLog',
'TicketExpedition', 'TicketExpedition',
'TicketService', 'TicketPurchaseRequest',
'TicketVolume',
'TicketNotes',
'TicketTracking', 'TicketTracking',
'TicketNotes',
'TicketVolume',
'TicketService',
'TicketSaleTracking',
'TicketBoxing', 'TicketBoxing',
'TicketSms', 'TicketSms',
'TicketPicture',
'TicketComponents',
'TicketPackage',
], ],
}, },
children: [ children: [
@ -147,41 +145,13 @@ export default {
component: () => import('src/pages/Ticket/Card/TicketLog.vue'), component: () => import('src/pages/Ticket/Card/TicketLog.vue'),
}, },
{ {
path: 'observation', path: 'boxing',
name: 'TicketNotes', name: 'TicketBoxing',
meta: { meta: {
title: 'notes', title: 'boxing',
icon: 'vn:notes',
},
component: () => import('src/pages/Ticket/Card/TicketNotes.vue'),
},
{
path: 'picture',
name: 'TicketPicture',
meta: {
title: 'pictures',
icon: 'vn:photo',
},
component: () => import('src/pages/Ticket/Card/TicketPicture.vue'),
},
{
path: 'volume',
name: 'TicketVolume',
meta: {
title: 'volume',
icon: 'vn:volume',
},
component: () => import('src/pages/Ticket/Card/TicketVolume.vue'),
},
{
path: 'expedition',
name: 'TicketExpedition',
meta: {
title: 'expedition',
icon: 'vn:package', icon: 'vn:package',
}, },
component: () => import('src/pages/Ticket/Card/TicketExpedition.vue'), component: () => import('src/pages/Ticket/Card/TicketBoxing.vue'),
}, },
{ {
path: 'service', path: 'service',
@ -193,31 +163,32 @@ export default {
component: () => import('src/pages/Ticket/Card/TicketService.vue'), component: () => import('src/pages/Ticket/Card/TicketService.vue'),
}, },
{ {
path: 'package', path: 'volume',
name: 'TicketPackage', name: 'TicketVolume',
meta: { meta: {
title: 'packages', title: 'volume',
icon: 'vn:bucket', icon: 'vn:volume',
}, },
component: () => import('src/pages/Ticket/Card/TicketPackage.vue'), component: () => import('src/pages/Ticket/Card/TicketVolume.vue'),
}, },
{ {
path: 'components', path: 'observation',
name: 'TicketComponents', name: 'TicketNotes',
meta: { meta: {
title: 'components', title: 'notes',
icon: 'vn:components', icon: 'vn:notes',
}, },
component: () => import('src/pages/Ticket/Card/TicketComponents.vue'), component: () => import('src/pages/Ticket/Card/TicketNotes.vue'),
}, },
{ {
path: 'boxing', path: 'sale-tracking',
name: 'TicketBoxing', name: 'TicketSaleTracking',
meta: { meta: {
title: 'boxing', title: 'saleTracking',
icon: 'science', icon: 'vn:buyrequest',
}, },
component: () => import('src/pages/Ticket/Card/TicketBoxing.vue'), component: () =>
import('src/pages/Ticket/Card/TicketSaleTracking.vue'),
}, },
{ {
path: 'sms', path: 'sms',