Reviewed-on: #806 Reviewed-by: Javi Gallego <jgallego@verdnatura.es> Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
commit
665e84d338
|
@ -0,0 +1,33 @@
|
|||
<script setup>
|
||||
import { useRoute } from 'vue-router';
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
routeName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
entityId: {
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const id = props.entityId;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-link
|
||||
v-if="route?.name !== routeName"
|
||||
:to="{ name: routeName, params: { id: id } }"
|
||||
class="header link"
|
||||
:href="url"
|
||||
>
|
||||
<QIcon name="open_in_new" color="white" size="sm" />
|
||||
</router-link>
|
||||
</template>
|
|
@ -0,0 +1,55 @@
|
|||
<script setup>
|
||||
import { defineProps, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps({
|
||||
usesMana: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
manaCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
manaVal: {
|
||||
type: String,
|
||||
default: 'mana',
|
||||
},
|
||||
manaLabel: {
|
||||
type: String,
|
||||
default: 'Promotion mana',
|
||||
},
|
||||
manaClaimVal: {
|
||||
type: String,
|
||||
default: 'manaClaim',
|
||||
},
|
||||
claimLabel: {
|
||||
type: String,
|
||||
default: 'Claim mana',
|
||||
},
|
||||
});
|
||||
|
||||
const manaCode = ref(props.manaCode);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="column q-gutter-y-sm q-mt-sm">
|
||||
<QRadio
|
||||
v-model="manaCode"
|
||||
dense
|
||||
:val="manaVal"
|
||||
:label="t(manaLabel)"
|
||||
:dark="true"
|
||||
class="q-mb-sm"
|
||||
/>
|
||||
<QRadio
|
||||
v-model="manaCode"
|
||||
dense
|
||||
:val="manaClaimVal"
|
||||
:label="t(claimLabel)"
|
||||
:dark="true"
|
||||
class="q-mb-sm"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
|
@ -11,6 +11,7 @@ import { toDate, toCurrency } from 'src/filters';
|
|||
import { getUrl } from 'src/composables/getUrl';
|
||||
import axios from 'axios';
|
||||
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
||||
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
@ -163,14 +164,12 @@ const fetchEntryBuys = async () => {
|
|||
data-key="EntrySummary"
|
||||
>
|
||||
<template #header-left>
|
||||
<router-link
|
||||
<VnToSummary
|
||||
v-if="route?.name !== 'EntrySummary'"
|
||||
:to="{ name: 'EntrySummary', params: { id: entityId } }"
|
||||
class="header link"
|
||||
:href="entryUrl"
|
||||
>
|
||||
<QIcon name="open_in_new" color="white" size="sm" />
|
||||
</router-link>
|
||||
:route-name="'EntrySummary'"
|
||||
:entity-id="entityId"
|
||||
:url="entryUrl"
|
||||
/>
|
||||
</template>
|
||||
<template #header>
|
||||
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
|
||||
|
|
|
@ -6,6 +6,7 @@ import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.v
|
|||
|
||||
import CardSummary from 'components/ui/CardSummary.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
||||
|
||||
onUpdated(() => summaryRef.value.fetch());
|
||||
|
||||
|
@ -55,6 +56,11 @@ async function setItemTypeData(data) {
|
|||
>
|
||||
<QIcon name="open_in_new" color="white" size="sm" />
|
||||
</router-link>
|
||||
<VnToSummary
|
||||
v-if="route?.name !== 'ItemTypeSummary'"
|
||||
:route-name="'ItemTypeSummary'"
|
||||
:entity-id="entityId"
|
||||
/>
|
||||
</template>
|
||||
<template #header>
|
||||
<span>
|
||||
|
|
|
@ -3,7 +3,7 @@ import axios from 'axios';
|
|||
import { ref, toRefs } from 'vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { usePrintService } from 'composables/usePrintService';
|
||||
import SendEmailDialog from 'components/common/SendEmailDialog.vue';
|
||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||
|
@ -23,6 +23,7 @@ const props = defineProps({
|
|||
required: true,
|
||||
},
|
||||
});
|
||||
const route = useRoute();
|
||||
|
||||
const { push, currentRoute } = useRouter();
|
||||
const { dialog, notify } = useQuasar();
|
||||
|
@ -40,6 +41,8 @@ const isEditable = ref();
|
|||
const hasInvoicing = useAcl('invoicing');
|
||||
const hasPdf = ref();
|
||||
const weight = ref();
|
||||
const hasDocuwareFile = ref();
|
||||
const quasar = useQuasar();
|
||||
const actions = {
|
||||
clone: async () => {
|
||||
const opts = { message: t('Ticket cloned'), type: 'positive' };
|
||||
|
@ -331,10 +334,49 @@ async function handleInvoiceOutData() {
|
|||
});
|
||||
hasPdf.value = data[0]?.hasPdf;
|
||||
}
|
||||
|
||||
async function docuwareDownload() {
|
||||
await axios.get(`Tickets/${ticketId}/docuwareDownload`);
|
||||
}
|
||||
|
||||
async function hasDocuware() {
|
||||
const { data } = await axios.post(`Docuwares/${ticketId}/checkFile`, {
|
||||
fileCabinet: 'deliveryNote',
|
||||
signed: true,
|
||||
});
|
||||
hasDocuwareFile.value = data;
|
||||
}
|
||||
|
||||
async function uploadDocuware(force) {
|
||||
console.log('force: ', force);
|
||||
if (!force)
|
||||
return quasar
|
||||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
title: t('Send PDF to tablet'),
|
||||
message: t('Are you sure you want to replace this delivery note?'),
|
||||
},
|
||||
})
|
||||
.onOk(async () => {
|
||||
uploadDocuware(true);
|
||||
});
|
||||
|
||||
const { data } = await axios.post(`Docuwares/upload`, {
|
||||
fileCabinet: 'deliveryNote',
|
||||
ticketIds: [parseInt(ticketId)],
|
||||
});
|
||||
|
||||
if (data) notify({ message: t('PDF sent!'), type: 'positive' });
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
:url="`Tickets/${ticketId}/isEditable`"
|
||||
:url="
|
||||
route.path.startsWith('/ticket')
|
||||
? `Tickets/${ticketId}/isEditable`
|
||||
: `Tickets/${ticket}/isEditable`
|
||||
"
|
||||
auto-load
|
||||
@on-fetch="handleFetchData"
|
||||
/>
|
||||
|
@ -452,7 +494,13 @@ async function handleInvoiceOutData() {
|
|||
<QItemSection side>
|
||||
<QIcon name="keyboard_arrow_right" />
|
||||
</QItemSection>
|
||||
<QMenu anchor="top end" self="top start" auto-close bordered>
|
||||
<QMenu
|
||||
anchor="top end"
|
||||
self="top start"
|
||||
auto-close
|
||||
bordered
|
||||
@click="hasDocuware()"
|
||||
>
|
||||
<QList>
|
||||
<QItem @click="openDeliveryNote('deliveryNote')" v-ripple clickable>
|
||||
<QItemSection>{{ t('as PDF') }}</QItemSection>
|
||||
|
@ -460,6 +508,14 @@ async function handleInvoiceOutData() {
|
|||
<QItem @click="openDeliveryNote('withoutPrices')" v-ripple clickable>
|
||||
<QItemSection>{{ t('as PDF without prices') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="hasDocuwareFile"
|
||||
@click="docuwareDownload()"
|
||||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItemSection>{{ t('as PDF signed') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
@click="openDeliveryNote('deliveryNote', 'csv')"
|
||||
v-ripple
|
||||
|
@ -478,7 +534,7 @@ async function handleInvoiceOutData() {
|
|||
<QItemSection side>
|
||||
<QIcon name="keyboard_arrow_right" />
|
||||
</QItemSection>
|
||||
<QMenu anchor="top end" self="top start" auto-close>
|
||||
<QMenu anchor="top end" self="top start" auto-close @click="hasDocuware()">
|
||||
<QList>
|
||||
<QItem
|
||||
@click="sendDeliveryNoteConfirmation('deliveryNote')"
|
||||
|
@ -487,11 +543,7 @@ async function handleInvoiceOutData() {
|
|||
>
|
||||
<QItemSection>{{ t('Send PDF') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
@click="sendDeliveryNoteConfirmation('withoutPrices')"
|
||||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItem @click="uploadDocuware(!hasDocuwareFile)" v-ripple clickable>
|
||||
<QItemSection>{{ t('Send PDF to tablet') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
|
@ -695,4 +747,6 @@ es:
|
|||
invoiceIds: "Se han generado las facturas con los siguientes ids: {invoiceIds}"
|
||||
This ticket will be removed from current route! Continue anyway?: ¡Se eliminará el ticket de la ruta actual! ¿Continuar de todas formas?
|
||||
You are going to delete this ticket: Vas a eliminar este ticket
|
||||
as PDF signed: como PDF firmado
|
||||
Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán?
|
||||
</i18n>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { toCurrency } from 'src/filters';
|
||||
import VnUsesMana from 'components/ui/VnUsesMana.vue';
|
||||
|
||||
const $props = defineProps({
|
||||
mana: {
|
||||
|
@ -13,12 +13,21 @@ const $props = defineProps({
|
|||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
usesMana: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
manaCode: {
|
||||
type: String,
|
||||
default: 'mana',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['save', 'cancel']);
|
||||
|
||||
const { t } = useI18n();
|
||||
const QPopupProxyRef = ref(null);
|
||||
const manaCode = ref($props.manaCode);
|
||||
|
||||
const save = () => {
|
||||
emit('save');
|
||||
|
@ -47,6 +56,9 @@ const cancel = () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
|
||||
<VnUsesMana :mana-code="manaCode" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<QBtn
|
||||
color="primary"
|
||||
|
|
|
@ -22,6 +22,7 @@ import { useVnConfirm } from 'composables/useVnConfirm';
|
|||
import useNotify from 'src/composables/useNotify.js';
|
||||
import axios from 'axios';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import VnUsesMana from 'src/components/ui/VnUsesMana.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
@ -768,6 +769,8 @@ watch(
|
|||
<TicketEditManaProxy
|
||||
:mana="mana"
|
||||
:new-price="getNewPrice"
|
||||
:uses-mana="usesMana"
|
||||
:mana-code="manaCode"
|
||||
@save="changeDiscount(row)"
|
||||
>
|
||||
<VnInput
|
||||
|
@ -775,6 +778,9 @@ watch(
|
|||
:label="t('ticketSale.discount')"
|
||||
type="number"
|
||||
/>
|
||||
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
|
||||
<VnUsesMana :mana-code="manaCode" />
|
||||
</div>
|
||||
</TicketEditManaProxy>
|
||||
</template>
|
||||
<span v-else>{{ toPercentage(row.discount / 100) }}</span>
|
||||
|
|
|
@ -19,6 +19,8 @@ import VnTitle from 'src/components/common/VnTitle.vue';
|
|||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
|
||||
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { notify } = useNotify();
|
||||
|
@ -68,7 +70,7 @@ function isEditable() {
|
|||
|
||||
async function changeState(value) {
|
||||
try {
|
||||
stateBtnDropdownRef.value.hide();
|
||||
stateBtnDropdownRef.value?.hide();
|
||||
const formData = {
|
||||
ticketFk: entityId.value,
|
||||
code: value,
|
||||
|
@ -85,6 +87,10 @@ async function changeState(value) {
|
|||
function toTicketUrl(section) {
|
||||
return '#/ticket/' + entityId.value + '/' + section;
|
||||
}
|
||||
function isOnTicketCard() {
|
||||
const currentPath = route.path;
|
||||
return currentPath.startsWith('/ticket');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -99,6 +105,14 @@ function toTicketUrl(section) {
|
|||
:url="`Tickets/${entityId}/summary`"
|
||||
data-key="TicketSummary"
|
||||
>
|
||||
<template #header-left>
|
||||
<VnToSummary
|
||||
v-if="route?.name !== 'TicketSummary'"
|
||||
:route-name="'TicketSummary'"
|
||||
:entity-id="entityId"
|
||||
:url="ticketUrl"
|
||||
/>
|
||||
</template>
|
||||
<template #header="{ entity }">
|
||||
<div>
|
||||
Ticket #{{ entity.id }} - {{ entity.client?.name }} ({{
|
||||
|
@ -108,23 +122,37 @@ function toTicketUrl(section) {
|
|||
</div>
|
||||
</template>
|
||||
<template #header-right>
|
||||
<QBtnDropdown
|
||||
ref="stateBtnDropdownRef"
|
||||
color="black"
|
||||
text-color="white"
|
||||
:label="t('ticket.summary.changeState')"
|
||||
:disable="!isEditable()"
|
||||
>
|
||||
<VnSelect
|
||||
:options="editableStates"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="code"
|
||||
hide-dropdown-icon
|
||||
focus-on-mount
|
||||
@update:model-value="changeState"
|
||||
/>
|
||||
</QBtnDropdown>
|
||||
<div class="flex items-end">
|
||||
<QBtnDropdown
|
||||
ref="stateBtnDropdownRef"
|
||||
color="black"
|
||||
text-color="white"
|
||||
:label="t('ticket.summary.changeState')"
|
||||
:disable="!isEditable()"
|
||||
>
|
||||
<VnSelect
|
||||
:options="editableStates"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="code"
|
||||
hide-dropdown-icon
|
||||
focus-on-mount
|
||||
@update:model-value="changeState"
|
||||
/>
|
||||
</QBtnDropdown>
|
||||
<QBtn
|
||||
v-if="!isOnTicketCard()"
|
||||
icon="more_vert"
|
||||
round
|
||||
size="md"
|
||||
flat
|
||||
color="white"
|
||||
>
|
||||
<QMenu>
|
||||
<TicketDescriptorMenu :ticket="entityId" />
|
||||
</QMenu>
|
||||
</QBtn>
|
||||
</div>
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<QCard class="vn-one">
|
||||
|
|
|
@ -20,11 +20,31 @@ const provinces = ref([]);
|
|||
const states = ref([]);
|
||||
const agencies = ref([]);
|
||||
const warehouses = ref([]);
|
||||
const groupedStates = ref([]);
|
||||
|
||||
const getGroupedStates = (data) => {
|
||||
for (const state of data) {
|
||||
groupedStates.value.push({
|
||||
id: state.id,
|
||||
name: t(`${state.code}`),
|
||||
code: state.code,
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData url="Provinces" @on-fetch="(data) => (provinces = data)" auto-load />
|
||||
<FetchData url="States" @on-fetch="(data) => (states = data)" auto-load />
|
||||
<FetchData
|
||||
url="AlertLevels"
|
||||
@on-fetch="
|
||||
(data) => {
|
||||
getGroupedStates(data);
|
||||
}
|
||||
"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData url="AgencyModes" @on-fetch="(data) => (agencies = data)" auto-load />
|
||||
<FetchData url="Warehouses" @on-fetch="(data) => (warehouses = data)" auto-load />
|
||||
<VnFilterPanel :data-key="props.dataKey" :search-button="true" search-url="table">
|
||||
|
@ -90,12 +110,35 @@ const warehouses = ref([]);
|
|||
option-label="name"
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection v-if="!groupedStates">
|
||||
<QSkeleton type="QInput" class="full-width" />
|
||||
</QItemSection>
|
||||
<QItemSection v-if="groupedStates">
|
||||
<QSelect
|
||||
:label="t('Grouped state')"
|
||||
v-model="params.groupedStates"
|
||||
@update:model-value="searchFn()"
|
||||
:options="groupedStates"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
sort-by="name ASC"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
|
@ -114,6 +157,15 @@ const warehouses = ref([]);
|
|||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
v-model="params.nickname"
|
||||
:label="t('Nickname')"
|
||||
is-outlined
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QCheckbox
|
||||
|
@ -176,6 +228,7 @@ const warehouses = ref([]);
|
|||
option-label="name"
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
@ -196,6 +249,7 @@ const warehouses = ref([]);
|
|||
option-label="name"
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
@ -216,12 +270,22 @@ const warehouses = ref([]);
|
|||
option-label="name"
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
v-model="params.collectionFk"
|
||||
:label="t('Collection')"
|
||||
is-outlined
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QExpansionItem>
|
||||
</template>
|
||||
</VnFilterPanel>
|
||||
|
@ -245,6 +309,11 @@ en:
|
|||
provinceFk: Province
|
||||
agencyModeFk: Agency
|
||||
warehouseFk: Warehouse
|
||||
FREE: Free
|
||||
ON_PREPARATION: On preparation
|
||||
PACKED: Packed
|
||||
DELIVERED: Delivered
|
||||
ON_PREVIOUS: ON_PREVIOUS
|
||||
es:
|
||||
params:
|
||||
search: Contiene
|
||||
|
@ -278,4 +347,12 @@ es:
|
|||
Yes: Si
|
||||
No: No
|
||||
Days onward: Días adelante
|
||||
Grouped state: Estado agrupado
|
||||
FREE: Libre
|
||||
ON_PREPARATION: En preparación
|
||||
PACKED: Encajado
|
||||
DELIVERED: Servido
|
||||
ON_PREVIOUS: ON_PREVIOUS
|
||||
Collection: Colección
|
||||
Nickname: Nombre mostrado
|
||||
</i18n>
|
||||
|
|
|
@ -550,7 +550,7 @@ function setReference(data) {
|
|||
</template>
|
||||
<template #column-salesPersonFk="{ row }">
|
||||
<span class="link" @click.stop>
|
||||
{{ dashIfEmpty(row.salesPerson) }}
|
||||
{{ dashIfEmpty(row.userName) }}
|
||||
<CustomerDescriptorProxy :id="row.salesPersonFk" />
|
||||
</span>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue