diff --git a/src/pages/ItemType/ItemTypeSearchbar.vue b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
similarity index 94%
rename from src/pages/ItemType/ItemTypeSearchbar.vue
rename to src/pages/Item/ItemType/ItemTypeSearchbar.vue
index 749033d43..87903a517 100644
--- a/src/pages/ItemType/ItemTypeSearchbar.vue
+++ b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
@@ -10,6 +10,7 @@ const { t } = useI18n();
url="ItemTypes"
:label="t('Search item type')"
:info="t('Search itemType by id, name or code')"
+ search-url="table"
/>
diff --git a/src/pages/ItemType/locale/en.yml b/src/pages/Item/ItemType/locale/en.yml
similarity index 69%
rename from src/pages/ItemType/locale/en.yml
rename to src/pages/Item/ItemType/locale/en.yml
index 7889418ea..575d5e402 100644
--- a/src/pages/ItemType/locale/en.yml
+++ b/src/pages/Item/ItemType/locale/en.yml
@@ -4,6 +4,10 @@ shared:
worker: Worker
category: Category
temperature: Temperature
+ life: Life
+ itemPackingType: Item packing type
+ maxRefs: Maximum references
+ fragile: Fragile
summary:
id: id
life: Life
diff --git a/src/pages/ItemType/locale/es.yml b/src/pages/Item/ItemType/locale/es.yml
similarity index 77%
rename from src/pages/ItemType/locale/es.yml
rename to src/pages/Item/ItemType/locale/es.yml
index 9a94dceb6..09ee5a1f7 100644
--- a/src/pages/ItemType/locale/es.yml
+++ b/src/pages/Item/ItemType/locale/es.yml
@@ -4,6 +4,10 @@ shared:
worker: Trabajador
category: Reino
temperature: Temperatura
+ life: Vida
+ itemPackingType: Tipo de embalaje
+ maxRefs: Referencias máximas
+ fragile: Frágil
summary:
id: id
code: Código
diff --git a/src/pages/Item/ItemTypeCreate.vue b/src/pages/Item/ItemTypeCreate.vue
deleted file mode 100644
index 290a40389..000000000
--- a/src/pages/Item/ItemTypeCreate.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
- (categoriesOptions = data)"
- :filter="{ order: 'name ASC', fields: ['id', 'name'] }"
- auto-load
- />
- (temperaturesOptions = data)"
- :filter="{ order: 'name ASC', fields: ['code', 'name'] }"
- auto-load
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index d874a5dcb..149de482d 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -1,113 +1,159 @@
-
+ (itemCategoriesOptions = data)"
+ auto-load
+ />
+ (temperatureOptions = data)"
+ auto-load
+ />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ t('New item type') }}
-
-
+
+
+
+
+ es:
+ id: Id
+ code: Código
+ name: Nombre
+ worker: Trabajador
+ ItemCategory: Reino
+ Temperature: Temperatura
+ Create ItemTypes: Crear familia
+ en:
+ code: Code
+ name: Name
+ worker: Worker
+ ItemCategory: ItemCategory
+ Temperature: Temperature
+
diff --git a/src/pages/Item/composables/cloneItem.js b/src/pages/Item/composables/cloneItem.js
new file mode 100644
index 000000000..2421c0808
--- /dev/null
+++ b/src/pages/Item/composables/cloneItem.js
@@ -0,0 +1,36 @@
+import axios from 'axios';
+import { useRouter } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+import { useQuasar } from 'quasar';
+import VnConfirm from 'components/ui/VnConfirm.vue';
+
+export function cloneItem() {
+ const { t } = useI18n();
+
+ const quasar = useQuasar();
+ const router = useRouter();
+ const cloneItem = async (entityId) => {
+ const { id } = entityId;
+ try {
+ const { data } = await axios.post(`Items/${id ?? entityId}/clone`);
+ router.push({ name: 'ItemTags', params: { id: data.id } });
+ } catch (err) {
+ console.error('Error cloning item');
+ }
+ };
+
+ const openCloneDialog = async (entityId) => {
+ quasar
+ .dialog({
+ component: VnConfirm,
+ componentProps: {
+ title: t('item.descriptor.clone.title'),
+ message: t('item.descriptor.clone.subTitle'),
+ },
+ })
+ .onOk(async () => {
+ await cloneItem(entityId);
+ });
+ };
+ return { openCloneDialog };
+}
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index c32ee493c..e99853760 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -88,3 +88,127 @@ itemType:
worker: Worker
category: Category
temperature: Temperature
+item:
+ params:
+ daysOnward: Days onward
+ search: General search
+ ticketFk: Ticket id
+ attenderFk: Atender
+ clientFk: Client id
+ warehouseFk: Warehouse
+ requesterFk: Salesperson
+ from: From
+ to: To
+ mine: For me
+ state: State
+ myTeam: My team
+ searchbar:
+ label: Search item
+ descriptor:
+ item: Item
+ buyer: Buyer
+ color: Color
+ category: Category
+ stems: Stems
+ visible: Visible
+ available: Available
+ warehouseText: 'Calculated on the warehouse of { warehouseName }'
+ itemDiary: Item diary
+ producer: Producer
+ clone:
+ title: All its properties will be copied
+ subTitle: Do you want to clone this item?
+ list:
+ id: Identifier
+ grouping: Grouping
+ packing: Packing
+ description: Description
+ stems: Stems
+ category: Category
+ typeName: Type
+ intrastat: Intrastat
+ isActive: Active
+ size: Size
+ origin: Origin
+ userName: Buyer
+ weightByPiece: Weight/Piece
+ stemMultiplier: Multiplier
+ producer: Producer
+ landed: Landed
+ basicData:
+ type: Type
+ reference: Reference
+ relevancy: Relevancy
+ stems: Stems
+ multiplier: Multiplier
+ generic: Generic
+ intrastat: Intrastat
+ expense: Expense
+ weightByPiece: Weight/Piece
+ boxUnits: Units/Box
+ recycledPlastic: Recycled Plastic
+ nonRecycledPlastic: Non recycled plastic
+ isActive: Active
+ hasKgPrice: Price in kg
+ isFragile: Fragile
+ isFragileTooltip: Is shown at website, app that this item cannot travel (wreath, palms, ...)
+ isPhotoRequested: Do photo
+ isPhotoRequestedTooltip: This item does need a photo
+ description: Description
+ fixedPrice:
+ itemFk: Item ID
+ groupingPrice: Grouping price
+ packingPrice: Packing price
+ hasMinPrice: Has min price
+ minPrice: Min price
+ started: Started
+ ended: Ended
+ warehouse: Warehouse
+ create:
+ name: Name
+ tag: Tag
+ priority: Priority
+ type: Type
+ intrastat: Intrastat
+ origin: Origin
+ buyRequest:
+ ticketId: 'Ticket ID'
+ shipped: 'Shipped'
+ requester: 'Requester'
+ requested: 'Requested'
+ price: 'Price'
+ attender: 'Attender'
+ item: 'Item'
+ achieved: 'Achieved'
+ concept: 'Concept'
+ state: 'State'
+ summary:
+ basicData: 'Basic data'
+ otherData: 'Other data'
+ description: 'Description'
+ tax: 'Tax'
+ tags: 'Tags'
+ botanical: 'Botanical'
+ barcode: 'Barcode'
+ name: 'Nombre'
+ completeName: 'Nombre completo'
+ family: 'Familia'
+ size: 'Medida'
+ origin: 'Origen'
+ stems: 'Tallos'
+ multiplier: 'Multiplicador'
+ buyer: 'Comprador'
+ doPhoto: 'Do photo'
+ intrastatCode: 'Código intrastat'
+ intrastat: 'Intrastat'
+ ref: 'Referencia'
+ relevance: 'Relevancia'
+ weight: 'Peso (gramos)/tallo'
+ units: 'Unidades/caja'
+ expense: 'Gasto'
+ generic: 'Genérico'
+ recycledPlastic: 'Plástico reciclado'
+ nonRecycledPlastic: 'Plástico no reciclado'
+ minSalesQuantity: 'Cantidad mínima de venta'
+ genus: 'Genus'
+ specie: 'Specie'
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index d32cb7885..56c6ec317 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -88,3 +88,129 @@ itemType:
worker: Trabajador
category: Reino
temperature: Temperatura
+params:
+ state: asfsdf
+item:
+ params:
+ daysOnward: Días adelante
+ search: Búsqueda general
+ ticketFk: Id ticket
+ attenderFk: Comprador
+ clientFk: Id cliente
+ warehouseFk: Almacén
+ requesterFk: Comercial
+ from: Desde
+ to: Hasta
+ mine: Para mi
+ state: Estado
+ myTeam: Mi equipo
+ searchbar:
+ label: Buscar artículo
+ descriptor:
+ item: Artículo
+ buyer: Comprador
+ color: Color
+ category: Categoría
+ stems: Tallos
+ visible: Visible
+ available: Disponible
+ warehouseText: 'Calculado sobre el almacén de { warehouseName }'
+ itemDiary: Registro de compra-venta
+ producer: Productor
+ clone:
+ title: Todas sus propiedades serán copiadas
+ subTitle: ¿Desea clonar este artículo?
+ list:
+ id: Identificador
+ grouping: Grouping
+ packing: Packing
+ description: Descripción
+ stems: Tallos
+ category: Reino
+ typeName: Tipo
+ intrastat: Intrastat
+ isActive: Activo
+ size: Medida
+ origin: Origen
+ weightByPiece: Peso (gramos)/tallo
+ userName: Comprador
+ stemMultiplier: Multiplicador
+ producer: Productor
+ landed: F. entrega
+ basicData:
+ type: Tipo
+ reference: Referencia
+ relevancy: Relevancia
+ stems: Tallos
+ multiplier: Multiplicador
+ generic: Genérico
+ intrastat: Intrastat
+ expense: Gasto
+ weightByPiece: Peso (gramos)/tallo
+ boxUnits: Unidades/caja
+ recycledPlastic: Plastico reciclado
+ nonRecycledPlastic: Plático no reciclado
+ isActive: Activo
+ hasKgPrice: Precio en kg
+ isFragile: Frágil
+ isFragileTooltip: Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...)
+ isPhotoRequested: Hacer foto
+ isPhotoRequestedTooltip: Este artículo necesita una foto
+ description: Descripción
+ fixedPrice:
+ itemFk: ID Artículo
+ groupingPrice: Precio grouping
+ packingPrice: Precio packing
+ hasMinPrice: Tiene precio mínimo
+ minPrice: Precio min
+ started: Inicio
+ ended: Fin
+ warehouse: Almacén
+ create:
+ name: Nombre
+ tag: Etiqueta
+ priority: Prioridad
+ type: Tipo
+ intrastat: Intrastat
+ origin: Origen
+ summary:
+ basicData: 'Datos básicos'
+ otherData: 'Otros datos'
+ description: 'Descripción'
+ tax: 'IVA'
+ tags: 'Etiquetas'
+ botanical: 'Botánico'
+ barcode: 'Código de barras'
+ name: 'Nombre'
+ completeName: 'Nombre completo'
+ family: 'Familia'
+ size: 'Medida'
+ origin: 'Origen'
+ stems: 'Tallos'
+ multiplier: 'Multiplicador'
+ buyer: 'Comprador'
+ doPhoto: 'Hacer foto'
+ intrastatCode: 'Código intrastat'
+ intrastat: 'Intrastat'
+ ref: 'Referencia'
+ relevance: 'Relevancia'
+ weight: 'Peso (gramos)/tallo'
+ units: 'Unidades/caja'
+ expense: 'Gasto'
+ generic: 'Genérico'
+ recycledPlastic: 'Plástico reciclado'
+ nonRecycledPlastic: 'Plástico no reciclado'
+ minSalesQuantity: 'Cantidad mínima de venta'
+ genus: 'Genus'
+ specie: 'Specie'
+ buyRequest:
+ ticketId: 'ID Ticket'
+ shipped: 'F. envío'
+ requester: 'Solicitante'
+ requested: 'Solicitado'
+ price: 'Precio'
+ attender: 'Comprador'
+ item: 'Artículo'
+ achieved: 'Conseguido'
+ concept: 'Concepto'
+ state: 'Estado'
diff --git a/src/pages/Parking/Card/ParkingCard.vue b/src/pages/Parking/Card/ParkingCard.vue
index ad37eb630..337106986 100644
--- a/src/pages/Parking/Card/ParkingCard.vue
+++ b/src/pages/Parking/Card/ParkingCard.vue
@@ -2,17 +2,11 @@
import VnCard from 'components/common/VnCard.vue';
import ParkingDescriptor from 'pages/Parking/Card/ParkingDescriptor.vue';
import ParkingFilter from 'pages/Parking/ParkingFilter.vue';
-
-const filter = {
- fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
- include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
-};
diff --git a/src/pages/Parking/ParkingList.vue b/src/pages/Parking/ParkingList.vue
index b6f4e8146..109613383 100644
--- a/src/pages/Parking/ParkingList.vue
+++ b/src/pages/Parking/ParkingList.vue
@@ -22,7 +22,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
const filter = {
fields: ['id', 'sectorFk', 'code', 'pickingOrder'],
- include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
};
function exprBuilder(param, value) {
@@ -55,10 +54,9 @@ function exprBuilder(param, value) {
diff --git a/src/pages/Route/RouteAutonomous.vue b/src/pages/Route/RouteAutonomous.vue
index 5ad349942..4a691dbef 100644
--- a/src/pages/Route/RouteAutonomous.vue
+++ b/src/pages/Route/RouteAutonomous.vue
@@ -126,7 +126,7 @@ const columns = computed(() => [
name: 'tableActions',
actions: [
{
- title: t('Preview'),
+ title: t('components.smartCard.viewSummary'),
icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row?.routeFk, RouteSummary),
diff --git a/src/pages/Route/RouteExtendedList.vue b/src/pages/Route/RouteExtendedList.vue
index 51da4ec12..dbf646935 100644
--- a/src/pages/Route/RouteExtendedList.vue
+++ b/src/pages/Route/RouteExtendedList.vue
@@ -204,7 +204,7 @@ const columns = computed(() => [
isPrimary: true,
},
{
- title: t('route.components.smartCard.viewSummary'),
+ title: t('components.smartCard.viewSummary'),
icon: 'preview',
action: (row) => viewSummary(row?.id, RouteSummary),
isPrimary: true,
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index fdc75abda..f6c20c514 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -12,6 +12,7 @@ import VnInputTime from 'components/common/VnInputTime.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
+import { useAcl } from 'src/composables/useAcl';
import { useValidator } from 'src/composables/useValidator';
import { toTimeFormat } from 'filters/date.js';
@@ -28,14 +29,17 @@ const { validate } = useValidator();
const { notify } = useNotify();
const router = useRouter();
const { t } = useI18n();
-const agencyFetchRef = ref(null);
-const zonesFetchRef = ref(null);
+const canEditZone = useAcl().hasAny([
+ { model: 'Ticket', props: 'editZone', accessType: 'WRITE' },
+]);
+const agencyFetchRef = ref();
const warehousesOptions = ref([]);
const companiesOptions = ref([]);
const agenciesOptions = ref([]);
const zonesOptions = ref([]);
const addresses = ref([]);
+const zoneSelectRef = ref();
const formData = ref($props.formData);
watch(
@@ -44,6 +48,8 @@ watch(
{ deep: true }
);
+onMounted(() => onFormModelInit());
+
const agencyByWarehouseFilter = computed(() => ({
fields: ['id', 'name'],
order: 'name ASC',
@@ -52,18 +58,16 @@ const agencyByWarehouseFilter = computed(() => ({
},
}));
-function zoneWhere() {
- if (formData?.value?.agencyModeFk) {
- return formData.value?.agencyModeFk
- ? {
- shipped: formData.value?.shipped,
- addressFk: formData.value?.addressFk,
- agencyModeFk: formData.value?.agencyModeFk,
- warehouseFk: formData.value?.warehouseFk,
- }
- : {};
- }
-}
+const zoneWhere = computed(() => {
+ return formData.value?.agencyModeFk
+ ? {
+ shipped: formData.value?.shipped,
+ addressFk: formData.value?.addressFk,
+ agencyModeFk: formData.value?.agencyModeFk,
+ warehouseFk: formData.value?.warehouseFk,
+ }
+ : {};
+});
const getLanded = async (params) => {
try {
@@ -108,32 +112,20 @@ const getShipped = async (params) => {
};
const onChangeZone = async (zoneId) => {
- try {
- formData.value.agencyModeFk = null;
- const { data } = await axios.get(`Zones/${zoneId}`);
- formData.value.agencyModeFk = data.agencyModeFk;
- } catch (error) {
- console.error(error);
- }
+ formData.value.agencyModeFk = null;
+ const { data } = await axios.get(`Zones/${zoneId}`);
+ formData.value.agencyModeFk = data.agencyModeFk;
};
const onChangeAddress = async (addressId) => {
- try {
- formData.value.nickname = null;
- const { data } = await axios.get(`Addresses/${addressId}`);
- formData.value.nickname = data.nickname;
- } catch (error) {
- console.error(error);
- }
+ formData.value.nickname = null;
+ const { data } = await axios.get(`Addresses/${addressId}`);
+ formData.value.nickname = data.nickname;
};
const getClientDefaultAddress = async (clientId) => {
- try {
- const { data } = await axios.get(`Clients/${clientId}`);
- if (data) addressId.value = data.defaultAddressFk;
- } catch (error) {
- console.error(error);
- }
+ const { data } = await axios.get(`Clients/${clientId}`);
+ if (data) addressId.value = data.defaultAddressFk;
};
const clientAddressesList = async (value) => {
@@ -270,7 +262,17 @@ const redirectToCustomerAddress = () => {
});
};
-onMounted(() => onFormModelInit());
+async function getZone(options) {
+ if (!zoneId.value) return;
+
+ const zone = options.find((z) => z.id == zoneId.value);
+ if (zone) return;
+
+ const { data } = await axios.get('Zones/' + zoneId.value, {
+ params: { filter: JSON.stringify({ fields: ['id', 'name'] }) },
+ });
+ zoneSelectRef.value.opts.push(data);
+}
onFormModelInit());
:rules="validate('basicData.agency')"
/>
onFormModelInit());
:fields="['id', 'name']"
sort-by="id"
:where="zoneWhere"
- hide-selected
- map-options
- :required="true"
- @focus="zonesFetchRef.fetch()"
:rules="validate('basicData.zone')"
+ :required="true"
+ :disable="!canEditZone"
+ @update:options="getZone"
>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
index 92640f898..fb7881403 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
@@ -70,60 +70,51 @@ const isFormInvalid = () => {
};
const getPriceDifference = async () => {
- try {
- const params = {
- landed: formData.value.landed,
- addressId: formData.value.addressFk,
- agencyModeId: formData.value.agencyModeFk,
- zoneId: formData.value.zoneFk,
- warehouseId: formData.value.warehouseFk,
- shipped: formData.value.shipped,
- };
- const { data } = await axios.post(
- `tickets/${formData.value.id}/priceDifference`,
- params
- );
- formData.value.sale = data;
- } catch (error) {
- console.error(error);
- }
+ const params = {
+ landed: formData.value.landed,
+ addressId: formData.value.addressFk,
+ agencyModeId: formData.value.agencyModeFk,
+ zoneId: formData.value.zoneFk,
+ warehouseId: formData.value.warehouseFk,
+ shipped: formData.value.shipped,
+ };
+ const { data } = await axios.post(
+ `tickets/${formData.value.id}/priceDifference`,
+ params
+ );
+ formData.value.sale = data;
};
const submit = async () => {
- try {
- if (!formData.value.option)
- return notify(t('basicData.chooseAnOption'), 'negative');
+ if (!formData.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
- const params = {
- clientFk: formData.value.clientFk,
- nickname: formData.value.nickname,
- agencyModeFk: formData.value.agencyModeFk,
- addressFk: formData.value.addressFk,
- zoneFk: formData.value.zoneFk,
- warehouseFk: formData.value.warehouseFk,
- companyFk: formData.value.companyFk,
- shipped: formData.value.shipped,
- landed: formData.value.landed,
- isDeleted: formData.value.isDeleted,
- option: formData.value.option,
- isWithoutNegatives: formData.value.withoutNegatives,
- withWarningAccept: formData.value.withWarningAccept,
- keepPrice: false,
- };
+ const params = {
+ clientFk: formData.value.clientFk,
+ nickname: formData.value.nickname,
+ agencyModeFk: formData.value.agencyModeFk,
+ addressFk: formData.value.addressFk,
+ zoneFk: formData.value.zoneFk,
+ warehouseFk: formData.value.warehouseFk,
+ companyFk: formData.value.companyFk,
+ shipped: formData.value.shipped,
+ landed: formData.value.landed,
+ isDeleted: formData.value.isDeleted,
+ option: formData.value.option,
+ isWithoutNegatives: formData.value.withoutNegatives,
+ withWarningAccept: formData.value.withWarningAccept,
+ keepPrice: false,
+ };
- const { data } = await axios.post(
- `tickets/${formData.value.id}/componentUpdate`,
- params
- );
+ const { data } = await axios.post(
+ `tickets/${formData.value.id}/componentUpdate`,
+ params
+ );
- if (!data) return;
+ if (!data) return;
- const ticketToMove = data.id;
- notify(t('basicData.unroutedTicket'), 'positive');
- router.push({ name: 'TicketSummary', params: { id: ticketToMove } });
- } catch (error) {
- console.error(error);
- }
+ const ticketToMove = data.id;
+ notify(t('basicData.unroutedTicket'), 'positive');
+ router.push({ name: 'TicketSummary', params: { id: ticketToMove } });
};
const submitWithNegatives = async () => {
diff --git a/src/pages/Ticket/Card/ExpeditionNewTicket.vue b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
index 9183ae405..c288f6cc2 100644
--- a/src/pages/Ticket/Card/ExpeditionNewTicket.vue
+++ b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
@@ -34,26 +34,20 @@ const newTicketFormData = reactive({});
const date = new Date();
const createTicket = async () => {
- try {
- const expeditionIds = $props.selectedExpeditions.map(
- (expedition) => expedition.id
- );
- const params = {
- clientId: $props.ticket.clientFk,
- landed: newTicketFormData.landed,
- warehouseId: $props.ticket.warehouseFk,
- addressId: $props.ticket.addressFk,
- agencyModeId: $props.ticket.agencyModeFk,
- routeId: newTicketFormData.routeFk,
- expeditionIds: expeditionIds,
- };
+ const expeditionIds = $props.selectedExpeditions.map((expedition) => expedition.id);
+ const params = {
+ clientId: $props.ticket.clientFk,
+ landed: newTicketFormData.landed,
+ warehouseId: $props.ticket.warehouseFk,
+ addressId: $props.ticket.addressFk,
+ agencyModeId: $props.ticket.agencyModeFk,
+ routeId: newTicketFormData.routeFk,
+ expeditionIds: expeditionIds,
+ };
- const { data } = await axios.post('Expeditions/moveExpeditions', params);
- notify(t('globals.dataSaved'), 'positive');
- router.push({ name: 'TicketSummary', params: { id: data.id } });
- } catch (error) {
- console.error(error);
- }
+ const { data } = await axios.post('Expeditions/moveExpeditions', params);
+ notify(t('globals.dataSaved'), 'positive');
+ router.push({ name: 'TicketSummary', params: { id: data.id } });
};
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index 0bccdaacd..b5b3c430c 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -150,31 +150,19 @@ const getTotal = computed(() => {
});
const getComponentsSum = async () => {
- try {
- const { data } = await axios.get(`Tickets/${route.params.id}/getComponentsSum`);
- componentsList.value = data;
- } catch (error) {
- console.error(error);
- }
+ const { data } = await axios.get(`Tickets/${route.params.id}/getComponentsSum`);
+ componentsList.value = data;
};
const getTheoricalCost = async () => {
- try {
- const { data } = await axios.get(`Tickets/${route.params.id}/freightCost`);
- theoricalCost.value = data;
- } catch (error) {
- console.error(error);
- }
+ const { data } = await axios.get(`Tickets/${route.params.id}/freightCost`);
+ theoricalCost.value = data;
};
const getTicketVolume = async () => {
- try {
- if (!ticketData.value) return;
- const { data } = await axios.get(`Tickets/${ticketData.value.id}/getVolume`);
- ticketVolume.value = data[0].volume;
- } catch (error) {
- console.error(error);
- }
+ if (!ticketData.value) return;
+ const { data } = await axios.get(`Tickets/${ticketData.value.id}/getVolume`);
+ ticketVolume.value = data[0].volume;
};
onMounted(() => {
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 73104fe27..bf4a1efb4 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -3,7 +3,7 @@ import axios from 'axios';
import { ref, toRefs } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
import { usePrintService } from 'composables/usePrintService';
import SendEmailDialog from 'components/common/SendEmailDialog.vue';
import VnConfirm from 'components/ui/VnConfirm.vue';
@@ -23,6 +23,7 @@ const props = defineProps({
required: true,
},
});
+const route = useRoute();
const { push, currentRoute } = useRouter();
const { dialog, notify } = useQuasar();
@@ -40,6 +41,8 @@ const isEditable = ref();
const hasInvoicing = useAcl('invoicing');
const hasPdf = ref();
const weight = ref();
+const hasDocuwareFile = ref();
+const quasar = useQuasar();
const actions = {
clone: async () => {
const opts = { message: t('Ticket cloned'), type: 'positive' };
@@ -331,10 +334,48 @@ async function handleInvoiceOutData() {
});
hasPdf.value = data[0]?.hasPdf;
}
+
+async function docuwareDownload() {
+ await axios.get(`Tickets/${ticketId}/docuwareDownload`);
+}
+
+async function hasDocuware() {
+ const { data } = await axios.post(`Docuwares/${ticketId}/checkFile`, {
+ fileCabinet: 'deliveryNote',
+ signed: true,
+ });
+ hasDocuwareFile.value = data;
+}
+
+async function uploadDocuware(force) {
+ if (!force)
+ return quasar
+ .dialog({
+ component: VnConfirm,
+ componentProps: {
+ title: t('Send PDF to tablet'),
+ message: t('Are you sure you want to replace this delivery note?'),
+ },
+ })
+ .onOk(async () => {
+ uploadDocuware(true);
+ });
+
+ const { data } = await axios.post(`Docuwares/upload`, {
+ fileCabinet: 'deliveryNote',
+ ticketIds: [parseInt(ticketId)],
+ });
+
+ if (data) notify({ message: t('PDF sent!'), type: 'positive' });
+}
@@ -452,7 +493,13 @@ async function handleInvoiceOutData() {
-
+
{{ t('as PDF') }}
@@ -460,6 +507,14 @@ async function handleInvoiceOutData() {
{{ t('as PDF without prices') }}
+
+ {{ t('as PDF signed') }}
+
-
+
{{ t('Send PDF') }}
-
+
{{ t('Send PDF to tablet') }}
diff --git a/src/pages/Ticket/Card/TicketEditMana.vue b/src/pages/Ticket/Card/TicketEditMana.vue
index 428e5e8c2..3d5b04a41 100644
--- a/src/pages/Ticket/Card/TicketEditMana.vue
+++ b/src/pages/Ticket/Card/TicketEditMana.vue
@@ -1,8 +1,8 @@
+ (expeditionStateTypes = data)"
+ auto-load
+ />
+
(stateStore.rightDrawer = false));
-
(stateStore.rightDrawer = false));
selection: 'multiple',
}"
auto-load
+ :expr-builder="
+ (param, value) => {
+ switch (param) {
+ case 'expeditionFk':
+ return { id: value };
+ case 'packageItemName':
+ return { packagingItemFk: value };
+ }
+ }
+ "
order="created DESC"
>
@@ -324,7 +321,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
@@ -345,11 +342,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
-
- {{
- row.isScanned === 1 ? t('expedition.yes') : t('expedition.no')
- }}
-
+
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 43af8d528..7529d4908 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -2,6 +2,7 @@
import { onMounted, ref, computed, onUnmounted, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter, useRoute } from 'vue-router';
+import { useQuasar } from 'quasar';
import FetchData from 'components/FetchData.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
@@ -22,6 +23,8 @@ import { useVnConfirm } from 'composables/useVnConfirm';
import useNotify from 'src/composables/useNotify.js';
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';
const route = useRoute();
const router = useRouter();
@@ -31,7 +34,7 @@ const { notify } = useNotify();
const { openConfirmationModal } = useVnConfirm();
const editPriceProxyRef = ref(null);
const stateBtnDropdownRef = ref(null);
-
+const quasar = useQuasar();
const arrayData = useArrayData('ticketData');
const { store } = arrayData;
const selectedRows = ref([]);
@@ -50,6 +53,7 @@ const transfer = ref({
sales: [],
});
const tableRef = ref([]);
+const canProceed = ref();
watch(
() => route.params.id,
@@ -213,7 +217,9 @@ const addSale = async (sale) => {
}
};
-const changeQuantity = (sale) => {
+const changeQuantity = async (sale) => {
+ canProceed.value = await isSalePrepared(sale);
+ if (!canProceed.value) return;
if (
!sale.itemFk ||
sale.quantity == null ||
@@ -225,6 +231,8 @@ const changeQuantity = (sale) => {
};
const updateConcept = async (sale) => {
+ canProceed.value = await isSalePrepared(sale);
+ if (!canProceed.value) return;
try {
const data = { newConcept: sale.concept };
await axios.post(`Sales/${sale.id}/updateConcept`, data);
@@ -285,6 +293,8 @@ const onOpenEditDiscountPopover = async (sale) => {
};
const updatePrice = async (sale) => {
+ canProceed.value = await isSalePrepared(sale);
+ if (!canProceed.value) return;
try {
const newPrice = edit.value.price;
if (newPrice != null && newPrice != sale.price) {
@@ -299,12 +309,18 @@ const updatePrice = async (sale) => {
}
};
-const changeDiscount = (sale) => {
+const changeDiscount = async (sale) => {
+ canProceed.value = await isSalePrepared(sale);
+ if (!canProceed.value) return;
const newDiscount = edit.value.discount;
if (newDiscount != null && newDiscount != sale.discount) updateDiscount([sale]);
};
const updateDiscount = async (sales, newDiscount = null) => {
+ for (const sale of sales) {
+ const canProceed = await isSalePrepared(sale);
+ if (!canProceed) return;
+ }
const saleIds = sales.map((sale) => sale.id);
const _newDiscount = newDiscount || edit.value.discount;
const params = {
@@ -432,7 +448,9 @@ onUnmounted(() => (stateStore.rightDrawer = false));
const items = ref([]);
const newRow = ref({});
-const updateItem = (row) => {
+const updateItem = async (row) => {
+ canProceed.value = await isSalePrepared(row);
+ if (!canProceed.value) return;
const selectedItem = items.value.find((item) => item.id === row.itemFk);
if (selectedItem) {
row.item = selectedItem;
@@ -475,6 +493,55 @@ const endNewRow = (row) => {
}
};
+async function isSalePrepared(item) {
+ const filter = {
+ params: {
+ where: { ticketFk: route.params.id },
+ order: ['concept ASC', 'quantity DESC'],
+ },
+ };
+ const { data } = await axios.get(`SaleTrackings/${route.params.id}/filter`, {
+ params: {
+ filter: JSON.stringify(filter),
+ },
+ });
+
+ const matchingSale = data.find((sale) => sale.itemFk === item.itemFk);
+ if (!matchingSale) {
+ return true;
+ }
+
+ if (
+ matchingSale.hasSaleGroupDetail ||
+ matchingSale.isControled ||
+ matchingSale.isPrepared ||
+ matchingSale.isPrevious ||
+ matchingSale.isPreviousSelected
+ ) {
+ try {
+ await new Promise((resolve, reject) => {
+ quasar
+ .dialog({
+ component: VnConfirm,
+ componentProps: {
+ title: t('Item prepared'),
+ message: t(
+ 'This item is already prepared. Do you want to continue?'
+ ),
+ data: item,
+ },
+ })
+ .onOk(() => resolve(true))
+ .onCancel(() => reject(new Error('cancelled')));
+ });
+ } catch (error) {
+ tableRef.value.reload();
+ return false;
+ }
+ }
+ return true;
+}
+
watch(
() => newRow.value.itemFk,
(newItemFk) => {
@@ -538,6 +605,7 @@ watch(
:ticket-config="ticketConfig"
@get-mana="getMana()"
@update-discounts="updateDiscount"
+ @refresh-table="resetChanges"
/>
+
+
+
{{ toPercentage(row.discount / 100) }}
@@ -814,4 +887,6 @@ es:
You are going to delete lines of the ticket: Vas a eliminar lineas del ticket
Add item: Añadir artículo
Transfer lines: Transferir líneas
+ Item prepared: Artículo preparado
+ This item is already prepared. Do you want to continue?: Este artículo ya esta preparado. Desea continuar?
diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
index 2ec519d2d..16b84ab5e 100644
--- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue
+++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
@@ -14,7 +14,7 @@ import { toDateFormat } from 'src/filters/date';
import { useRole } from 'src/composables/useRole';
import { useVnConfirm } from 'composables/useVnConfirm';
-const emit = defineEmits(['updateDiscounts', 'getMana']);
+const emit = defineEmits(['updateDiscounts', 'getMana', 'refreshTable']);
const props = defineProps({
disable: {
@@ -107,6 +107,7 @@ const calculateSalePrice = async () => {
await axios.post(`Sales/recalculatePrice`, props.sales);
notify(t('globals.dataSaved'), 'positive');
+ emit('refreshTable', props.sales);
};
const changeMultipleDiscount = () => {
@@ -165,14 +166,10 @@ const createRefund = async (withWarehouse) => {
negative: true,
};
- try {
- const { data } = await axios.post('Tickets/cloneAll', params);
- const [refundTicket] = data;
- notify(t('refundTicketCreated', { ticketId: refundTicket.id }), 'positive');
- push({ name: 'TicketSale', params: { id: refundTicket.id } });
- } catch (error) {
- console.error(error);
- }
+ const { data } = await axios.post('Tickets/cloneAll', params);
+ const [refundTicket] = data;
+ notify(t('refundTicketCreated', { ticketId: refundTicket.id }), 'positive');
+ push({ name: 'TicketSale', params: { id: refundTicket.id } });
};
diff --git a/src/pages/Ticket/Card/TicketSaleTracking.vue b/src/pages/Ticket/Card/TicketSaleTracking.vue
index e7830bf37..1083393c4 100644
--- a/src/pages/Ticket/Card/TicketSaleTracking.vue
+++ b/src/pages/Ticket/Card/TicketSaleTracking.vue
@@ -150,18 +150,14 @@ const shelvingsTableColumns = computed(() => [
]);
const getSaleTrackings = async (sale) => {
- try {
- const filter = {
- where: { saleFk: sale.saleFk },
- order: ['itemFk DESC'],
- };
- const { data } = await axios.get(`SaleTrackings/listSaleTracking`, {
- params: { filter: JSON.stringify(filter) },
- });
- saleTrackings.value = data;
- } catch (error) {
- console.error(error);
- }
+ const filter = {
+ where: { saleFk: sale.saleFk },
+ order: ['itemFk DESC'],
+ };
+ const { data } = await axios.get(`SaleTrackings/listSaleTracking`, {
+ params: { filter: JSON.stringify(filter) },
+ });
+ saleTrackings.value = data;
};
const showLog = async (sale) => {
@@ -170,17 +166,13 @@ const showLog = async (sale) => {
};
const getItemShelvingSales = async (sale) => {
- try {
- const filter = {
- where: { saleFk: sale.saleFk },
- };
- const { data } = await axios.get(`ItemShelvingSales/filter`, {
- params: { filter: JSON.stringify(filter) },
- });
- itemShelvingsSales.value = data;
- } catch (error) {
- console.error(error);
- }
+ const filter = {
+ where: { saleFk: sale.saleFk },
+ };
+ const { data } = await axios.get(`ItemShelvingSales/filter`, {
+ params: { filter: JSON.stringify(filter) },
+ });
+ itemShelvingsSales.value = data;
};
const showShelving = async (sale) => {
@@ -189,36 +181,28 @@ const showShelving = async (sale) => {
};
const updateQuantity = async (sale) => {
- try {
- if (oldQuantity.value === sale.quantity) return;
- const params = {
- quantity: sale.quantity,
- };
- await axios.patch(`ItemShelvingSales/${sale.id}`, params);
- oldQuantity.value = null;
- } catch (error) {
- console.error(error);
- }
+ if (oldQuantity.value === sale.quantity) return;
+ const params = {
+ quantity: sale.quantity,
+ };
+ await axios.patch(`ItemShelvingSales/${sale.id}`, params);
+ oldQuantity.value = null;
};
const updateParking = async (sale) => {
- try {
- const filter = {
- fields: ['id'],
- where: {
- code: sale.shelvingFk,
- },
- };
- const { data } = await axios.get(`Shelvings/findOne`, {
- params: { filter: JSON.stringify(filter) },
- });
- const params = {
- parkingFk: sale.parkingFk,
- };
- await axios.patch(`Shelvings/${data.id}`, params);
- } catch (error) {
- console.error(error);
- }
+ const filter = {
+ fields: ['id'],
+ where: {
+ code: sale.shelvingFk,
+ },
+ };
+ const { data } = await axios.get(`Shelvings/findOne`, {
+ params: { filter: JSON.stringify(filter) },
+ });
+ const params = {
+ parkingFk: sale.parkingFk,
+ };
+ await axios.patch(`Shelvings/${data.id}`, params);
};
const updateShelving = async (sale) => {
@@ -241,61 +225,41 @@ const updateShelving = async (sale) => {
};
const saleTrackingNew = async (sale, stateCode, isChecked) => {
- try {
- const params = {
- saleFk: sale.saleFk,
- isChecked,
- quantity: sale.quantity,
- stateCode,
- };
- await axios.post(`SaleTrackings/new`, params);
- notify(t('globals.dataSaved'), 'positive');
- } catch (error) {
- console.error(error);
- }
+ const params = {
+ saleFk: sale.saleFk,
+ isChecked,
+ quantity: sale.quantity,
+ stateCode,
+ };
+ await axios.post(`SaleTrackings/new`, params);
+ notify(t('globals.dataSaved'), 'positive');
};
const saleTrackingDel = async ({ saleFk }, stateCode) => {
- try {
- const params = {
- saleFk,
- stateCodes: [stateCode],
- };
- await axios.post(`SaleTrackings/delete`, params);
- notify(t('globals.dataSaved'), 'positive');
- } catch (error) {
- console.error(error);
- }
+ const params = {
+ saleFk,
+ stateCodes: [stateCode],
+ };
+ await axios.post(`SaleTrackings/delete`, params);
+ notify(t('globals.dataSaved'), 'positive');
};
const clickSaleGroupDetail = async (sale) => {
- try {
- if (!sale.saleGroupDetailFk) return;
+ if (!sale.saleGroupDetailFk) return;
- await axios.delete(`SaleGroupDetails/${sale.saleGroupDetailFk}`);
- sale.hasSaleGroupDetail = false;
- notify(t('globals.dataSaved'), 'positive');
- } catch (error) {
- console.error(error);
- }
+ await axios.delete(`SaleGroupDetails/${sale.saleGroupDetailFk}`);
+ sale.hasSaleGroupDetail = false;
+ notify(t('globals.dataSaved'), 'positive');
};
const clickPreviousSelected = (sale) => {
- try {
- qCheckBoxController(sale, 'isPreviousSelected');
- if (!sale.isPreviousSelected) sale.isPrevious = false;
- } catch (error) {
- console.error(error);
- }
+ qCheckBoxController(sale, 'isPreviousSelected');
+ if (!sale.isPreviousSelected) sale.isPrevious = false;
};
const clickPrevious = (sale) => {
- try {
- qCheckBoxController(sale, 'isPrevious');
- if (sale.isPrevious) sale.isPreviousSelected = true;
- } catch (error) {
- console.error(error);
- }
+ qCheckBoxController(sale, 'isPrevious');
+ if (sale.isPrevious) sale.isPreviousSelected = true;
};
const qCheckBoxController = (sale, action) => {
@@ -306,16 +270,12 @@ const qCheckBoxController = (sale, action) => {
isPreviousSelected: 'PREVIOUS_PREPARATION',
};
const stateCode = STATE_CODES[action];
- try {
- if (!sale[action]) {
- saleTrackingNew(sale, stateCode, true);
- sale[action] = true;
- } else {
- saleTrackingDel(sale, stateCode);
- sale[action] = false;
- }
- } catch (error) {
- console.error(error);
+ if (!sale[action]) {
+ saleTrackingNew(sale, stateCode, true);
+ sale[action] = true;
+ } else {
+ saleTrackingDel(sale, stateCode);
+ sale[action] = false;
}
};
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index 45a870f7f..47c28a422 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -46,40 +46,32 @@ watch(
onMounted(async () => await getDefaultTaxClass());
const createRefund = async () => {
- try {
- if (!selected.value.length) return;
+ if (!selected.value.length) return;
- const params = {
- servicesIds: selected.value.map((s) => +s.id),
- withWarehouse: false,
- negative: true,
- };
- const { data } = await axios.post('Sales/clone', params);
- const [refundTicket] = data;
- notify(
- t('service.createRefundSuccess', {
- ticketId: refundTicket.id,
- }),
- 'positive'
- );
- router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
- } catch (error) {
- console.error(error);
- }
+ const params = {
+ servicesIds: selected.value.map((s) => +s.id),
+ withWarehouse: false,
+ negative: true,
+ };
+ const { data } = await axios.post('Sales/clone', params);
+ const [refundTicket] = data;
+ notify(
+ t('service.createRefundSuccess', {
+ ticketId: refundTicket.id,
+ }),
+ 'positive'
+ );
+ router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
};
const getDefaultTaxClass = async () => {
- try {
- let filter = {
- where: { code: 'G' },
- };
- const { data } = await axios.get('TaxClasses/findOne', {
- params: { filter: JSON.stringify(filter) },
- });
- defaultTaxClass.value = data;
- } catch (error) {
- console.error(error);
- }
+ let filter = {
+ where: { code: 'G' },
+ };
+ const { data } = await axios.get('TaxClasses/findOne', {
+ params: { filter: JSON.stringify(filter) },
+ });
+ defaultTaxClass.value = data;
};
const columns = computed(() => [
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index af96c2724..5fb99b849 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -19,6 +19,8 @@ import VnTitle from 'src/components/common/VnTitle.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
+import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
+import VnToSummary from 'src/components/ui/VnToSummary.vue';
const route = useRoute();
const { notify } = useNotify();
@@ -68,7 +70,7 @@ function isEditable() {
async function changeState(value) {
try {
- stateBtnDropdownRef.value.hide();
+ stateBtnDropdownRef.value?.hide();
const formData = {
ticketFk: entityId.value,
code: value,
@@ -85,6 +87,10 @@ async function changeState(value) {
function toTicketUrl(section) {
return '#/ticket/' + entityId.value + '/' + section;
}
+function isOnTicketCard() {
+ const currentPath = route.path;
+ return currentPath.startsWith('/ticket');
+}
@@ -99,6 +105,14 @@ function toTicketUrl(section) {
:url="`Tickets/${entityId}/summary`"
data-key="TicketSummary"
>
+
+
+
Ticket #{{ entity.id }} - {{ entity.client?.name }} ({{
@@ -112,7 +126,7 @@ function toTicketUrl(section) {
ref="stateBtnDropdownRef"
color="black"
text-color="white"
- :label="t('ticket.summary.changeState')"
+ :label="t('globals.changeState')"
:disable="!isEditable()"
>
[
]);
const applyVolumes = async (salesData) => {
- try {
- if (!salesData.length) return;
+ if (!salesData.length) return;
- sales.value = salesData;
- const ticket = sales.value[0].ticketFk;
- const { data } = await axios.get(`Tickets/${ticket}/getVolume`);
- const volumes = new Map(data.saleVolume.map((volume) => [volume.saleFk, volume]));
+ sales.value = salesData;
+ const ticket = sales.value[0].ticketFk;
+ const { data } = await axios.get(`Tickets/${ticket}/getVolume`);
+ const volumes = new Map(data.saleVolume.map((volume) => [volume.saleFk, volume]));
- sales.value.forEach((sale) => {
- sale.saleVolume = volumes.get(sale.id);
- });
+ sales.value.forEach((sale) => {
+ sale.saleVolume = volumes.get(sale.id);
+ });
- packingTypeVolume.value = data.packingTypeVolume;
- } catch (error) {
- console.error(error);
- }
+ packingTypeVolume.value = data.packingTypeVolume;
};
onMounted(() => (stateStore.rightDrawer = true));
diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue
index 43b500dc0..bdd980c07 100644
--- a/src/pages/Ticket/TicketAdvance.vue
+++ b/src/pages/Ticket/TicketAdvance.vue
@@ -1,24 +1,19 @@
+watch(
+ () => vnTableRef.value.tableRef?.$el,
+ ($el) => {
+ if (!$el) return;
+ const head = $el.querySelector('thead');
+ const firstRow = $el.querySelector('thead > tr');
+ const newRow = document.createElement('tr');
+ destinationElRef.value = document.createElement('th');
+ originElRef.value = document.createElement('th');
+
+ newRow.classList.add('bg-header');
+ destinationElRef.value.classList.add('text-uppercase', 'color-vn-label');
+ originElRef.value.classList.add('text-uppercase', 'color-vn-label');
+
+ destinationElRef.value.setAttribute('colspan', '7');
+ originElRef.value.setAttribute('colspan', '9');
+
+ destinationElRef.value.textContent = `${t(
+ 'advanceTickets.destination'
+ )} ${toDateFormat(vnTableRef.value.params.dateToAdvance)}`;
+ originElRef.value.textContent = `${t('advanceTickets.origin')} ${toDateFormat(
+ vnTableRef.value.params.dateFuture
+ )}`;
+
+ newRow.append(destinationElRef.value, originElRef.value);
+ head.insertBefore(newRow, firstRow);
+ },
+ { once: true, inmmediate: true }
+);
+
+watch(
+ () => vnTableRef.value.params,
+ () => {
+ if (originElRef.value && destinationElRef.value) {
+ destinationElRef.value.textContent = `${t(
+ 'advanceTickets.destination'
+ )} ${toDateFormat(vnTableRef.value.params.dateToAdvance)}`;
+ originElRef.value.textContent = `${t('advanceTickets.origin')} ${toDateFormat(
+ vnTableRef.value.params.dateFuture
+ )}`;
+ }
+ },
+ { deep: true }
+);
+
{
auto-load
@on-fetch="(data) => (zonesOptions = data)"
/>
-
{
-
+
-
-
- {{ userParams.scopeDays }}
-
-
- {{ t('advanceTickets.destination') }}
- {{ toDateFormat(userParams.dateToAdvance) }}
-
-
- {{ t('advanceTickets.origin') }}
- {{ toDateFormat(userParams.dateFuture) }}
-
-
-
-
-
-
-
- {{ col.label }}
-
-
+
+
+
+
+ {{
+ t('advanceTickets.originAgency', {
+ agency: row.futureAgency,
+ })
+ }}
+
+
+ {{
+ t('advanceTickets.destinationAgency', {
+ agency: row.agency,
+ })
+ }}
+
+
+
-
-
-
-
-
-
-
+
+
+ {{ row.id }}
+
+
-
-
- {{ col.label }}
-
+
+
+ {{ row.state }}
+
+ {{ dashIfEmpty(row.state) }}
-
-
-
-
-
- {{
- t('advanceTickets.originAgency', {
- agency: row.futureAgency,
- })
- }}
-
-
- {{
- t('advanceTickets.destinationAgency', {
- agency: row.agency,
- })
- }}
-
-
-
-
+
+
+ {{ toCurrency(row.totalWithVat || 0) }}
+
-
-
-
-
- {{ row.id }}
-
-
-
+
+
+ {{ row.futureId }}
+
+
-
-
-
- {{ row.state }}
-
- {{ dashIfEmpty(row.state) }}
-
+
+
+ {{ row.futureState }}
+
-
-
-
- {{ toCurrency(row.totalWithVat || 0) }}
-
-
+
+
+ {{ toCurrency(row.futureTotalWithVat || 0) }}
+
-
-
-
- {{ row.futureId }}
-
-
-
-
-
-
-
- {{ row.futureState }}
-
-
-
-
-
-
- {{ toCurrency(row.futureTotalWithVat || 0) }}
-
-
-
-
+
{
diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue
index b25ebdea6..a1d301f35 100644
--- a/src/pages/Ticket/TicketAdvanceFilter.vue
+++ b/src/pages/Ticket/TicketAdvanceFilter.vue
@@ -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,
@@ -27,20 +27,21 @@ const warehousesOptions = ref([]);
const itemPackingTypes = ref([]);
const getItemPackingTypes = async () => {
- try {
- const filter = {
- where: { isActive: true },
- };
- const { data } = await axios.get('ItemPackingTypes', {
- params: { filter: JSON.stringify(filter) },
- });
- itemPackingTypes.value = data.map((ipt) => ({
- description: t(ipt.description),
- code: ipt.code,
- }));
- } catch (error) {
- console.error(error);
- }
+ const filter = {
+ where: { isActive: true },
+ };
+ const { data } = await axios.get('ItemPackingTypes', {
+ params: { filter: JSON.stringify(filter) },
+ });
+ itemPackingTypes.value = data.map((ipt) => ({
+ description: t(ipt.description),
+ code: ipt.code,
+ }));
+};
+
+const getLocale = (val) => {
+ const param = `params.${val}`;
+ return te(param) ? t(param) : t(`globals.${param}`);
};
onMounted(async () => await getItemPackingTypes());
@@ -53,6 +54,7 @@ onMounted(async () => await getItemPackingTypes());
auto-load
/>
await getItemPackingTypes());
>
- {{ t(`params.${tag.label}`) }}:
+ {{ getLocale(tag.label) }}:
{{ formatFn(tag.value) }}
@@ -96,6 +98,7 @@ onMounted(async () => await getItemPackingTypes());
dense
outlined
rounded
+ :use-like="false"
>
@@ -113,6 +116,7 @@ onMounted(async () => await getItemPackingTypes());
dense
outlined
rounded
+ :use-like="false"
>
@@ -136,6 +140,19 @@ onMounted(async () => await getItemPackingTypes());
/>
+
+
+
+
+
{
+ for (const state of data) {
+ groupedStates.value.push({
+ id: state.id,
+ name: t(`${state.code}`),
+ code: state.code,
+ });
+ }
+};
(provinces = data)" auto-load />
(states = data)" auto-load />
+ {
+ getGroupedStates(data);
+ }
+ "
+ auto-load
+ />
(agencies = data)" auto-load />
(warehouses = data)" auto-load />
@@ -90,12 +110,35 @@ const warehouses = ref([]);
option-label="name"
emit-value
map-options
+ use-input
dense
outlined
rounded
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -245,6 +309,11 @@ en:
provinceFk: Province
agencyModeFk: Agency
warehouseFk: Warehouse
+ FREE: Free
+ ON_PREPARATION: On preparation
+ PACKED: Packed
+ DELIVERED: Delivered
+ ON_PREVIOUS: ON_PREVIOUS
es:
params:
search: Contiene
@@ -278,4 +347,12 @@ es:
Yes: Si
No: No
Days onward: Días adelante
+ Grouped state: Estado agrupado
+ FREE: Libre
+ ON_PREPARATION: En preparación
+ PACKED: Encajado
+ DELIVERED: Servido
+ ON_PREVIOUS: ON_PREVIOUS
+ Collection: Colección
+ Nickname: Nombre mostrado
diff --git a/src/pages/Ticket/TicketFutureFilter.vue b/src/pages/Ticket/TicketFutureFilter.vue
index 6345f62b3..ffe967272 100644
--- a/src/pages/Ticket/TicketFutureFilter.vue
+++ b/src/pages/Ticket/TicketFutureFilter.vue
@@ -24,33 +24,25 @@ const itemPackingTypes = ref([]);
const stateOptions = ref([]);
const getItemPackingTypes = async () => {
- try {
- const filter = {
- where: { isActive: true },
- };
- const { data } = await axios.get('ItemPackingTypes', {
- params: { filter: JSON.stringify(filter) },
- });
- itemPackingTypes.value = data.map((ipt) => ({
- description: t(ipt.description),
- code: ipt.code,
- }));
- } catch (error) {
- console.error(error);
- }
+ const filter = {
+ where: { isActive: true },
+ };
+ const { data } = await axios.get('ItemPackingTypes', {
+ params: { filter: JSON.stringify(filter) },
+ });
+ itemPackingTypes.value = data.map((ipt) => ({
+ description: t(ipt.description),
+ code: ipt.code,
+ }));
};
const getGroupedStates = async () => {
- try {
- const { data } = await axios.get('AlertLevels');
- stateOptions.value = data.map((state) => ({
- id: state.id,
- name: t(`futureTickets.${state.code}`),
- code: state.code,
- }));
- } catch (error) {
- console.error(error);
- }
+ const { data } = await axios.get('AlertLevels');
+ stateOptions.value = data.map((state) => ({
+ id: state.id,
+ name: t(`futureTickets.${state.code}`),
+ code: state.code,
+ }));
};
onMounted(async () => {
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index ad97e75c1..dd1f2d69a 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -95,6 +95,7 @@ const columns = computed(() => [
columnField: {
component: null,
},
+ columnClass: 'expand',
format: (row, dashIfEmpty) => dashIfEmpty(row.salesPerson),
},
{
@@ -153,11 +154,6 @@ const columns = computed(() => [
},
columnClass: 'expand',
},
- {
- align: 'left',
- name: 'refFk',
- label: t('ticketList.ref'),
- },
{
align: 'left',
name: 'zoneFk',
@@ -191,6 +187,12 @@ const columns = computed(() => [
},
format: (row) => toCurrency(row.totalWithVat),
},
+ {
+ align: 'left',
+ name: 'packing',
+ label: t('ticketSale.packaging'),
+ format: (row, dashIfEmpty) => dashIfEmpty(row.packing),
+ },
{
align: 'right',
name: 'tableActions',
@@ -202,7 +204,7 @@ const columns = computed(() => [
action: (row) => redirectToLines(row.id),
},
{
- title: t('ticketList.summary'),
+ title: t('components.smartCard.viewSummary'),
icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row.id, TicketSummary),
@@ -548,7 +550,7 @@ function setReference(data) {
- {{ row.salesPerson }}
+ {{ dashIfEmpty(row.userName) }}
@@ -577,16 +579,16 @@ function setReference(data) {
{{ row.state }}
+
+
+ {{ row.refFk }}
+
+
+
{{ row.state }}
-
-
- {{ dashIfEmpty(row.refFk) }}
-
-
-
{{ dashIfEmpty(row.zoneName) }}
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index b372e48ef..eab38a402 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -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
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index a3620a6ba..d6245e655 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -72,6 +72,16 @@ const agenciesOptions = ref([]);
+
+
+
+ {{ t('raidDays') }}
+
+
+
+
+
+es:
+ raidDays: Al rellenarlo, generamos una redada. Indica los días que un travel se moverá automáticamente en el tiempo
+en:
+ raidDays: When filling, a raid is generated. Enter the number of days the travel will automatically forward in time
+
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index bda29903b..6025ad045 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -32,6 +32,7 @@ const filter = {
'warehouseOutFk',
'cargoSupplierFk',
'agencyModeFk',
+ 'daysInForward',
],
include: [
{
@@ -77,6 +78,22 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
+
+
+
+
+ {{
+ t('globals.raid', { daysInForward: entity.daysInForward })
+ }}
+
+
+
`#/travel/${entityId.value}/${param}`;
+
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index a8c0e69cb..334640bff 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -45,6 +45,10 @@ const redirectCreateEntryView = (travelData) => {
};
const columns = computed(() => [
+ {
+ name: 'status',
+ columnFilter: false,
+ },
{
align: 'left',
name: 'id',
@@ -221,6 +225,17 @@ const columns = computed(() => [
:is-editable="false"
:use-model="true"
>
+
+
+
+
+ {{
+ t('globals.raid', { daysInForward: row.daysInForward })
+ }}
+
+
+
-import { ref } from 'vue';
+import { ref, onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import VnInputDate from 'src/components/common/VnInputDate.vue';
@@ -8,32 +8,22 @@ import FormModel from 'src/components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
+import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
-const route = useRoute();
const { t } = useI18n();
-
const educationLevels = ref([]);
const countries = ref([]);
const maritalStatus = [
{ code: 'M', name: t('Married') },
{ code: 'S', name: t('Single') },
];
+const advancedSummary = ref({});
-const workerFilter = {
- include: [
- {
- relation: 'user',
- scope: {
- fields: ['name', 'emailVerified'],
- include: { relation: 'emailUser', scope: { fields: ['email'] } },
- },
- },
- { relation: 'sip', scope: { fields: ['extension', 'secret'] } },
- { relation: 'department', scope: { include: { relation: 'department' } } },
- ],
-};
+onBeforeMount(async () => {
+ advancedSummary.value =
+ (await useAdvancedSummary('Workers', +useRoute().params.id)) ?? {};
+});
-
{
+ Object.assign(data, advancedSummary);
+ }
+ "
>
@@ -134,7 +130,7 @@ const workerFilter = {
-
+
{
-
+
diff --git a/src/pages/Worker/Card/WorkerLocker.vue b/src/pages/Worker/Card/WorkerLocker.vue
index 4a19e472c..015bced35 100644
--- a/src/pages/Worker/Card/WorkerLocker.vue
+++ b/src/pages/Worker/Card/WorkerLocker.vue
@@ -18,7 +18,7 @@ const { store } = useArrayData('Worker');
const entityId = computed(() => useRoute().params.id);
const filter = computed(() => ({
where: {
- gender: store.data?.sex,
+ gender: store.data?.[0]?.sex,
or: [{ workerFk: null }, { workerFk: entityId.value }],
},
}));
@@ -51,6 +51,7 @@ const init = async (data) => {
>
+import { useI18n } from 'vue-i18n';
+import { useRoute } from 'vue-router';
+import { ref, computed } from 'vue';
+import FetchData from 'components/FetchData.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 CrudModel from 'components/CrudModel.vue';
+import axios from 'axios';
+
+const { t } = useI18n();
+
+const crudModelRef = ref();
+const warehousesData = ref([]);
+const itemPackingTypesData = ref([]);
+const sectorsData = ref([]);
+const trainsData = ref([]);
+const machinesData = ref([]);
+const route = useRoute();
+const routeId = computed(() => route.params.id);
+
+const initialData = computed(() => {
+ return {
+ workerFk: routeId.value,
+ numberOfWagons: 2,
+ trainFk: 1,
+ itemPackingTypeFk: 'H',
+ warehouseFk: 60,
+ sectorFk: null,
+ labelerFk: null,
+ linesLimit: 20,
+ volumenLimit: 0.5,
+ sizeLimit: null,
+ isOnReservationMode: 0,
+ machineFk: null,
+ };
+});
+
+async function insert() {
+ await axios.post('Operators', initialData.value);
+ crudModelRef.value.reload();
+}
+
+
+
+
+ (trainsData = data)" auto-load />
+ (itemPackingTypesData = data)"
+ auto-load
+ />
+ (warehousesData = data)"
+ auto-load
+ />
+ (PrintersData = data)" auto-load />
+ (sectorsData = data)" auto-load />
+ (machinesData = data)" auto-load />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID: {{ scope.opt?.id }}
+
+ {{ scope.opt?.id }},
+ {{ scope.opt?.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+es:
+ Model: Modelo
+ Serial number: Número de serie
+ Current SIM: SIM actual
+ Add new device: Añadir nuevo dispositivo
+ PDA deallocated: PDA desasignada
+ Remove PDA: Eliminar PDA
+ Do you want to remove this PDA?: ¿Desea eliminar este PDA?
+ You can only have one PDA: Solo puedes tener un PDA si no eres autonomo
+ This PDA is already assigned to another user: Este PDA ya está asignado a otro usuario
+
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index ed34e771d..0a0694fdf 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -2,7 +2,6 @@
import { ref, onBeforeMount, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
-import axios from 'axios';
import { dashIfEmpty, toDate } from 'src/filters';
import VnLv from 'src/components/ui/VnLv.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
@@ -11,7 +10,7 @@ import VnUserLink from 'src/components/ui/VnUserLink.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
-import { useRole } from 'src/composables/useRole';
+import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
const route = useRoute();
const { t } = useI18n();
@@ -25,18 +24,11 @@ const $props = defineProps({
const entityId = computed(() => $props.id || route.params.id);
const basicDataUrl = ref(null);
-const isHr = computed(() => useRole().hasAny(['hr']));
const advancedSummary = ref();
onBeforeMount(async () => {
- if (isHr.value) {
- advancedSummary.value = (
- await axios.get('Workers/advancedSummary', {
- params: { filter: { where: { id: entityId.value } } },
- })
- ).data[0];
- basicDataUrl.value = `#/worker/${entityId.value}/basic-data`;
- }
+ advancedSummary.value = await useAdvancedSummary('Workers', entityId.value);
+ basicDataUrl.value = `#/worker/${entityId.value}/basic-data`;
});
@@ -45,7 +37,7 @@ onBeforeMount(async () => {
ref="summary"
:url="`Workers/summary`"
:filter="{ where: { id: entityId } }"
- data-key="WorkerSummary"
+ data-key="Worker"
>
{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}
@@ -101,21 +93,27 @@ onBeforeMount(async () => {
:label="t('worker.summary.seniority')"
:value="toDate(worker.seniority)"
/>
-
-
+
+
+
-
diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue
index 7a3f760bc..022cecdc6 100644
--- a/src/pages/Worker/WorkerList.vue
+++ b/src/pages/Worker/WorkerList.vue
@@ -169,7 +169,7 @@ async function autofillBic(worker) {
@@ -191,13 +191,13 @@ async function autofillBic(worker) {
/>
-
+
+describe('Client consignee', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/address', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientBalance.spec.js b/test/cypress/integration/client/clientBalance.spec.js
new file mode 100644
index 000000000..dfba56b16
--- /dev/null
+++ b/test/cypress/integration/client/clientBalance.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client balance', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/balance', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientBasicData.spec.js b/test/cypress/integration/client/clientBasicData.spec.js
new file mode 100644
index 000000000..7b0a19828
--- /dev/null
+++ b/test/cypress/integration/client/clientBasicData.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client basic data', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/basic-data', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientBillingData.spec.js b/test/cypress/integration/client/clientBillingData.spec.js
new file mode 100644
index 000000000..00af82e39
--- /dev/null
+++ b/test/cypress/integration/client/clientBillingData.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client billing data', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/billing-data', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientCredits.spec.js b/test/cypress/integration/client/clientCredits.spec.js
new file mode 100644
index 000000000..5f303b40d
--- /dev/null
+++ b/test/cypress/integration/client/clientCredits.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client credits', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/credits', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientFiscalData.spec.js b/test/cypress/integration/client/clientFiscalData.spec.js
new file mode 100644
index 000000000..e337c26f8
--- /dev/null
+++ b/test/cypress/integration/client/clientFiscalData.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client fiscal data', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/fiscal-data', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientGreuges.spec.js b/test/cypress/integration/client/clientGreuges.spec.js
new file mode 100644
index 000000000..23f8b3182
--- /dev/null
+++ b/test/cypress/integration/client/clientGreuges.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client greuges', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/greuges', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
new file mode 100644
index 000000000..22bca15ac
--- /dev/null
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -0,0 +1,46 @@
+///
+describe('Client list', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('/#/customer/list', {
+ timeout: 5000,
+ onBeforeLoad(win) {
+ cy.stub(win, 'open');
+ },
+ });
+ });
+
+ it('Client list create new client', () => {
+ cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
+ const data = {
+ Name: { val: 'Name 1' },
+ 'Social name': { val: 'TEST 1' },
+ 'Tax number': { val: '20852113Z' },
+ 'Web user': { val: 'user_test_1' },
+ Street: { val: 'C/ STREET 1' },
+ Email: { val: 'user.test@1.com' },
+ 'Business type': { val: 'Otros', type: 'select' },
+ 'Sales person': { val: 'salesboss', type: 'select' },
+ Location: { val: '46000, Valencia(Province one), España', type: 'select' },
+ };
+ cy.fillInForm(data);
+
+ cy.get('.q-mt-lg > .q-btn--standard').click();
+
+ cy.checkNotification('Data created');
+ cy.url().should('include', '/summary');
+ });
+ it('Client list search client', () => {
+ const search = 'Jessica Jones';
+ cy.searchByLabel('Name', search);
+
+ cy.get('.title > span').should('have.text', search);
+ let id = null;
+ cy.get('.q-item > .q-item__label').then((text) => {
+ id = text.text().trim().split('#')[1];
+ cy.get('.q-item > .q-item__label').should('have.text', ` #${id}`);
+ cy.url().should('include', `/customer/${id}/summary`);
+ });
+ });
+});
diff --git a/test/cypress/integration/client/clientNotes.spec.js b/test/cypress/integration/client/clientNotes.spec.js
new file mode 100644
index 000000000..99a7c66c5
--- /dev/null
+++ b/test/cypress/integration/client/clientNotes.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client notes', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/notes', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientRecoveries.spec.js b/test/cypress/integration/client/clientRecoveries.spec.js
new file mode 100644
index 000000000..ea6f14407
--- /dev/null
+++ b/test/cypress/integration/client/clientRecoveries.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client recoveries', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/recoveries', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/clientWebAccess.spec.js b/test/cypress/integration/client/clientWebAccess.spec.js
new file mode 100644
index 000000000..47f9efa4c
--- /dev/null
+++ b/test/cypress/integration/client/clientWebAccess.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client web-access', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/web-access', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/credit-management/clientCreditContracts.spec.js b/test/cypress/integration/client/credit-management/clientCreditContracts.spec.js
new file mode 100644
index 000000000..3c35d5ed0
--- /dev/null
+++ b/test/cypress/integration/client/credit-management/clientCreditContracts.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client credit opinion', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/credit-management/credit-contracts', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js b/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js
new file mode 100644
index 000000000..c32215f01
--- /dev/null
+++ b/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client credit opinion', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/credit-management/credit-opinion', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/others/clientConsumption.spec.js b/test/cypress/integration/client/others/clientConsumption.spec.js
new file mode 100644
index 000000000..bbc11998e
--- /dev/null
+++ b/test/cypress/integration/client/others/clientConsumption.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client consumption', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/others/consumption', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/others/clientContacts.spec.js b/test/cypress/integration/client/others/clientContacts.spec.js
new file mode 100644
index 000000000..66a86801a
--- /dev/null
+++ b/test/cypress/integration/client/others/clientContacts.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client contacts', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/others/contacts', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/others/clientMandates.spec.js b/test/cypress/integration/client/others/clientMandates.spec.js
new file mode 100644
index 000000000..055eda2d0
--- /dev/null
+++ b/test/cypress/integration/client/others/clientMandates.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client mandates', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/others/mandates', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/others/clientSamples.spec.js b/test/cypress/integration/client/others/clientSamples.spec.js
new file mode 100644
index 000000000..a50120402
--- /dev/null
+++ b/test/cypress/integration/client/others/clientSamples.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client samples', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/others/samples', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/others/clientUnpaid.spec.js b/test/cypress/integration/client/others/clientUnpaid.spec.js
new file mode 100644
index 000000000..9972ba0e9
--- /dev/null
+++ b/test/cypress/integration/client/others/clientUnpaid.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client unpaid', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1110/others/unpaid', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-card').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/client/others/clientWebPayments.spec.js b/test/cypress/integration/client/others/clientWebPayments.spec.js
new file mode 100644
index 000000000..f35b12612
--- /dev/null
+++ b/test/cypress/integration/client/others/clientWebPayments.spec.js
@@ -0,0 +1,13 @@
+///
+describe('Client web payments', () => {
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('developer');
+ cy.visit('#/customer/1101/others/web-payment', {
+ timeout: 5000,
+ });
+ });
+ it('Should load layout', () => {
+ cy.get('.q-page').should('be.visible');
+ });
+});
diff --git a/test/cypress/integration/outLogin/logout.spec.js b/test/cypress/integration/outLogin/logout.spec.js
index 423189908..8d4e90aac 100644
--- a/test/cypress/integration/outLogin/logout.spec.js
+++ b/test/cypress/integration/outLogin/logout.spec.js
@@ -13,7 +13,7 @@ describe('Logout', () => {
});
describe('not user', () => {
beforeEach(() => {
- cy.intercept('GET', '**/VnUsers/acl', {
+ cy.intercept('GET', '**DefaultViewConfigs**', {
statusCode: 401,
body: {
error: {
@@ -24,10 +24,11 @@ describe('Logout', () => {
},
},
statusMessage: 'AUTHORIZATION_REQUIRED',
- }).as('someRoute');
+ });
});
+
it('when token not exists', () => {
- cy.reload();
+ cy.get('.q-list > [href="#/item"]').click();
cy.get('.q-notification__message').should(
'have.text',
'Authorization Required'
diff --git a/test/cypress/integration/parking/parkingList.spec.js b/test/cypress/integration/parking/parkingList.spec.js
index b78a660d1..f1efaa375 100644
--- a/test/cypress/integration/parking/parkingList.spec.js
+++ b/test/cypress/integration/parking/parkingList.spec.js
@@ -1,5 +1,6 @@
///
describe('ParkingList', () => {
+ const searchbar = '#searchbar input';
const firstCard = '.q-card:nth-child(1)';
const firstChipId =
':nth-child(1) > :nth-child(1) > .justify-between > .flex > .q-chip > .q-chip__content';
@@ -14,6 +15,7 @@ describe('ParkingList', () => {
});
it('should redirect on clicking a parking', () => {
+ cy.get(searchbar).type('{enter}');
cy.get(firstChipId)
.invoke('text')
.then((content) => {
@@ -24,6 +26,7 @@ describe('ParkingList', () => {
});
it('should open the details', () => {
+ cy.get(searchbar).type('{enter}');
cy.get(firstDetailBtn).click();
cy.get(summaryHeader).contains('Basic data');
});
diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index 353c5805b..fdfcd4286 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -7,31 +7,20 @@ describe('AgencyWorkCenter', () => {
const createButton = '.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon';
const workCenterCombobox = 'input[role="combobox"]';
- it('assign workCenter', () => {
+ it('check workCenter crud', () => {
+ // create
cy.get(createButton).click();
cy.get(workCenterCombobox).type('workCenterOne{enter}');
- cy.get('.q-notification__message').should('have.text', 'Data created');
- });
+ cy.checkNotification('Data created');
- it('delete workCenter', () => {
+ // expect error when duplicate
+ cy.get(createButton).click();
+ cy.get('[data-cy="FormModelPopup_save"]').click();
+ cy.checkNotification('This workCenter is already assigned to this agency');
+ cy.get('[data-cy="FormModelPopup_cancel"]').click();
+
+ // delete
cy.get('.q-item__section--side > .q-btn > .q-btn__content > .q-icon').click();
- cy.get('.q-notification__message').should(
- 'have.text',
- 'WorkCenter removed successfully'
- );
- });
-
- it('error on duplicate workCenter', () => {
- cy.get(createButton).click();
- cy.get(workCenterCombobox).type('workCenterOne{enter}');
- cy.get('.q-notification__message').should('have.text', 'Data created');
- cy.get(createButton).click();
- cy.get(
- '.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container'
- ).type('workCenterOne{enter}');
-
- cy.get(
- ':nth-child(2) > .q-notification__wrapper > .q-notification__content > .q-notification__message'
- ).should('have.text', 'This workCenter is already assigned to this agency');
+ cy.checkNotification('WorkCenter removed successfully');
});
});
diff --git a/test/cypress/integration/ticket/ticketExpedition.spec.js b/test/cypress/integration/ticket/ticketExpedition.spec.js
new file mode 100644
index 000000000..d4afd401f
--- /dev/null
+++ b/test/cypress/integration/ticket/ticketExpedition.spec.js
@@ -0,0 +1,26 @@
+///
+
+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('show');
+ cy.intercept('POST', /\/api\/ExpeditionStates\/addExpeditionState/).as('add');
+
+ cy.wait('@show');
+ cy.selectRows([1, 2]);
+ cy.selectOption('[data-cy="change-state"]', 'Perdida');
+ cy.wait('@add');
+
+ cy.get(`${tableContent} tr:nth-child(-n+2) ${stateTd}`).each(($el) => {
+ cy.wrap($el).contains('Perdida');
+ });
+ });
+});
diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js
index 8a8bea443..c1c37fd32 100644
--- a/test/cypress/integration/worker/workerList.spec.js
+++ b/test/cypress/integration/worker/workerList.spec.js
@@ -11,7 +11,7 @@ describe('WorkerList', () => {
it('should open the worker summary', () => {
cy.get(inputName).type('jessica{enter}');
cy.get(searchBtn).click();
- cy.intercept('GET', /\/api\/Workers\/\d+/).as('worker');
+ cy.intercept('GET', /\/api\/Workers\/summary+/).as('worker');
cy.wait('@worker').then(() =>
cy.get(descriptorTitle).should('include.text', 'Jessica')
);
diff --git a/test/cypress/integration/worker/workerLocker.spec.js b/test/cypress/integration/worker/workerLocker.spec.js
index 8a169dfb2..c222414fd 100644
--- a/test/cypress/integration/worker/workerLocker.spec.js
+++ b/test/cypress/integration/worker/workerLocker.spec.js
@@ -1,8 +1,7 @@
describe('WorkerLocker', () => {
const productionId = 49;
- const lockerCode = '2F';
- const input = '.q-card input';
- const thirdOpt = '[role="listbox"] .q-item:nth-child(1)';
+ const lockerCode = '4F';
+ const lockerSelect = '[data-cy="locker"]';
beforeEach(() => {
cy.viewport(1280, 720);
cy.login('productionBoss');
@@ -10,10 +9,8 @@ describe('WorkerLocker', () => {
});
it('should allocates a locker', () => {
- cy.get(input).click();
- cy.waitForElement('[role="listbox"]');
- cy.get(thirdOpt).click();
+ cy.selectOption(lockerSelect, lockerCode);
cy.saveCard();
- cy.get(input).invoke('val').should('eq', lockerCode);
+ cy.get(lockerSelect).invoke('val').should('eq', lockerCode);
});
});
diff --git a/test/cypress/integration/worker/workerNotificationsManager.spec.js b/test/cypress/integration/worker/workerNotificationsManager.spec.js
index ac452c4ff..f121b3894 100644
--- a/test/cypress/integration/worker/workerNotificationsManager.spec.js
+++ b/test/cypress/integration/worker/workerNotificationsManager.spec.js
@@ -17,8 +17,7 @@ describe('WorkerNotificationsManager', () => {
cy.login('developer');
cy.visit(`/#/worker/${salesPersonId}/notifications`);
cy.get(firstAvailableNotification).click();
- cy.notificationHas(
- '.q-notification__message',
+ cy.checkNotification(
'The notification subscription of this worker cant be modified'
);
});
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 83f45b721..76bdefd27 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -82,7 +82,7 @@ Cypress.Commands.add('getValue', (selector) => {
// Fill Inputs
Cypress.Commands.add('selectOption', (selector, option) => {
cy.waitForElement(selector);
- cy.get(selector).find('.q-select__dropdown-icon').click();
+ cy.get(selector).click();
cy.get('.q-menu .q-item').contains(option).click();
});
@@ -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');
@@ -245,6 +253,13 @@ Cypress.Commands.add('validateContent', (selector, expectedValue) => {
cy.get(selector).should('have.text', expectedValue);
});
+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('.header > :nth-child(3) > .q-btn__content > .q-icon').click();
});
@@ -254,3 +269,21 @@ Cypress.Commands.add('openUserPanel', () => {
'.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
).click();
});
+
+Cypress.Commands.add('openActions', (row) => {
+ cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
+});
+
+Cypress.Commands.add('checkNotification', (text) => {
+ cy.get('.q-notification')
+ .should('be.visible')
+ .last()
+ .then(($lastNotification) => {
+ if (!Cypress.$($lastNotification).text().includes(text))
+ throw new Error(`Notification not found: "${text}"`);
+ });
+});
+
+Cypress.Commands.add('searchByLabel', (label, value) => {
+ cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
+});
diff --git a/test/vitest/__tests__/boot/axios.spec.js b/test/vitest/__tests__/boot/axios.spec.js
index feb0d93ea..19d396ec5 100644
--- a/test/vitest/__tests__/boot/axios.spec.js
+++ b/test/vitest/__tests__/boot/axios.spec.js
@@ -7,75 +7,59 @@ vi.mock('src/composables/useSession', () => ({
getToken: () => 'DEFAULT_TOKEN',
isLoggedIn: () => vi.fn(),
destroy: () => vi.fn(),
- })
+ }),
+}));
+
+vi.mock('src/stores/useStateQueryStore', () => ({
+ useStateQueryStore: () => ({
+ add: () => vi.fn(),
+ remove: () => vi.fn(),
+ }),
}));
describe('Axios boot', () => {
-
describe('onRequest()', async () => {
it('should set the "Authorization" property on the headers', async () => {
const config = { headers: {} };
const resultConfig = onRequest(config);
- expect(resultConfig).toEqual(expect.objectContaining({
- headers: {
- Authorization: 'DEFAULT_TOKEN'
- }
- }));
- });
- })
-
- describe('onResponseError()', async () => {
- it('should call to the Notify plugin with a message error for an status code "500"', async () => {
- Notify.create = vi.fn()
-
- const error = {
- response: {
- status: 500
- }
- };
-
- const result = onResponseError(error);
-
-
- expect(result).rejects.toEqual(
- expect.objectContaining(error)
- );
- expect(Notify.create).toHaveBeenCalledWith(
+ expect(resultConfig).toEqual(
expect.objectContaining({
- message: 'An internal server error has ocurred',
- type: 'negative',
+ headers: {
+ Authorization: 'DEFAULT_TOKEN',
+ },
})
);
});
+ });
+
+ describe('onResponseError()', async () => {
+ it('should call to the Notify plugin with a message error for an status code "500"', async () => {
+ const error = {
+ response: {
+ status: 500,
+ },
+ };
+
+ const result = onResponseError(error);
+ expect(result).rejects.toEqual(expect.objectContaining(error));
+ });
it('should call to the Notify plugin with a message from the response property', async () => {
- Notify.create = vi.fn()
-
const error = {
response: {
status: 401,
data: {
error: {
- message: 'Invalid user or password'
- }
- }
- }
+ message: 'Invalid user or password',
+ },
+ },
+ },
};
const result = onResponseError(error);
-
-
- expect(result).rejects.toEqual(
- expect.objectContaining(error)
- );
- expect(Notify.create).toHaveBeenCalledWith(
- expect.objectContaining({
- message: 'Invalid user or password',
- type: 'negative',
- })
- );
+ expect(result).rejects.toEqual(expect.objectContaining(error));
});
- })
+ });
});
diff --git a/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js b/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
new file mode 100644
index 000000000..ab1a47544
--- /dev/null
+++ b/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
@@ -0,0 +1,120 @@
+import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vitest';
+import { createWrapper, axios } from 'app/test/vitest/helper';
+import TicketAdvance from 'pages/Ticket/TicketAdvance.vue';
+import { Notify } from 'quasar';
+import { nextTick } from 'vue';
+
+describe('TicketAdvance', () => {
+ let wrapper;
+ let vm;
+
+ beforeAll(() => {
+ vi.spyOn(axios, 'get').mockImplementation(() => ({ data: [] }));
+ wrapper = createWrapper(TicketAdvance);
+ vm = wrapper.vm;
+ vi.spyOn(vm.vnTableRef, 'reload').mockImplementation(() => vi.fn());
+ vm.vnTableRef.value = { params: {} };
+ });
+ beforeEach(() => {
+ Notify.create = vi.fn();
+ });
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ describe('requestComponentUpdate()', () => {
+ const mockTicket = {
+ futureId: 1,
+ futureClientFk: 1,
+ nickname: 'test',
+ futureAddressFk: 1,
+ futureAgencyModeFk: 1,
+ futureWarehouseFk: 1,
+ futureCompanyFk: 1,
+ landed: '2023-01-02',
+ zoneFk: 1,
+ };
+ const mockParams = {
+ clientFk: 1,
+ nickname: 'test',
+ agencyModeFk: 1,
+ addressFk: 1,
+ zoneFk: 1,
+ warehouseFk: 1,
+ companyFk: 1,
+ landed: '2023-01-02',
+ shipped: '2023-01-01',
+ isDeleted: false,
+ isWithoutNegatives: false,
+ newTicket: undefined,
+ keepPrice: true,
+ };
+ const queryResult = 'tickets/1/componentUpdate';
+
+ it('should return query and params when ticket has no landed', async () => {
+ vm.vnTableRef.params.dateToAdvance = '2023-01-01';
+ await nextTick();
+
+ const mockLanded = { landed: '2023-01-02', zoneFk: 1 };
+ vi.spyOn(vm, 'getLanded').mockResolvedValue(mockLanded);
+
+ const { query, params } = await vm.requestComponentUpdate(mockTicket, false);
+
+ expect(query).toBe(queryResult);
+ expect(params).toEqual(mockParams);
+ });
+
+ it('should return query and params when ticket has landed', async () => {
+ const { query, params } = await vm.requestComponentUpdate(mockTicket, false);
+
+ expect(query).toBe(queryResult);
+ expect(params).toEqual(mockParams);
+ });
+ });
+
+ describe('moveTicketsAdvance()', () => {
+ it('should move tickets and notify success', async () => {
+ const tickets = [
+ {
+ id: 1,
+ futureId: 2,
+ futureShipped: '2023-01-01',
+ shipped: '2023-01-02',
+ workerFk: 1,
+ },
+ {
+ id: 2,
+ futureId: 3,
+ futureShipped: '2023-01-01',
+ shipped: '2023-01-02',
+ workerFk: 1,
+ },
+ ];
+ vm.selectedTickets = tickets;
+ vi.spyOn(axios, 'post').mockResolvedValue({});
+ await vm.moveTicketsAdvance();
+
+ expect(axios.post).toHaveBeenCalledOnce('Tickets/merge', {
+ tickets: [
+ {
+ originId: 2,
+ destinationId: 1,
+ originShipped: '2023-01-01',
+ destinationShipped: '2023-01-02',
+ workerFk: 1,
+ },
+ {
+ originId: 3,
+ destinationId: 2,
+ originShipped: '2023-01-01',
+ destinationShipped: '2023-01-02',
+ workerFk: 1,
+ },
+ ],
+ });
+ expect(vm.vnTableRef.reload).toHaveBeenCalled();
+ expect(Notify.create).toHaveBeenCalled();
+ expect(vm.selectedTickets).toEqual([]);
+ });
+ });
+});
diff --git a/test/vitest/__tests__/stores/useStateQueryStore.spec.js b/test/vitest/__tests__/stores/useStateQueryStore.spec.js
new file mode 100644
index 000000000..ab3afb007
--- /dev/null
+++ b/test/vitest/__tests__/stores/useStateQueryStore.spec.js
@@ -0,0 +1,58 @@
+import { describe, expect, it, beforeEach, beforeAll } from 'vitest';
+import { createWrapper } from 'app/test/vitest/helper';
+
+import { useStateQueryStore } from 'src/stores/useStateQueryStore';
+
+describe('useStateQueryStore', () => {
+ beforeAll(() => {
+ createWrapper({}, {});
+ });
+
+ const stateQueryStore = useStateQueryStore();
+ const { add, isLoading, remove, reset } = useStateQueryStore();
+ const firstQuery = { url: 'myQuery' };
+
+ function getQueries() {
+ return stateQueryStore.queries;
+ }
+
+ beforeEach(() => {
+ reset();
+ expect(getQueries().size).toBeFalsy();
+ });
+
+ it('should add two queries', async () => {
+ expect(getQueries().size).toBeFalsy();
+ add(firstQuery);
+
+ expect(getQueries().size).toBeTruthy();
+ expect(getQueries().has(firstQuery)).toBeTruthy();
+
+ add();
+ expect(getQueries().size).toBe(2);
+ });
+
+ it('should add and remove loading state', async () => {
+ expect(isLoading().value).toBeFalsy();
+ add(firstQuery);
+ expect(isLoading().value).toBeTruthy();
+ remove(firstQuery);
+ expect(isLoading().value).toBeFalsy();
+ });
+
+ it('should add and remove query', async () => {
+ const secondQuery = { ...firstQuery };
+ const thirdQuery = { ...firstQuery };
+
+ add(firstQuery);
+ add(secondQuery);
+
+ const beforeCount = getQueries().size;
+ add(thirdQuery);
+ expect(getQueries().has(thirdQuery)).toBeTruthy();
+
+ remove(thirdQuery);
+ expect(getQueries().has(thirdQuery)).toBeFalsy();
+ expect(getQueries().size).toBe(beforeCount);
+ });
+});
diff --git a/test/vitest/helper.js b/test/vitest/helper.js
index e201535ec..4bfae5dc8 100644
--- a/test/vitest/helper.js
+++ b/test/vitest/helper.js
@@ -70,8 +70,10 @@ class FormDataMock {
vi.fn();
}
}
+
global.FormData = FormDataMock;
global.URL = class URL {};
+global.Date.vnNew = () => new Date(Date.UTC(2001, 0, 1, 11));
export function createWrapper(component, options) {
const defaultOptions = {