#7553 modified TicketExpedition & changes in ticket section #571

Merged
jon merged 79 commits from 7553_FixTicketExpedition into dev 2024-09-25 05:51:16 +00:00
4 changed files with 303 additions and 286 deletions
Showing only changes of commit 954a6ff6c0 - Show all commits

View File

@ -303,7 +303,7 @@ const columns = computed(() => [
{
title: t('salesTicketsTable.goToLines'),
icon: 'vn:lines',
color: 'priamry',
color: 'primary',
action: (row) => redirectToSales(row.id),
isPrimary: true,
attrs: {
@ -314,7 +314,7 @@ const columns = computed(() => [
{
title: t('salesTicketsTable.preview'),
icon: 'preview',
color: 'priamry',
color: 'primary',
action: (row) => viewSummary(row.id, TicketSummary),
isPrimary: true,
attrs: {

View File

@ -1,27 +1,32 @@
<script setup>
import { ref, computed, watch, reactive } from 'vue';
import axios from 'axios';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import VnInput from 'src/components/common/VnInput.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import CrudModel from 'src/components/CrudModel.vue';
import TicketCreateRequest from './TicketCreateRequest.vue';
import { dashIfEmpty } from 'src/filters';
import { toDateFormat } from 'src/filters/date.js';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'src/components/FetchData.vue';
import { useVnConfirm } from 'composables/useVnConfirm';
import useNotify from 'src/composables/useNotify.js';
const route = useRoute();
const { t } = useI18n();
const createTicketRequestDialogRef = ref(null);
const crudModelRef = ref(null);
const tableRef = ref();
const attendersOptions = ref([]);
const { openConfirmationModal } = useVnConfirm();
const { notify } = useNotify();
watch(
() => route.params.id,
async (val) => {
crudModelFilter.where.ticketFk = val;
crudModelRef.value.reload();
tableRef.value.reload();
}
);
@ -72,64 +77,90 @@ const crudModelFilter = reactive({
const columns = computed(() => [
{
align: 'left',
label: t('purchaseRequest.id'),
name: 'id',
field: 'id',
align: 'left',
columnFilter: null,
chip: {
condition: () => true,
},
isId: true,
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.description'),
name: 'description',
field: 'description',
align: 'left',
format: (val) => dashIfEmpty(val),
columnClass: 'expand',
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.created'),
name: 'created',
field: 'created',
align: 'left',
format: (val) => toDateFormat(val),
format: (row) => toDateFormat(row.created),
cardVisible: true,
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.requester'),
name: 'requester',
align: 'left',
sortable: true,
name: 'requesterFk',
cardVisible: true,
format: (row) => dashIfEmpty(row.requester?.user?.nickname),
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.atender'),
name: 'atender',
align: 'left',
name: 'attenderFk',
cardVisible: true,
format: (row) => dashIfEmpty(row.atender?.user?.nickname),
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.quantity'),
name: 'quantity',
align: 'left',
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.price'),
name: 'price',
align: 'left',
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.saleFk'),
name: 'saleFk',
align: 'left',
cardVisible: true,
hidden: true,
},
{
align: 'left',
label: t('purchaseRequest.state'),
name: 'state',
field: 'isOk',
align: 'left',
format: (val) => t(getRequestState(val)),
name: 'isOk',
cardVisible: true,
isHidden: true,
},
{
label: '',
name: 'actions',
align: 'left',
columnFilter: null,
align: 'right',
name: 'tableActions',
actions: [
{
title: t('globals.delete'),
icon: 'delete',
isPrimary: true,
action: (row) =>
openConfirmationModal(
t('You are going to delete this ticket purchase request'),
t(
'This ticket will be removed from ticket purchase requests! Continue anyway?'
),
() => removeLine(row.id)
),
},
],
},
]);
@ -140,131 +171,114 @@ const getRequestState = (state) => {
case false:
return 'Denied';
case true:
return 'Acepted';
return 'Accepted';
}
};
const isEditable = (isOk) => isOk !== null;
const removeLine = async (row) => crudModelRef.value.remove([row]);
const openCreateModal = () => createTicketRequestDialogRef.value.show();
async function removeLine(id) {
try {
await axios.delete(`TicketRequests/${id}`);
notify(t('globals.dataSaved'), 'positive');
location.reload();
} catch (err) {
console.error('Error ', err);
}
}
</script>
<template>
<QPage class="column items-center q-pa-md">
<CrudModel
data-key="PurchaseRequests"
url="TicketRequests"
ref="crudModelRef"
:filter="crudModelFilter"
:order="['created ASC']"
:default-remove="false"
:default-save="false"
:default-reset="false"
:limit="0"
auto-load
>
<template #body="{ rows }">
<QTable
:rows="rows"
:columns="columns"
row-key="id"
:pagination="{ rowsPerPage: 0 }"
class="full-width q-mt-md"
:no-data-label="t('globals.noResults')"
@row-click="(_, row) => redirectToTicketSummary(row.ticketFk)"
>
<template #body-cell-description="{ row }">
<QTd @click.stop>
<VnInput
v-model="row.description"
@blur="crudModelRef.saveChanges()"
:disable="isEditable(row.isOk)"
/>
</QTd>
</template>
<template #body-cell-requester="{ row }">
<QTd @click.stop>
<span class="link">
<QBtn flat>
{{ row.requester?.user?.nickname }}
<WorkerDescriptorProxy :id="row.requesterFk" />
</QBtn>
</span>
</QTd>
</template>
<template #body-cell-atender="{ row }">
<QTd @click.stop>
<span class="link">
<QBtn flat>
{{ row.atender?.user?.nickname }}
<WorkerDescriptorProxy :id="row.attenderFk" />
</QBtn>
</span>
</QTd>
</template>
<template #body-cell-quantity="{ row }">
<QTd @click.stop>
<VnInput
v-model="row.quantity"
@blur="crudModelRef.saveChanges()"
:disable="isEditable(row.isOk)"
/>
</QTd>
</template>
<template #body-cell-price="{ row }">
<QTd @click.stop>
<VnInput
v-model="row.price"
@blur="crudModelRef.saveChanges()"
:disable="isEditable(row.isOk)"
/>
</QTd>
</template>
<template #body-cell-saleFk="{ row }">
<QTd @click.stop>
<span class="link">
<QBtn v-if="row.saleFk" flat>
{{ row.sale.itemFk }}
<ItemDescriptorProxy :id="row.sale.itemFk" />
</QBtn>
</span>
</QTd>
</template>
<template #body-cell-actions="{ row }">
<QTd>
<QIcon
@click.stop="removeLine(row)"
class="q-ml-sm cursor-pointer"
color="primary"
name="delete"
size="sm"
>
<QTooltip>
{{ t('globals.delete') }}
</QTooltip>
</QIcon>
</QTd>
</template>
</QTable>
</template>
</CrudModel>
<QDialog
ref="createTicketRequestDialogRef"
transition-show="scale"
transition-hide="scale"
>
<TicketCreateRequest @on-request-created="crudModelRef.reload()" />
</QDialog>
<QPageSticky :offset="[20, 20]">
<QBtn @click="openCreateModal()" color="primary" fab icon="add" />
<QTooltip class="text-no-wrap">
{{ t('purchaseRequest.newRequest') }}
</QTooltip>
</QPageSticky>
</QPage>
<FetchData
url="TicketRequests/getItemTypeWorker"
:filter="{ fields: ['id', 'nickname'], order: 'nickname ASC' }"
auto-load
@on-fetch="(data) => (attendersOptions = data)"
/>
<VnTable
ref="tableRef"
data-key="PurchaseRequests"
url="TicketRequests"
:create="{
urlCreate: 'TicketRequests',
title: t('Create request'),
onDataSaved: ({ id }) => tableRef.reload(id),
formInitialData: {
ticketFk: route.params.id,
jon marked this conversation as resolved Outdated

Los campos de cantidad y precio tienen el mismo tamaño que descripción?
Propongo recortar el tamaño y asi ganar ancho en campos como el que he dicho
Igual pasa con la columna de borrar

Los campos de cantidad y precio tienen el mismo tamaño que descripción? Propongo recortar el tamaño y asi ganar ancho en campos como el que he dicho Igual pasa con la columna de borrar
},
}"
save-url="TicketRequests/crud"
:filter="crudModelFilter"
:columns="columns"
:is-editable="true"
:right-search="false"
auto-load
>
<template #column-description="{ row }">
<VnInput v-model="row.description" :disable="isEditable(row.isOk)" />
</template>
<template #column-requesterFk="{ row }">
<span class="link" @click.stop>
{{ row.requester?.user?.nickname }}
<WorkerDescriptorProxy :id="row.requesterFk" />
</span>
</template>
<template #column-attenderFk="{ row }">
<span class="link" @click.stop>
{{ row.atender?.user?.nickname }}
<WorkerDescriptorProxy :id="row.attenderFk" />
</span>
</template>
<template #column-quantity="{ row }">
<VnInput v-model="row.quantity" :disable="isEditable(row.isOk)" />
</template>
<template #column-price="{ row }">
<span @click.stop>
<VnInput v-model="row.price" :disable="isEditable(row.isOk)">
{{ row.price }}
</VnInput>
</span>
</template>
<template #column-saleFk="{ row }">
<QTd style="width: 3%">
<span class="link" @click.stop>
{{ dashIfEmpty(row.sale?.itemFk) }}
<ItemDescriptorProxy :id="row.sale?.itemFk" /> </span
></QTd>
</template>
<template #column-isOk="{ row }">
{{ t(getRequestState(row.isOk)) }}
</template>
<template #more-create-dialog="{ data }">
<VnInput
v-model="data.description"
:label="t('purchaseRequest.description')"
/>
<VnSelect
:label="t('purchaseRequest.atender')"
v-model="data.attenderFk"
:options="attendersOptions"
hide-selected
option-label="nickname"
option-value="id"
/>
<VnInput
v-model="data.quantity"
:label="t('purchaseRequest.quantity')"
type="number"
min="1"
/>
<VnInput
v-model="data.price"
:label="t('purchaseRequest.price')"
type="number"
min="0"
/>
</template>
</VnTable>
</template>
<i18n>
es:
New: Nueva

View File

@ -16,11 +16,12 @@ import TicketSaleMoreActions from './TicketSaleMoreActions.vue';
import TicketTransfer from './TicketTransfer.vue';
import { useStateStore } from 'stores/useStateStore';
import { toCurrency, toPercentage, dashIfEmpty } from 'src/filters';
import { toCurrency, toPercentage } from 'src/filters';
import { useArrayData } from 'composables/useArrayData';
import { useVnConfirm } from 'composables/useVnConfirm';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import VnTable from 'src/components/VnTable/VnTable.vue';
const route = useRoute();
const router = useRouter();
@ -33,7 +34,8 @@ const stateBtnDropdownRef = ref(null);
const arrayData = useArrayData('ticketData');
const { store } = arrayData;
const selectedRows = ref([]);
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
const ticketConfig = ref(null);
const isLocked = ref(false);
const isTicketEditable = ref(false);
@ -56,86 +58,104 @@ watch(
const columns = computed(() => [
{
label: '',
align: 'left',
name: 'statusIcons',
align: 'left',
hidden: true,
},
{
label: '',
name: 'picture',
align: 'left',
align: 'center',
label: t('lines.image'),
name: 'image',
columnField: {
component: VnImg,
attrs: (id) => {
return {
id,
width: '50px',
};
},
},
columnFilter: false,
},
{
align: 'left',
label: t('ticketSale.visible'),
name: 'visible',
field: 'visible',
align: 'left',
sortable: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.visible),
hidden: true,
},
{
align: 'left',
label: t('ticketSale.available'),
name: 'available',
field: 'available',
align: 'left',
sortable: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.available),
hidden: true,
},
{
align: 'left',
label: t('ticketSale.id'),
name: 'itemFk',
field: 'itemFk',
align: 'left',
sortable: true,
hidden: true,
},
{
align: 'left',
label: t('ticketSale.quantity'),
name: 'quantity',
field: 'quantity',
align: 'left',
sortable: true,
cardVisible: true,
format: (row) => toCurrency(row.quantity),
hidden: true,
},
{
align: 'left',
label: t('ticketSale.item'),
name: 'item',
field: 'item',
align: 'left',
sortable: true,
format: (row) => row?.item?.name,
columnClass: 'expand',
cardVisible: true,
hidden: true,
},
{
align: 'left',
label: t('ticketSale.price'),
name: 'price',
field: 'price',
align: 'left',
sortable: true,
format: (val) => toCurrency(val),
cardVisible: true,
format: (row) => toCurrency(row.price),
hidden: true,
},
{
align: 'left',
label: t('ticketSale.discount'),
name: 'discount',
field: 'discount',
align: 'left',
sortable: true,
cardVisible: true,
format: (row) => toPercentage(row.discount),
hidden: true,
},
{
align: 'left',
label: t('ticketSale.amount'),
name: 'amount',
field: 'amount',
align: 'left',
sortable: true,
format: (val) => toCurrency(val),
format: (row) => parseInt(row.amount * row.quantity),
hidden: true,
},
{
align: 'left',
label: t('ticketSale.packaging'),
name: 'itemPackingTypeFk',
field: 'item',
align: 'left',
sortable: true,
format: (val) => dashIfEmpty(val?.itemPackingTypeFk),
cardVisible: true,
format: (row, dashIfEmpty) => dashIfEmpty(row?.item?.itemPackingTypeFk),
hidden: true,
},
{
label: '',
name: 'history',
align: 'left',
columnFilter: null,
align: 'right',
name: 'tableActions',
actions: [
{
title: t('ticketSale.history'),
icon: 'history',
isPrimary: true,
action: (row) => goToLog(row.id),
},
],
},
]);
@ -478,7 +498,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
:ticket="store.data"
:is-ticket-editable="isTicketEditable"
:sales="selectedValidSales"
:disable="!selectedSales.length"
:disable="!hasSelectedRows"
:mana="mana"
:ticket-config="ticketConfig"
@get-mana="getMana()"
@ -487,7 +507,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<QBtn
color="primary"
icon="delete"
:disable="!isTicketEditable || !selectedSales.length"
:disable="!isTicketEditable || !hasSelectedRows"
@click="
openConfirmationModal(
t('Continue anyway?'),
@ -501,7 +521,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<QBtn
color="primary"
icon="vn:splitline"
:disable="!isTicketEditable || !selectedSales.length"
:disable="!isTicketEditable || !hasSelectedRows"
@click="setTransferParams()"
>
<QTooltip>{{ t('Transfer lines') }}</QTooltip>
@ -540,17 +560,21 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QCardSection>
</div></QDrawer
>
<QTable
:rows="sales"
<!-- TODO: el botón de añadir filas como está en salix-->
<VnTable
ref="tableRef"
data-key="TicketSales"
:url="`Tickets/${route.params.id}/getSales`"
:columns="columns"
row-key="id"
:pagination="{ rowsPerPage: 0 }"
class="full-width q-mt-md"
selection="multiple"
v-model:selected="selectedSales"
:no-data-label="t('globals.noResults')"
v-model:selected="selectedRows"
:table="{
'row-key': 'id',
selection: 'multiple',
}"
:right-search="false"
auto-load
>
<template #body-cell-statusIcons="{ row }">
<template #column-statusIcons="{ row }">
<QTd class="q-gutter-x-xs">
<router-link
v-if="row.claim?.claimFk"
@ -595,58 +619,40 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QIcon>
jon marked this conversation as resolved Outdated

Podemos hacer que la columna articulo sea mas ancho para que quepan mas registros por filas?
Por ejemplo hay campos numéricos que tienen mucho ancho

Podemos hacer que la columna articulo sea mas ancho para que quepan mas registros por filas? Por ejemplo hay campos numéricos que tienen mucho ancho
</QTd>
</template>
<template #body-cell-picture="{ row }">
<QTd>
<div class="image-wrapper">
<VnImg :id="row.itemFk" class="rounded" />
<template #column-image="{ row }">
<div class="image-wrapper">
<VnImg :id="parseInt(row?.item?.id)" class="rounded" />
</div>
</template>
<template #column-visible="{ row }">
<QBadge :color="row.available < 0 ? 'alert' : 'transparent'" dense>
{{ row.visible }}
</QBadge>
</template>
<template #column-available="{ row }">
<QBadge :color="row.available < 0 ? 'alert' : 'transparent'" dense>
{{ row.available }}
</QBadge>
</template>
<template #column-itemFk="{ row }">
<span class="link" @click.stop>
{{ row?.itemFk }}
<ItemDescriptorProxy :id="row?.itemFk" />
</span>
</template>
<template #column-item="{ row }">
<div class="row column full-width justify-between items-start">
{{ row?.item?.name }}
<div v-if="row?.item?.subName" class="subName">
{{ row?.item?.subName.toUpperCase() }}
</div>
</QTd>
</div>
<FetchedTags :item="row?.item" :max-length="6" />
<QPopupProxy v-if="row.id && isTicketEditable">
<VnInput v-model="row.concept" @change="updateConcept(row)" />
</QPopupProxy>
</template>
<template #body-cell-visible="{ row }">
<QTd @click.stop>
<QBadge :color="row.visible < 0 ? 'alert' : 'transparent'" dense>
{{ row.visible }}
</QBadge>
</QTd>
</template>
<template #body-cell-available="{ row }">
<QTd @click.stop>
<QBadge :color="row.available < 0 ? 'alert' : 'transparent'" dense>
{{ row.available }}
</QBadge>
</QTd>
</template>
<template #body-cell-itemFk="{ row }">
<QTd @click.stop>
<div v-if="row.id">
<span class="link">
<QBtn flat dense>
{{ row.itemFk }}
</QBtn>
<ItemDescriptorProxy :id="row.itemFk" />
</span>
</div>
<VnSelect
v-else
:options="itemsWithNameOptions"
hide-selected
option-label="name"
option-value="id"
@update:model-value="changeQuantity(row)"
v-model="row.itemFk"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel> #{{ scope.opt?.id }} </QItemLabel>
<QItemLabel caption>{{ scope.opt?.name }}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QTd>
</template>
<template #body-cell-quantity="{ row }">
<template #column-quantity="{ row }">
<QTd @click.stop>
<VnInput
v-if="isTicketEditable"
@ -658,19 +664,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<span v-else>{{ row.quantity }}</span>
</QTd>
</template>
<template #body-cell-item="{ row }">
<QTd class="col">
<div class="column">
<span>{{ row.concept }}</span>
<span class="color-vn-label">{{ row.item?.subName }}</span>
<FetchedTags v-if="row.item" :item="row.item" :max-length="6" />
<QPopupProxy v-if="row.id && isTicketEditable">
<VnInput v-model="row.concept" @change="updateConcept(row)" />
</QPopupProxy>
</div>
</QTd>
</template>
<template #body-cell-price="{ row }">
<template #column-price="{ row }">
<QTd>
<template v-if="isTicketEditable && row.id">
<QBtn flat color="primary" dense @click="onOpenEditPricePopover(row)">
@ -692,7 +686,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<span v-else>{{ toCurrency(row.price) }}</span>
</QTd>
</template>
<template #body-cell-discount="{ row }">
<template #column-discount="{ row }">
<QTd>
<template v-if="!isLocked && row.id">
<QBtn
@ -718,21 +712,8 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<span v-else>{{ toPercentage(row.discount / 100) }}</span>
</QTd>
</template>
<template #body-cell-history="{ row }">
<QTd>
<QBtn
v-if="row.$hasLogs"
@click.stop="goToLog(row.id)"
color="primary"
icon="history"
size="md"
flat
>
<QTooltip class="text-no-wrap">
{{ t('ticketSale.history') }}
</QTooltip>
</QBtn>
</QTd>
<template #column-amount="{ row }">
{{ toCurrency(row.quantity * row.price) }}
</template>
<template #bottom-row>
<QBtn
@ -750,7 +731,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QTooltip>
</QBtn>
</template>
</QTable>
</VnTable>
<QPageSticky :offset="[20, 20]">
<QBtn @click="newOrderFromTicket()" color="primary" fab icon="add" />
@ -760,6 +741,18 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QPageSticky>
</template>
<style lang="scss" scoped>
.image-wrapper {
height: 50px;
width: 50px;
}
.subName {
text-transform: uppercase;
color: var(--vn-label-color);
}
</style>
<i18n>
es:
New item: Nuevo artículo

View File

@ -345,7 +345,7 @@ const qCheckBoxController = (sale, action) => {
:no-data-label="t('globals.noResults')"
>
<template #body-cell-isChecked="{ row }">
<QTd @click.stop>
<QTd @click.stop style="width: 20%">
<QCheckbox
:model-value="!!row.hasSaleGroupDetail"
color="pink"
@ -404,7 +404,7 @@ const qCheckBoxController = (sale, action) => {
</QTd>
</template>
<template #body-cell-item="{ row }">
<QTd @click.stop>
<QTd @click.stop style="width: 20%">
<div>
<span class="link">
jon marked this conversation as resolved Outdated

Podemos recortar la columna de acciones en favor de tener FetchedTags en una linea?

Podemos recortar la columna de acciones en favor de tener FetchedTags en una linea?
<QBtn flat>
@ -426,8 +426,18 @@ const qCheckBoxController = (sale, action) => {
</div>
</QTd>
</template>
<template #body-cell-quantity="{ row }">
<QTd style="width: 10%">
{{ row.quantity }}
</QTd>
</template>
<template #body-cell-parking="{ row }">
<QTd style="width: 10%">
{{ dashIfEmpty(row.parkingFk) }}
</QTd>
</template>
<template #body-cell-actions="{ row }">
<QTd>
<QTd style="width: 20%">
<QBtn
@click.stop="showLog(row)"
color="primary"