Item Fixed prices #307

Merged
jsegarra merged 17 commits from :feature/FixedPrices into dev 2024-04-24 07:39:23 +00:00
2 changed files with 159 additions and 38 deletions
Showing only changes of commit 2903c6a2bf - Show all commits

View File

@ -1,9 +1,12 @@
<script setup>
import { ref, reactive } from 'vue';
import { ref, markRaw } from 'vue';
import { useI18n } from 'vue-i18n';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import VnInput from 'src/components/common/VnInput.vue';
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';
@ -28,11 +31,16 @@ const $props = defineProps({
const { t } = useI18n();
const { notify } = useNotify();
const formData = reactive({
field: null,
newValue: null,
});
const inputs = {
input: markRaw(VnInput),
number: markRaw(VnInput),
date: markRaw(VnInputDate),
checkbox: markRaw(QCheckbox),
select: markRaw(VnSelectFilter),
};
const newValue = ref(null);
const selectedField = ref(null);
const closeButton = ref(null);
const isLoading = ref(false);
@ -47,8 +55,8 @@ const submitData = async () => {
isLoading.value = true;
const rowsToEdit = $props.rows.map((row) => ({ id: row.id, itemFk: row.itemFk }));
const payload = {
field: formData.field,
newValue: formData.newValue,
field: selectedField.value.field,
newValue: newValue.value,
lines: rowsToEdit,
};
@ -75,19 +83,20 @@ const closeForm = () => {
<span class="countLines">{{ ` ${rows.length} ` }}</span>
<span class="title">{{ t('buy(s)') }}</span>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Field to edit')"
:options="fieldsOptions"
hide-selected
option-label="label"
option-value="field"
v-model="formData.field"
/>
</div>
<div class="col">
<VnInput :label="t('Value')" v-model="formData.newValue" />
</div>
<VnSelectFilter
:label="t('Field to edit')"
:options="fieldsOptions"
hide-selected
option-label="label"
v-model="selectedField"
/>
<component
:is="inputs[selectedField?.component || 'input']"
v-bind="selectedField?.attrs || {}"
v-model="newValue"
:label="t('Value')"
style="width: 200px"
/>
</VnRow>
<div class="q-mt-lg row justify-end">
<QBtn

View File

@ -1,5 +1,5 @@
<script setup>
import { onMounted, ref, computed, reactive, onUnmounted } from 'vue';
import { onMounted, ref, computed, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
@ -220,16 +220,63 @@ const columns = computed(() => [
// },
// },
},
{ name: 'deleteAction', align: 'center' },
]);
const editTableFieldsOptions = [
{ field: 'rate2', label: t('item.fixedPrice.groupingPrice') },
{ field: 'rate3', label: t('item.fixedPrice.packingPrice') },
{ field: 'hasMinPrice', label: t('item.fixedPrice.hasMinPrice') },
{ field: 'minPrice', label: t('item.fixedPrice.minPrice') },
{ field: 'started', label: t('item.fixedPrice.started') },
{ field: 'ended', label: t('item.fixedPrice.ended') },
{ field: 'warehouseFk', label: t('item.fixedPrice.warehouse') },
{
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: 'hasMinPrice',
label: t('item.fixedPrice.hasMinPrice'),
component: 'checkbox',
attrs: {
'false-value': 0,
'true-value': 1,
},
},
{
field: 'started',
label: t('item.fixedPrice.started'),
component: 'date',
},
{
field: 'ended',
label: t('item.fixedPrice.ended'),
component: 'date',
},
{
field: 'warehouseFk',
label: t('item.fixedPrice.warehouse'),
component: 'select',
attrs: {
options: [],
'option-label': 'name',
'option-value': 'id',
},
},
];
const onFixedPricesFetched = (data) => {
@ -255,17 +302,25 @@ const getRowUpdateInputEvents = (props, resetMinPrice, inputType = 'text') => {
// };
// };
const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice) => {
// Si la row no tiene id significa que fue agregada con addRow y no se ha guardado en la base de datos
const validations = (row, rowIndex, col) => {
const isNew = !row.id;
// Si la row no tiene id significa que fue agregada con addRow y no se ha guardado en la base de datos
// Si isNew es falso no se checkea si el valor es igual a la original
if (!isNew)
if (fixedPricesOriginalData.value[rowIndex][col.field] == row[col.field]) return;
if (fixedPricesOriginalData.value[rowIndex][col.field] == row[col.field])
return false;
const requiredFields = ['itemFk', 'started', 'ended', 'rate2', 'rate3'];
return requiredFields.every(
(field) => row[field] !== null && row[field] !== undefined
);
};
const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice = false) => {
if (!validations(row, rowIndex, col)) return;
jsegarra marked this conversation as resolved
Review

Mismo objeto

Mismo objeto
Review

Cambiado

Commit: dce48b536d

Cambiado Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/dce48b536d536ab01a401422662ce14533085f42
try {
if (resetMinPrice) row.hasMinPrice = 0;
const requiredFields = ['itemFk', 'started', 'ended', 'rate2', 'rate3'];
for (const field of requiredFields) if (!row[field]) return;
const { data } = await axios.patch('FixedPrices/upsertFixedPrice', row);
row = data;
@ -296,8 +351,9 @@ const addRow = () => {
return;
}
const lastIndex = fixedPrices.value.length - 1;
const lastItemCopy = JSON.parse(JSON.stringify(fixedPrices.value[lastIndex]));
const lastItemCopy = JSON.parse(
JSON.stringify(fixedPrices.value[fixedPrices.value.length - 1])
);
const { id, ...restOfData } = lastItemCopy;
fixedPricesOriginalData.value.push(restOfData);
fixedPrices.value.push(restOfData);
@ -312,6 +368,37 @@ const onEditCellDataSaved = async () => {
await fixedPricesFetchRef.value.fetch();
};
const onWarehousesFetched = (data) => {
warehousesOptions.value = data;
// Actualiza las 'options' del elemento con field 'warehouseFk' en 'editTableFieldsOptions'.
const warehouseField = editTableFieldsOptions.find(
(field) => field.field === 'warehouseFk'
);
warehouseField.attrs.options = data;
};
const removePrice = async (id, rowIndex) => {
try {
await axios.delete(`FixedPrices/${id}`);
fixedPrices.value.splice(rowIndex, 1);
fixedPricesOriginalData.value.splice(rowIndex, 1);
notify(t('globals.dataSaved'), 'positive');
} catch (err) {
console.error('Error removing price', err);
}
};
const updateMinPrice = async (value, props) => {
// El checkbox hasMinPrice se encuentra en la misma columna que el input hasMinPrice
// Por lo tanto le mandamos otro objeto con las mismas propiedades pero con el campo 'field' cambiado
props.row.hasMinPrice = value;
await upsertPrice({
row: props.row,
col: { field: 'hasMinPrice' },
rowIndex: props.rowIndex,
});
};
onMounted(async () => {
stateStore.rightDrawer = true;
});
@ -332,7 +419,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
url="Warehouses"
:filter="{ order: ['name'] }"
auto-load
@on-fetch="(data) => (warehousesOptions = data)"
@on-fetch="(data) => onWarehousesFetched(data)"
/>
<FetchData
url="Items/withName"
@ -422,10 +509,11 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<div class="row">
<QCheckbox
class="col"
v-model="props.row.hasMinPrice"
:model-value="props.row.hasMinPrice"
@update:model-value="updateMinPrice($event, props)"
:false-value="0"
:true-value="1"
v-on="getRowUpdateInputEvents(props)"
:toggle-indeterminate="false"
/>
<VnInput
class="col"
@ -465,6 +553,27 @@ onUnmounted(() => (stateStore.rightDrawer = false));
/>
</QTd>
</template>
<template #body-cell-deleteAction="{ row, rowIndex }">
<QTd class="col">
<QIcon
name="delete"
size="sm"
class="cursor-pointer fill-icon-on-hover"
color="primary"
@click.stop="
openConfirmationModal(
t('This row will be removed'),
t('Do you want to clone this item?'),
() => removePrice(row.id, rowIndex)
)
"
>
<QTooltip class="text-no-wrap">
{{ t('Delete') }}
</QTooltip>
</QIcon>
</QTd>
</template>
<template #bottom-row>
<QTd align="center">
<QIcon
@ -502,4 +611,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
es:
Add fixed price: Añadir precio fijado
Edit fixed price(s): Editar precio(s) fijado(s)
This row will be removed: Esta linea se eliminará
Are you sure you want to continue?: ¿Seguro que quieres continuar?
Delete: Eliminar
</i18n>