diff --git a/src/components/common/VnDateBadge.vue b/src/components/common/VnDateBadge.vue
new file mode 100644
index 000000000..fd6c9e8a4
--- /dev/null
+++ b/src/components/common/VnDateBadge.vue
@@ -0,0 +1,31 @@
+
+
+
+ {{ formatShippedDate(date) }}
+
+
diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index 83af77442..f4c0091d2 100644
--- a/src/components/ui/CardDescriptor.vue
+++ b/src/components/ui/CardDescriptor.vue
@@ -222,8 +222,8 @@ const toModule = computed(() =>
/>
-
-
diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index 7606e6a22..e1b97d7c9 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -46,7 +46,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
{
/>
+
{
/>
+
+
+
+
+
+
+
+
+
+
[
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',
@@ -250,19 +293,6 @@ const columns = computed(() => [
},
]);
-const getBadgeAttrs = (date) => {
- let today = Date.vnNew();
- today.setHours(0, 0, 0, 0);
- let timeTicket = new Date(date);
- timeTicket.setHours(0, 0, 0, 0);
-
- let timeDiff = today - timeTicket;
-
- if (timeDiff == 0) return { color: 'warning', 'text-color': 'black' };
- if (timeDiff < 0) return { color: 'success', 'text-color': 'black' };
- return { color: 'transparent', 'text-color': 'white' };
-};
-
let refreshTimer = null;
const autoRefreshHandler = (value) => {
@@ -279,14 +309,6 @@ const totalPriceColor = (ticket) => {
if (total > 0 && total < 50) return 'warning';
};
-const formatShippedDate = (date) => {
- if (!date) return '-';
- const dateSplit = date.split('T');
- const [year, month, day] = dateSplit[0].split('-');
- const newDate = new Date(year, month - 1, day);
- return toDateFormat(newDate);
-};
-
const openTab = (id) =>
window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer');
@@ -318,6 +340,24 @@ const openTab = (id) =>
auto-load
@on-fetch="(data) => (zoneOpts = data)"
/>
+ (ItemPackingTypeOpts = data)"
+ />
+ (DepartmentOpts = data)"
+ />
@@ -337,7 +377,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 }"
>
-
- {{ formatShippedDate(row.shippedDate) }}
-
+
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index ff4031654..e61a24979 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -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
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index a2ed3bb1a..30afb1904 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -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
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 60a703f84..38e2af612 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -1,6 +1,6 @@
{{ t('Show Proforma') }}
+
+
+
+
+ {{ t('Restore ticket') }}
+
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index 73ea34fe9..f09aec816 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -10,6 +10,7 @@ import { useState } from 'src/composables/useState';
import axios from 'axios';
import VnImg from 'src/components/ui/VnImg.vue';
import EditPictureForm from 'components/EditPictureForm.vue';
+import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
const $props = defineProps({
id: {
@@ -143,10 +144,14 @@ const handlePhotoUpdated = (evt = false) => {
:value="entity.user?.emailUser?.email"
copy
/>
-
+
+
+
+
+
+
{{ t('globals.phone') }}
diff --git a/test/cypress/integration/item/itemLastEntries.spec.js b/test/cypress/integration/item/itemLastEntries.spec.js
new file mode 100644
index 000000000..c94cfa480
--- /dev/null
+++ b/test/cypress/integration/item/itemLastEntries.spec.js
@@ -0,0 +1,20 @@
+describe('ItemLastEntries', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('buyer');
+ cy.visit('/#/item/1/last-entries');
+ cy.intercept('GET', /.*lastEntriesFilter/).as('item');
+ cy.waitForElement('tbody');
+ });
+
+ it('should filter by agency', () => {
+ cy.get('tbody > tr')
+ .its('length')
+ .then((rowCount) => {
+ cy.get('[data-cy="hideInventory"]').click();
+ cy.wait('@item');
+ cy.waitForElement('tbody');
+ cy.get('tbody > tr').should('have.length.greaterThan', rowCount);
+ });
+ });
+});
diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js
index de85dac94..6229039b7 100644
--- a/test/cypress/integration/zone/zoneBasicData.spec.js
+++ b/test/cypress/integration/zone/zoneBasicData.spec.js
@@ -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');
});
});
diff --git a/test/vitest/__tests__/components/common/VnDiscount.spec.js b/test/vitest/__tests__/components/common/VnDiscount.spec.js
new file mode 100644
index 000000000..5d5be61ac
--- /dev/null
+++ b/test/vitest/__tests__/components/common/VnDiscount.spec.js
@@ -0,0 +1,28 @@
+import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
+import { createWrapper } from 'app/test/vitest/helper';
+import VnDiscount from 'components/common/vnDiscount.vue';
+
+describe('VnDiscount', () => {
+ let vm;
+
+ beforeAll(() => {
+ vm = createWrapper(VnDiscount, {
+ props: {
+ data: {},
+ price: 100,
+ quantity: 2,
+ discount: 10,
+ }
+ }).vm;
+ });
+
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ describe('total', () => {
+ it('should calculate total correctly', () => {
+ expect(vm.total).toBe(180);
+ });
+ });
+});
\ No newline at end of file