diff --git a/package.json b/package.json
index 17f39cad7..d23ed0ced 100644
--- a/package.json
+++ b/package.json
@@ -1,74 +1,74 @@
{
- "name": "salix-front",
- "version": "25.06.0",
- "description": "Salix frontend",
- "productName": "Salix",
- "author": "Verdnatura",
- "private": true,
- "packageManager": "pnpm@8.15.1",
- "type": "module",
- "scripts": {
- "resetDatabase": "cd ../salix && gulp docker",
- "lint": "eslint --ext .js,.vue ./",
- "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
- "test:e2e": "cypress open",
- "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
- "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
- "test:unit": "vitest",
- "test:unit:ci": "vitest run",
- "commitlint": "commitlint --edit",
- "prepare": "npx husky install",
- "addReferenceTag": "node .husky/addReferenceTag.js",
- "docs:dev": "vitepress dev docs",
- "docs:build": "vitepress build docs",
- "docs:preview": "vitepress preview docs"
- },
- "dependencies": {
- "@quasar/cli": "^2.4.1",
- "@quasar/extras": "^1.16.16",
- "axios": "^1.4.0",
- "chromium": "^3.0.3",
- "croppie": "^2.6.5",
- "moment": "^2.30.1",
- "pinia": "^2.1.3",
- "quasar": "^2.17.7",
- "validator": "^13.9.0",
- "vue": "^3.5.13",
- "vue-i18n": "^9.3.0",
- "vue-router": "^4.2.5"
- },
- "devDependencies": {
- "@commitlint/cli": "^19.2.1",
- "@commitlint/config-conventional": "^19.1.0",
- "@intlify/unplugin-vue-i18n": "^0.8.2",
- "@pinia/testing": "^0.1.2",
- "@quasar/app-vite": "^2.0.8",
- "@quasar/quasar-app-extension-qcalendar": "^4.0.2",
- "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
- "@vue/test-utils": "^2.4.4",
- "autoprefixer": "^10.4.14",
- "cypress": "^13.6.6",
- "cypress-mochawesome-reporter": "^3.8.2",
- "eslint": "^9.18.0",
- "eslint-config-prettier": "^10.0.1",
- "eslint-plugin-cypress": "^4.1.0",
- "eslint-plugin-vue": "^9.32.0",
- "husky": "^8.0.0",
- "postcss": "^8.4.23",
- "prettier": "^3.4.2",
- "sass": "^1.83.4",
- "vitepress": "^1.6.3",
- "vitest": "^0.34.0"
- },
- "engines": {
- "node": "^20 || ^18 || ^16",
- "npm": ">= 8.1.2",
- "yarn": ">= 1.21.1",
- "bun": ">= 1.0.25"
- },
- "overrides": {
- "@vitejs/plugin-vue": "^5.2.1",
- "vite": "^6.0.11",
- "vitest": "^0.31.1"
- }
+ "name": "salix-front",
+ "version": "25.08.0",
+ "description": "Salix frontend",
+ "productName": "Salix",
+ "author": "Verdnatura",
+ "private": true,
+ "packageManager": "pnpm@8.15.1",
+ "type": "module",
+ "scripts": {
+ "resetDatabase": "cd ../salix && gulp docker",
+ "lint": "eslint --ext .js,.vue ./",
+ "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
+ "test:e2e": "cypress open",
+ "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
+ "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+ "test:unit": "vitest",
+ "test:unit:ci": "vitest run",
+ "commitlint": "commitlint --edit",
+ "prepare": "npx husky install",
+ "addReferenceTag": "node .husky/addReferenceTag.js",
+ "docs:dev": "vitepress dev docs",
+ "docs:build": "vitepress build docs",
+ "docs:preview": "vitepress preview docs"
+ },
+ "dependencies": {
+ "@quasar/cli": "^2.4.1",
+ "@quasar/extras": "^1.16.16",
+ "axios": "^1.4.0",
+ "chromium": "^3.0.3",
+ "croppie": "^2.6.5",
+ "moment": "^2.30.1",
+ "pinia": "^2.1.3",
+ "quasar": "^2.17.7",
+ "validator": "^13.9.0",
+ "vue": "^3.5.13",
+ "vue-i18n": "^9.3.0",
+ "vue-router": "^4.2.5"
+ },
+ "devDependencies": {
+ "@commitlint/cli": "^19.2.1",
+ "@commitlint/config-conventional": "^19.1.0",
+ "@intlify/unplugin-vue-i18n": "^0.8.2",
+ "@pinia/testing": "^0.1.2",
+ "@quasar/app-vite": "^2.0.8",
+ "@quasar/quasar-app-extension-qcalendar": "^4.0.2",
+ "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
+ "@vue/test-utils": "^2.4.4",
+ "autoprefixer": "^10.4.14",
+ "cypress": "^13.6.6",
+ "cypress-mochawesome-reporter": "^3.8.2",
+ "eslint": "^9.18.0",
+ "eslint-config-prettier": "^10.0.1",
+ "eslint-plugin-cypress": "^4.1.0",
+ "eslint-plugin-vue": "^9.32.0",
+ "husky": "^8.0.0",
+ "postcss": "^8.4.23",
+ "prettier": "^3.4.2",
+ "sass": "^1.83.4",
+ "vitepress": "^1.6.3",
+ "vitest": "^0.34.0"
+ },
+ "engines": {
+ "node": "^20 || ^18 || ^16",
+ "npm": ">= 8.1.2",
+ "yarn": ">= 1.21.1",
+ "bun": ">= 1.0.25"
+ },
+ "overrides": {
+ "@vitejs/plugin-vue": "^5.2.1",
+ "vite": "^6.0.11",
+ "vitest": "^0.31.1"
+ }
}
\ No newline at end of file
diff --git a/src/components/TicketProblems.vue b/src/components/TicketProblems.vue
index 2965396b1..a24735a5f 100644
--- a/src/components/TicketProblems.vue
+++ b/src/components/TicketProblems.vue
@@ -2,26 +2,9 @@
defineProps({ row: { type: Object, required: true } });
-
+
- {{ $t('salesTicketsTable.noVerifiedData') }}
-
-
- {{ $t('salesTicketsTable.purchaseRequest') }}
-
-
- {{ $t('salesTicketsTable.notVisible') }}
-
-
- {{ $t('salesTicketsTable.clientFrozen') }}
-
-
-
+
{{ $t('salesTicketsTable.componentLack') }}
-
+
+
+ {{ $t('ticket.summary.hasItemDelay') }}
+
+
+
+
+ {{ $t('salesTicketsTable.hasItemLost') }}
+
+
+
+ {{ $t('salesTicketsTable.notVisible') }}
+
+
+
+ {{ $t('ticketList.rounding') }}
+
+
+
+ {{ $t('salesTicketsTable.purchaseRequest') }}
+
+
+ {{ $t('salesTicketsTable.noVerifiedData') }}
+
+
+ {{ $t('salesTicketsTable.clientFrozen') }}
+
+
{{ $t('salesTicketsTable.tooLittle') }}
diff --git a/src/components/__tests__/UserPanel.spec.js b/src/components/__tests__/UserPanel.spec.js
new file mode 100644
index 000000000..ac20f911e
--- /dev/null
+++ b/src/components/__tests__/UserPanel.spec.js
@@ -0,0 +1,61 @@
+import { vi, describe, expect, it, beforeEach, beforeAll, afterEach } from 'vitest';
+import { createWrapper } from 'app/test/vitest/helper';
+import UserPanel from 'src/components/UserPanel.vue';
+import axios from 'axios';
+import { useState } from 'src/composables/useState';
+
+describe('UserPanel', () => {
+ let wrapper;
+ let vm;
+ let state;
+
+ beforeEach(() => {
+ wrapper = createWrapper(UserPanel, {});
+ state = useState();
+ state.setUser({
+ id: 115,
+ name: 'itmanagement',
+ nickname: 'itManagementNick',
+ lang: 'en',
+ darkMode: false,
+ companyFk: 442,
+ warehouseFk: 1,
+ });
+ wrapper = wrapper.wrapper;
+ vm = wrapper.vm;
+ });
+
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('should fetch warehouses data on mounted', async () => {
+ const fetchData = wrapper.findComponent({ name: 'FetchData' });
+ expect(fetchData.props('url')).toBe('Warehouses');
+ expect(fetchData.props('autoLoad')).toBe(true);
+ });
+
+ it('should toggle dark mode correctly and update preferences', async () => {
+ await vm.saveDarkMode(true);
+ expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
+ expect(vm.user.darkMode).toBe(true);
+ vm.updatePreferences();
+ expect(vm.darkMode).toBe(true);
+ });
+
+ it('should change user language and update preferences', async () => {
+ const userLanguage = 'es';
+ await vm.saveLanguage(userLanguage);
+ expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
+ expect(vm.user.lang).toBe(userLanguage);
+ vm.updatePreferences();
+ expect(vm.locale).toBe(userLanguage);
+ });
+
+ it('should update user data', async () => {
+ const key = 'name';
+ const value = 'itboss';
+ await vm.saveUserData(key, value);
+ expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
+ });
+});
diff --git a/src/components/common/VnDmsList.vue b/src/components/common/VnDmsList.vue
index 36c87bab0..59a4f9f90 100644
--- a/src/components/common/VnDmsList.vue
+++ b/src/components/common/VnDmsList.vue
@@ -17,7 +17,7 @@ import { useSession } from 'src/composables/useSession';
const route = useRoute();
const quasar = useQuasar();
const { t } = useI18n();
-const rows = ref();
+const rows = ref([]);
const dmsRef = ref();
const formDialog = ref({});
const token = useSession().getTokenMultimedia();
@@ -389,6 +389,14 @@ defineExpose({
+
+
+ {{ t('No data to display') }}
+
+
diff --git a/src/components/common/__tests__/VnNotes.spec.js b/src/components/common/__tests__/VnNotes.spec.js
index 8f24a7f14..2603bf03c 100644
--- a/src/components/common/__tests__/VnNotes.spec.js
+++ b/src/components/common/__tests__/VnNotes.spec.js
@@ -1,51 +1,78 @@
-import { describe, it, expect, vi, beforeAll, afterEach, beforeEach } from 'vitest';
+import {
+ describe,
+ it,
+ expect,
+ vi,
+ beforeAll,
+ afterEach,
+ beforeEach,
+ afterAll,
+} from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import VnNotes from 'src/components/ui/VnNotes.vue';
+import vnDate from 'src/boot/vnDate';
describe('VnNotes', () => {
let vm;
let wrapper;
let spyFetch;
let postMock;
- let expectedBody;
- const mockData= {name: 'Tony', lastName: 'Stark', text: 'Test Note', observationTypeFk: 1};
-
- function generateExpectedBody() {
- expectedBody = {...vm.$props.body, ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk }};
- }
-
- async function setTestParams(text, observationType, type){
- vm.newNote.text = text;
- vm.newNote.observationTypeFk = observationType;
- wrapper.setProps({ selectType: type });
- }
-
- beforeAll(async () => {
- vi.spyOn(axios, 'get').mockReturnValue({ data: [] });
-
+ let patchMock;
+ let expectedInsertBody;
+ let expectedUpdateBody;
+ const defaultOptions = {
+ url: '/test',
+ body: { name: 'Tony', lastName: 'Stark' },
+ selectType: false,
+ saveUrl: null,
+ justInput: false,
+ };
+ function generateWrapper(
+ options = defaultOptions,
+ text = null,
+ observationType = null,
+ ) {
+ vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
wrapper = createWrapper(VnNotes, {
- propsData: {
- url: '/test',
- body: { name: 'Tony', lastName: 'Stark' },
- }
+ propsData: options,
});
wrapper = wrapper.wrapper;
vm = wrapper.vm;
- });
+ vm.newNote.text = text;
+ vm.newNote.observationTypeFk = observationType;
+ }
+
+ function createSpyFetch() {
+ spyFetch = vi.spyOn(vm.$refs.vnPaginateRef, 'fetch');
+ }
+
+ function generateExpectedBody() {
+ expectedInsertBody = {
+ ...vm.$props.body,
+ ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk },
+ };
+ expectedUpdateBody = { ...vm.$props.body, ...{ notes: vm.newNote.text } };
+ }
beforeEach(() => {
- postMock = vi.spyOn(axios, 'post').mockResolvedValue(mockData);
- spyFetch = vi.spyOn(vm.vnPaginateRef, 'fetch').mockImplementation(() => vi.fn());
+ postMock = vi.spyOn(axios, 'post');
+ patchMock = vi.spyOn(axios, 'patch');
});
afterEach(() => {
vi.clearAllMocks();
- expectedBody = {};
+ expectedInsertBody = {};
+ expectedUpdateBody = {};
+ });
+
+ afterAll(() => {
+ vi.restoreAllMocks();
});
describe('insert', () => {
- it('should not call axios.post and vnPaginateRef.fetch if newNote.text is null', async () => {
- await setTestParams( null, null, true );
+ it('should not call axios.post and vnPaginateRef.fetch when newNote.text is null', async () => {
+ generateWrapper({ selectType: true });
+ createSpyFetch();
await vm.insert();
@@ -53,8 +80,9 @@ describe('VnNotes', () => {
expect(spyFetch).not.toHaveBeenCalled();
});
- it('should not call axios.post and vnPaginateRef.fetch if newNote.text is empty', async () => {
- await setTestParams( "", null, false );
+ it('should not call axios.post and vnPaginateRef.fetch when newNote.text is empty', async () => {
+ generateWrapper(null, '');
+ createSpyFetch();
await vm.insert();
@@ -62,8 +90,9 @@ describe('VnNotes', () => {
expect(spyFetch).not.toHaveBeenCalled();
});
- it('should not call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is true', async () => {
- await setTestParams( "Test Note", null, true );
+ it('should not call axios.post and vnPaginateRef.fetch when observationTypeFk is null and selectType is true', async () => {
+ generateWrapper({ selectType: true }, 'Test Note');
+ createSpyFetch();
await vm.insert();
@@ -71,37 +100,57 @@ describe('VnNotes', () => {
expect(spyFetch).not.toHaveBeenCalled();
});
- it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is false', async () => {
- await setTestParams( "Test Note", null, false );
-
+ it('should call axios.post and vnPaginateRef.fetch when observationTypeFk is missing and selectType is false', async () => {
+ generateWrapper(null, 'Test Note');
+ createSpyFetch();
generateExpectedBody();
await vm.insert();
- expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
- expect(spyFetch).toHaveBeenCalled();
- });
-
- it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is setted and selectType is false', async () => {
- await setTestParams( "Test Note", 1, false );
-
- generateExpectedBody();
-
- await vm.insert();
-
- expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+ expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
expect(spyFetch).toHaveBeenCalled();
});
it('should call axios.post and vnPaginateRef.fetch when newNote is valid', async () => {
- await setTestParams( "Test Note", 1, true );
-
+ generateWrapper({ selectType: true }, 'Test Note', 1);
+ createSpyFetch();
generateExpectedBody();
-
+
await vm.insert();
- expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+ expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
expect(spyFetch).toHaveBeenCalled();
});
});
-});
\ No newline at end of file
+
+ describe('update', () => {
+ it('should call axios.patch with saveUrl when saveUrl is set and justInput is true', async () => {
+ generateWrapper({
+ url: '/business',
+ justInput: true,
+ saveUrl: '/saveUrlTest',
+ });
+ generateExpectedBody();
+
+ await vm.update();
+
+ expect(patchMock).toHaveBeenCalledWith(vm.$props.saveUrl, expectedUpdateBody);
+ });
+
+ it('should call axios.patch with url when saveUrl is not set and justInput is true', async () => {
+ generateWrapper({
+ url: '/business',
+ body: { workerFk: 1110 },
+ justInput: true,
+ });
+ generateExpectedBody();
+
+ await vm.update();
+
+ expect(patchMock).toHaveBeenCalledWith(
+ `${vm.$props.url}/${vm.$props.body.workerFk}`,
+ expectedUpdateBody,
+ );
+ });
+ });
+});
diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index f9de8e0c1..c815b8e16 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -15,6 +15,10 @@ const props = defineProps({
type: Object,
default: null,
},
+ userFilter: {
+ type: Object,
+ default: null,
+ },
entityId: {
type: [Number, String],
default: null,
@@ -34,6 +38,7 @@ const isSummary = ref();
const arrayData = useArrayData(props.dataKey, {
url: props.url,
filter: props.filter,
+ userFilter: props.userFilter,
skip: 0,
});
const { store } = arrayData;
diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue
index 3c0f37c77..b9448dc55 100644
--- a/src/components/ui/VnNotes.vue
+++ b/src/components/ui/VnNotes.vue
@@ -1,6 +1,6 @@
{
auto-load
@on-fetch="(data) => (observationTypes = data)"
/>
-
-
+
+
+
{{ t('New note') }}
@@ -75,19 +138,19 @@ onBeforeRouteLeave((to, from, next) => {
v-model="newNote.observationTypeFk"
option-label="description"
style="flex: 0.15"
- :required="true"
+ :required="isRequired"
@keyup.enter.stop="insert"
/>
{
icon="save"
color="primary"
flat
- @click="insert"
+ @click="handleClick"
class="q-mb-xs"
dense
data-cy="saveNote"
@@ -106,6 +169,7 @@ onBeforeRouteLeave((to, from, next) => {
{
}
}
}
+.just-input {
+ padding-right: 18px;
+ margin-bottom: 2px;
+ box-shadow: none;
+}
es:
@@ -205,4 +274,6 @@ onBeforeRouteLeave((to, from, next) => {
New note: Nueva nota
Save (Enter): Guardar (Intro)
Observation type: Tipo de observación
+ New note is empty: La nueva nota esta vacia
+ Are you sure remove this note?: Estas seguro de quitar esta nota?
diff --git a/src/components/ui/VnSubToolbar.vue b/src/components/ui/VnSubToolbar.vue
index 5ded4be00..8d4126d1d 100644
--- a/src/components/ui/VnSubToolbar.vue
+++ b/src/components/ui/VnSubToolbar.vue
@@ -19,23 +19,26 @@ onMounted(() => {
const observer = new MutationObserver(
() =>
(hasContent.value =
- actions.value?.childNodes?.length + data.value?.childNodes?.length)
+ actions.value?.childNodes?.length + data.value?.childNodes?.length),
);
if (actions.value) observer.observe(actions.value, opts);
if (data.value) observer.observe(data.value, opts);
});
-onBeforeUnmount(() => stateStore.toggleSubToolbar());
+const actionsChildCount = () => !!actions.value?.childNodes?.length;
+
+onBeforeUnmount(() => stateStore.toggleSubToolbar() && hasSubToolbar);
-
+
+
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index 3268939de..bd3cecf08 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -93,6 +93,9 @@ export function useArrayData(key, userOptions) {
if (params.filter.where || exprFilter)
params.filter.where = { ...params.filter.where, ...exprFilter };
+
+ if (!params?.filter?.order?.length) delete params?.filter?.order;
+
params.filter = JSON.stringify(params.filter);
store.isLoading = true;
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 8a9b0c889..d1fbdc312 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -378,7 +378,7 @@ login:
loginError: Invalid username or password
fieldRequired: This field is required
twoFactorRequired: Two-factor verification required
-twoFactorRequired:
+twoFactor:
validate: Validate
insert: Enter the verification code
explanation: >-
@@ -457,48 +457,6 @@ ticket:
consigneeStreet: Street
create:
address: Address
-invoiceOut:
- card:
- issued: Issued
- customerCard: Customer card
- ticketList: Ticket List
- summary:
- issued: Issued
- dued: Due
- booked: Booked
- taxBreakdown: Tax breakdown
- taxableBase: Taxable base
- rate: Rate
- fee: Fee
- tickets: Tickets
- totalWithVat: Amount
- globalInvoices:
- errors:
- chooseValidClient: Choose a valid client
- chooseValidCompany: Choose a valid company
- chooseValidPrinter: Choose a valid printer
- chooseValidSerialType: Choose a serial type
- fillDates: Invoice date and the max date should be filled
- invoiceDateLessThanMaxDate: Invoice date can not be less than max date
- invoiceWithFutureDate: Exists an invoice with a future date
- noTicketsToInvoice: There are not tickets to invoice
- criticalInvoiceError: 'Critical invoicing error, process stopped'
- invalidSerialTypeForAll: The serial type must be global when invoicing all clients
- table:
- addressId: Address id
- streetAddress: Street
- statusCard:
- percentageText: '{getPercentage}% {getAddressNumber} of {getNAddresses}'
- pdfsNumberText: '{nPdfs} of {totalPdfs} PDFs'
- negativeBases:
- clientId: Client Id
- base: Base
- active: Active
- hasToInvoice: Has to Invoice
- verifiedData: Verified Data
- comercial: Comercial
- errors:
- downloadCsvFailed: CSV download failed
department:
chat: Chat
bossDepartment: Boss Department
diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index ce402541d..d7a8a59a1 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -192,6 +192,7 @@ const debtWarning = computed(() => {
query: {
createForm: JSON.stringify({
clientFk: entity.id,
+ addressId: entity.defaultAddressFk,
}),
},
}"
diff --git a/src/pages/Customer/Card/CustomerNotes.vue b/src/pages/Customer/Card/CustomerNotes.vue
index f00132a95..c60a549e8 100644
--- a/src/pages/Customer/Card/CustomerNotes.vue
+++ b/src/pages/Customer/Card/CustomerNotes.vue
@@ -35,5 +35,6 @@ const body = {
:body="body"
style="overflow-y: auto"
:select-type="true"
+ required
/>
diff --git a/src/pages/Customer/composables/getAddresses.js b/src/pages/Customer/composables/getAddresses.js
index eecc0150b..e65e64455 100644
--- a/src/pages/Customer/composables/getAddresses.js
+++ b/src/pages/Customer/composables/getAddresses.js
@@ -1,8 +1,9 @@
import axios from 'axios';
-export async function getAddresses(clientId) {
+export async function getAddresses(clientId, _filter = {}) {
if (!clientId) return;
const filter = {
+ ..._filter,
fields: ['nickname', 'street', 'city', 'id'],
where: { isActive: true },
order: 'nickname ASC',
diff --git a/src/pages/Customer/composables/getClient.js b/src/pages/Customer/composables/getClient.js
index ecacc67c0..3b9e811de 100644
--- a/src/pages/Customer/composables/getClient.js
+++ b/src/pages/Customer/composables/getClient.js
@@ -1,7 +1,8 @@
import axios from 'axios';
-export async function getClient(clientId) {
+export async function getClient(clientId, _filter = {}) {
const filter = {
+ ..._filter,
include: {
relation: 'defaultAddress',
scope: {
diff --git a/src/pages/Entry/EntryBuysTableDialog.vue b/src/pages/Entry/EntryBuysTableDialog.vue
index a2d8c9117..86a9b018f 100644
--- a/src/pages/Entry/EntryBuysTableDialog.vue
+++ b/src/pages/Entry/EntryBuysTableDialog.vue
@@ -134,6 +134,7 @@ function downloadCSV(rows) {
@click="
openReport(`Entries/${entityId}/labelSupplier`)
"
+ data-cy="printLabelsBtn"
/>
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index 805f41726..e1723e3b1 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -177,7 +177,7 @@ const cols = computed(() => [
:required="true"
/>
[
:required="true"
/>
diff --git a/src/pages/Item/Card/ItemDiary.vue b/src/pages/Item/Card/ItemDiary.vue
index c2f2c19a0..4b6775183 100644
--- a/src/pages/Item/Card/ItemDiary.vue
+++ b/src/pages/Item/Card/ItemDiary.vue
@@ -125,7 +125,7 @@ onMounted(async () => {
inventoriedDate.value =
(await axios.get('Configs/findOne')).data?.inventoried || today;
- if (query.warehouseFk) ref.warehouseFk = query.warehouseFk;
+ if (query.warehouseFk) ref.warehouseFk = +query.warehouseFk;
else if (!ref.warehouseFk && user.value) ref.warehouseFk = user.value.warehouseFk;
if (ref.date) showWhatsBeforeInventory.value = true;
ref.itemFk = route.params.id;
@@ -143,7 +143,7 @@ onMounted(async () => {
const fetchItemBalances = async () => await arrayDataItemBalances.fetch({});
const getBadgeAttrs = (_date) => {
- const isSameDate = date.isSameDate(today.value, _date);
+ const isSameDate = date.isSameDate(today, _date);
const attrs = {
'text-color': isSameDate ? 'black' : 'white',
color: isSameDate ? 'warning' : 'transparent',
@@ -153,8 +153,6 @@ const getBadgeAttrs = (_date) => {
const scrollToToday = async () => {
await nextTick();
- const today = Date.vnNew();
- today.setHours(0, 0, 0, 0);
const todayCell = document.querySelector(`td[data-date="${today.toISOString()}"]`);
if (todayCell) {
todayCell.scrollIntoView({ behavior: 'smooth', block: 'center' });
diff --git a/src/pages/Monitor/Ticket/MonitorTickets.vue b/src/pages/Monitor/Ticket/MonitorTickets.vue
index e6b4631a0..3b5dccb56 100644
--- a/src/pages/Monitor/Ticket/MonitorTickets.vue
+++ b/src/pages/Monitor/Ticket/MonitorTickets.vue
@@ -293,7 +293,7 @@ const columns = computed(() => [
title: t('globals.preview'),
icon: 'preview',
color: 'primary',
- action: (row) => viewSummary(row.id, TicketSummary),
+ action: (row) => viewSummary(row.id, TicketSummary, 'lg-width'),
isPrimary: true,
attrs: {
flat: true,
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index 21324087c..496c8761a 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -38,6 +38,7 @@ salesTicketsTable:
payMethod: Pay method
department: Department
packing: ITP
+ hasItemLost: Item lost
searchBar:
label: Search tickets
info: Search tickets by id or alias
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index 30afb1904..f6a29879f 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -39,6 +39,7 @@ salesTicketsTable:
payMethod: Método de pago
department: Departamento
packing: ITP
+ hasItemLost: Artículo perdido
searchBar:
label: Buscar tickets
info: Buscar tickets por identificador o alias
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 6e4f0aac8..21cb5ed7e 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -81,7 +81,7 @@ const columns = computed(() => [
label: t('module.created'),
component: 'date',
cardVisible: true,
- format: (row) => toDateTimeFormat(row?.landed),
+ format: (row) => toDateTimeFormat(row?.created),
columnField: {
component: null,
},
diff --git a/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js b/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js
index 9897173f1..ccf7872cb 100644
--- a/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js
+++ b/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js
@@ -3,14 +3,17 @@ import axios from 'axios';
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
vi.mock('axios');
+const response = { data: [{ agencyModeFk: 'Agency1' }, { agencyModeFk: 'Agency2' }] };
+axios.get.mockResolvedValue(response);
describe('getAgencies', () => {
afterEach(() => {
vi.clearAllMocks();
});
- const generateParams = (formData) => ({
+ const generateParams = (formData, filter = {}) => ({
params: {
+ filter: JSON.stringify(filter),
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
@@ -23,10 +26,15 @@ describe('getAgencies', () => {
addressId: '456',
landed: 'true',
};
+ const filter = {
+ fields: ['nickname', 'street', 'city', 'id'],
+ where: { isActive: true },
+ order: 'nickname ASC',
+ };
- await getAgencies(formData);
+ await getAgencies(formData, null, filter);
- expect(axios.get).toHaveBeenCalledWith('Agencies/getAgenciesWithWarehouse', generateParams(formData));
+ expect(axios.get).toHaveBeenCalledWith('Agencies/getAgenciesWithWarehouse', generateParams(formData, filter));
});
it('should not call API when formData is missing required landed field', async () => {
@@ -52,4 +60,23 @@ describe('getAgencies', () => {
expect(axios.get).not.toHaveBeenCalled();
});
+
+ it('should return options and agency when default agency is found', async () => {
+ const formData = { warehouseId: '123', addressId: '456', landed: 'true' };
+ const client = { defaultAddress: { agencyModeFk: 'Agency1' } };
+
+ const { options, agency } = await getAgencies(formData, client);
+
+ expect(options).toEqual(response.data);
+ expect(agency).toEqual(response.data[0]);
+ });
+
+ it('should return options and agency when client is not provided', async () => {
+ const formData = { warehouseId: '123', addressId: '456', landed: 'true' };
+
+ const { options, agency } = await getAgencies(formData);
+
+ expect(options).toEqual(response.data);
+ expect(agency).toBeNull();
+ });
});
diff --git a/src/pages/Route/Agency/composables/getAgencies.js b/src/pages/Route/Agency/composables/getAgencies.js
index 7299d7e23..850f87456 100644
--- a/src/pages/Route/Agency/composables/getAgencies.js
+++ b/src/pages/Route/Agency/composables/getAgencies.js
@@ -1,12 +1,26 @@
import axios from 'axios';
+import agency from 'src/router/modules/agency';
-export async function getAgencies(formData) {
+export async function getAgencies(formData, client, _filter = {}) {
if (!formData.warehouseId || !formData.addressId || !formData.landed) return;
+
+ const filter = {
+ ..._filter
+ };
+
+ let defaultAgency = null;
let params = {
+ filter: JSON.stringify(filter),
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
};
- return await axios.get('Agencies/getAgenciesWithWarehouse', { params });
+ const { data } = await axios.get('Agencies/getAgenciesWithWarehouse', { params });
+
+ if(data && client) {
+ defaultAgency = data.find((agency) => agency.agencyModeFk === client.defaultAddress.agencyModeFk );
+ };
+
+ return {options: data, agency: defaultAgency}
}
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index c9849d631..25887fd39 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -9,6 +9,8 @@ import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { toDateTimeFormat } from 'src/filters/date';
+import FetchData from 'src/components/FetchData.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
const $props = defineProps({
id: {
@@ -28,6 +30,7 @@ const { t } = useI18n();
const entityId = computed(() => {
return $props.id || route.params.id;
});
+const problems = ref({});
const filter = {
include: [
@@ -113,6 +116,11 @@ const setData = (entity) => {
+ ([problems] = data)"
+ />
{
-
-
-
- {{ t('Client inactive') }}
-
-
- {{ t('Client Frozen') }}
-
-
- {{ t('Client has debt') }}
-
-
- {{ t('Client not checked') }}
-
-
- {{ t('This ticket is deleted') }}
-
+
+
+
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 89f7015d7..63e45c8ab 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -69,14 +69,16 @@ const onAddressSelected = (addressId) => {
}
const fetchClient = async () => {
- const { data } = await getClient(client.value)
- const [retrievedClient] = data;
+ const response = await getClient(client.value)
+ if (!response) return;
+ const [retrievedClient] = response.data;
selectedClient.value = retrievedClient;
};
const fetchAddresses = async () => {
- const { data } = await getAddresses(client.value);
- addressesOptions.value = data;
+ const response = await getAddresses(client.value);
+ if (!response) return;
+ addressesOptions.value = response.data;
const { defaultAddress } = selectedClient.value;
address.value = defaultAddress.id;
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 3ebb69319..adbd4ee00 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -24,6 +24,7 @@ import axios from 'axios';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnUsesMana from 'src/components/ui/VnUsesMana.vue';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
const route = useRoute();
@@ -56,7 +57,7 @@ const canProceed = ref();
watch(
() => route.params.id,
- () => tableRef.value.reload()
+ () => tableRef.value.reload(),
);
const columns = computed(() => [
@@ -199,7 +200,7 @@ const changeQuantity = async (sale) => {
await updateQuantity(sale);
} catch (e) {
const { quantity } = tableRef.value.CrudModelRef.originalData.find(
- (s) => s.id === sale.id
+ (s) => s.id === sale.id,
);
sale.quantity = quantity;
throw e;
@@ -503,7 +504,7 @@ async function isSalePrepared(item) {
componentProps: {
title: t('Item prepared'),
message: t(
- 'This item is already prepared. Do you want to continue?'
+ 'This item is already prepared. Do you want to continue?',
),
data: item,
},
@@ -525,7 +526,7 @@ watch(
if (newItemFk) {
updateItem(newRow.value);
}
- }
+ },
);
@@ -595,7 +596,7 @@ watch(
openConfirmationModal(
t('Continue anyway?'),
t('You are going to delete lines of the ticket'),
- removeSales
+ removeSales,
)
"
>
@@ -679,53 +680,7 @@ watch(
:disabled-attr="isTicketEditable"
>
-
-
-
- {{ t('ticketSale.claim') }}:
- {{ row.claim?.claimFk }}
-
-
-
-
-
- {{ t('ticketSale.visible') }}: {{ row.visible || 0 }}
-
-
-
-
- {{ t('ticketSale.reserved') }}
-
-
-
-
- {{ t('ticketSale.noVisible') }}
-
-
-
-
- {{ t('ticketSale.hasComponentLack') }}
-
-
+
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index bb338191b..151bea97a 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -20,6 +20,7 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
const route = useRoute();
const { notify } = useNotify();
@@ -311,83 +312,7 @@ onMounted(async () => {
-
-
- {{ t('ticket.summary.claim') }}:
- {{ props.row.claim.claimFk }}
-
-
-
-
- {{ t('ticket.summary.claim') }}:
- {{ props.row.claimBeginning.claimFk }}
-
-
-
-
- {{ t('globals.visible') }}:
- {{ props.row.visible }}
-
-
-
-
- {{ t('ticket.summary.reserved') }}
-
-
-
-
- {{ t('ticket.summary.itemShortage') }}
-
-
-
-
- {{ t('ticket.summary.hasComponentLack') }}
-
-
+
diff --git a/src/pages/Ticket/TicketCreate.vue b/src/pages/Ticket/TicketCreate.vue
index 4c32448e4..96d200547 100644
--- a/src/pages/Ticket/TicketCreate.vue
+++ b/src/pages/Ticket/TicketCreate.vue
@@ -38,35 +38,43 @@ onBeforeMount(async () => {
await onClientSelected(initialFormState);
});
+function resetAgenciesSelector(formData) {
+ agenciesOptions.value = [];
+ formData.agencyModeId = null;
+}
+
const fetchClient = async (formData) => {
- const { data } = await getClient(formData.clientId);
- const [client] = data;
+ const response = await getClient(formData.clientId);
+ if (!response) return;
+ const [client] = response.data;
selectedClient.value = client;
};
const fetchAddresses = async (formData) => {
- const { data } = await getAddresses(formData.clientId);
- addressesOptions.value = data;
+ const response = await getAddresses(formData.clientId);
+ if (!response) return;
+ addressesOptions.value = response.data;
const { defaultAddress } = selectedClient.value;
formData.addressId = defaultAddress.id;
};
const onClientSelected = async (formData) => {
+ resetAgenciesSelector(formData);
await fetchClient(formData);
await fetchAddresses(formData);
};
const fetchAvailableAgencies = async (formData) => {
- const { data } = await getAgencies(formData);
- agenciesOptions.value = data;
-
- const defaultAgency = agenciesOptions.value.find(
- (agency) =>
- agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk
- );
-
- if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk;
+ resetAgenciesSelector(formData);
+ const response= await getAgencies(formData, selectedClient.value);
+ if (!response) return;
+
+ const { options, agency } = response
+ if(options)
+ agenciesOptions.value = options;
+ if(agency)
+ formData.agencyModeId = agency;
};
const redirectToTicketList = (_, { id }) => {
diff --git a/src/pages/Ticket/TicketCreateDialog.vue b/src/pages/Ticket/TicketCreateDialog.vue
index c8b126d7d..2245c5c81 100644
--- a/src/pages/Ticket/TicketCreateDialog.vue
+++ b/src/pages/Ticket/TicketCreateDialog.vue
@@ -38,35 +38,43 @@ onBeforeMount(async () => {
await onClientSelected(initialFormState);
});
+function resetAgenciesSelector(formData) {
+ agenciesOptions.value = [];
+ if(formData) formData.agencyModeId = null;
+}
+
const fetchClient = async (formData) => {
- const { data } = await getClient(formData.clientId);
- const [client] = data;
+ const response = await getClient(formData.clientId);
+ if (!response) return;
+ const [client] = response.data;
selectedClient.value = client;
};
const fetchAddresses = async (formData) => {
- const { data } = await getAddresses(formData.clientId);
- addressesOptions.value = data;
+ const response = await getAddresses(formData.clientId);
+ if (!response) return;
+ addressesOptions.value = response.data;
const { defaultAddress } = selectedClient.value;
formData.addressId = defaultAddress.id;
};
const onClientSelected = async (formData) => {
+ resetAgenciesSelector(formData);
await fetchClient(formData);
await fetchAddresses(formData);
};
const fetchAvailableAgencies = async (formData) => {
- const { data } = await getAgencies(formData);
- agenciesOptions.value = data;
-
- const defaultAgency = agenciesOptions.value.find(
- (agency) =>
- agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk
- );
-
- if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk;
+ resetAgenciesSelector(formData);
+ const response= await getAgencies(formData, selectedClient.value);
+ if (!response) return;
+
+ const { options, agency } = response
+ if(options)
+ agenciesOptions.value = options;
+ if(agency)
+ formData.agencyModeId = agency;
};
const redirectToTicketList = (_, { id }) => {
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index 8cf1184eb..8df19c0d9 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -229,37 +229,46 @@ const columns = computed(() => [
],
},
]);
+
+function resetAgenciesSelector(formData) {
+ agenciesOptions.value = [];
+ if(formData) formData.agencyModeId = null;
+}
+
function redirectToLines(id) {
const url = `#/ticket/${id}/sale`;
window.open(url, '_blank');
}
-const onClientSelected = async (formData) => {
+const onClientSelected = async (formData) => {
+ resetAgenciesSelector(formData);
await fetchClient(formData);
await fetchAddresses(formData);
};
const fetchAvailableAgencies = async (formData) => {
- const { data } = await getAgencies(formData);
- agenciesOptions.value = data;
-
- const defaultAgency = agenciesOptions.value.find(
- (agency) =>
- agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk
- );
-
- if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk;
+ resetAgenciesSelector(formData);
+ const response= await getAgencies(formData, selectedClient.value);
+ if (!response) return;
+
+ const { options, agency } = response
+ if(options)
+ agenciesOptions.value = options;
+ if(agency)
+ formData.agencyModeId = agency;
};
const fetchClient = async (formData) => {
- const { data } = await getClient(formData.clientId);
- const [client] = data;
+ const response = await getClient(formData.clientId);
+ if (!response) return;
+ const [client] = response.data;
selectedClient.value = client;
};
const fetchAddresses = async (formData) => {
- const { data } = await getAddresses(formData.clientId);
- addressesOptions.value = data;
+ const response = await getAddresses(formData.clientId);
+ if (!response) return;
+ addressesOptions.value = response.data;
const { defaultAddress } = selectedClient.value;
formData.addressId = defaultAddress.id;
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index f11b32c3a..d4bfd1103 100644
--- a/src/pages/Ticket/locale/en.yml
+++ b/src/pages/Ticket/locale/en.yml
@@ -208,3 +208,9 @@ ticketList:
toLines: Go to lines
addressNickname: Address nickname
ref: Reference
+ rounding: Rounding
+ noVerifiedData: No verified data
+ purchaseRequest: Purchase request
+ notVisible: Not visible
+ clientFrozen: Client frozen
+ componentLack: Component lack
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index 945da8367..ff68461fa 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -213,3 +213,9 @@ ticketList:
toLines: Ir a lineas
addressNickname: Alias consignatario
ref: Referencia
+ rounding: Redondeo
+ noVerifiedData: Sin datos comprobados
+ purchaseRequest: Petición de compra
+ notVisible: No visible
+ clientFrozen: Cliente congelado
+ componentLack: Faltan componentes
diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue
index 5ca95a1a4..df4616011 100644
--- a/src/pages/Worker/Card/WorkerCalendar.vue
+++ b/src/pages/Worker/Card/WorkerCalendar.vue
@@ -1,7 +1,8 @@
@@ -181,6 +193,20 @@ watch([year, businessFk], () => refreshData());
/>
+
+ {
+ saveUrl = `Businesses/${data.id}`;
+ }
+ "
+ :body="body"
+ />
+
diff --git a/src/pages/Worker/Card/WorkerCalendarFilter.vue b/src/pages/Worker/Card/WorkerCalendarFilter.vue
index 67b7df907..48fc4094b 100644
--- a/src/pages/Worker/Card/WorkerCalendarFilter.vue
+++ b/src/pages/Worker/Card/WorkerCalendarFilter.vue
@@ -180,8 +180,6 @@ const yearList = ref(generateYears());
:is-clearable="false"
/>
-
-
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
-import { ref, computed } from 'vue';
+import { ref, computed, watch } from 'vue';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
@@ -19,6 +19,7 @@ const trainsData = ref([]);
const machinesData = ref([]);
const route = useRoute();
const routeId = computed(() => route.params.id);
+const selected = ref([]);
const initialData = computed(() => {
return {
@@ -41,6 +42,21 @@ async function insert() {
await axios.post('Operators', initialData.value);
crudModelRef.value.reload();
}
+
+watch(
+ () => crudModelRef.value?.formData,
+ (formData) => {
+ if (formData && formData.length) {
+ if (JSON.stringify(selected.value) !== JSON.stringify(formData)) {
+ selected.value = formData;
+ }
+ } else if (selected.value.length > 0) {
+ selected.value = [];
+ }
+ },
+ { immediate: true, deep: true }
+);
+
@@ -67,6 +83,7 @@ async function insert() {
:data-required="{ workerFk: route.params.id }"
ref="crudModelRef"
search-url="operator"
+ :selected="selected"
auto-load
>
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 98bdffe25..992f6ec71 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -12,7 +12,6 @@ import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
-import axios from 'axios';
const route = useRoute();
const { t } = useI18n();
@@ -28,76 +27,6 @@ const entityId = computed(() => $props.id || route.params.id);
const basicDataUrl = ref(null);
const advancedSummary = ref();
-const filter = {
- include: [
- {
- relation: 'user',
- scope: {
- fields: ['name', 'nickname', 'roleFk'],
-
- include: [
- {
- relation: 'role',
- scope: {
- fields: ['name'],
- },
- },
- {
- relation: 'emailUser',
- scope: {
- fields: ['email'],
- },
- },
- ],
- },
- },
- {
- relation: 'department',
- scope: {
- include: {
- relation: 'department',
- scope: {
- fields: ['name'],
- },
- },
- },
- },
- {
- relation: 'boss',
- },
- {
- relation: 'client',
- },
- {
- relation: 'sip',
- },
- {
- relation: 'business',
- scope: {
- include: [
- {
- relation: 'department',
- scope: {
- fields: ['id', 'name'],
- },
- },
- {
- relation: 'reasonEnd',
- scope: {
- fields: ['id', 'reason'],
- },
- },
- {
- relation: 'workerBusinessProfessionalCategory',
- scope: {
- fields: ['id', 'description'],
- },
- },
- ],
- },
- },
- ],
-};
onBeforeMount(async () => {
advancedSummary.value = await useAdvancedSummary('Workers', entityId.value);
basicDataUrl.value = `#/worker/${entityId.value}/basic-data`;
@@ -107,8 +36,8 @@ onBeforeMount(async () => {
diff --git a/src/router/modules/shelving.js b/src/router/modules/shelving.js
index cd8a2bf15..55fb04278 100644
--- a/src/router/modules/shelving.js
+++ b/src/router/modules/shelving.js
@@ -44,6 +44,7 @@ const shelvingCard = {
path: ':id',
component: () => import('pages/Shelving/Card/ShelvingCard.vue'),
redirect: { name: 'ShelvingSummary' },
+ meta: { menu: ['ShelvingBasicData', 'ShelvingLog'] },
children: [
{
name: 'ShelvingSummary',
@@ -81,13 +82,10 @@ export default {
title: 'shelving',
icon: 'vn:inventory',
moduleName: 'Shelving',
+ menu: ['ShelvingList', 'ParkingMain'],
},
component: RouterView,
redirect: { name: 'ShelvingMain' },
- menus: {
- main: ['ShelvingList', 'ParkingMain'],
- card: ['ShelvingBasicData', 'ShelvingLog'],
- },
children: [
{
path: '',
diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index dcded63b0..f2e3671ba 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -62,10 +62,9 @@ describe('Client list', () => {
it('Client founded create order', () => {
const search = 'Jessica Jones';
cy.searchByLabel('Name', search);
- cy.openActionDescriptor('New order');
+ cy.clickButtonWith('icon', 'icon-basketadd');
cy.waitForElement('#formModel');
cy.waitForElement('.q-form');
cy.checkValueForm(1, search);
- cy.checkValueForm(2, search);
});
});
diff --git a/test/cypress/integration/client/clientSms.spec.js b/test/cypress/integration/client/clientSms.spec.js
index 731522a5c..5c82fd9a3 100644
--- a/test/cypress/integration/client/clientSms.spec.js
+++ b/test/cypress/integration/client/clientSms.spec.js
@@ -7,6 +7,5 @@ describe('Client notes', () => {
});
it('Should load layout', () => {
cy.get('.q-page').should('be.visible');
- cy.get('.q-page > :nth-child(2) > :nth-child(1)').should('be.visible');
});
});
diff --git a/test/cypress/integration/entry/myEntry.spec.js b/test/cypress/integration/entry/myEntry.spec.js
index c25476419..49d75cf39 100644
--- a/test/cypress/integration/entry/myEntry.spec.js
+++ b/test/cypress/integration/entry/myEntry.spec.js
@@ -8,12 +8,12 @@ describe('EntryMy when is supplier', () => {
},
});
});
- // https://redmine.verdnatura.es/issues/8418
- it.skip('should open buyLabel when is supplier', () => {
+
+ it('should open buyLabel when is supplier', () => {
cy.get(
- '[to="/null/3"] > .q-card > .column > .q-btn > .q-btn__content > .q-icon'
+ '[to="/null/3"] > .q-card > :nth-child(2) > .q-btn > .q-btn__content > .q-icon'
).click();
- cy.get('.q-card__actions > .q-btn').click();
+ cy.dataCy('printLabelsBtn').click();
cy.window().its('open').should('be.called');
});
});
diff --git a/test/cypress/integration/item/itemTag.spec.js b/test/cypress/integration/item/itemTag.spec.js
index 28e0a747f..10d68d08a 100644
--- a/test/cypress/integration/item/itemTag.spec.js
+++ b/test/cypress/integration/item/itemTag.spec.js
@@ -12,28 +12,22 @@ describe('Item tag', () => {
cy.get('.q-page-sticky > div').click();
cy.dataCy('Tag_select').eq(7).type('Tallos');
cy.get('.q-menu .q-item').contains('Tallos').click();
- cy.get(
- ':nth-child(8) > [label="Value"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Value_input"]'
- ).type('1');
+ cy.get(':nth-child(8) > [label="Value"]').type('1');
+cy.dataCy('crudModelDefaultSaveBtn').click();
cy.checkNotification("The tag or priority can't be repeated for an item");
});
- // https://redmine.verdnatura.es/issues/8422
- it.skip('should add a new tag', () => {
+
+ it('should add a new tag', () => {
cy.get('.q-page').should('be.visible');
cy.get('.q-page-sticky > div').click();
cy.get('.q-page-sticky > div').click();
cy.dataCy('Tag_select').eq(7).click();
- cy.get('.q-menu .q-item').contains('Ancho de la base').click();
- cy.get(
- ':nth-child(8) > [label="Value"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Value_input"]'
- ).type('50');
+ cy.get('.q-menu .q-item').contains('Ancho de la base').type('{enter}');
+ cy.get(':nth-child(8) > [label="Value"]').type('50');
cy.dataCy('crudModelDefaultSaveBtn').click();
cy.checkNotification('Data saved');
- cy.get(
- '[data-cy="itemTags"] > :nth-child(7) > .justify-center > .q-icon'
- ).click();
+ cy.dataCy('itemTags').children(':nth-child(8)').find('.justify-center > .q-icon').click();
cy.dataCy('VnConfirm_confirm').click();
cy.checkNotification('Data saved');
});
-});
+});
\ No newline at end of file
diff --git a/test/cypress/integration/parking/parkingBasicData.spec.js b/test/cypress/integration/parking/parkingBasicData.spec.js
index b5633992c..0d130d335 100644
--- a/test/cypress/integration/parking/parkingBasicData.spec.js
+++ b/test/cypress/integration/parking/parkingBasicData.spec.js
@@ -5,7 +5,7 @@ describe('ParkingBasicData', () => {
const sectorOpt = '.q-menu .q-item';
beforeEach(() => {
cy.login('developer');
- cy.visit(`/#/parking/1/basic-data`);
+ cy.visit(`/#/shelving/parking/1/basic-data`);
});
it('should edit the code and sector', () => {
diff --git a/test/cypress/integration/parking/parkingList.spec.js b/test/cypress/integration/parking/parkingList.spec.js
index f1efaa375..8b7152ca4 100644
--- a/test/cypress/integration/parking/parkingList.spec.js
+++ b/test/cypress/integration/parking/parkingList.spec.js
@@ -11,7 +11,7 @@ describe('ParkingList', () => {
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('developer');
- cy.visit(`/#/parking/list`);
+ cy.visit(`/#/shelving/parking/list`);
});
it('should redirect on clicking a parking', () => {
diff --git a/test/cypress/integration/ticket/ticketList.spec.js b/test/cypress/integration/ticket/ticketList.spec.js
index 2984a4ee4..593021e6e 100644
--- a/test/cypress/integration/ticket/ticketList.spec.js
+++ b/test/cypress/integration/ticket/ticketList.spec.js
@@ -53,4 +53,29 @@ describe('TicketList', () => {
cy.checkNotification('Data created');
cy.url().should('match', /\/ticket\/\d+\/summary/);
});
+
+ it('should show the corerct problems', () => {
+ cy.intercept('GET', '**/api/Tickets/filter*', (req) => {
+ req.headers['cache-control'] = 'no-cache';
+ req.headers['pragma'] = 'no-cache';
+ req.headers['expires'] = '0';
+
+ req.on('response', (res) => {
+ delete res.headers['if-none-match'];
+ delete res.headers['if-modified-since'];
+ });
+ }).as('ticket');
+
+ cy.get('[data-cy="Warehouse_select"]').type('Warehouse Five');
+ cy.get('.q-menu .q-item').contains('Warehouse Five').click();
+ cy.wait('@ticket').then((interception) => {
+ const data = interception.response.body[1];
+ expect(data.hasComponentLack).to.equal(1);
+ expect(data.isTooLittle).to.equal(1);
+ expect(data.hasItemShortage).to.equal(1);
+ });
+ cy.get('.icon-components').should('exist');
+ cy.get('.icon-unavailable').should('exist');
+ cy.get('.icon-isTooLittle').should('exist');
+ });
});
diff --git a/test/cypress/integration/vnComponent/VnSearchBar.spec.js b/test/cypress/integration/vnComponent/VnSearchBar.spec.js
index c710d5192..11d9bbe6a 100644
--- a/test/cypress/integration/vnComponent/VnSearchBar.spec.js
+++ b/test/cypress/integration/vnComponent/VnSearchBar.spec.js
@@ -1,7 +1,6 @@
///
describe('VnSearchBar', () => {
const employeeId = ' #1';
- const salesPersonId = ' #18';
const idGap = '.q-item > .q-item__label';
const vnTableRow = '.q-virtual-scroll__content';
beforeEach(() => {
@@ -12,11 +11,10 @@ describe('VnSearchBar', () => {
it('should redirect to account summary page', () => {
searchAndCheck('1', employeeId);
- searchAndCheck('salesPerson', salesPersonId);
+ searchAndCheck('employee', employeeId);
});
it('should stay on the list page if there are several results or none', () => {
- cy.typeSearchbar('salesA{enter}');
cy.typeSearchbar('salesA{enter}');
checkTableLength(2);
@@ -29,7 +27,6 @@ describe('VnSearchBar', () => {
const searchAndCheck = (searchTerm, expectedText) => {
cy.clearSearchbar();
cy.typeSearchbar(`${searchTerm}{enter}`);
- cy.typeSearchbar(`${searchTerm}{enter}`);
cy.get(idGap).should('have.text', expectedText);
};
diff --git a/test/cypress/integration/wagon/wagonCreate.spec.js b/test/cypress/integration/wagon/wagonCreate.spec.js
index 501375d8c..ce3723e54 100644
--- a/test/cypress/integration/wagon/wagonCreate.spec.js
+++ b/test/cypress/integration/wagon/wagonCreate.spec.js
@@ -8,16 +8,16 @@ describe('WagonCreate', () => {
it('should create and delete a new wagon', () => {
cy.dataCy('vnTableCreateBtn').click();
cy.get(
- '.grid-create > [label="Label"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Label_input"]'
+ '.grid-create > [label="Label"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Label_input"]',
).type('1234');
cy.get(
- '.grid-create > [label="Plate"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Plate_input"]'
+ '.grid-create > [label="Plate"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Plate_input"]',
).type('1234ABCD');
cy.get(
- '.grid-create > [label="Volume"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Volume_input"]'
+ '.grid-create > [label="Volume"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Volume_input"]',
).type('100');
cy.dataCy('Type_select').type('{downarrow}{enter}');
- // // Delete wagon type created
- cy.get('[to="/null/1"] > .q-card > .column > [title="Remove"]').click();
+
+ cy.get('[title="Remove"] > .q-btn__content > .q-icon').click();
});
});
diff --git a/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js b/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
index 0ad98e597..343c1c127 100644
--- a/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
+++ b/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
@@ -6,14 +6,10 @@ describe('WagonTypeCreate', () => {
cy.waitForElement('.q-page', 6000);
});
- it('should create a new wagon type', () => {
+ it('should create a new wagon type and then delete it', () => {
cy.get('.q-page-sticky > div > .q-btn').click();
cy.get('input').first().type('Example for testing');
cy.get('button[type="submit"]').click();
- });
- it('delete a wagon type', () => {
- cy.get(
- '[to="/null/2"] > .q-card > .column > [title="Remove"] > .q-btn__content > .q-icon'
- ).click();
+ cy.get('[title="Remove"] > .q-btn__content > .q-icon').first().click();
});
});
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 6a436c1eb..2c93fbf84 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -289,40 +289,13 @@ Cypress.Commands.add('openActionDescriptor', (opt) => {
cy.openActionsDescriptor();
const listItem = '[role="menu"] .q-list .q-item';
cy.contains(listItem, opt).click();
- 1;
});
Cypress.Commands.add('openActionsDescriptor', () => {
cy.get('[data-cy="descriptor-more-opts"]').click();
});
-Cypress.Commands.add('clickButtonsDescriptor', (id) => {
- cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
- .invoke('removeAttr', 'target')
- .click();
-});
-
-Cypress.Commands.add('openActionDescriptor', (opt) => {
- cy.openActionsDescriptor();
- const listItem = '[role="menu"] .q-list .q-item';
- cy.contains(listItem, opt).click();
- 1;
-});
-
-Cypress.Commands.add('clickButtonsDescriptor', (id) => {
- cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
- .invoke('removeAttr', 'target')
- .click();
-});
-
-Cypress.Commands.add('openActionDescriptor', (opt) => {
- cy.openActionsDescriptor();
- const listItem = '[role="menu"] .q-list .q-item';
- cy.contains(listItem, opt).click();
- 1;
-});
-
-Cypress.Commands.add('clickButtonsDescriptor', (id) => {
+Cypress.Commands.add('clickButtonDescriptor', (id) => {
cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
.invoke('removeAttr', 'target')
.click();
@@ -374,3 +347,21 @@ Cypress.Commands.add('addBtnClick', () => {
.and('be.visible')
.click();
});
+
+Cypress.Commands.add('clickButtonWith', (type, value) => {
+ switch (type) {
+ case 'icon':
+ cy.clickButtonWithIcon(value);
+ break;
+
+ default:
+ cy.clickButtonWithText(value);
+ break;
+ }
+});
+Cypress.Commands.add('clickButtonWithIcon', (iconClass) => {
+ cy.get(`.q-icon.${iconClass}`).parent().click();
+});
+Cypress.Commands.add('clickButtonWithText', (buttonText) => {
+ cy.get('.q-btn').contains(buttonText).click();
+});