forked from verdnatura/salix-front
Merge branch 'dev' into Fix_OrderModuleProblems
This commit is contained in:
commit
76ed5150a5
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
|
|
|
@ -316,6 +316,7 @@ defineExpose({
|
|||
selected,
|
||||
CrudModelRef,
|
||||
params,
|
||||
tableRef,
|
||||
});
|
||||
|
||||
function handleOnDataSaved(_) {
|
||||
|
@ -815,6 +816,7 @@ es:
|
|||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vnTable {
|
||||
thead tr th {
|
||||
position: sticky;
|
||||
|
|
|
@ -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>
|
|
@ -304,12 +304,14 @@ globals:
|
|||
from: From
|
||||
To: To
|
||||
stateFk: State
|
||||
departmentFk: Department
|
||||
email: Email
|
||||
SSN: SSN
|
||||
fi: FI
|
||||
myTeam: My team
|
||||
departmentFk: Department
|
||||
changePass: Change password
|
||||
deleteConfirmTitle: Delete selected elements
|
||||
changeState: Change state
|
||||
errors:
|
||||
statusUnauthorized: Access denied
|
||||
statusInternalServerError: An internal server error has ocurred
|
||||
|
@ -556,7 +558,6 @@ ticket:
|
|||
package: Package
|
||||
taxClass: Tax class
|
||||
services: Services
|
||||
changeState: Change state
|
||||
requester: Requester
|
||||
atender: Atender
|
||||
request: Request
|
||||
|
|
|
@ -312,8 +312,10 @@ globals:
|
|||
email: Correo
|
||||
SSN: NSS
|
||||
fi: NIF
|
||||
myTeam: Mi equipo
|
||||
changePass: Cambiar contraseña
|
||||
deleteConfirmTitle: Eliminar los elementos seleccionados
|
||||
changeState: Cambiar estado
|
||||
errors:
|
||||
statusUnauthorized: Acceso denegado
|
||||
statusInternalServerError: Ha ocurrido un error interno del servidor
|
||||
|
@ -565,7 +567,6 @@ ticket:
|
|||
package: Embalaje
|
||||
taxClass: Tipo IVA
|
||||
services: Servicios
|
||||
changeState: Cambiar estado
|
||||
requester: Solicitante
|
||||
atender: Comprador
|
||||
request: Petición de compra
|
||||
|
|
|
@ -204,7 +204,7 @@ function claimUrl(section) {
|
|||
top
|
||||
color="black"
|
||||
text-color="white"
|
||||
:label="t('ticket.summary.changeState')"
|
||||
:label="t('globals.changeState')"
|
||||
>
|
||||
<QList>
|
||||
<QVirtualScroll
|
||||
|
|
|
@ -258,15 +258,28 @@ onBeforeMount(() => {
|
|||
<template #body-cell-attender="{ row }">
|
||||
<QTd>
|
||||
<VnSelect
|
||||
url="Workers/search"
|
||||
v-model="row.attenderFk"
|
||||
:where="{ role: 'buyer' }"
|
||||
sort-by="id"
|
||||
url="Workers"
|
||||
:params="{ departmentCodes: ['shopping'] }"
|
||||
:fields="['id', 'nickname']"
|
||||
sort-by="nickname ASC"
|
||||
hide-selected
|
||||
option-label="firstName"
|
||||
option-label="nickname"
|
||||
option-value="id"
|
||||
dense
|
||||
/>
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption
|
||||
>{{ scope.opt?.nickname }},
|
||||
{{ scope.opt?.code }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-item="{ row }">
|
||||
|
|
|
@ -52,15 +52,27 @@ const redirectToItemTypeBasicData = (_, { id }) => {
|
|||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
url="Workers/search"
|
||||
v-model="data.workerFk"
|
||||
:label="t('itemType.shared.worker')"
|
||||
url="Workers"
|
||||
sort-by="firstName ASC"
|
||||
:fields="['id', 'firstName']"
|
||||
:label="t('shared.worker')"
|
||||
sort-by="nickname ASC"
|
||||
:fields="['id', 'nickname']"
|
||||
:params="{ departmentCodes: ['shopping'] }"
|
||||
option-label="nickname"
|
||||
option-value="id"
|
||||
option-label="firstName"
|
||||
hide-selected
|
||||
/>
|
||||
><template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption
|
||||
>{{ scope.opt?.nickname }},
|
||||
{{ scope.opt?.code }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnSelect
|
||||
v-model="data.categoryFk"
|
||||
:label="t('itemType.shared.category')"
|
||||
|
|
|
@ -41,15 +41,27 @@ const temperaturesOptions = ref([]);
|
|||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
url="Workers/search"
|
||||
v-model="data.workerFk"
|
||||
:label="t('shared.worker')"
|
||||
url="Workers"
|
||||
sort-by="firstName ASC"
|
||||
:fields="['id', 'firstName']"
|
||||
sort-by="nickname ASC"
|
||||
:fields="['id', 'nickname']"
|
||||
:params="{ departmentCodes: ['shopping'] }"
|
||||
option-label="nickname"
|
||||
option-value="id"
|
||||
option-label="firstName"
|
||||
hide-selected
|
||||
/>
|
||||
><template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption
|
||||
>{{ scope.opt?.nickname }},
|
||||
{{ scope.opt?.code }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template></VnSelect
|
||||
>
|
||||
<VnSelect
|
||||
v-model="data.categoryFk"
|
||||
:label="t('shared.category')"
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
@ -15,6 +15,8 @@ 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();
|
||||
|
@ -23,50 +25,24 @@ const { notify } = useNotify();
|
|||
const { openConfirmationModal } = useVnConfirm();
|
||||
const newTicketDialogRef = ref(null);
|
||||
const logsTableDialogRef = ref(null);
|
||||
const tableRef = ref();
|
||||
const vnTableRef = ref();
|
||||
const expeditionsLogsData = ref([]);
|
||||
const selectedExpeditions = ref([]);
|
||||
const allColumnNames = ref([]);
|
||||
const newTicketWithRoute = ref(false);
|
||||
const selectedRows = ref([]);
|
||||
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
|
||||
|
||||
const exprBuilder = (param, value) => {
|
||||
switch (param) {
|
||||
case 'expeditionFk':
|
||||
return { id: value };
|
||||
case 'packageItemName':
|
||||
return { packagingItemFk: value };
|
||||
}
|
||||
};
|
||||
const expeditionStateTypes = ref([]);
|
||||
|
||||
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',
|
||||
|
@ -188,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) {
|
||||
|
@ -242,9 +216,34 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="expeditionStateTypes"
|
||||
@on-fetch="(data) => (expeditionStateTypes = data)"
|
||||
auto-load
|
||||
/>
|
||||
<VnSubToolbar>
|
||||
<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"
|
||||
|
@ -298,11 +297,11 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
</QBtnGroup>
|
||||
</template>
|
||||
</VnSubToolbar>
|
||||
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
ref="vnTableRef"
|
||||
data-key="TicketExpedition"
|
||||
url="Expeditions/filter"
|
||||
search-url="expeditions"
|
||||
:columns="columns"
|
||||
:filter="expeditionsFilter"
|
||||
v-model:selected="selectedRows"
|
||||
|
@ -310,7 +309,18 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
'row-key': 'id',
|
||||
selection: 'multiple',
|
||||
}"
|
||||
save-url="Expeditions/crud"
|
||||
auto-load
|
||||
:expr-builder="
|
||||
(param, value) => {
|
||||
switch (param) {
|
||||
case 'expeditionFk':
|
||||
return { id: value };
|
||||
case 'packageItemName':
|
||||
return { packagingItemFk: value };
|
||||
}
|
||||
}
|
||||
"
|
||||
order="created DESC"
|
||||
>
|
||||
<template #column-packagingItemFk="{ row }">
|
||||
|
@ -324,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">
|
||||
|
|
|
@ -122,37 +122,23 @@ function isOnTicketCard() {
|
|||
</div>
|
||||
</template>
|
||||
<template #header-right>
|
||||
<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>
|
||||
<QBtnDropdown
|
||||
ref="stateBtnDropdownRef"
|
||||
color="black"
|
||||
text-color="white"
|
||||
:label="t('globals.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>
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<QCard class="vn-one">
|
||||
|
|
|
@ -463,6 +463,9 @@ onMounted(async () => {
|
|||
userParams.dateToAdvance = today;
|
||||
userParams.scopeDays = 1;
|
||||
userParams.warehouseFk = user.value.warehouseFk;
|
||||
userParams.ipt = 'H';
|
||||
userParams.futureIpt = 'H';
|
||||
userParams.isFullMovable = true;
|
||||
const filter = { limit: 0 };
|
||||
await arrayData.addFilter({ filter, userParams });
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ import axios from 'axios';
|
|||
import { onMounted } from 'vue';
|
||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { t, te } = useI18n();
|
||||
const props = defineProps({
|
||||
dataKey: {
|
||||
type: String,
|
||||
|
@ -43,6 +43,11 @@ const getItemPackingTypes = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const getLocale = (val) => {
|
||||
const param = `params.${val}`;
|
||||
return te(param) ? t(param) : t(`globals.${param}`);
|
||||
};
|
||||
|
||||
onMounted(async () => await getItemPackingTypes());
|
||||
</script>
|
||||
|
||||
|
@ -60,7 +65,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>
|
||||
|
@ -136,6 +141,19 @@ onMounted(async () => await getItemPackingTypes());
|
|||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnSelect
|
||||
:label="t('globals.params.departmentFk')"
|
||||
v-model="params.departmentFk"
|
||||
url="Departments"
|
||||
:fields="['id', 'name']"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnSelect
|
||||
|
|
|
@ -100,7 +100,7 @@ weeklyTickets:
|
|||
advanceTickets:
|
||||
preparation: Preparación
|
||||
origin: Origen
|
||||
destination: Destinatario
|
||||
destination: Destino
|
||||
originAgency: 'Agencia origen: {agency}'
|
||||
destinationAgency: 'Agencia destino: {agency}'
|
||||
ticketId: ID
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
|
|
Loading…
Reference in New Issue