refactor: update ItemDescriptor to use dynamic labels for values #1505
|
@ -295,8 +295,14 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
|||
if (evt?.shiftKey && added) {
|
||||
const rowIndex = selectedRows[0].$index;
|
||||
const selectedIndexes = new Set(selected.value.map((row) => row.$index));
|
||||
for (const row of rows) {
|
||||
if (row.$index == rowIndex) break;
|
||||
const minIndex = selectedIndexes.size
|
||||
? Math.min(...selectedIndexes, rowIndex)
|
||||
: 0;
|
||||
const maxIndex = Math.max(...selectedIndexes, rowIndex);
|
||||
|
||||
for (let i = minIndex; i <= maxIndex; i++) {
|
||||
const row = rows[i];
|
||||
if (row.$index == rowIndex) continue;
|
||||
if (!selectedIndexes.has(row.$index)) {
|
||||
selected.value.push(row);
|
||||
selectedIndexes.add(row.$index);
|
||||
|
|
|
@ -27,30 +27,58 @@ describe('VnTable', () => {
|
|||
beforeEach(() => (vm.selected = []));
|
||||
|
||||
describe('handleSelection()', () => {
|
||||
const rows = [{ $index: 0 }, { $index: 1 }, { $index: 2 }];
|
||||
const rows = [
|
||||
{ $index: 0 },
|
||||
{ $index: 1 },
|
||||
{ $index: 2 },
|
||||
{ $index: 3 },
|
||||
{ $index: 4 },
|
||||
];
|
||||
|
||||
it('should add rows to selected when shift key is pressed and rows are added in ascending order', () => {
|
||||
const selectedRows = [{ $index: 1 }];
|
||||
it('should add rows to selected when shift key is pressed and rows are added except last one', () => {
|
||||
vm.handleSelection(
|
||||
{ evt: { shiftKey: true }, added: true, rows: selectedRows },
|
||||
rows
|
||||
rows,
|
||||
);
|
||||
expect(vm.selected).toEqual([{ $index: 0 }]);
|
||||
});
|
||||
|
||||
it('should add rows to selected when shift key is pressed and rows are added in descending order', () => {
|
||||
const selectedRows = [{ $index: 3 }];
|
||||
vm.handleSelection(
|
||||
{ evt: { shiftKey: true }, added: true, rows: selectedRows },
|
||||
rows,
|
||||
);
|
||||
expect(vm.selected).toEqual([{ $index: 0 }, { $index: 1 }, { $index: 2 }]);
|
||||
});
|
||||
|
||||
it('should not add rows to selected when shift key is not pressed', () => {
|
||||
const selectedRows = [{ $index: 1 }];
|
||||
vm.handleSelection(
|
||||
{ evt: { shiftKey: false }, added: true, rows: selectedRows },
|
||||
rows
|
||||
rows,
|
||||
);
|
||||
expect(vm.selected).toEqual([]);
|
||||
});
|
||||
|
||||
it('should not add rows to selected when rows are not added', () => {
|
||||
const selectedRows = [{ $index: 1 }];
|
||||
vm.handleSelection(
|
||||
{ evt: { shiftKey: true }, added: false, rows: selectedRows },
|
||||
rows
|
||||
rows,
|
||||
);
|
||||
expect(vm.selected).toEqual([]);
|
||||
});
|
||||
|
||||
it('should add all rows between the smallest and largest selected indexes', () => {
|
||||
vm.selected = [{ $index: 1 }, { $index: 3 }];
|
||||
const selectedRows = [{ $index: 4 }];
|
||||
vm.handleSelection(
|
||||
{ evt: { shiftKey: true }, added: true, rows: selectedRows },
|
||||
rows,
|
||||
);
|
||||
expect(vm.selected).toEqual([{ $index: 1 }, { $index: 3 }, { $index: 2 }]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||
|
@ -148,6 +147,7 @@ const exprBuilder = (param, value) => {
|
|||
outlined
|
||||
rounded
|
||||
auto-load
|
||||
sortBy="name ASC"
|
||||
/></QItemSection>
|
||||
</QItem>
|
||||
<QItem class="q-mb-sm">
|
||||
|
|
|
@ -78,10 +78,20 @@ const columns = computed(() => [
|
|||
component: 'select',
|
||||
attrs: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
fields: ['id', 'name'],
|
||||
fields: ['id', 'name', 'firstName'],
|
||||
where: { role: 'salesPerson' },
|
||||
optionFilter: 'firstName',
|
||||
},
|
||||
columnFilter: {
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
fields: ['id', 'name', 'firstName'],
|
||||
where: { role: 'salesPerson' },
|
||||
optionLabel: 'firstName',
|
||||
optionValue: 'id',
|
||||
},
|
||||
},
|
||||
create: false,
|
||||
columnField: {
|
||||
component: null,
|
||||
|
|
|
@ -77,24 +77,23 @@ onBeforeMount(() => {
|
|||
function setPaymentType(accounting) {
|
||||
if (!accounting) return;
|
||||
accountingType.value = accounting.accountingType;
|
||||
|
||||
initialData.description = [];
|
||||
initialData.payed = Date.vnNew();
|
||||
isCash.value = accountingType.value.code == 'cash';
|
||||
viewReceipt.value = isCash.value;
|
||||
if (accountingType.value.daysInFuture)
|
||||
initialData.payed.setDate(
|
||||
initialData.payed.getDate() + accountingType.value.daysInFuture
|
||||
initialData.payed.getDate() + accountingType.value.daysInFuture,
|
||||
);
|
||||
maxAmount.value = accountingType.value && accountingType.value.maxAmount;
|
||||
|
||||
if (accountingType.value.code == 'compensation')
|
||||
return (initialData.description = '');
|
||||
if (accountingType.value.receiptDescription)
|
||||
initialData.description.push(accountingType.value.receiptDescription);
|
||||
if (initialData.description) initialData.description.push(initialData.description);
|
||||
|
||||
initialData.description = initialData.description.join(', ');
|
||||
let descriptions = [];
|
||||
if (accountingType.value.receiptDescription)
|
||||
descriptions.push(accountingType.value.receiptDescription);
|
||||
if (initialData.description) descriptions.push(initialData.description);
|
||||
initialData.description = descriptions.join(', ');
|
||||
}
|
||||
|
||||
const calculateFromAmount = (event) => {
|
||||
|
|
|
@ -87,7 +87,7 @@ const insertTag = (rows) => {
|
|||
tagFk: undefined,
|
||||
}"
|
||||
:default-remove="false"
|
||||
:filter="{
|
||||
:user-filter="{
|
||||
fields: ['id', 'itemFk', 'tagFk', 'value', 'priority'],
|
||||
where: { itemFk: route.params.id },
|
||||
include: {
|
||||
|
@ -119,6 +119,7 @@ const insertTag = (rows) => {
|
|||
"
|
||||
:required="true"
|
||||
:rules="validate('itemTag.tagFk')"
|
||||
:data-cy="`tag${row?.tag?.name}`"
|
||||
/>
|
||||
<VnSelect
|
||||
v-if="row.tag?.isFree === false"
|
||||
|
@ -145,6 +146,7 @@ const insertTag = (rows) => {
|
|||
:label="t('itemTags.value')"
|
||||
:is-clearable="false"
|
||||
@keyup.enter.stop="(data) => itemTagsRef.onSubmit(data)"
|
||||
:data-cy="`tag${row?.tag?.name}Value`"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('itemBasicData.relevancy')"
|
||||
|
@ -162,6 +164,7 @@ const insertTag = (rows) => {
|
|||
name="delete"
|
||||
size="sm"
|
||||
dense
|
||||
:data-cy="`deleteTag${row?.tag?.name}`"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('itemTags.removeTag') }}
|
||||
|
@ -177,6 +180,7 @@ const insertTag = (rows) => {
|
|||
icon="add"
|
||||
shortcut="+"
|
||||
fab
|
||||
data-cy="createNewTag"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('itemTags.addTag') }}
|
||||
|
|
|
@ -1,32 +1,26 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { toCurrency } from 'src/filters';
|
||||
import VnUsesMana from 'components/ui/VnUsesMana.vue';
|
||||
|
||||
const $props = defineProps({
|
||||
mana: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
newPrice: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
usesMana: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
manaCode: {
|
||||
type: String,
|
||||
default: 'mana',
|
||||
},
|
||||
sale: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const mana = ref(null);
|
||||
const usesMana = ref(false);
|
||||
|
||||
const emit = defineEmits(['save', 'cancel']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
@ -38,20 +32,35 @@ const save = (sale = $props.sale) => {
|
|||
QPopupProxyRef.value.hide();
|
||||
};
|
||||
|
||||
const getMana = async () => {
|
||||
const { data } = await axios.get(`Tickets/${route.params.id}/getSalesPersonMana`);
|
||||
mana.value = data;
|
||||
await getUsesMana();
|
||||
};
|
||||
|
||||
const getUsesMana = async () => {
|
||||
const { data } = await axios.get('Sales/usesMana');
|
||||
usesMana.value = data;
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
emit('cancel');
|
||||
QPopupProxyRef.value.hide();
|
||||
};
|
||||
const hasMana = computed(() => typeof mana.value === 'number');
|
||||
defineExpose({ save });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPopupProxy ref="QPopupProxyRef" data-cy="ticketEditManaProxy">
|
||||
<QPopupProxy
|
||||
ref="QPopupProxyRef"
|
||||
@before-show="getMana"
|
||||
data-cy="ticketEditManaProxy"
|
||||
>
|
||||
<div class="container">
|
||||
<QSpinner v-if="!mana" color="primary" size="md" />
|
||||
<div v-else>
|
||||
<div class="header">Mana: {{ toCurrency(mana) }}</div>
|
||||
<div class="q-pa-md">
|
||||
<QSpinner v-if="!hasMana" color="primary" size="md" />
|
||||
<div class="q-pa-md" v-else>
|
||||
<slot :popup="QPopupProxyRef" />
|
||||
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
|
||||
<VnUsesMana :mana-code="manaCode" />
|
||||
|
@ -63,7 +72,7 @@ defineExpose({ save });
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<QBtn
|
||||
color="primary"
|
||||
|
|
|
@ -44,7 +44,6 @@ const isTicketEditable = ref(false);
|
|||
const sales = ref([]);
|
||||
const editableStatesOptions = ref([]);
|
||||
const selectedSales = ref([]);
|
||||
const mana = ref(null);
|
||||
const manaCode = ref('mana');
|
||||
const ticketState = computed(() => store.data?.ticketState?.state?.code);
|
||||
const transfer = ref({
|
||||
|
@ -258,18 +257,6 @@ const DEFAULT_EDIT = {
|
|||
oldQuantity: null,
|
||||
};
|
||||
const edit = ref({ ...DEFAULT_EDIT });
|
||||
const usesMana = ref(null);
|
||||
|
||||
const getUsesMana = async () => {
|
||||
const { data } = await axios.get('Sales/usesMana');
|
||||
usesMana.value = data;
|
||||
};
|
||||
|
||||
const getMana = async () => {
|
||||
const { data } = await axios.get(`Tickets/${route.params.id}/getSalesPersonMana`);
|
||||
mana.value = data;
|
||||
await getUsesMana();
|
||||
};
|
||||
|
||||
const selectedValidSales = computed(() => {
|
||||
if (!sales.value) return;
|
||||
|
@ -277,7 +264,6 @@ const selectedValidSales = computed(() => {
|
|||
});
|
||||
|
||||
const onOpenEditPricePopover = async (sale) => {
|
||||
await getMana();
|
||||
edit.value = {
|
||||
sale: JSON.parse(JSON.stringify(sale)),
|
||||
price: sale.price,
|
||||
|
@ -285,7 +271,6 @@ const onOpenEditPricePopover = async (sale) => {
|
|||
};
|
||||
|
||||
const onOpenEditDiscountPopover = async (sale) => {
|
||||
await getMana();
|
||||
if (isLocked.value) return;
|
||||
if (sale) {
|
||||
edit.value = {
|
||||
|
@ -306,7 +291,6 @@ const changePrice = async (sale) => {
|
|||
await confirmUpdate(() => updatePrice(sale, newPrice));
|
||||
} else updatePrice(sale, newPrice);
|
||||
}
|
||||
await getMana();
|
||||
};
|
||||
const updatePrice = async (sale, newPrice) => {
|
||||
await axios.post(`Sales/${sale.id}/updatePrice`, { newPrice });
|
||||
|
@ -599,9 +583,7 @@ watch(
|
|||
:is-ticket-editable="isTicketEditable"
|
||||
:sales="selectedValidSales"
|
||||
:disable="!hasSelectedRows"
|
||||
:mana="mana"
|
||||
:ticket-config="ticketConfig"
|
||||
@get-mana="getMana()"
|
||||
@update-discounts="updateDiscounts"
|
||||
@refresh-table="resetChanges"
|
||||
/>
|
||||
|
@ -829,7 +811,6 @@ watch(
|
|||
</QBtn>
|
||||
<TicketEditManaProxy
|
||||
ref="editPriceProxyRef"
|
||||
:mana="mana"
|
||||
:sale="row"
|
||||
:new-price="getNewPrice"
|
||||
@save="changePrice"
|
||||
|
@ -852,10 +833,8 @@ watch(
|
|||
|
||||
<TicketEditManaProxy
|
||||
ref="editManaProxyRef"
|
||||
:mana="mana"
|
||||
:sale="row"
|
||||
:new-price="getNewPrice"
|
||||
:uses-mana="usesMana"
|
||||
:mana-code="manaCode"
|
||||
@save="changeDiscount"
|
||||
>
|
||||
|
|
|
@ -34,10 +34,6 @@ const props = defineProps({
|
|||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
mana: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
ticketConfig: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
|
@ -220,7 +216,6 @@ const createRefund = async (withWarehouse) => {
|
|||
<TicketEditManaProxy
|
||||
ref="editManaProxyRef"
|
||||
:sale="row"
|
||||
:mana="props.mana"
|
||||
@save="changeMultipleDiscount"
|
||||
>
|
||||
<VnInput
|
||||
|
|
|
@ -1,33 +1,36 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item tag', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/1/tags`);
|
||||
cy.get('.q-page').should('be.visible');
|
||||
cy.waitForElement('[data-cy="itemTags"]');
|
||||
});
|
||||
|
||||
const createNewTag = 'createNewTag';
|
||||
const saveBtn = 'crudModelDefaultSaveBtn';
|
||||
const newTag = 'tagundefined';
|
||||
|
||||
it('should throw an error adding an existent tag', () => {
|
||||
cy.get('.q-page').should('be.visible');
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.dataCy('Tag_select').eq(7).type('Tallos');
|
||||
cy.get('.q-menu .q-item').contains('Tallos').click();
|
||||
cy.get(':nth-child(8) > [label="Value"]').type('1');
|
||||
+cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.checkNotification("The tag or priority can't be repeated for an item");
|
||||
cy.dataCy(createNewTag).click();
|
||||
cy.dataCy(newTag).should('be.visible').click().type('Genero{enter}');
|
||||
cy.dataCy('tagGeneroValue').eq(1).should('be.visible');
|
||||
cy.dataCy(saveBtn).click();
|
||||
cy.get('.q-notification__message').should(
|
||||
'have.text',
|
||||
"The tag or priority can't be repeated for an item",
|
||||
);
|
||||
});
|
||||
|
||||
it('should add a new tag', () => {
|
||||
cy.get('.q-page').should('be.visible');
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.dataCy('Tag_select').eq(7).click();
|
||||
cy.get('.q-menu .q-item').contains('Ancho de la base').type('{enter}');
|
||||
cy.get(':nth-child(8) > [label="Value"]').type('50');
|
||||
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.dataCy(createNewTag).click();
|
||||
cy.dataCy(newTag).should('be.visible').click().type('Forma{enter}');
|
||||
cy.dataCy('tagFormaValue').should('be.visible').type('50');
|
||||
cy.dataCy(saveBtn).click();
|
||||
|
||||
cy.checkNotification('Data saved');
|
||||
cy.dataCy('itemTags').children(':nth-child(8)').find('.justify-center > .q-icon').click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.dataCy('deleteTagForma').should('be.visible').click();
|
||||
cy.dataCy('VnConfirm_confirm').should('be.visible').click();
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue