From 2b2ccbc6a105da40fb07f20fc012d4cb87589f9f Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Mon, 21 Oct 2024 12:14:54 +0200 Subject: [PATCH 1/8] feat: refs #7524 myTeam filter & default params --- src/i18n/locale/en.yml | 1 + src/i18n/locale/es.yml | 1 + src/pages/Ticket/TicketAdvance.vue | 3 +++ src/pages/Ticket/TicketAdvanceFilter.vue | 19 +++++++++++++++++-- src/pages/Ticket/locale/es.yml | 4 ++-- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index 7eb3829fe..17a3e097a 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -296,6 +296,7 @@ globals: from: From To: To stateFk: State + myTeam: My team errors: statusUnauthorized: Access denied statusInternalServerError: An internal server error has ocurred diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index 9d5cd53f3..fc61936d2 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -300,6 +300,7 @@ globals: from: Desde To: Hasta stateFk: Estado + myTeam: Mi equipo errors: statusUnauthorized: Acceso denegado statusInternalServerError: Ha ocurrido un error interno del servidor diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue index 177b3a29b..2cce1dba8 100644 --- a/src/pages/Ticket/TicketAdvance.vue +++ b/src/pages/Ticket/TicketAdvance.vue @@ -462,6 +462,9 @@ onMounted(async () => { userParams.dateFuture = tomorrow; userParams.dateToAdvance = today; userParams.warehouseFk = user.value.warehouseFk; + userParams.ipt = 'H'; + userParams.futureIpt = 'H'; + userParams.isFullMovable = true; const filter = { limit: 0 }; await arrayData.addFilter({ filter, userParams }); }); diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue index 209a1a307..38a0dd4c2 100644 --- a/src/pages/Ticket/TicketAdvanceFilter.vue +++ b/src/pages/Ticket/TicketAdvanceFilter.vue @@ -10,7 +10,7 @@ import VnInputDate from 'src/components/common/VnInputDate.vue'; import axios from 'axios'; import { onMounted } from 'vue'; -const { t } = useI18n(); +const { t, te } = useI18n(); const props = defineProps({ dataKey: { type: String, @@ -42,6 +42,11 @@ const getItemPackingTypes = async () => { } }; +const getLocale = (val) => { + const param = `params.${val}`; + return te(param) ? t(param) : t(`globals.${param}`); +}; + onMounted(async () => await getItemPackingTypes()); </script> @@ -59,7 +64,7 @@ onMounted(async () => await getItemPackingTypes()); > <template #tags="{ tag, formatFn }"> <div class="q-gutter-x-xs"> - <strong>{{ t(`params.${tag.label}`) }}: </strong> + <strong>{{ getLocale(tag.label) }}: </strong> <span>{{ formatFn(tag.value) }}</span> </div> </template> @@ -142,6 +147,16 @@ onMounted(async () => await getItemPackingTypes()); </VnSelect> </QItemSection> </QItem> + <QItem> + <QItemSection> + <QCheckbox + :label="t('globals.params.myTeam')" + v-model="params.myTeam" + toggle-indeterminate + @update:model-value="searchFn()" + /> + </QItemSection> + </QItem> </template> </VnFilterPanel> </template> diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml index 0a27519ad..d4ba1f26a 100644 --- a/src/pages/Ticket/locale/es.yml +++ b/src/pages/Ticket/locale/es.yml @@ -86,9 +86,9 @@ weeklyTickets: search: Buscar por tickets programados searchInfo: Buscar tickets programados por el identificador o el identificador del cliente advanceTickets: - preparation: Preparación + preparation: Preparación origin: Origen - destination: Destinatario + destination: Destino originAgency: 'Agencia origen: {agency}' destinationAgency: 'Agencia destino: {agency}' ticketId: ID From a4358ec0edbcebd07fcf427c8a49097913b62dcb Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Mon, 21 Oct 2024 12:36:16 +0200 Subject: [PATCH 2/8] chore: refs #7524 refactor order --- src/pages/Ticket/TicketAdvanceFilter.vue | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue index 38a0dd4c2..07c745250 100644 --- a/src/pages/Ticket/TicketAdvanceFilter.vue +++ b/src/pages/Ticket/TicketAdvanceFilter.vue @@ -129,6 +129,12 @@ onMounted(async () => await getItemPackingTypes()); toggle-indeterminate @update:model-value="searchFn()" /> + <QCheckbox + :label="t('globals.params.myTeam')" + v-model="params.myTeam" + toggle-indeterminate + @update:model-value="searchFn()" + /> </QItemSection> </QItem> <QItem> @@ -147,16 +153,6 @@ onMounted(async () => await getItemPackingTypes()); </VnSelect> </QItemSection> </QItem> - <QItem> - <QItemSection> - <QCheckbox - :label="t('globals.params.myTeam')" - v-model="params.myTeam" - toggle-indeterminate - @update:model-value="searchFn()" - /> - </QItemSection> - </QItem> </template> </VnFilterPanel> </template> From 0fbd5f45e1c929aaaa1c1918c346ee9e7fcb56eb Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Mon, 21 Oct 2024 14:29:29 +0200 Subject: [PATCH 3/8] fix: refs #7524 select department --- src/i18n/locale/en.yml | 1 + src/i18n/locale/es.yml | 1 + src/pages/Ticket/TicketAdvanceFilter.vue | 17 ++++++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index 17a3e097a..1c17e92f9 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -297,6 +297,7 @@ globals: To: To stateFk: State myTeam: My team + departmentFk: Department errors: statusUnauthorized: Access denied statusInternalServerError: An internal server error has ocurred diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index fc61936d2..5d3d9d859 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -301,6 +301,7 @@ globals: To: Hasta stateFk: Estado myTeam: Mi equipo + departmentFk: Departamento errors: statusUnauthorized: Acceso denegado statusInternalServerError: Ha ocurrido un error interno del servidor diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue index 07c745250..182f715a3 100644 --- a/src/pages/Ticket/TicketAdvanceFilter.vue +++ b/src/pages/Ticket/TicketAdvanceFilter.vue @@ -129,11 +129,18 @@ onMounted(async () => await getItemPackingTypes()); toggle-indeterminate @update:model-value="searchFn()" /> - <QCheckbox - :label="t('globals.params.myTeam')" - v-model="params.myTeam" - toggle-indeterminate - @update:model-value="searchFn()" + </QItemSection> + </QItem> + <QItem> + <QItemSection> + <VnSelect + :label="t('globals.params.departmentFk')" + v-model="params.departmentFk" + url="Departments" + :fields="['id', 'name']" + dense + outlined + rounded /> </QItemSection> </QItem> From f751408de2bfc1e34e6294f294de7365dd699a07 Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Tue, 22 Oct 2024 13:22:43 +0200 Subject: [PATCH 4/8] feat: refs #8083 add change state btn --- src/components/VnTable/VnTable.vue | 3 + src/components/common/VnBtnSelect.vue | 19 + src/i18n/locale/en.yml | 2 +- src/i18n/locale/es.yml | 2 +- src/pages/Claim/Card/ClaimSummary.vue | 2 +- src/pages/Ticket/Card/TicketExpedition.vue | 338 +++++++----------- src/pages/Ticket/Card/TicketSummary.vue | 2 +- .../ticket/ticketExpedition.spec.js | 28 ++ test/cypress/support/commands.js | 8 + 9 files changed, 190 insertions(+), 214 deletions(-) create mode 100644 src/components/common/VnBtnSelect.vue create mode 100644 test/cypress/integration/ticket/ticketExpedition.spec.js diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index f18892a31..9d64591e9 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -127,6 +127,7 @@ const splittedColumns = ref({ columns: [] }); const columnsVisibilitySkipped = ref(); const createForm = ref(); const tableFilterRef = ref([]); +const tableRef = ref(); const tableModes = [ { @@ -308,6 +309,7 @@ defineExpose({ selected, CrudModelRef, params, + tableRef, }); function handleOnDataSaved(_) { @@ -398,6 +400,7 @@ function handleOnDataSaved(_) { </template> <template #body="{ rows }"> <QTable + ref="tableRef" v-bind="table" class="vnTable" :columns="splittedColumns.columns" diff --git a/src/components/common/VnBtnSelect.vue b/src/components/common/VnBtnSelect.vue new file mode 100644 index 000000000..b0616a6b2 --- /dev/null +++ b/src/components/common/VnBtnSelect.vue @@ -0,0 +1,19 @@ +<script setup> +import VnSelect from './VnSelect.vue'; + +defineProps({ + selectProps: { type: Object, required: true }, + promise: { type: Function, default: () => {} }, +}); +</script> +<template> + <QBtnDropdown v-bind="$attrs" color="primary"> + <VnSelect + v-bind="selectProps" + hide-selected + hide-dropdown-icon + focus-on-mount + @update:model-value="promise" + /> + </QBtnDropdown> +</template> diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index 7eb3829fe..33ecb4850 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -296,6 +296,7 @@ globals: from: From To: To stateFk: State + changeState: Change state errors: statusUnauthorized: Access denied statusInternalServerError: An internal server error has ocurred @@ -538,7 +539,6 @@ ticket: package: Package taxClass: Tax class services: Services - changeState: Change state requester: Requester atender: Atender request: Request diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index 9d5cd53f3..f8a796116 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -300,6 +300,7 @@ globals: from: Desde To: Hasta stateFk: Estado + changeState: Cambiar estado errors: statusUnauthorized: Acceso denegado statusInternalServerError: Ha ocurrido un error interno del servidor @@ -547,7 +548,6 @@ ticket: package: Embalaje taxClass: Tipo IVA services: Servicios - changeState: Cambiar estado requester: Solicitante atender: Comprador request: Petición de compra diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index d77f718c6..edfa52b4b 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -204,7 +204,7 @@ function claimUrl(section) { top color="black" text-color="white" - :label="t('ticket.summary.changeState')" + :label="t('globals.changeState')" > <QList> <QVirtualScroll diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue index c4ab63b39..987862c22 100644 --- a/src/pages/Ticket/Card/TicketExpedition.vue +++ b/src/pages/Ticket/Card/TicketExpedition.vue @@ -1,39 +1,38 @@ <script setup> -import { onMounted, ref, computed, onUnmounted, reactive, watch } from 'vue'; +import { onMounted, ref, computed, onUnmounted, watch } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRoute } from 'vue-router'; -import VnInput from 'src/components/common/VnInput.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; -import TicketEditManaProxy from './TicketEditMana.vue'; -import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import ExpeditionNewTicket from './ExpeditionNewTicket.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; -import VnSelect from 'src/components/common/VnSelect.vue'; import { useStateStore } from 'stores/useStateStore'; -import { toCurrency, toPercentage } from 'src/filters'; import { useArrayData } from 'composables/useArrayData'; import { useVnConfirm } from 'composables/useVnConfirm'; import useNotify from 'src/composables/useNotify.js'; import { toDateTimeFormat } from 'src/filters/date'; import axios from 'axios'; +import VnTable from 'src/components/VnTable/VnTable.vue'; +import VnBtnSelect from 'src/components/common/VnBtnSelect.vue'; +import FetchData from 'src/components/FetchData.vue'; const route = useRoute(); const stateStore = useStateStore(); const { t } = useI18n(); const { notify } = useNotify(); const { openConfirmationModal } = useVnConfirm(); -const editPriceProxyRef = ref(null); const newTicketDialogRef = ref(null); const logsTableDialogRef = ref(null); - +const vnTableRef = ref(); const expeditionsLogsData = ref([]); const selectedExpeditions = ref([]); const allColumnNames = ref([]); -const visibleColumns = ref([]); const newTicketWithRoute = ref(false); +const selectedRows = ref([]); +const hasSelectedRows = computed(() => selectedRows.value.length > 0); +const expeditionStateTypes = ref([]); const exprBuilder = (param, value) => { switch (param) { @@ -54,8 +53,6 @@ const expeditionsArrayData = useArrayData('ticketExpeditions', { filter: expeditionsFilter.value, exprBuilder: exprBuilder, }); -const expeditionsStore = expeditionsArrayData.store; -const ticketExpeditions = computed(() => expeditionsStore.data); const ticketArrayData = useArrayData('ticketData'); const ticketStore = ticketArrayData.store; @@ -73,129 +70,87 @@ watch( { immediate: true } ); -const params = reactive({}); - -const applyColumnFilter = async (col) => { - try { - const paramKey = col.columnFilter?.filterParamKey || col.field; - params[paramKey] = col.columnFilter.filterValue; - await expeditionsArrayData.addFilter({ filter: expeditionsFilter.value, params }); - } catch (err) { - console.error('Error applying column filter', err); - } -}; - -const getInputEvents = (col) => { - return col.columnFilter.type === 'select' - ? { 'update:modelValue': () => applyColumnFilter(col) } - : { - 'keyup.enter': () => applyColumnFilter(col), - }; -}; - const columns = computed(() => [ { + align: 'left', label: t('expedition.id'), name: 'id', - field: 'id', - align: 'left', - sortable: true, + chip: { + condition: () => true, + }, + isId: true, columnFilter: { - component: VnInput, - type: 'text', - filterParamKey: 'expeditionFk', - filterValue: null, - event: getInputEvents, - attrs: { - dense: true, - }, + inWhere: true, }, }, { label: t('expedition.item'), - name: 'item', + name: 'packagingItemFk', align: 'left', + cardVisible: true, columnFilter: { - component: VnInput, - type: 'text', - filterParamKey: 'packageItemName', - filterValue: null, - event: getInputEvents, - attrs: { - dense: true, - }, + inWhere: true, }, }, { label: t('expedition.name'), - name: 'name', - field: 'packageItemName', + name: 'packageItemName', align: 'left', + isTitle: true, columnFilter: { - component: VnSelect, - type: 'select', - filterValue: null, - event: getInputEvents, - attrs: { - url: 'Items', - fields: ['id', 'name'], - 'sort-by': 'name ASC', - 'option-value': 'id', - 'option-label': 'name', - dense: true, - }, + inWhere: true, }, }, { label: t('expedition.packageType'), - name: 'packageType', - field: 'freightItemName', + name: 'freightItemName', align: 'left', columnFilter: { - component: VnInput, - type: 'text', - // filterParamKey: 'expeditionFk', - filterValue: null, - event: getInputEvents, - attrs: { - dense: true, - }, + inWhere: true, }, }, { label: t('expedition.counter'), name: 'counter', - field: 'counter', align: 'left', - columnFilter: null, + columnFilter: { + inWhere: true, + }, }, { label: t('expedition.externalId'), name: 'externalId', - field: 'externalId', align: 'left', - columnFilter: null, + cardVisible: true, + columnFilter: { + inWhere: true, + }, }, { label: t('expedition.created'), name: 'created', - field: 'created', align: 'left', - columnFilter: null, - format: (value) => toDateTimeFormat(value), + cardVisible: true, + format: (row) => toDateTimeFormat(row.created), }, { label: t('expedition.state'), name: 'state', - field: 'state', align: 'left', - columnFilter: null, + cardVisible: true, + columnFilter: { inWhere: true }, }, { - label: '', - name: 'history', - align: 'left', - columnFilter: null, + align: 'right', + name: 'tableActions', + actions: [ + { + title: t('expedition.historyAction'), + icon: 'history', + isPrimary: true, + action: (row) => showLog(row), + }, + ], }, ]); @@ -204,23 +159,29 @@ const logTableColumns = computed(() => [ label: t('expedition.state'), name: 'state', field: 'state', - align: 'left', + align: 'center', sortable: true, }, { label: t('expedition.name'), name: 'name', - align: 'name', + field: 'name', + align: 'center', columnFilter: null, }, { label: t('expedition.created'), name: 'created', field: 'created', - align: 'left', - columnFilter: null, + align: 'center', format: (value) => toDateTimeFormat(value), }, + { + label: t('expedition.isScanned'), + name: 'isScanned', + field: 'isScanned', + align: 'center', + }, ]); const showNewTicketDialog = (withRoute = false) => { @@ -255,10 +216,20 @@ const getExpeditionState = async (expedition) => { order: ['created DESC'], }; - const { data } = await axios.get(`ExpeditionStates/filter`, { + const { data: expeditionStates } = await axios.get(`ExpeditionStates/filter`, { params: { filter: JSON.stringify(filter) }, }); - expeditionsLogsData.value = data; + const { data: scannedStates } = await axios.get(`ExpeditionStates`, { + params: { filter: JSON.stringify(filter), fields: ['id', 'isScanned'] }, + }); + + expeditionsLogsData.value = expeditionStates.map((state) => { + const scannedState = scannedStates.find((s) => s.id === state.id); + return { + ...state, + isScanned: scannedState ? scannedState.isScanned : false, + }; + }); } catch (error) { console.error(error); } @@ -274,22 +245,39 @@ onUnmounted(() => (stateStore.rightDrawer = false)); </script> <template> + <FetchData + url="expeditionStateTypes" + @on-fetch="(data) => (expeditionStateTypes = data)" + auto-load + /> <VnSubToolbar> - <template #st-data> - <TableVisibleColumns - :all-columns="allColumnNames" - table-code="expeditionIndex" - labels-traductions-path="expedition" - @on-config-saved="visibleColumns = [...$event, 'history']" - /> - </template> <template #st-actions> <QBtnGroup push class="q-gutter-x-sm" flat> + <VnBtnSelect + :disable="!hasSelectedRows" + color="primary" + :label="t('globals.changeState')" + :select-props="{ + options: expeditionStateTypes, + optionLabel: 'description', + }" + :promise=" + async (stateTypeFk) => { + await vnTableRef.CrudModelRef.saveChanges({ + updates: selectedRows.map(({ id }) => ({ + data: { stateTypeFk }, + where: { id }, + })), + }); + vnTableRef.tableRef.clearSelection(); + } + " + /> <QBtnDropdown ref="btnDropdownRef" color="primary" :label="t('expedition.move')" - :disable="!selectedExpeditions.length" + :disable="!hasSelectedRows" > <template #label> <QTooltip>{{ t('Select lines to see the options') }}</QTooltip> @@ -322,7 +310,7 @@ onUnmounted(() => (stateStore.rightDrawer = false)); </QList> </QBtnDropdown> <QBtn - :disable="!selectedExpeditions.length" + :disable="!hasSelectedRows" icon="delete" color="primary" @click=" @@ -332,115 +320,34 @@ onUnmounted(() => (stateStore.rightDrawer = false)); deleteExpedition ) " - /> + > + <QTooltip>{{ t('expedition.removeExpedition') }}</QTooltip> + </QBtn> </QBtnGroup> </template> </VnSubToolbar> - - <QTable - :rows="ticketExpeditions" + <VnTable + ref="vnTableRef" + data-key="TicketExpedition" + url="Expeditions/filter" :columns="columns" - row-key="id" - :pagination="{ rowsPerPage: 0 }" - class="full-width q-mt-md" - selection="multiple" - v-model:selected="selectedExpeditions" - :visible-columns="visibleColumns" - :no-data-label="t('globals.noResults')" + :filter="expeditionsFilter" + v-model:selected="selectedRows" + :table="{ + 'row-key': 'id', + selection: 'multiple', + }" + save-url="Expeditions/crud" + auto-load + order="created DESC" > - <template #top-row="{ cols }"> - <QTr> - <QTd /> - <QTd v-for="(col, index) in cols" :key="index" style="max-width: 100px"> - <component - :is="col.columnFilter.component" - v-if="col.columnFilter" - v-model="col.columnFilter.filterValue" - v-bind="col.columnFilter.attrs" - v-on="col.columnFilter.event(col)" - dense - /> - </QTd> - </QTr> - </template> - <template #body-cell-item="{ row }"> - <QTd auto-width @click.stop> - <QBtn flat color="primary">{{ row.packagingItemFk }}</QBtn> + <template #column-packagingItemFk="{ row }"> + <span class="link" @click.stop> + {{ row.packagingItemFk }} <ItemDescriptorProxy :id="row.packagingItemFk" /> - </QTd> + </span> </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-price="{ row }"> - <QTd> - <template v-if="isTicketEditable && row.id"> - <QBtn flat color="primary" dense @click="onOpenEditPricePopover(row)"> - {{ toCurrency(row.price) }} - </QBtn> - <TicketEditManaProxy - ref="editPriceProxyRef" - :mana="mana" - :new-price="getNewPrice" - @save="updatePrice(row)" - > - <VnInput - v-model.number="edit.price" - :label="t('ticketSale.price')" - type="number" - /> - </TicketEditManaProxy> - </template> - <span v-else>{{ toCurrency(row.price) }}</span> - </QTd> - </template> - <template #body-cell-discount="{ row }"> - <QTd> - <template v-if="!isLocked && row.id"> - <QBtn - flat - color="primary" - dense - @click="onOpenEditDiscountPopover(row)" - > - {{ toPercentage(row.discount / 100) }} - </QBtn> - <TicketEditManaProxy - :mana="mana" - :new-price="getNewPrice" - @save="changeDiscount(row)" - > - <VnInput - v-model.number="edit.discount" - :label="t('ticketSale.discount')" - type="number" - /> - </TicketEditManaProxy> - </template> - <span v-else>{{ toPercentage(row.discount / 100) }}</span> - </QTd> - </template> - <template #body-cell-history="{ row }"> - <QTd> - <QBtn - @click.stop="showLog(row)" - color="primary" - icon="history" - size="md" - flat - > - <QTooltip class="text-no-wrap"> - {{ t('expedition.historyAction') }} - </QTooltip> - </QBtn> - </QTd> - </template> - </QTable> + </VnTable> <QDialog ref="newTicketDialogRef" transition-show="scale" transition-hide="scale"> <ExpeditionNewTicket :ticket="ticketData" @@ -454,12 +361,23 @@ onUnmounted(() => (stateStore.rightDrawer = false)); data-key="TicketExpeditionLog" :rows="expeditionsLogsData" :columns="logTableColumns" - class="q-pa-sm" + class="q-pa-md full-width" > <template #body-cell-name="{ row }"> - <QTd auto-width> - <QBtn flat dense color="primary">{{ row.name }}</QBtn> - <WorkerDescriptorProxy :id="row.workerFk" /> + <QTd style="text-align: center"> + <span class="link" @click.stop> + <QBtn flat dense>{{ row.name }}</QBtn> + <WorkerDescriptorProxy :id="row.workerFk" /> + </span> + </QTd> + </template> + <template #body-cell-isScanned="{ row }"> + <QTd style="text-align: center"> + <QCheckbox disable v-model="row.isScanned"> + {{ + row.isScanned === 1 ? t('expedition.yes') : t('expedition.no') + }} + </QCheckbox> </QTd> </template> </QTable> diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue index 1f2a7ca79..358f74af2 100644 --- a/src/pages/Ticket/Card/TicketSummary.vue +++ b/src/pages/Ticket/Card/TicketSummary.vue @@ -105,7 +105,7 @@ async function changeState(value) { ref="stateBtnDropdownRef" color="black" text-color="white" - :label="t('ticket.summary.changeState')" + :label="t('globals.changeState')" :disable="!isEditable()" > <VnSelect diff --git a/test/cypress/integration/ticket/ticketExpedition.spec.js b/test/cypress/integration/ticket/ticketExpedition.spec.js new file mode 100644 index 000000000..5eb2c1a2a --- /dev/null +++ b/test/cypress/integration/ticket/ticketExpedition.spec.js @@ -0,0 +1,28 @@ +/// <reference types="cypress" /> + +describe('Ticket expedtion', () => { + const tableContent = '.q-table .q-virtual-scroll__content'; + const stateTd = 'td:nth-child(9)'; + + beforeEach(() => { + cy.login('developer'); + cy.viewport(1920, 1080); + }); + + it('should change the state', () => { + cy.visit('#/ticket/1/expedition'); + cy.intercept('GET', /\/api\/Expeditions\/filter/).as('expeditions'); + cy.intercept('POST', /\/api\/Expeditions\/crud/).as('crud'); + + cy.wait('@expeditions'); + + cy.selectRows([1, 2]); + cy.get('#subToolbar [aria-controls]:nth-child(1)').click(); + cy.get('.q-menu .q-item').contains('Perdida').click(); + cy.wait('@crud'); + + cy.get(`${tableContent} tr:nth-child(-n+2) ${stateTd}`).each(($el) => { + cy.wrap($el).contains('Perdida'); + }); + }); +}); diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js index 43788f59f..f895d7bb3 100755 --- a/test/cypress/support/commands.js +++ b/test/cypress/support/commands.js @@ -152,6 +152,14 @@ Cypress.Commands.add('notificationHas', (selector, text) => { cy.get(selector).should('have.text', text); }); +Cypress.Commands.add('selectRows', (rows) => { + rows.forEach((row) => { + cy.get('.q-table .q-virtual-scroll__content tr .q-checkbox__inner') + .eq(row - 1) + .click(); + }); +}); + Cypress.Commands.add('fillRow', (rowSelector, data) => { // Usar el selector proporcionado para obtener la fila deseada cy.waitForElement('tbody'); From b1a511ff6f7aee7fb218e78f909d7b73a4e98ac3 Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Tue, 22 Oct 2024 14:21:03 +0200 Subject: [PATCH 5/8] fix: refs #8083 delete btn & redirect --- src/pages/Ticket/Card/TicketExpedition.vue | 47 +++++++--------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue index 987862c22..61cedc1bf 100644 --- a/src/pages/Ticket/Card/TicketExpedition.vue +++ b/src/pages/Ticket/Card/TicketExpedition.vue @@ -1,5 +1,5 @@ <script setup> -import { onMounted, ref, computed, onUnmounted, watch } from 'vue'; +import { onMounted, ref, computed, onUnmounted } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRoute } from 'vue-router'; @@ -34,42 +34,15 @@ const selectedRows = ref([]); const hasSelectedRows = computed(() => selectedRows.value.length > 0); const expeditionStateTypes = ref([]); -const exprBuilder = (param, value) => { - switch (param) { - case 'expeditionFk': - return { id: value }; - case 'packageItemName': - return { packagingItemFk: value }; - } -}; - const expeditionsFilter = computed(() => ({ where: { ticketFk: route.params.id }, order: ['created DESC'], })); -const expeditionsArrayData = useArrayData('ticketExpeditions', { - url: 'Expeditions/filter', - filter: expeditionsFilter.value, - exprBuilder: exprBuilder, -}); - const ticketArrayData = useArrayData('ticketData'); const ticketStore = ticketArrayData.store; const ticketData = computed(() => ticketStore.data); -const refetchExpeditions = async () => { - await expeditionsArrayData.applyFilter({ - filter: expeditionsFilter.value, - }); -}; - -watch( - () => route.params.id, - async () => await refetchExpeditions(), - { immediate: true } -); - const columns = computed(() => [ { align: 'left', @@ -191,12 +164,10 @@ const showNewTicketDialog = (withRoute = false) => { const deleteExpedition = async () => { try { - const expeditionIds = selectedExpeditions.value.map( - (expedition) => expedition.id - ); + const expeditionIds = selectedRows.value.map((expedition) => expedition.id); const params = { expeditionIds }; await axios.post('Expeditions/deleteExpeditions', params); - await refetchExpeditions(); + vnTableRef.value.reload(); selectedExpeditions.value = []; notify(t('expedition.expeditionRemoved'), 'positive'); } catch (error) { @@ -330,6 +301,7 @@ onUnmounted(() => (stateStore.rightDrawer = false)); ref="vnTableRef" data-key="TicketExpedition" url="Expeditions/filter" + search-url="expeditions" :columns="columns" :filter="expeditionsFilter" v-model:selected="selectedRows" @@ -339,7 +311,16 @@ onUnmounted(() => (stateStore.rightDrawer = false)); }" save-url="Expeditions/crud" auto-load - order="created DESC" + :expr-builder=" + (param, value) => { + switch (param) { + case 'expeditionFk': + return { id: value }; + case 'packageItemName': + return { packagingItemFk: value }; + } + } + " > <template #column-packagingItemFk="{ row }"> <span class="link" @click.stop> From da4c1e9c12fab1a686df8866d3b8c2e3d41f75af Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Tue, 22 Oct 2024 14:36:30 +0200 Subject: [PATCH 6/8] fix: refs #8083 add order --- src/pages/Ticket/Card/TicketExpedition.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue index 61cedc1bf..307c42645 100644 --- a/src/pages/Ticket/Card/TicketExpedition.vue +++ b/src/pages/Ticket/Card/TicketExpedition.vue @@ -321,6 +321,7 @@ onUnmounted(() => (stateStore.rightDrawer = false)); } } " + order="created DESC" > <template #column-packagingItemFk="{ row }"> <span class="link" @click.stop> From 033d6bddbee60806a5311f48ad5719639db6e844 Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Tue, 22 Oct 2024 14:43:43 +0200 Subject: [PATCH 7/8] fix: refs #8083 move expeditions --- src/pages/Ticket/Card/TicketExpedition.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue index 307c42645..93749ebec 100644 --- a/src/pages/Ticket/Card/TicketExpedition.vue +++ b/src/pages/Ticket/Card/TicketExpedition.vue @@ -334,7 +334,7 @@ onUnmounted(() => (stateStore.rightDrawer = false)); <ExpeditionNewTicket :ticket="ticketData" :with-route="newTicketWithRoute" - :selected-expeditions="selectedExpeditions" + :selected-expeditions="selectedRows" /> </QDialog> <QDialog ref="logsTableDialogRef" transition-show="scale" transition-hide="scale"> From 81a55a9e7a9960dcb7f66dac86add05f3d3107f2 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Tue, 22 Oct 2024 14:55:47 +0200 Subject: [PATCH 8/8] chore: test gitea --- src/components/VnTable/VnTable.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index 9d64591e9..9209eaf7b 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -794,6 +794,7 @@ es: top: 0; } } + .vnTable { thead tr th { position: sticky;