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
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
9f8c491eda
commit
f3fa931c70
|
@ -8,11 +8,6 @@ import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import { QCheckbox } from 'quasar';
|
import { QCheckbox } from 'quasar';
|
||||||
|
|
||||||
import axios from 'axios';
|
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
|
||||||
|
|
||||||
const emit = defineEmits(['onDataSaved']);
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -26,10 +21,13 @@ const $props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
beforeSave: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notify } = useNotify();
|
|
||||||
|
|
||||||
const inputs = {
|
const inputs = {
|
||||||
input: markRaw(VnInput),
|
input: markRaw(VnInput),
|
||||||
|
@ -44,24 +42,12 @@ const selectedField = ref(null);
|
||||||
const closeButton = ref(null);
|
const closeButton = ref(null);
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
const onDataSaved = () => {
|
|
||||||
notify('globals.dataSaved', 'positive');
|
|
||||||
emit('onDataSaved');
|
|
||||||
closeForm();
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
const rowsToEdit = $props.rows.map((row) => ({ id: row.id, itemFk: row.itemFk }));
|
$props.rows.forEach((row) => {
|
||||||
const payload = {
|
row[selectedField.value.name] = newValue.value;
|
||||||
field: selectedField.value.field,
|
});
|
||||||
newValue: newValue.value,
|
closeForm();
|
||||||
lines: rowsToEdit,
|
|
||||||
};
|
|
||||||
|
|
||||||
await axios.post($props.editUrl, payload);
|
|
||||||
onDataSaved();
|
|
||||||
isLoading.value = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeForm = () => {
|
const closeForm = () => {
|
||||||
|
@ -86,6 +72,7 @@ const closeForm = () => {
|
||||||
option-label="label"
|
option-label="label"
|
||||||
v-model="selectedField"
|
v-model="selectedField"
|
||||||
data-cy="EditFixedPriceSelectOption"
|
data-cy="EditFixedPriceSelectOption"
|
||||||
|
@update:model-value="newValue = null"
|
||||||
/>
|
/>
|
||||||
<component
|
<component
|
||||||
:is="inputs[selectedField?.component || 'input']"
|
:is="inputs[selectedField?.component || 'input']"
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import ItemDescriptor from 'src/pages/Item/Card/ItemDescriptor.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
|
import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
|
||||||
import { checkEntryLock } from 'src/composables/checkEntryLock';
|
import { checkEntryLock } from 'src/composables/checkEntryLock';
|
||||||
|
import { beforeSave } from 'src/composables/updateMinPriceBeforeSave';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -340,13 +341,6 @@ const columns = [
|
||||||
toggleIndeterminate: false,
|
toggleIndeterminate: false,
|
||||||
},
|
},
|
||||||
component: 'checkbox',
|
component: 'checkbox',
|
||||||
cellEvent: {
|
|
||||||
'update:modelValue': async (value, oldValue, row) => {
|
|
||||||
await axios.patch(`Items/${row['itemFk']}`, {
|
|
||||||
hasMinPrice: value,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
width: '25px',
|
width: '25px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -356,13 +350,6 @@ const columns = [
|
||||||
toolTip: t('Minimum price'),
|
toolTip: t('Minimum price'),
|
||||||
name: 'minPrice',
|
name: 'minPrice',
|
||||||
component: 'number',
|
component: 'number',
|
||||||
cellEvent: {
|
|
||||||
'update:modelValue': async (value, oldValue, row) => {
|
|
||||||
await axios.patch(`Items/${row['itemFk']}`, {
|
|
||||||
minPrice: value,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
width: '35px',
|
width: '35px',
|
||||||
style: (row) => {
|
style: (row) => {
|
||||||
if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
|
if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
|
||||||
|
@ -435,56 +422,6 @@ function getAmountStyle(row) {
|
||||||
return { color: 'var(--vn-label-color)' };
|
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) {
|
function invertQuantitySign(rows, sign) {
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
if (sign > 0) row.quantity = Math.abs(row.quantity);
|
if (sign > 0) row.quantity = Math.abs(row.quantity);
|
||||||
|
@ -658,7 +595,7 @@ onMounted(() => {
|
||||||
:right-search="editableMode"
|
:right-search="editableMode"
|
||||||
:row-click="false"
|
:row-click="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:beforeSaveFn="beforeSave"
|
:beforeSaveFn="(data, getChanges) => beforeSave(data, getChanges, 'Buys')"
|
||||||
class="buyList"
|
class="buyList"
|
||||||
:table-height="$props.tableHeight ?? '84vh'"
|
:table-height="$props.tableHeight ?? '84vh'"
|
||||||
auto-load
|
auto-load
|
||||||
|
|
|
@ -4,7 +4,10 @@ import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
import { beforeSave } from 'src/composables/updateMinPriceBeforeSave';
|
||||||
|
|
||||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.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 VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import VnColor from 'src/components/common/VnColor.vue';
|
import VnColor from 'src/components/common/VnColor.vue';
|
||||||
import VnImg from 'src/components/ui/VnImg.vue';
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
|
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
import { isLower, isBigger } from 'src/filters/date.js';
|
import { isLower, isBigger } from 'src/filters/date.js';
|
||||||
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
|
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
|
||||||
|
@ -28,7 +32,7 @@ const editTableCellDialogRef = ref(null);
|
||||||
const fixedPrices = ref([]);
|
const fixedPrices = ref([]);
|
||||||
const selectedRows = ref([]);
|
const selectedRows = ref([]);
|
||||||
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
|
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
|
||||||
|
const dateColor = 'var(--vn-label-text-color)';
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
});
|
});
|
||||||
|
@ -47,19 +51,19 @@ const columns = computed(() => [
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
width: '45px',
|
width: '50px',
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'itemFk',
|
name: 'itemFk',
|
||||||
label: t('item.fixedPrice.itemFk'),
|
label: t('item.fixedPrice.itemFk'),
|
||||||
labelAbbreviation: 'ID',
|
labelAbbreviation: 'Id',
|
||||||
toolTip: t('item.fixedPrice.itemFk'),
|
toolTip: t('item.fixedPrice.itemFk'),
|
||||||
component: 'number',
|
component: 'number',
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
inWhere: true,
|
inWhere: true,
|
||||||
},
|
},
|
||||||
width: '50px',
|
width: '60px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
labelAbbreviation: '',
|
labelAbbreviation: '',
|
||||||
|
@ -87,9 +91,12 @@ const columns = computed(() => [
|
||||||
optionValue: 'name',
|
optionValue: 'name',
|
||||||
uppercase: false,
|
uppercase: false,
|
||||||
},
|
},
|
||||||
|
isEditable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.groupingPrice'),
|
label: t('item.fixedPrice.groupingPrice'),
|
||||||
|
labelAbbreviation: 'Group.',
|
||||||
|
toolTip: t('item.fixedPrice.groupingPrice'),
|
||||||
name: 'rate2',
|
name: 'rate2',
|
||||||
component: 'number',
|
component: 'number',
|
||||||
create: true,
|
create: true,
|
||||||
|
@ -98,6 +105,8 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.packingPrice'),
|
label: t('item.fixedPrice.packingPrice'),
|
||||||
|
labelAbbreviation: 'pack.',
|
||||||
|
toolTip: t('item.fixedPrice.packingPrice'),
|
||||||
name: 'rate3',
|
name: 'rate3',
|
||||||
component: 'number',
|
component: 'number',
|
||||||
create: true,
|
create: true,
|
||||||
|
@ -118,13 +127,10 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.minPrice'),
|
label: t('item.fixedPrice.minPrice'),
|
||||||
|
labelAbbreviation: 'Min.P',
|
||||||
|
toolTip: t('item.fixedPrice.minPrice'),
|
||||||
name: 'minPrice',
|
name: 'minPrice',
|
||||||
component: 'number',
|
component: 'number',
|
||||||
cellEvent: {
|
|
||||||
'update:modelValue': async (value, oldValue, row) => {
|
|
||||||
updateMinPrice(value, row);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
width: '55px',
|
width: '55px',
|
||||||
style: (row) => {
|
style: (row) => {
|
||||||
if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
|
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) => {
|
const updateMinPrice = async (value, props) => {
|
||||||
props.row.hasMinPrice = value;
|
props.row.hasMinPrice = value;
|
||||||
await upsertPrice({
|
await upsertPrice({
|
||||||
|
@ -313,7 +272,7 @@ const dateStyle = (date) =>
|
||||||
? {
|
? {
|
||||||
color: 'var(--vn-black-text-color)',
|
color: 'var(--vn-black-text-color)',
|
||||||
}
|
}
|
||||||
: { 'background-color': 'transparent' };
|
: { color: dateColor, 'background-color': 'transparent' };
|
||||||
|
|
||||||
async function cloneFixedPrice(rows) {
|
async function cloneFixedPrice(rows) {
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
|
@ -344,7 +303,7 @@ async function cloneFixedPrice(rows) {
|
||||||
:disable="!hasSelectedRows"
|
:disable="!hasSelectedRows"
|
||||||
@click="openEditTableCellDialog()"
|
@click="openEditTableCellDialog()"
|
||||||
color="primary"
|
color="primary"
|
||||||
icon="edit"
|
icon="vn:wand"
|
||||||
flat
|
flat
|
||||||
:label="t('globals.edit')"
|
:label="t('globals.edit')"
|
||||||
data-cy="FixedPriceToolbarEditBtn"
|
data-cy="FixedPriceToolbarEditBtn"
|
||||||
|
@ -391,6 +350,7 @@ async function cloneFixedPrice(rows) {
|
||||||
}"
|
}"
|
||||||
:disable-option="{ card: true }"
|
:disable-option="{ card: true }"
|
||||||
auto-load
|
auto-load
|
||||||
|
:beforeSaveFn="(data, getChanges) => beforeSave(data, getChanges, 'FixedPrices')"
|
||||||
>
|
>
|
||||||
<template #column-image="{ row }">
|
<template #column-image="{ row }">
|
||||||
<div class="image-wrapper">
|
<div class="image-wrapper">
|
||||||
|
@ -478,8 +438,13 @@ async function cloneFixedPrice(rows) {
|
||||||
<EditTableCellValueForm
|
<EditTableCellValueForm
|
||||||
edit-url="FixedPrices/editFixedPrice"
|
edit-url="FixedPrices/editFixedPrice"
|
||||||
:rows="selectedRows"
|
:rows="selectedRows"
|
||||||
:fields-options="editTableFieldsOptions"
|
:fields-options="
|
||||||
@on-data-saved="onEditCellDataSaved()"
|
columns.filter(
|
||||||
|
({ isEditable, component, name }) =>
|
||||||
|
isEditable !== false && component && name !== 'itemFk',
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:beforeSave="beforeSave"
|
||||||
/>
|
/>
|
||||||
</QDialog>
|
</QDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -60,6 +60,7 @@ describe('Handle Items FixedPrice', () => {
|
||||||
cy.get('.q-menu .q-item').contains(grouping).click();
|
cy.get('.q-menu .q-item').contains(grouping).click();
|
||||||
cy.dataCy('EditFixedPriceValueOption').type('5');
|
cy.dataCy('EditFixedPriceValueOption').type('5');
|
||||||
cy.get(saveEditBtn).click();
|
cy.get(saveEditBtn).click();
|
||||||
|
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||||
cy.checkNotification('Data saved');
|
cy.checkNotification('Data saved');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue