feat(WorkerPDA): refs #5926 send to docuware #1617
|
@ -633,6 +633,7 @@ const rowCtrlClickFunction = computed(() => {
|
|||
:data-key="$attrs['data-key']"
|
||||
:columns="columns"
|
||||
:redirect="redirect"
|
||||
v-bind="$attrs?.['table-filter']"
|
||||
>
|
||||
<template
|
||||
v-for="(_, slotName) in $slots"
|
||||
|
|
|
@ -5,20 +5,30 @@ import { exportFile } from 'quasar';
|
|||
|
||||
const { getTokenMultimedia } = useSession();
|
||||
const token = getTokenMultimedia();
|
||||
const appUrl = (await getUrl('', 'lilium')).replace('/#/', '');
|
||||
|
||||
export async function downloadFile(id, model = 'dms', urlPath = '/downloadFile', url) {
|
||||
const appUrl = (await getUrl('', 'lilium')).replace('/#/', '');
|
||||
const response = await axios.get(
|
||||
url ?? `${appUrl}/api/${model}/${id}${urlPath}?access_token=${token}`,
|
||||
{ responseType: 'blob' }
|
||||
);
|
||||
|
||||
download(response);
|
||||
}
|
||||
|
||||
export async function downloadDocuware(url, params) {
|
||||
const response = await axios.get(`${appUrl}/api/` + url, {
|
||||
responseType: 'blob',
|
||||
params,
|
||||
});
|
||||
|
||||
download(response);
|
||||
}
|
||||
|
||||
function download(response) {
|
||||
const contentDisposition = response.headers['content-disposition'];
|
||||
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(contentDisposition);
|
||||
const filename =
|
||||
matches != null && matches[1]
|
||||
? matches[1].replace(/['"]/g, '')
|
||||
: 'downloaded-file';
|
||||
const filename = matches?.[1] ? matches[1].replace(/['"]/g, '') : 'downloaded-file';
|
||||
|
||||
exportFile(filename, response.data);
|
||||
}
|
||||
|
|
|
@ -646,6 +646,7 @@ worker:
|
|||
model: Model
|
||||
serialNumber: Serial number
|
||||
removePDA: Deallocate PDA
|
||||
sendToTablet: Send to tablet
|
||||
create:
|
||||
lastName: Last name
|
||||
birth: Birth
|
||||
|
|
|
@ -731,6 +731,7 @@ worker:
|
|||
model: Modelo
|
||||
serialNumber: Número de serie
|
||||
removePDA: Desasignar PDA
|
||||
sendToTablet: Enviar a la tablet
|
||||
create:
|
||||
lastName: Apellido
|
||||
birth: Fecha de nacimiento
|
||||
|
|
|
@ -5,24 +5,25 @@ import { ref, computed } from 'vue';
|
|||
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { downloadDocuware } from 'src/composables/downloadFile';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModelPopup from 'src/components/FormModelPopup.vue';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
|
||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const paginate = ref();
|
||||
const loadingDocuware = ref(true);
|
||||
const tableRef = ref();
|
||||
const dialog = ref();
|
||||
const route = useRoute();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
const routeId = computed(() => route.params.id);
|
||||
|
||||
const worker = computed(() => useArrayData('Worker').store.data);
|
||||
const initialData = computed(() => {
|
||||
return {
|
||||
userFk: routeId.value,
|
||||
|
@ -31,154 +32,277 @@ const initialData = computed(() => {
|
|||
};
|
||||
});
|
||||
|
||||
const deallocatePDA = async (deviceProductionFk) => {
|
||||
await axios.post(`Workers/${route.params.id}/deallocatePDA`, {
|
||||
pda: deviceProductionFk,
|
||||
});
|
||||
notify(t('PDA deallocated'), 'positive');
|
||||
|
||||
paginate.value.fetch();
|
||||
};
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'center',
|
||||
label: t('globals.state'),
|
||||
name: 'state',
|
||||
format: (row) => row?.docuware?.state,
|
||||
columnFilter: false,
|
||||
chip: {
|
||||
condition: (_, row) => !!row.docuware,
|
||||
color: (row) => (isSigned(row) ? 'bg-positive' : 'bg-warning'),
|
||||
},
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
label: t('worker.pda.currentPDA'),
|
||||
name: 'deviceProductionFk',
|
||||
columnClass: 'shrink',
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('Model'),
|
||||
name: 'modelFk',
|
||||
format: ({ deviceProduction }) => deviceProduction.modelFk,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
label: t('Serial number'),
|
||||
name: 'serialNumber',
|
||||
format: ({ deviceProduction }) => deviceProduction.serialNumber,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('Current SIM'),
|
||||
name: 'simFk',
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
name: 'actions',
|
||||
columnFilter: false,
|
||||
cardVisible: true,
|
||||
},
|
||||
]);
|
||||
|
||||
function reloadData() {
|
||||
initialData.value.deviceProductionFk = null;
|
||||
initialData.value.simFk = null;
|
||||
paginate.value.fetch();
|
||||
tableRef.value.reload();
|
||||
}
|
||||
|
||||
async function fetchDocuware() {
|
||||
loadingDocuware.value = true;
|
||||
const id = worker.value?.lastName + ' ' + worker.value?.firstName;
|
||||
const promises = [];
|
||||
|
||||
for (const row of tableRef.value.CrudModelRef.formData) {
|
||||
promises.push(
|
||||
alexm marked this conversation as resolved
|
||||
(async () => {
|
||||
const { data } = await axios.post(`Docuwares/${id}/checkFile`, {
|
||||
fileCabinet: 'hr',
|
||||
signed: false,
|
||||
mergeFilter: [
|
||||
{
|
||||
DBName: 'TIPO_DOCUMENTO',
|
||||
Value: ['PDA'],
|
||||
},
|
||||
{
|
||||
DBName: 'FILENAME',
|
||||
Value: [row.deviceProductionFk + '-pda'],
|
||||
},
|
||||
],
|
||||
});
|
||||
row.docuware = data;
|
||||
})(),
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
loadingDocuware.value = false;
|
||||
}
|
||||
|
||||
async function sendToTablet(rows) {
|
||||
const promises = [];
|
||||
for (const row of rows) {
|
||||
alexm marked this conversation as resolved
Outdated
jsegarra
commented
Reemplazar por map Reemplazar por map
|
||||
promises.push(
|
||||
(async () => {
|
||||
await axios.post(`Docuwares/upload-pda-pdf`, {
|
||||
alexm marked this conversation as resolved
jsegarra
commented
un await pero luego un promises.all? un await pero luego un promises.all?
|
||||
ids: [row.deviceProductionFk],
|
||||
});
|
||||
row.docuware = true;
|
||||
})(),
|
||||
);
|
||||
}
|
||||
await Promise.all(promises);
|
||||
alexm marked this conversation as resolved
Outdated
jsegarra
commented
Promise.all will reject as soon as one of the Promises in the array rejects. Promise.allSettled will never reject - it will resolve once all Promises in the array have either rejected or resolved. Promise.all will reject as soon as one of the Promises in the array rejects.
Promise.allSettled will never reject - it will resolve once all Promises in the array have either rejected or resolved.
jsegarra
commented
1ª ✅ 1ª ✅
2ª 💣
3ª ❌, nunca se ejcutará
|
||||
notify(t('PDF sended to signed'), 'positive');
|
||||
tableRef.value.reload();
|
||||
}
|
||||
|
||||
async function deallocatePDA(deviceProductionFk) {
|
||||
await axios.post(`Workers/${route.params.id}/deallocatePDA`, {
|
||||
pda: deviceProductionFk,
|
||||
});
|
||||
const index = tableRef.value.CrudModelRef.formData.findIndex(
|
||||
(data) => data?.deviceProductionFk == deviceProductionFk,
|
||||
);
|
||||
delete tableRef.value.CrudModelRef.formData[index];
|
||||
notify(t('PDA deallocated'), 'positive');
|
||||
}
|
||||
|
||||
function isSigned(row) {
|
||||
return row.docuware?.state === 'Firmado';
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage class="column items-center q-pa-md centerCard">
|
||||
<FetchData
|
||||
url="workers/getAvailablePda"
|
||||
@on-fetch="(data) => (deviceProductions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<VnPaginate
|
||||
ref="paginate"
|
||||
data-key="WorkerPda"
|
||||
url="DeviceProductionUsers"
|
||||
:user-filter="{ where: { userFk: routeId } }"
|
||||
order="id"
|
||||
search-url="pda"
|
||||
auto-load
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
<QCard
|
||||
flat
|
||||
bordered
|
||||
:key="row.id"
|
||||
v-for="row of rows"
|
||||
class="card q-px-md q-mb-sm container"
|
||||
>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('worker.pda.currentPDA')"
|
||||
:model-value="row?.deviceProductionFk"
|
||||
disable
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('Model')"
|
||||
:model-value="row?.deviceProduction?.modelFk"
|
||||
disable
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('Serial number')"
|
||||
:model-value="row?.deviceProduction?.serialNumber"
|
||||
disable
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('Current SIM')"
|
||||
:model-value="row?.simFk"
|
||||
disable
|
||||
/>
|
||||
<QBtn
|
||||
flat
|
||||
icon="delete"
|
||||
color="primary"
|
||||
class="btn-delete"
|
||||
@click="
|
||||
openConfirmationModal(
|
||||
t(`Remove PDA`),
|
||||
t('Do you want to remove this PDA?'),
|
||||
() => deallocatePDA(row.deviceProductionFk),
|
||||
)
|
||||
"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('worker.pda.removePDA') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</VnRow>
|
||||
</QCard>
|
||||
</template>
|
||||
</VnPaginate>
|
||||
<QPageSticky :offset="[18, 18]">
|
||||
<FetchData
|
||||
url="workers/getAvailablePda"
|
||||
@on-fetch="(data) => (deviceProductions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="WorkerPda"
|
||||
url="DeviceProductionUsers"
|
||||
:user-filter="{ order: 'id' }"
|
||||
:filter="{ where: { userFk: routeId } }"
|
||||
search-url="pda"
|
||||
auto-load
|
||||
:columns="columns"
|
||||
@onFetch="fetchDocuware"
|
||||
:hasSubToolbar="true"
|
||||
:default-remove="false"
|
||||
:default-reset="false"
|
||||
:default-save="false"
|
||||
:table="{
|
||||
'row-key': 'deviceProductionFk',
|
||||
selection: 'multiple',
|
||||
}"
|
||||
:table-filter="{ hiddenTags: ['userFk'] }"
|
||||
>
|
||||
<template #moreBeforeActions>
|
||||
<QBtn
|
||||
@click.stop="dialog.show()"
|
||||
:label="t('globals.refresh')"
|
||||
icon="refresh"
|
||||
@click="tableRef.reload()"
|
||||
/>
|
||||
<QBtn
|
||||
:disable="!tableRef?.selected?.length"
|
||||
:label="t('globals.send')"
|
||||
icon="install_mobile"
|
||||
@click="sendToTablet(tableRef?.selected)"
|
||||
class="bg-primary"
|
||||
/>
|
||||
</template>
|
||||
<template #column-actions="{ row }">
|
||||
<QBtn
|
||||
flat
|
||||
icon="delete"
|
||||
color="primary"
|
||||
fab
|
||||
icon="add"
|
||||
v-shortcut="'+'"
|
||||
@click="
|
||||
openConfirmationModal(
|
||||
t(`Remove PDA`),
|
||||
t('Do you want to remove this PDA?'),
|
||||
() => deallocatePDA(row.deviceProductionFk),
|
||||
)
|
||||
"
|
||||
data-cy="workerPda-remove"
|
||||
>
|
||||
<QDialog ref="dialog">
|
||||
<FormModelPopup
|
||||
:title="t('Add new device')"
|
||||
url-create="DeviceProductionUsers"
|
||||
model="DeviceProductionUser"
|
||||
:form-initial-data="initialData"
|
||||
@on-data-saved="reloadData()"
|
||||
>
|
||||
<template #form-inputs="{ data }">
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('worker.pda.newPDA')"
|
||||
v-model="data.deviceProductionFk"
|
||||
:options="deviceProductions"
|
||||
option-label="id"
|
||||
option-value="id"
|
||||
id="deviceProductionFk"
|
||||
hide-selected
|
||||
data-cy="pda-dialog-select"
|
||||
:required="true"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel
|
||||
>ID: {{ scope.opt?.id }}</QItemLabel
|
||||
>
|
||||
<QItemLabel caption>
|
||||
{{ scope.opt?.modelFk }},
|
||||
{{ scope.opt?.serialNumber }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnInput
|
||||
v-model="data.simFk"
|
||||
:label="t('SIM serial number')"
|
||||
id="simSerialNumber"
|
||||
use-input
|
||||
/>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
</QDialog>
|
||||
<QTooltip>
|
||||
{{ t('worker.pda.removePDA') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
<QTooltip>
|
||||
{{ t('globals.new') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
</QPage>
|
||||
<QBtn
|
||||
v-if="!isSigned(row)"
|
||||
:loading="loadingDocuware"
|
||||
icon="install_mobile"
|
||||
flat
|
||||
color="primary"
|
||||
@click="
|
||||
openConfirmationModal(
|
||||
t('Sign PDA'),
|
||||
t('Are you sure you want to send it?'),
|
||||
|
||||
() => sendToTablet([row]),
|
||||
)
|
||||
"
|
||||
data-cy="workerPda-send"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('worker.pda.sendToTablet') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
v-if="isSigned(row)"
|
||||
:loading="loadingDocuware"
|
||||
icon="cloud_download"
|
||||
flat
|
||||
color="primary"
|
||||
@click="
|
||||
downloadDocuware('Docuwares/download-pda-pdf', {
|
||||
file: row.deviceProductionFk + '-pda',
|
||||
worker: worker?.lastName + ' ' + worker?.firstName,
|
||||
})
|
||||
"
|
||||
data-cy="workerPda-download"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('worker.pda.download') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
</VnTable>
|
||||
<QPageSticky :offset="[18, 18]">
|
||||
<QBtn @click.stop="dialog.show()" color="primary" fab icon="add" v-shortcut="'+'">
|
||||
<QDialog ref="dialog">
|
||||
<FormModelPopup
|
||||
:title="t('Add new device')"
|
||||
url-create="DeviceProductionUsers"
|
||||
model="DeviceProductionUser"
|
||||
:form-initial-data="initialData"
|
||||
@on-data-saved="reloadData()"
|
||||
>
|
||||
<template #form-inputs="{ data }">
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('PDA')"
|
||||
v-model="data.deviceProductionFk"
|
||||
:options="deviceProductions"
|
||||
option-label="modelFk"
|
||||
option-value="id"
|
||||
id="deviceProductionFk"
|
||||
hide-selected
|
||||
data-cy="pda-dialog-select"
|
||||
:required="true"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel
|
||||
>ID: {{ scope.opt?.id }}</QItemLabel
|
||||
>
|
||||
<QItemLabel caption>
|
||||
{{ scope.opt?.modelFk }},
|
||||
{{ scope.opt?.serialNumber }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnSelect
|
||||
url="Sims"
|
||||
option-label="line"
|
||||
option-value="code"
|
||||
v-model="data.simFk"
|
||||
:label="t('SIM serial number')"
|
||||
id="simSerialNumber"
|
||||
/>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
</QDialog>
|
||||
</QBtn>
|
||||
<QTooltip>
|
||||
{{ t('globals.new') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.btn-delete {
|
||||
max-width: 4%;
|
||||
margin-top: 30px;
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
es:
|
||||
Model: Modelo
|
||||
|
|
|
@ -1,23 +1,91 @@
|
|||
describe('WorkerPda', () => {
|
||||
const select = '[data-cy="pda-dialog-select"]';
|
||||
const deviceId = 4;
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/worker/1110/pda`);
|
||||
});
|
||||
|
||||
it('assign pda', () => {
|
||||
cy.addBtnClick();
|
||||
cy.get(select).click();
|
||||
cy.get(select).type('{downArrow}{enter}');
|
||||
cy.get('.q-notification__message').should('have.text', 'Data created');
|
||||
it('assign and delete pda', () => {
|
||||
creatNewPDA();
|
||||
cy.checkNotification('Data created');
|
||||
cy.visit(`/#/worker/1110/pda`);
|
||||
removeNewPDA();
|
||||
cy.checkNotification('PDA deallocated');
|
||||
});
|
||||
|
||||
it('delete pda', () => {
|
||||
cy.get('.btn-delete').click();
|
||||
cy.get(
|
||||
'.q-card__actions > .q-btn--unelevated > .q-btn__content > .block'
|
||||
).click();
|
||||
cy.get('.q-notification__message').should('have.text', 'PDA deallocated');
|
||||
it('send to docuware', () => {
|
||||
cy.intercept('POST', '/api/Docuwares/upload-pda-pdf', (req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: {},
|
||||
});
|
||||
});
|
||||
|
||||
creatNewPDA();
|
||||
cy.dataCy('workerPda-send').click();
|
||||
confirmButton();
|
||||
cy.checkNotification('PDF sended to signed');
|
||||
|
||||
removeNewPDA();
|
||||
});
|
||||
|
||||
it('send 2 pdfs to docuware', () => {
|
||||
cy.intercept('POST', '/api/Docuwares/upload-pda-pdf', (req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: {},
|
||||
});
|
||||
});
|
||||
|
||||
creatNewPDA();
|
||||
creatNewPDA(2);
|
||||
cy.selectRows([1, 2]);
|
||||
cy.get('#st-actions').contains('Send').click();
|
||||
|
||||
confirmButton();
|
||||
cy.checkNotification('PDF sended to signed');
|
||||
|
||||
removeNewPDA();
|
||||
});
|
||||
|
||||
it('download file', () => {
|
||||
alexm marked this conversation as resolved
Outdated
jsegarra
commented
podemos enviar y descargar? Nos ahorramos un it, no? podemos enviar y descargar? Nos ahorramos un it, no?
|
||||
cy.intercept('POST', /\/api\/Docuwares\/Jones%20Jessica\/checkFile/, (req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: {
|
||||
id: deviceId,
|
||||
state: 'Firmado',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
cy.intercept('GET', '/api/Docuwares/download-pda-pdf**', (req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: {},
|
||||
});
|
||||
});
|
||||
cy.get('#st-actions').contains('refresh').click();
|
||||
|
||||
creatNewPDA();
|
||||
cy.dataCy('workerPda-download').click();
|
||||
removeNewPDA();
|
||||
});
|
||||
|
||||
function creatNewPDA(id = deviceId) {
|
||||
cy.addBtnClick();
|
||||
cy.selectOption('[data-cy="pda-dialog-select"]', id);
|
||||
cy.saveCard();
|
||||
}
|
||||
|
||||
function removeNewPDA() {
|
||||
cy.dataCy('workerPda-remove').first().click();
|
||||
confirmButton();
|
||||
}
|
||||
|
||||
function confirmButton() {
|
||||
cy.get(
|
||||
'.q-card__actions > .q-btn--unelevated > .q-btn__content > .block',
|
||||
).click();
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
es correcto que esta funcion se ejecute 2 veces al cargar la tabla?
Parece que el @on-fetch se esta activando 2 veces con los mismos datos