Item last entries #342

Merged
jsegarra merged 11 commits from :feature/ItemLastEntries into dev 2024-05-02 12:43:05 +00:00
8 changed files with 387 additions and 11 deletions

View File

@ -15,6 +15,10 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
emitDateFormat: {
type: Boolean,
default: false,
},
}); });
const hover = ref(false); const hover = ref(false);
@ -37,7 +41,10 @@ const value = computed({
return props.modelValue; return props.modelValue;
}, },
set(value) { set(value) {
emit('update:modelValue', joinDateAndTime(value, time.value)); emit(
'update:modelValue',
props.emitDateFormat ? new Date(value) : joinDateAndTime(value, time.value)
);
}, },
}); });

View File

@ -1138,6 +1138,7 @@ item:
botanical: Botanical botanical: Botanical
itemTypeCreate: New item type itemTypeCreate: New item type
family: Item Type family: Item Type
lastEntries: Last entries
descriptor: descriptor:
item: Item item: Item
buyer: Buyer buyer: Buyer

View File

@ -1137,6 +1137,7 @@ item:
log: Historial log: Historial
itemTypeCreate: Nueva familia itemTypeCreate: Nueva familia
family: Familia family: Familia
lastEntries: Últimas entradas
descriptor: descriptor:
item: Artículo item: Artículo
buyer: Comprador buyer: Comprador

View File

@ -70,7 +70,7 @@ const columns = computed(() => [
const isNotEuro = (code) => code != 'EUR'; const isNotEuro = (code) => code != 'EUR';
async function insert() { async function insert() {
await axios.post('/InvoiceInDueDays/new ', { id: +invoiceId }); await axios.post('/InvoiceInDueDays/new', { id: +invoiceId });
await invoiceInFormRef.value.reload(); await invoiceInFormRef.value.reload();
} }
</script> </script>

View File

@ -0,0 +1,317 @@
<script setup>
import { onMounted, computed, onUnmounted, reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import { useStateStore } from 'stores/useStateStore';
import { toDateTimeFormat } from 'src/filters/date.js';
import { dashIfEmpty } from 'src/filters';
import { toCurrency } from 'filters/index';
import { useArrayData } from 'composables/useArrayData';
const { t } = useI18n();
const route = useRoute();
const stateStore = useStateStore();
const exprBuilder = (param, value) => {
switch (param) {
case 'id':
case 'quantity':
case 'packagingFk':
return { [`b.${param}`]: value };
case 'supplierFk':
return { [`s.id`]: value };
case 'warehouseFk':
return { 'tr.warehouseInFk': value };
case 'landed':
return {
'tr.landed': {
between: getDateRange(value),
},
};
}
};
const dateRange = reactive({
from: null,
to: null,
});
const getDateRange = (val) => {
const minHour = new Date(val);
minHour.setHours(0, 0, 0, 0);
const maxHour = new Date(val);
maxHour.setHours(23, 59, 59, 59);
return [minHour, maxHour];
};
const from = computed({
get: () => dateRange.from,
set: (val) => {
updateFrom(val);
updateFilter();
},
});
const to = computed({
get: () => dateRange.to,
set: (val) => {
updateTo(val);
updateFilter();
},
});
const arrayData = useArrayData('ItemLastEntries', {
url: 'Items/lastEntriesFilter',
order: ['landed DESC', 'buyFk DESC'],
exprBuilder: exprBuilder,
userFilter: {
where: {
itemFk: route.params.id,
},
},
});
const itemLastEntries = ref([]);
const columns = computed(() => [
{
label: t('lastEntries.ig'),
name: 'ig',
align: 'center',
},
{
label: t('lastEntries.warehouse'),
name: 'warehouse',
field: 'warehouse',
align: 'left',
},
{
label: t('lastEntries.landed'),
name: 'id',
field: 'landed',
align: 'left',
format: (val) => toDateTimeFormat(val),
},
{
label: t('lastEntries.entry'),
name: 'entry',
field: 'stateName',
align: 'left',
format: (val) => dashIfEmpty(val),
},
{
label: t('lastEntries.pvp'),
name: 'pvp',
field: 'reference',
align: 'left',
format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
Review

Fata tooltip

Fata tooltip
},
{
label: t('lastEntries.label'),
name: 'label',
field: 'stickers',
align: 'center',
format: (val) => dashIfEmpty(val),
},
{
label: t('lastEntries.packing'),
name: 'packing',
align: 'center',
},
{
label: t('lastEntries.grouping'),
name: 'grouping',
align: 'center',
},
{
label: t('lastEntries.stems'),
name: 'stems',
field: 'stems',
align: 'center',
},
{
label: t('lastEntries.quantity'),
name: 'stems',
field: 'quantity',
align: 'center',
},
{
label: t('lastEntries.cost'),
name: 'cost',
align: 'left',
},
{
label: t('lastEntries.kg'),
name: 'stems',
field: 'weight',
align: 'center',
},
{
label: t('lastEntries.cube'),
name: 'cube',
field: 'packagingFk',
align: 'center',
},
{
label: t('lastEntries.supplier'),
name: 'stems',
field: 'supplier',
align: 'left',
},
]);
const fetchItemLastEntries = async () => {
const { data } = await arrayData.fetch({ append: false });
itemLastEntries.value = data;
};
const updateFrom = async (date) => {
date.setHours(0, 0, 0, 0);
dateRange.from = date.toISOString();
};
const updateTo = async (date) => {
date.setHours(23, 59, 59, 59);
dateRange.to = date.toISOString();
};
const updateFilter = async () => {
arrayData.store.userFilter.where.landed = {
between: [dateRange.from, dateRange.to],
};
await fetchItemLastEntries();
};
onMounted(async () => {
const _from = Date.vnNew();
_from.setDate(_from.getDate() - 75);
updateFrom(_from);
const _to = Date.vnNew();
_to.setDate(_to.getDate() + 10);
updateTo(_to);
updateFilter();
});
onUnmounted(() => (stateStore.rightDrawer = false));
</script>
<template>
<QToolbar class="justify-end">
<div id="st-data" class="row">
<VnInputDate
:label="t('lastEntries.since')"
dense
emit-date-format
v-model="from"
class="q-mr-lg"
/>
<VnInputDate
:label="t('lastEntries.to')"
dense
emit-date-format
v-model="to"
/>
</div>
<QSpace />
<div id="st-actions"></div>
</QToolbar>
<QPage class="column items-center q-pa-md">
<QTable
:rows="itemLastEntries"
:columns="columns"
class="full-width q-mt-md"
:no-data-label="t('globals.noResults')"
>
<template #body-cell-ig="{ row }">
<QTd @click.stop>
<QCheckbox
v-model="row.isIgnored"
:disable="true"
:false-value="0"
:true-value="1"
/>
</QTd>
</template>
<template #body-cell-entry="{ row }">
<QTd @click.stop>
<div class="full-width flex justify-center">
<EntryDescriptorProxy :id="row.entryFk" class="q-ma-none" dense />
<span class="link">{{ row.entryFk }}</span>
</div>
</QTd>
</template>
<template #body-cell-packing="{ row }">
<QTd @click.stop>
<QBadge
class="center-content"
rounded
:color="row.groupingMode == 'packing' ? 'grey-13' : 'black'"
>
{{ dashIfEmpty(row.packing) }}
<QTooltip>{{ t('lastEntries.packing') }}</QTooltip>
</QBadge>
</QTd>
</template>
<template #body-cell-pvp="{ value }">
<QTd @click.stop
><span> {{ value }}</span>
<QTooltip>
{{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }}
</QTooltip></QTd
>
</template>
<template #body-cell-grouping="{ row }">
<QTd @click.stop>
<QBadge
class="center-content"
rounded
:color="row.groupingMode == 'grouping' ? 'grey-13' : 'black'"
>
{{ dashIfEmpty(row.grouping) }}
<QTooltip>{{ t('lastEntries.grouping') }}</QTooltip>
</QBadge>
</QTd>
</template>
<template #body-cell-cost="{ row }">
<QTd @click.stop>
<span>
{{ toCurrency(row.cost, 'EUR', 3) }}
<QTooltip>
{{ t('lastEntries.cost') }}:
{{ toCurrency(dashIfEmpty(row.buyingValue), 'EUR', 3) }}<br />
{{ t('lastEntries.package') }}:
Review

Revisar estilos

Revisar estilos
{{ toCurrency(dashIfEmpty(row.packageValue), 'EUR', 3)
}}<br />
{{ $t('lastEntries.freight') }}:
{{ toCurrency(dashIfEmpty(row.freightValue), 'EUR', 3)
}}<br />
{{ t('lastEntries.comission') }}:
{{ toCurrency(dashIfEmpty(row.comissionValue), 'EUR', 3) }}
</QTooltip>
</span>
</QTd>
</template>
</QTable>
</QPage>
</template>
<style lang="scss" scoped>
.q-badge--rounded {
border-radius: 50%;
}
.center-content {
display: flex;
max-width: max-content;
margin: auto;
padding: 0 11px;
height: 28px;
}
</style>

View File

@ -14,3 +14,23 @@ itemDiary:
tax: tax:
country: Country country: Country
class: Class class: Class
lastEntries:
since: Since
to: To
ig: Ig
warehouse: Warehouse
landed: Landed
entry: Entry
pvp: PVP
label: Label
packing: Packing
grouping: Grouping
stems: Stems
quantity: Quantity
cost: Cost
kg: Kg.
cube: Cube
supplier: Supplier
package: Package
freight: Freight
comission: Comission

View File

@ -14,3 +14,23 @@ itemDiary:
tax: tax:
country: País country: País
class: Clase class: Clase
lastEntries:
since: Desde
to: Hasta
ig: Ig
warehouse: Almacén
landed: F. Entrega
entry: Entrada
pvp: PVP
label: Etiquetas
packing: Packing
grouping: Grouping
stems: Tallos
quantity: Cantidad
cost: Coste
kg: Kg.
cube: Cubo
supplier: Proveedor
package: Embalaje
freight: Porte
comission: Comisión

View File

@ -26,6 +26,7 @@ export default {
'ItemTax', 'ItemTax',
'ItemBotanical', 'ItemBotanical',
'ItemBarcode', 'ItemBarcode',
'ItemLastEntries',
], ],
}, },
children: [ children: [
@ -135,6 +136,15 @@ export default {
}, },
component: () => import('src/pages/Item/Card/ItemTags.vue'), component: () => import('src/pages/Item/Card/ItemTags.vue'),
}, },
{
path: 'last-entries',
name: 'ItemLastEntries',
meta: {
title: 'lastEntries',
icon: 'vn:regentry',
},
component: () => import('src/pages/Item/Card/ItemLastEntries.vue'),
},
{ {
path: 'tax', path: 'tax',
name: 'ItemTax', name: 'ItemTax',
@ -144,6 +154,15 @@ export default {
}, },
component: () => import('src/pages/Item/Card/ItemTax.vue'), component: () => import('src/pages/Item/Card/ItemTax.vue'),
}, },
{
path: 'botanical',
name: 'ItemBotanical',
meta: {
title: 'botanical',
icon: 'local_florist',
},
component: () => import('src/pages/Item/Card/ItemBotanical.vue'),
},
{ {

El icono no es correcto

El icono no es correcto
path: 'barcode', path: 'barcode',
name: 'ItemBarcode', name: 'ItemBarcode',
@ -171,15 +190,6 @@ export default {
}, },
component: () => import('src/pages/Item/Card/ItemLog.vue'), component: () => import('src/pages/Item/Card/ItemLog.vue'),
}, },
{
path: 'botanical',
name: 'ItemBotanical',
meta: {
title: 'botanical',
icon: 'vn:botanical',
},
component: () => import('src/pages/Item/Card/ItemBotanical.vue'),
},
], ],
}, },
], ],