<script setup> import { ref, computed, onMounted } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import { useI18n } from 'vue-i18n'; import { toDate } from 'src/filters'; import { getUrl } from 'src/composables/getUrl'; import { useQuasar } from 'quasar'; import { usePrintService } from 'composables/usePrintService'; import CardDescriptor from 'components/ui/CardDescriptor.vue'; import VnLv from 'src/components/ui/VnLv.vue'; import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue'; import axios from 'axios'; const quasar = useQuasar(); const { push } = useRouter(); const { openReport } = usePrintService(); const $props = defineProps({ id: { type: Number, required: false, default: null, }, }); const route = useRoute(); const { t } = useI18n(); const entryDescriptorRef = ref(null); const url = ref(); const entryFilter = { include: [ { relation: 'travel', scope: { fields: ['id', 'landed', 'shipped', 'agencyModeFk', 'warehouseOutFk'], include: [ { relation: 'agency', scope: { fields: ['name'], }, }, { relation: 'warehouseOut', scope: { fields: ['name'], }, }, { relation: 'warehouseIn', scope: { fields: ['name'], }, }, ], }, }, { relation: 'supplier', scope: { fields: ['id', 'nickname'], }, }, ], }; const entityId = computed(() => { return $props.id || route.params.id; }); onMounted(async () => { url.value = await getUrl(''); }); const getEntryRedirectionFilter = (entry) => { let entryTravel = entry && entry.travel; if (!entryTravel || !entryTravel.landed) return null; const date = new Date(entryTravel.landed); date.setHours(0, 0, 0, 0); const from = new Date(date.getTime()); from.setDate(from.getDate() - 10); const to = new Date(date.getTime()); to.setDate(to.getDate() + 10); return JSON.stringify({ supplierFk: entry.supplierFk, from, to, }); }; function showEntryReport() { openReport(`Entries/${entityId.value}/entry-order-pdf`); } function showNotification(type, message) { quasar.notify({ type: type, message: t(message), }); } async function recalculateRates(entity) { try { const entryConfig = await axios.get('EntryConfigs/findOne'); if (entryConfig.data?.inventorySupplierFk === entity.supplierFk) { showNotification( 'negative', 'Cannot recalculate prices because this is an inventory entry', ); return; } await axios.post(`Entries/${entityId.value}/recalcEntryPrices`); showNotification('positive', 'Entry prices recalculated'); } catch (error) { showNotification('negative', 'Failed to recalculate rates'); console.error(error); } } async function cloneEntry() { try { const response = await axios.post(`Entries/${entityId.value}/cloneEntry`); push({ path: `/entry/${response.data[0].vNewEntryFk}` }); showNotification('positive', 'Entry cloned'); } catch (error) { showNotification('negative', 'Failed to clone entry'); console.error(error); } } async function deleteEntry() { try { await axios.post(`Entries/${entityId.value}/deleteEntry`); push({ path: `/entry/list` }); showNotification('positive', 'Entry deleted'); } catch (error) { showNotification('negative', 'Failed to delete entry'); console.error(error); } } </script> <template> <CardDescriptor ref="entryDescriptorRef" module="Entry" :url="`Entries/${entityId}`" :userFilter="entryFilter" title="supplier.nickname" data-key="Entry" width="lg-width" > <template #menu="{ entity }"> <QItem v-ripple clickable @click="showEntryReport(entity)" data-cy="show-entry-report" > <QItemSection>{{ t('Show entry report') }}</QItemSection> </QItem> <QItem v-ripple clickable @click="recalculateRates(entity)" data-cy="recalculate-rates" > <QItemSection>{{ t('Recalculate rates') }}</QItemSection> </QItem> <QItem v-ripple clickable @click="cloneEntry(entity)" data-cy="clone-entry"> <QItemSection>{{ t('Clone') }}</QItemSection> </QItem> <QItem v-ripple clickable @click="deleteEntry(entity)" data-cy="delete-entry" v-if="entity?.travelFk" > <QItemSection>{{ t('Delete') }}</QItemSection> </QItem> </template> <template #body="{ entity }"> <VnLv :label="t('Travel')"> <template #value> <span class="link" v-if="entity?.travelFk"> {{ entity.travel?.agency?.name }} {{ entity.travel?.warehouseOut?.code }} → {{ entity.travel?.warehouseIn?.code }} <TravelDescriptorProxy :id="entity?.travelFk" /> </span> </template> </VnLv> <VnLv :label="t('entry.summary.travelShipped')" :value="toDate(entity.travel?.shipped)" /> <VnLv :label="t('entry.summary.travelLanded')" :value="toDate(entity.travel?.landed)" /> <VnLv :label="t('entry.summary.currency')" :value="entity?.currency?.code" /> <VnLv :label="t('entry.summary.invoiceAmount')" :value="entity?.invoiceAmount" /> <VnLv :label="t('entry.summary.entryType')" :value="entity?.entryType?.description" /> </template> <template #icons="{ entity }"> <QCardActions class="q-gutter-x-md"> <QIcon v-if="entity?.isExcludedFromAvailable" name="vn:inventory" color="primary" size="xs" > <QTooltip>{{ t('Inventory entry') }}</QTooltip> </QIcon> <QIcon v-if="entity?.travel?.daysInForward" name="vn:net" color="primary" size="xs" > <QTooltip> {{ t('globals.raid', { daysInForward: entity?.travel?.daysInForward, }) }}</QTooltip > </QIcon> <QIcon v-if="!entity?.travelFk" name="vn:deletedTicket" size="xs" color="primary" > <QTooltip>{{ t('This entry is deleted') }}</QTooltip> </QIcon> </QCardActions> </template> <template #actions="{ entity }"> <QCardActions> <QBtn :to="`/supplier/${entity.supplier?.id}`" size="md" icon="vn:supplier" color="primary" > <QTooltip>{{ t('Supplier card') }}</QTooltip> </QBtn> <QBtn :to="{ name: 'EntryMain', query: { params: getEntryRedirectionFilter(entity), }, }" size="md" icon="vn:entry" color="primary" > <QTooltip>{{ t('All entries with current supplier') }}</QTooltip> </QBtn> </QCardActions> </template> </CardDescriptor> </template> <i18n> es: Travel: Envío Supplier card: Ficha del proveedor All travels with current agency: Todos los envíos con la agencia actual All entries with current supplier: Todas las entradas con el proveedor actual Show entry report: Ver informe del pedido Inventory entry: Es inventario Virtual entry: Es una redada shipped: Enviado landed: Recibido This entry is deleted: Esta entrada está eliminada Cannot recalculate prices because this is an inventory entry: No se pueden recalcular los precios porque es una entrada de inventario Entry deleted: Entrada eliminada Entry cloned: Entrada clonada Entry prices recalculated: Precios de la entrada recalculados Failed to recalculate rates: No se pudieron recalcular las tarifas Failed to clone entry: No se pudo clonar la entrada Failed to delete entry: No se pudo eliminar la entrada </i18n>