Ticket tracking #485

Merged
jsegarra merged 7 commits from :feature/TicketTracking into dev 2024-07-01 12:51:11 +00:00
7 changed files with 237 additions and 8 deletions

View File

@ -450,6 +450,7 @@ ticket:
futureTickets: Future tickets
purchaseRequest: Purchase request
weeklyTickets: Weekly tickets
tracking: Tracking
list:
nickname: Nickname
state: State

View File

@ -449,6 +449,7 @@ ticket:
futureTickets: Tickets a futuro
purchaseRequest: Petición de compra
weeklyTickets: Tickets programados
tracking: Estados
list:
nickname: Alias
state: Estado

View File

@ -0,0 +1,86 @@
<script setup>
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import FormModelPopup from 'components/FormModelPopup.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
import { useState } from 'src/composables/useState';
const emit = defineEmits(['onRequestCreated']);
const route = useRoute();
const { t } = useI18n();
const state = useState();
const user = state.getUser();
const stateFetchDataRef = ref(null);
const statesOptions = ref([]);
const workersOptions = ref([]);
const onStateFkChange = (formData) => (formData.userFk = user.value.id);
</script>
<template>
<FetchData
ref="stateFetchDataRef"
url="States"
auto-load
@on-fetch="(data) => (statesOptions = data)"
/>
<FetchData
url="Workers/search"
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
auto-load
@on-fetch="(data) => (workersOptions = data)"
/>
<FormModelPopup
:title="t('Create tracking')"
url-create="Tickets/state"
model="CreateTicketTracking"
:form-initial-data="{ ticketFk: route.params.id }"
@on-data-saved="() => emit('onRequestCreated')"
>
<template #form-inputs="{ data }">
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
v-model="data.stateFk"
:label="t('tracking.state')"
:options="statesOptions"
@update:model-value="onStateFkChange(data)"
hide-selected
option-label="name"
option-value="id"
/>
<VnSelect
:label="t('tracking.worker')"
v-model="data.userFk"
:options="workersOptions"
hide-selected
option-label="name"
option-value="id"
>
<template #option="{ opt, itemProps }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>
{{ opt.name }}
</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }}, {{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template></VnSelect
>
</VnRow>
</template>
</FormModelPopup>
</template>
<i18n>
es:
Create tracking: Crear estado
</i18n>

View File

@ -0,0 +1,121 @@
<script setup>
import { ref, computed, watch, reactive } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import TicketCreateTracking from './TicketCreateTracking.vue';
import VnPaginate from 'components/ui/VnPaginate.vue';
import { toDateTimeFormat } from 'src/filters/date.js';
const route = useRoute();
const { t } = useI18n();
const createTrackingDialogRef = ref(null);
const paginateRef = ref(null);
watch(
() => route.params.id,
async (val) => {
paginateFilter.where.ticketFk = val;
paginateRef.value.fetch();
}
);
const paginateFilter = reactive({
include: [
{
relation: 'user',
scope: {
fields: ['id', 'name'],
include: {
relation: 'worker',
scope: {
fields: ['id'],
},
},
},
},
{
relation: 'state',
scope: {
fields: ['name'],
},
},
],
order: ['created DESC'],
where: {
ticketFk: route.params.id,
},
});
const columns = computed(() => [
{
label: t('tracking.state'),
name: 'state',
field: 'state',
align: 'left',
format: (val) => val.name,
},
{
label: t('tracking.worker'),
name: 'worker',
align: 'left',
},
{
label: t('tracking.created'),
name: 'created',
field: 'created',
align: 'left',
format: (val) => toDateTimeFormat(val),
},
]);
const openCreateModal = () => createTrackingDialogRef.value.show();
</script>
<template>
Review

@alexm Implementamos VnTable?

@alexm Implementamos VnTable?
Review

Si ya lo tiene hecho no le marearia.
Para próximas implementaciones si que estaria bien.

Si ya lo tiene hecho no le marearia. Para próximas implementaciones si que estaria bien.
Review

Perfecto, estamos de acuerdo

Perfecto, estamos de acuerdo
<QPage class="column items-center q-pa-md">
<VnPaginate
ref="paginateRef"
data-key="TicketTracking"
:filter="paginateFilter"
url="TicketTrackings"
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')"
>
<template #body-cell-worker="{ row }">
<QTd @click.stop>
<QBtn flat color="primary">
{{ row.user?.name }}
<WorkerDescriptorProxy :id="row.user?.worker?.id" />
</QBtn>
</QTd>
</template>
</QTable>
</template>
</VnPaginate>
<QDialog
ref="createTrackingDialogRef"
transition-show="scale"
transition-hide="scale"
>
<TicketCreateTracking @on-request-created="paginateRef.fetch()" />
</QDialog>
<QPageSticky :offset="[20, 20]">
<QBtn @click="openCreateModal()" color="primary" fab icon="add" />
<QTooltip class="text-no-wrap">
{{ t('tracking.addState') }}
</QTooltip>
</QPageSticky>
</QPage>
</template>

View File

@ -149,3 +149,8 @@ weeklyTickets:
salesperson: Salesperson
search: Search weekly tickets
searchInfo: Search weekly tickets by id or client id
tracking:
state: State
worker: Worker
created: Created
addState: Add state

View File

@ -1,3 +1,8 @@
tracking:
state: Estado
worker: Trabajador
created: Fecha creación
addState: Añadir estado
card:
search: Buscar tickets
searchInfo: Buscar tickets por identificador o alias

View File

@ -19,6 +19,7 @@ export default {
'TicketSale',
'TicketLog',
'TicketPurchaseRequest',
'TicketTracking',
'TicketVolume',
'TicketNotes',
],
@ -31,8 +32,8 @@ export default {
redirect: { name: 'TicketList' },
children: [
{
name: 'TicketList',
path: 'list',
name: 'TicketList',
meta: {
title: 'list',
icon: 'view_list',
@ -40,8 +41,8 @@ export default {
component: () => import('src/pages/Ticket/TicketList.vue'),
},
{
name: 'TicketCreate',
path: 'create',
name: 'TicketCreate',
meta: {
title: 'createTicket',
icon: 'vn:ticketAdd',
@ -50,8 +51,8 @@ export default {
component: () => import('src/pages/Ticket/TicketCreate.vue'),
},
{
name: 'TicketWeekly',
path: 'weekly',
name: 'TicketWeekly',
meta: {
title: 'weeklyTickets',
icon: 'access_time',
@ -59,8 +60,8 @@ export default {
component: () => import('src/pages/Ticket/TicketWeekly.vue'),
},
{
name: 'TicketFuture',
path: 'future',
name: 'TicketFuture',
meta: {
title: 'futureTickets',
icon: 'keyboard_double_arrow_right',
@ -68,8 +69,8 @@ export default {
component: () => import('src/pages/Ticket/TicketFuture.vue'),
},
{
name: 'TicketAdvance',
path: 'advance',
name: 'TicketAdvance',
meta: {
title: 'ticketAdvance',
icon: 'keyboard_double_arrow_left',
@ -85,8 +86,8 @@ export default {
redirect: { name: 'TicketSummary' },
children: [
{
name: 'TicketSummary',
path: 'summary',
name: 'TicketSummary',
meta: {
title: 'summary',
icon: 'launch',
@ -94,8 +95,8 @@ export default {
component: () => import('src/pages/Ticket/Card/TicketSummary.vue'),
},
{
name: 'TicketBasicData',
path: 'basic-data',
name: 'TicketBasicData',
meta: {
title: 'basicData',
icon: 'vn:settings',
@ -104,8 +105,8 @@ export default {
import('src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue'),
},
{
name: 'TicketSale',
path: 'sale',
name: 'TicketSale',
meta: {
title: 'sale',
icon: 'vn:lines',
@ -122,6 +123,15 @@ export default {
component: () =>
import('src/pages/Ticket/Card/TicketPurchaseRequest.vue'),
},
{
path: 'tracking',
name: 'TicketTracking',
meta: {
title: 'tracking',
icon: 'vn:eye',
},
component: () => import('src/pages/Ticket/Card/TicketTracking.vue'),
},
{
path: 'log',
name: 'TicketLog',