8315-devToTest #1094

Merged
alexm merged 253 commits from 8315-devToTest into test 2024-12-18 10:31:55 +00:00
8 changed files with 183 additions and 10 deletions
Showing only changes of commit ad27eef162 - Show all commits

View File

@ -329,6 +329,7 @@ globals:
email: Email
SSN: SSN
fi: FI
packing: ITP
myTeam: My team
departmentFk: Department
countryFk: Country

View File

@ -335,6 +335,7 @@ globals:
SSN: NSS
fi: NIF
myTeam: Mi equipo
packing: ITP
countryFk: País
changePass: Cambiar contraseña
deleteConfirmTitle: Eliminar los elementos seleccionados

View File

@ -134,6 +134,7 @@ const getLocale = (label) => {
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
@ -209,6 +210,34 @@ const getLocale = (label) => {
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
:label="t('globals.params.departmentFk')"
v-model="params.department"
option-label="name"
option-value="name"
url="Departments"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
:label="t('globals.params.packing')"
v-model="params.packing"
url="ItemPackingTypes"
option-label="code"
option-value="code"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QCheckbox
@ -258,7 +287,7 @@ en:
ON_PREVIOUS: On previous
PACKED: Packed
No one: No one
es:
params:
orderFk: Id cesta

View File

@ -24,6 +24,9 @@ const tableRef = ref(null);
const provinceOpts = ref([]);
const stateOpts = ref([]);
const zoneOpts = ref([]);
const DepartmentOpts = ref([]);
const ItemPackingTypeOpts = ref([]);
const visibleColumns = ref([]);
const { viewSummary } = useSummaryDialog();
const [from, to] = dateRange(Date.vnNew());
@ -51,6 +54,8 @@ function exprBuilder(param, value) {
case 'nickname':
return { [`t.nickname`]: { like: `%${value}%` } };
case 'zoneFk':
case 'department':
return { 'd.name': value };
case 'totalWithVat':
return { [`t.${param}`]: value };
}
@ -137,6 +142,7 @@ const columns = computed(() => [
align: 'left',
format: (row) => row.practicalHour,
columnFilter: false,
dense: true,
},
{
label: t('salesTicketsTable.preparation'),
@ -190,6 +196,7 @@ const columns = computed(() => [
'false-value': 0,
'true-value': 1,
},
component: false,
},
{
label: t('salesTicketsTable.zone'),
@ -206,6 +213,12 @@ const columns = computed(() => [
},
},
},
{
label: t('salesTicketsTable.payMethod'),
name: 'payMethod',
align: 'left',
columnFilter: false,
},
{
label: t('salesTicketsTable.total'),
name: 'totalWithVat',
@ -219,6 +232,36 @@ const columns = computed(() => [
},
},
},
{
label: t('salesTicketsTable.department'),
name: 'department',
align: 'left',
columnFilter: {
component: 'select',
url: 'Departments',
attrs: {
options: DepartmentOpts.value,
optionValue: 'name',
optionLabel: 'name',
dense: true,
},
},
},
{
label: t('salesTicketsTable.packing'),
name: 'packing',
align: 'left',
columnFilter: {
component: 'select',
url: 'ItemPackingTypes',
attrs: {
options: ItemPackingTypeOpts.value,
'option-value': 'code',
'option-label': 'code',
dense: true,
},
},
},
{
align: 'right',
name: 'tableActions',
@ -318,6 +361,24 @@ const openTab = (id) =>
auto-load
@on-fetch="(data) => (zoneOpts = data)"
/>
<FetchData
url="ItemPackingTypes"
:filter="{
fields: ['code'],
order: 'code ASC',
}"
auto-load
@on-fetch="(data) => (ItemPackingTypeOpts = data)"
/>
<FetchData
url="Departments"
:filter="{
fields: ['id', 'name'],
order: 'id ASC',
}"
auto-load
@on-fetch="(data) => (DepartmentOpts = data)"
/>
<MonitorTicketSearchbar />
<RightMenu>
<template #right-panel>
@ -337,7 +398,7 @@ const openTab = (id) =>
auto-load
:row-click="({ id }) => openTab(id)"
:disable-option="{ card: true }"
:user-params="{ from, to, scopeDays: 0 }"
:user-params="{ from, to, scopeDays: 0, packing }"
>
<template #top-left>
<QBtn

View File

@ -26,8 +26,8 @@ salesTicketsTable:
componentLack: Component lack
tooLittle: Ticket too little
identifier: Identifier
theoretical: Theoretical
practical: Practical
theoretical: H.Theor
practical: H.Prac
province: Province
state: State
isFragile: Is fragile
@ -35,7 +35,10 @@ salesTicketsTable:
goToLines: Go to lines
preview: Preview
total: Total
preparation: Preparation
preparation: H.Prep
payMethod: Pay method
department: Department
packing: ITP
searchBar:
label: Search tickets
info: Search tickets by id or alias

View File

@ -26,8 +26,8 @@ salesTicketsTable:
componentLack: Faltan componentes
tooLittle: Ticket demasiado pequeño
identifier: Identificador
theoretical: Teórica
practical: Práctica
theoretical: H.Teór
practical: H.Prác
province: Provincia
state: Estado
isFragile: Es frágil
@ -35,7 +35,10 @@ salesTicketsTable:
goToLines: Ir a líneas
preview: Vista previa
total: Total
preparation: Preparación
preparation: H.Prep
payMethod: Método de pago
department: Departamento
packing: ITP
searchBar:
label: Buscar tickets
info: Buscar tickets por identificador o alias

View File

@ -1,6 +1,6 @@
<script setup>
import axios from 'axios';
import { computed, ref, toRefs } from 'vue';
import { computed, onMounted, ref, toRefs, watch } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
@ -24,6 +24,15 @@ const props = defineProps({
},
});
onMounted(() => {
restoreTicket();
});
watch(
() => props.ticket,
() => restoreTicket
);
const { push, currentRoute } = useRouter();
const { dialog, notify } = useQuasar();
const { t } = useI18n();
@ -42,6 +51,7 @@ const hasPdf = ref();
const weight = ref();
const hasDocuwareFile = ref();
const quasar = useQuasar();
const canRestoreTicket = ref(false);
const actions = {
clone: async () => {
const opts = { message: t('Ticket cloned'), type: 'positive' };
@ -373,6 +383,54 @@ async function uploadDocuware(force) {
if (data) notify({ message: t('PDF sent!'), type: 'positive' });
}
const restoreTicket = async () => {
const filter = {
fields: ['id', 'originFk', 'creationDate', 'newInstance'],
where: {
originFk: ticketId.value,
newInstance: { like: '%"isDeleted":true%' },
},
order: 'creationDate DESC',
limit: 1,
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`TicketLogs`, { params });
if (data && data.length) {
const now = Date.vnNew();
const maxDate = new Date(data[0].creationDate);
maxDate.setHours(maxDate.getHours() + 1);
if (now <= maxDate) {
return (canRestoreTicket.value = true);
}
return (canRestoreTicket.value = false);
}
return (canRestoreTicket.value = false);
};
async function openRestoreConfirmation(force) {
if (!force)
return quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t('Are you sure you want to restore the ticket?'),
message: t('You are going to restore this ticket'),
},
})
.onOk(async () => {
ticketToRestore();
});
}
async function ticketToRestore() {
const { data } = await axios.post(`Tickets/${ticketId.value}/restore`);
if (data) {
notify({ message: t('Ticket restored'), type: 'positive' });
}
}
</script>
<template>
<FetchData
@ -560,6 +618,12 @@ async function uploadDocuware(force) {
</QItemSection>
<QItemSection>{{ t('Show Proforma') }}</QItemSection>
</QItem>
<QItem v-if="canRestoreTicket" @click="openRestoreConfirmation()" v-ripple clickable>
<QItemSection avatar>
<QIcon name="restore" />
</QItemSection>
<QItemSection>{{ t('Restore ticket') }}</QItemSection>
</QItem>
<QItem
v-if="isEditable"
@click="showChangeTimeDialog = !showChangeTimeDialog"
@ -746,4 +810,8 @@ es:
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?
Restore ticket: Restaurar ticket
Are you sure you want to restore the ticket?: ¿Seguro que quieres restaurar el ticket?
You are going to restore this ticket: Vas a restaurar este ticket
Ticket restored: Ticket restaurado
</i18n>

View File

@ -1,5 +1,6 @@
describe('ZoneBasicData', () => {
const notification = '.q-notification__message';
const priceBasicData = '[data-cy="Price_input"]';
beforeEach(() => {
cy.viewport(1280, 720);
@ -13,9 +14,15 @@ describe('ZoneBasicData', () => {
cy.get(notification).should('contains.text', "can't be blank");
});
it('should throw an error if the price is empty', () => {
cy.get(priceBasicData).clear();
cy.get('.q-btn-group > .q-btn--standard').click();
cy.get(notification).should('contains.text', 'cannot be blank');
});
it("should edit the basicData's zone", () => {
cy.get('.q-card > :nth-child(1)').type(' modified');
cy.get('.q-btn-group > .q-btn--standard').click();
cy.get(notification).should('contains.text', 'Data saved');
cy.checkNotification('Data saved');
});
});