feat: refs #8363 created composable to modify minPrice and adapt e2e
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Jon Elias 2025-03-07 10:51:43 +01:00
parent 9f8c491eda
commit f3fa931c70
5 changed files with 90 additions and 147 deletions

View File

@ -8,11 +8,6 @@ import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnRow from 'components/ui/VnRow.vue';
import { QCheckbox } from 'quasar';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
const emit = defineEmits(['onDataSaved']);
const $props = defineProps({
rows: {
type: Array,
@ -26,10 +21,13 @@ const $props = defineProps({
type: String,
default: '',
},
beforeSave: {
type: Function,
default: () => {},
},
});
const { t } = useI18n();
const { notify } = useNotify();
const inputs = {
input: markRaw(VnInput),
@ -44,24 +42,12 @@ const selectedField = ref(null);
const closeButton = ref(null);
const isLoading = ref(false);
const onDataSaved = () => {
notify('globals.dataSaved', 'positive');
emit('onDataSaved');
closeForm();
};
const onSubmit = async () => {
isLoading.value = true;
const rowsToEdit = $props.rows.map((row) => ({ id: row.id, itemFk: row.itemFk }));
const payload = {
field: selectedField.value.field,
newValue: newValue.value,
lines: rowsToEdit,
};
await axios.post($props.editUrl, payload);
onDataSaved();
isLoading.value = false;
$props.rows.forEach((row) => {
row[selectedField.value.name] = newValue.value;
});
closeForm();
};
const closeForm = () => {
@ -86,6 +72,7 @@ const closeForm = () => {
option-label="label"
v-model="selectedField"
data-cy="EditFixedPriceSelectOption"
@update:model-value="newValue = null"
/>
<component
:is="inputs[selectedField?.component || 'input']"

View File

@ -0,0 +1,53 @@
import axios from 'axios';
export async function beforeSave(data, getChanges, modelOrigin) {
console.log('data: ', data);
try {
const changes = data.updates;
if (!changes) return data;
const patchPromises = [];
for (const change of changes) {
console.log('change: ', change);
let patchData = {};
if ('hasMinPrice' in change.data) {
patchData.hasMinPrice = change.data?.hasMinPrice;
delete change.data.hasMinPrice;
}
if ('minPrice' in change.data) {
patchData.minPrice = change.data?.minPrice;
delete change.data.minPrice;
}
if (Object.keys(patchData).length > 0) {
const promise = axios
.get(`${modelOrigin}/findOne`, {
params: {
filter: {
fields: ['itemFk'],
where: { id: change.where.id },
},
},
})
.then((row) => {
return axios.patch(`Items/${row.data.itemFk}`, patchData);
})
.catch((error) => {
console.error('Error processing change: ', change, error);
});
patchPromises.push(promise);
}
}
await Promise.all(patchPromises);
data.updates = changes.filter((change) => Object.keys(change.data).length > 0);
return data;
} catch (error) {
console.error('Error in beforeSave:', error);
throw error;
}
}

View File

@ -16,6 +16,7 @@ import ItemDescriptor from 'src/pages/Item/Card/ItemDescriptor.vue';
import axios from 'axios';
import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
import { checkEntryLock } from 'src/composables/checkEntryLock';
import { beforeSave } from 'src/composables/updateMinPriceBeforeSave';
const $props = defineProps({
id: {
@ -340,13 +341,6 @@ const columns = [
toggleIndeterminate: false,
},
component: 'checkbox',
cellEvent: {
'update:modelValue': async (value, oldValue, row) => {
await axios.patch(`Items/${row['itemFk']}`, {
hasMinPrice: value,
});
},
},
width: '25px',
},
{
@ -356,13 +350,6 @@ const columns = [
toolTip: t('Minimum price'),
name: 'minPrice',
component: 'number',
cellEvent: {
'update:modelValue': async (value, oldValue, row) => {
await axios.patch(`Items/${row['itemFk']}`, {
minPrice: value,
});
},
},
width: '35px',
style: (row) => {
if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
@ -435,56 +422,6 @@ function getAmountStyle(row) {
return { color: 'var(--vn-label-color)' };
}
async function beforeSave(data, getChanges) {
try {
const changes = data.updates;
if (!changes) return data;
const patchPromises = [];
for (const change of changes) {
let patchData = {};
if ('hasMinPrice' in change.data) {
patchData.hasMinPrice = change.data?.hasMinPrice;
delete change.data.hasMinPrice;
}
if ('minPrice' in change.data) {
patchData.minPrice = change.data?.minPrice;
delete change.data.minPrice;
}
if (Object.keys(patchData).length > 0) {
const promise = axios
.get('Buys/findOne', {
params: {
filter: {
fields: ['itemFk'],
where: { id: change.where.id },
},
},
})
.then((buy) => {
return axios.patch(`Items/${buy.data.itemFk}`, patchData);
})
.catch((error) => {
console.error('Error processing change: ', change, error);
});
patchPromises.push(promise);
}
}
await Promise.all(patchPromises);
data.updates = changes.filter((change) => Object.keys(change.data).length > 0);
return data;
} catch (error) {
console.error('Error in beforeSave:', error);
throw error;
}
}
function invertQuantitySign(rows, sign) {
for (const row of rows) {
if (sign > 0) row.quantity = Math.abs(row.quantity);
@ -658,7 +595,7 @@ onMounted(() => {
:right-search="editableMode"
:row-click="false"
:columns="columns"
:beforeSaveFn="beforeSave"
:beforeSaveFn="(data, getChanges) => beforeSave(data, getChanges, 'Buys')"
class="buyList"
:table-height="$props.tableHeight ?? '84vh'"
auto-load

View File

@ -4,7 +4,10 @@ import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useQuasar } from 'quasar';
import { useStateStore } from 'stores/useStateStore';
import useNotify from 'src/composables/useNotify.js';
import { beforeSave } from 'src/composables/updateMinPriceBeforeSave';
import FetchedTags from 'components/ui/FetchedTags.vue';
import VnConfirm from 'components/ui/VnConfirm.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
@ -14,6 +17,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnColor from 'src/components/common/VnColor.vue';
import VnImg from 'src/components/ui/VnImg.vue';
import { toDate } from 'src/filters';
import { isLower, isBigger } from 'src/filters/date.js';
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
@ -28,7 +32,7 @@ const editTableCellDialogRef = ref(null);
const fixedPrices = ref([]);
const selectedRows = ref([]);
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
const dateColor = 'var(--vn-label-text-color)';
onMounted(async () => {
stateStore.rightDrawer = true;
});
@ -47,19 +51,19 @@ const columns = computed(() => [
};
},
},
width: '45px',
width: '50px',
columnFilter: false,
},
{
name: 'itemFk',
label: t('item.fixedPrice.itemFk'),
labelAbbreviation: 'ID',
labelAbbreviation: 'Id',
toolTip: t('item.fixedPrice.itemFk'),
component: 'number',
columnFilter: {
inWhere: true,
},
width: '50px',
width: '60px',
},
{
labelAbbreviation: '',
@ -87,9 +91,12 @@ const columns = computed(() => [
optionValue: 'name',
uppercase: false,
},
isEditable: false,
},
{
label: t('item.fixedPrice.groupingPrice'),
labelAbbreviation: 'Group.',
toolTip: t('item.fixedPrice.groupingPrice'),
name: 'rate2',
component: 'number',
create: true,
@ -98,6 +105,8 @@ const columns = computed(() => [
},
{
label: t('item.fixedPrice.packingPrice'),
labelAbbreviation: 'pack.',
toolTip: t('item.fixedPrice.packingPrice'),
name: 'rate3',
component: 'number',
create: true,
@ -118,13 +127,10 @@ const columns = computed(() => [
},
{
label: t('item.fixedPrice.minPrice'),
labelAbbreviation: 'Min.P',
toolTip: t('item.fixedPrice.minPrice'),
name: 'minPrice',
component: 'number',
cellEvent: {
'update:modelValue': async (value, oldValue, row) => {
updateMinPrice(value, row);
},
},
width: '55px',
style: (row) => {
if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
@ -181,53 +187,6 @@ const columns = computed(() => [
},
]);
const editTableFieldsOptions = [
{
field: 'rate2',
label: t('item.fixedPrice.groupingPrice'),
component: 'input',
attrs: {
type: 'number',
},
},
{
field: 'rate3',
label: t('item.fixedPrice.packingPrice'),
component: 'input',
attrs: {
type: 'number',
},
},
{
field: 'minPrice',
label: t('item.fixedPrice.minPrice'),
component: 'input',
attrs: {
type: 'number',
},
},
{
field: 'started',
label: t('item.fixedPrice.started'),
component: 'date',
},
{
field: 'ended',
label: t('item.fixedPrice.ended'),
component: 'date',
},
{
field: 'warehouseFk',
label: t('globals.warehouse'),
component: 'select',
attrs: {
options: [],
'option-label': 'name',
'option-value': 'id',
},
},
];
const updateMinPrice = async (value, props) => {
props.row.hasMinPrice = value;
await upsertPrice({
@ -313,7 +272,7 @@ const dateStyle = (date) =>
? {
color: 'var(--vn-black-text-color)',
}
: { 'background-color': 'transparent' };
: { color: dateColor, 'background-color': 'transparent' };
async function cloneFixedPrice(rows) {
for (let row of rows) {
@ -344,7 +303,7 @@ async function cloneFixedPrice(rows) {
:disable="!hasSelectedRows"
@click="openEditTableCellDialog()"
color="primary"
icon="edit"
icon="vn:wand"
flat
:label="t('globals.edit')"
data-cy="FixedPriceToolbarEditBtn"
@ -391,6 +350,7 @@ async function cloneFixedPrice(rows) {
}"
:disable-option="{ card: true }"
auto-load
:beforeSaveFn="(data, getChanges) => beforeSave(data, getChanges, 'FixedPrices')"
>
<template #column-image="{ row }">
<div class="image-wrapper">
@ -478,8 +438,13 @@ async function cloneFixedPrice(rows) {
<EditTableCellValueForm
edit-url="FixedPrices/editFixedPrice"
:rows="selectedRows"
:fields-options="editTableFieldsOptions"
@on-data-saved="onEditCellDataSaved()"
:fields-options="
columns.filter(
({ isEditable, component, name }) =>
isEditable !== false && component && name !== 'itemFk',
)
"
:beforeSave="beforeSave"
/>
</QDialog>
</template>

View File

@ -60,6 +60,7 @@ describe('Handle Items FixedPrice', () => {
cy.get('.q-menu .q-item').contains(grouping).click();
cy.dataCy('EditFixedPriceValueOption').type('5');
cy.get(saveEditBtn).click();
cy.dataCy('crudModelDefaultSaveBtn').click();
cy.checkNotification('Data saved');
});