Ticket basic data #474

Merged
jsegarra merged 15 commits from :feature/TicketBasicData into dev 2024-06-25 20:28:01 +00:00
5 changed files with 595 additions and 487 deletions
Showing only changes of commit dfb67f6f2b - Show all commits

View File

@ -1,34 +1,47 @@
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import FetchData from 'components/FetchData.vue';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useStateStore } from 'stores/useStateStore';
import { toCurrency } from 'filters/index';
import { useRole } from 'src/composables/useRole';
const $props = defineProps({
ticketData: {
formData: {
type: Object,
required: true,
},
haveNegatives: {
type: Boolean,
required: true,
default: false,
},
});
const emit = defineEmits(['updateForm', 'update:haveNegatives']);
const stateStore = useStateStore();
const { t } = useI18n();
const { hasAny } = useRole();
const { openConfirmationModal } = useVnConfirm();
const _ticketData = ref($props.ticketData);
const _ticketData = ref($props.formData);
const ticketUpdateActions = ref(null);
const haveNegatives = ref(false);
const haveNegatives = computed({
get: () => $props.haveNegatives,
set: (val) => emit('update:haveNegatives', val),
});
const rows = computed(() => _ticketData.value?.sale?.items || []);
watch(
() => _ticketData.value,
(val) => emit('updateForm', val)
);
const columns = computed(() => [
{
label: t('basicData.item'),
@ -103,7 +116,6 @@ const ticketHaveNegatives = () => {
let haveNotNegatives = false;
_ticketData.value.withoutNegatives = false;
const haveDifferences = _ticketData.value.sale.haveDifferences;
_ticketData.value.sale.items.forEach((item) => {
if (item.quantity > item.movable) _haveNegatives = true;
else haveNotNegatives = true;
@ -117,7 +129,6 @@ onMounted(() => {
stateStore.rightDrawer = true;
loadDefaultTicketAction();
ticketHaveNegatives();
console.log('ticketData: ', _ticketData.value);
});
onUnmounted(() => (stateStore.rightDrawer = false));
@ -234,7 +245,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #body-cell-movable="{ row }">
<QTd>
<QBadge
v-if="row.haveDifferences"
v-if="_ticketData?.sale?.haveDifferences"
:text-color="row.quantity > row.movable ? 'black' : 'white'"
:color="row.quantity > row.movable ? 'negative' : 'transparent'"
:label="row.movable"

View File

@ -0,0 +1,463 @@
<script setup>
import { ref, computed, onMounted, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
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 VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInputTime from 'components/common/VnInputTime.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
import { toTimeFormat } from 'filters/date.js';
const $props = defineProps({
formData: {
type: Object,
required: true,
default: () => ({}),
},
});
const emit = defineEmits(['updateForm']);
const { notify } = useNotify();
const router = useRouter();
const { t } = useI18n();
const agencyFetchRef = ref(null);
const zonesFetchRef = ref(null);
const clientsOptions = ref([]);
const warehousesOptions = ref([]);
const companiesOptions = ref([]);
const agenciesOptions = ref([]);
const zonesOptions = ref([]);
const addresses = ref([]);
const _formData = ref($props.formData);

duda, porque _formData y no formData??

duda, porque _formData y no formData??
watch(
() => _formData.value,
(val) => emit('updateForm', val)
);
const agencyByWarehouseFilter = computed(() => ({
fields: ['id', 'name'],
order: 'name ASC',
where: {
warehouseFk: warehouseId.value,
},
}));
const zonesFilter = computed(() => ({
fields: ['id', 'name'],
order: 'name ASC',
where: _formData.value?.agencyModeFk
? {
shipped: _formData.value?.shipped,
addressFk: _formData.value?.addressFk,
agencyModeFk: _formData.value?.agencyModeFk,
warehouseFk: _formData.value?.warehouseFk,
}
: {},
}));
const getLanded = async (params) => {
try {
const validParams =
shipped.value && addressId.value && agencyModeId.value && warehouseId.value;
if (!validParams) return;
_formData.value.zoneFk = null;
zonesOptions.value = [];
const { data } = await axios.get(`Agencies/getLanded`, { params });
if (data) {
_formData.value.zoneFk = data.zoneFk;
_formData.value.landed = data.landed;
_formData.value.shipped = params.shipped;
}
} catch (error) {
console.error(error);
notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
}
};
const getShipped = async (params) => {
try {
const validParams =
landed.value && addressId.value && agencyModeId.value && warehouseId.value;
if (!validParams) return;
_formData.value.zoneFk = null;
zonesOptions.value = [];
const { data } = await axios.get(`Agencies/getShipped`, { params });
if (data) {
_formData.value.zoneFk = data.zoneFk;
_formData.value.landed = params.landed;
_formData.value.shipped = data.shipped;
} else {
notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
}
} catch (error) {
console.error(error);
notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
}
};
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);
}
};
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);
}
};
const getClientDefaultAddress = async (clientId) => {
try {
const { data } = await axios.get(`Clients/${clientId}`);
if (data) addressId.value = data.defaultAddressFk;
} catch (error) {
console.error(error);
}
};
const clientAddressesList = async (value) => {
let filter = {
include: [
{
relation: 'province',
scope: {
fields: ['name'],
},
},
{
relation: 'agencyMode',
scope: {
fields: ['name'],
},
},
],
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`Clients/${value}/addresses`, { params });
if (data) addresses.value = data;
};
const addressId = computed({
get: () => _formData.value?.addressFk,
set: (val) => {
if (val != _formData.value?.addressFk) {
_formData.value.addressFk = val;
onChangeAddress(val);
getShipped({
landed: _formData.value?.landed,
addressFk: val,
agencyModeFk: _formData.value?.agencyModeFk,
warehouseFk: _formData.value?.warehouseFk,
});
}
},
});
const clientId = computed({
get: () => _formData.value?.clientFk,
set: (val) => {
_formData.value.clientFk = val;
_formData.value.addressFk = null;
if (!val) return;
getClientDefaultAddress(val);
clientAddressesList(val);
},
});
const landed = computed({
get: () => _formData.value?.landed,
set: (val) => {
_formData.value.landed = val;
getShipped({
landed: val,
addressFk: _formData.value?.addressFk,
agencyModeFk: _formData.value?.agencyModeFk,
warehouseFk: _formData.value?.warehouseFk,
});
},
});
const agencyModeId = computed({
get: () => _formData.value.agencyModeFk,
set: (val) => {
if (val != _formData.value.agencyModeFk) {
_formData.value.agencyModeFk = val;
if (!val) return;
const agencyMode = agenciesOptions.value.find((a) => a.id == val);
_formData.value.warehouseFk = agencyMode.warehouseFk;
getLanded({
shipped: _formData.value?.shipped,
addressFk: _formData.value?.addressFk,
agencyModeFk: val,
warehouseFk: _formData.value?.warehouseFk,
});
}
},
});
const zoneId = computed({
get: () => _formData.value?.zoneFk,
set: (val) => {
if (val != _formData.value?.zoneFk) {
_formData.value.zoneFk = val;
onChangeZone(val);
}
},
});
const warehouseId = computed({
get: () => _formData.value?.warehouseFk,
set: (val) => {
if (val != _formData.value?.warehouseFk) {
_formData.value.warehouseFk = val;
getShipped({
landed: _formData.value?.landed,
addressFk: _formData.value?.addressFk,
agencyModeFk: _formData.value?.agencyModeFk,
warehouseFk: val,
}).then(() => {
if (zoneId.value == null) _formData.value.agencyModeFk = null;
});
}
},
});
const shipped = computed({
get: () => _formData.value?.shipped,
set: (val) => {
if (new Date(_formData.value?.shipped).toDateString() != val.toDateString())
val.setHours(0, 0, 0, 0);
_formData.value.shipped = val;
getLanded({
shipped: val,
addressFk: _formData.value?.addressFk,
agencyModeFk: _formData.value?.agencyModeFk,
warehouseFk: _formData.value?.warehouseFk,
});
},
});
const onFormModelInit = () => {
if (_formData.value?.clientFk) clientAddressesList(_formData.value?.clientFk);
};
const redirectToCustomerAddress = () => {
router.push({
name: 'CustomerAddressEditCard',
params: { id: clientId.value, addressId: addressId.value },
});
};
onMounted(() => onFormModelInit());
</script>
<template>
<FetchData
url="Clients"
:filter="{
fields: ['id', 'name'],
order: 'id',
}"
@on-fetch="(data) => (clientsOptions = data)"
auto-load
/>
<FetchData
url="Warehouses"
@on-fetch="(data) => (warehousesOptions = data)"
auto-load
/>
<FetchData
url="Companies"
:filter="{
fields: ['id', 'code'],
order: 'code ASC',
}"
@on-fetch="(data) => (companiesOptions = data)"
auto-load
/>
<FetchData
ref="agencyFetchRef"
url="AgencyModes/byWarehouse"
:filter="agencyByWarehouseFilter"
@on-fetch="(data) => (agenciesOptions = data)"
auto-load
/>
<FetchData
ref="zonesFetchRef"
url="Zones/includingExpired"
:filter="zonesFilter"
@on-fetch="(data) => (zonesOptions = data)"
auto-load
/>
<QForm>
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
:label="t('basicData.client')"
v-model="clientId"
option-value="id"
option-label="name"
:options="clientsOptions"
hide-selected
map-options
:required="true"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
>#{{ scope.opt?.id }} {{ scope.opt?.name }}</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnSelect
:label="t('basicData.warehouse')"
v-model="warehouseId"
option-value="id"
option-label="name"
:options="warehousesOptions"
hide-selected
map-options
:required="true"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
:label="t('basicData.address')"
v-model="addressId"
option-value="id"
option-label="nickname"
:options="addresses"
hide-selected
map-options
:required="true"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
:class="{
'color-vn-label': !scope.opt?.isActive,
}"
>
{{
`${
!scope.opt?.isActive
? t('basicData.inactive')
: ''
} `
}}
<span> {{ scope.opt?.nickname }}</span>
<span
v-if="
scope.opt?.province ||
scope.opt?.city ||
scope.opt?.street
"
>, {{ scope.opt?.street }}, {{ scope.opt?.city }},
{{ scope.opt?.province?.name }} -
{{ scope.opt?.agencyMode?.name }}</span
>
</QItemLabel>
</QItemSection>
</QItem>
</template>
<template #append>
<QIcon
name="edit"
color="primary"
size="sm"
class="fill-icon cursor-pointer"
@click.stop="redirectToCustomerAddress()"
>
<QTooltip>{{ t('basicData.editAddress') }}</QTooltip>
</QIcon>
</template>
</VnSelect>
<VnInput :label="t('basicData.alias')" v-model="_formData.nickname" />
</VnRow>

deberia ser requerido no? Quiero decir, le falta el *

deberia ser requerido no? Quiero decir, le falta el *

Revisar el resto de campos

Revisar el resto de campos

Añadido.

Commit: 54e3eb6f0d

Añadido. Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/54e3eb6f0d7de3726ffa6269e7d9c02b2b9faa5d
<VnRow class="row q-gutter-md q-mb-md no-wrap">
<VnSelect
:label="t('basicData.company')"
v-model="_formData.companyFk"
option-value="id"
option-label="code"
:options="companiesOptions"
hide-selected
map-options
:required="true"
/>
<VnSelect
:label="t('basicData.agency')"
v-model="agencyModeId"
option-value="id"
option-label="name"
:options="agenciesOptions"
hide-selected
map-options
:required="true"
@focus="agencyFetchRef.fetch()"
/>
<VnSelect
:label="t('basicData.zone')"
Review

No se ve el texto, sino el id del registro

No se ve el texto, sino el id del registro
Review

No se ve el name ya que no hay no existen zoneOptions para los registros cargados, es algo medio raro la verdad como esta planteado, ya que en salix si desplegas el input de zonas te va a aparecer que no hay resultados.
Y en lilium esto es un problema porque el QSelect utiliza las options para mapear el resultado en base al value.

No se ve el name ya que no hay no existen `zoneOptions` para los registros cargados, es algo medio raro la verdad como esta planteado, ya que en salix si desplegas el input de zonas te va a aparecer que no hay resultados. Y en lilium esto es un problema porque el `QSelect` utiliza las options para mapear el resultado en base al value.
v-model="zoneId"
option-value="id"
option-label="name"
:options="zonesOptions"
hide-selected
map-options
:required="true"
@focus="zonesFetchRef.fetch()"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
>{{ scope.opt?.name }} - Max.
{{ toTimeFormat(scope.opt?.hour) }}
h.</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnInputDate
:label="t('basicData.shipped')"
v-model="_formData.shipped"
:required="true"
/>
<VnInputTime
:label="t('basicData.shippedHour')"
v-model="_formData.shipped"
/>
<VnInputDate
:label="t('basicData.landed')"
v-model="_formData.landed"
:required="true"
/>
</VnRow>
</QForm>
</template>

View File

@ -1,31 +1,28 @@
<script setup>
import { ref, computed } from 'vue';
import { ref, onBeforeMount } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.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 VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInputTime from 'components/common/VnInputTime.vue';
import BasicDataTable from './BasicDataTable.vue';
import TicketBasicDataForm from './TicketBasicDataForm.vue';
import { useVnConfirm } from 'composables/useVnConfirm';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
import { toTimeFormat } from 'filters/date.js';
const { notify } = useNotify();
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const stepperRef = ref(null);
const formModelRef = ref(null);
const agencyFetchRef = ref(null);
const zonesFetchRef = ref(null);
const { openConfirmationModal } = useVnConfirm();
const filter = {
const step = ref(1);
const formData = ref({});
const initialDataLoaded = ref(false);
const haveNegatives = ref(false);
const ticketFilter = {
include: [
{ relation: 'address' },
{
@ -53,319 +50,108 @@ const filter = {
],
};
const step = ref(1);
const clientsOptions = ref([]);
const warehousesOptions = ref([]);
const companiesOptions = ref([]);
const agenciesOptions = ref([]);
const zonesOptions = ref([]);
const addresses = ref([]);
const agencyByWarehouseFilter = computed(() => ({
fields: ['id', 'name'],
order: 'name ASC',
where: {
warehouseFk: warehouseId.value,
},
}));
const zonesFilter = computed(() => ({
fields: ['id', 'name'],
order: 'name ASC',
where: formModelRef.value?.formData?.agencyModeFk
? {
shipped: formModelRef.value?.formData?.shipped,
addressFk: formModelRef.value?.formData?.addressFk,
agencyModeFk: formModelRef.value?.formData?.agencyModeFk,
warehouseFk: formModelRef.value?.formData?.warehouseFk,
}
: {},
}));
const getLanded = async (params) => {
try {
const validParams =
shipped.value && addressId.value && agencyModeId.value && warehouseId.value;
if (!validParams) {
// this.$q.resolve(); ???????
return;
}
formModelRef.value.formData.zoneFk = null;
const { data } = await axios.get(`Agencies/getLanded`, { params });
if (data) {
formModelRef.value.formData.zoneFk = data.zoneFk;
formModelRef.value.formData.landed = data.landed;
formModelRef.value.formData.shipped = params.shipped;
}
} catch (error) {
console.error(error);
notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
}
const getTicketData = async () => {
const params = { filter: JSON.stringify(ticketFilter) };
const { data } = await axios.get(`tickets/${route.params.id}`, { params });
formData.value = data;
initialDataLoaded.value = true;
};
const getShipped = async (params) => {
try {
const validParams =
landed.value && addressId.value && agencyModeId.value && warehouseId.value;
if (!validParams) return;
formModelRef.value.formData.zoneFk = null;
const { data } = await axios.get(`Agencies/getShipped`, { params });
if (data) {
formModelRef.value.formData.zoneFk = data.zoneFk;
formModelRef.value.formData.landed = params.landed;
formModelRef.value.formData.shipped = data.shipped;
} else {
notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
}
} catch (error) {
console.error(error);
notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
}
};
const onChangeZone = async (zoneId) => {
try {
formModelRef.value.formData.agencyModeFk = null;
const { data } = await axios.get(`Zones/${zoneId}`);
formModelRef.value.formData.agencyModeFk = data.agencyModeFk;
} catch (error) {
console.error(error);
}
};
const onChangeAddress = async (addressId) => {
try {
formModelRef.value.formData.nickname = null;
const { data } = await axios.get(`Addresses/${addressId}`);
formModelRef.value.formData.nickname = data.nickname;
} catch (error) {
console.error(error);
}
};
const getClientDefaultAddress = async (clientId) => {
try {
const { data } = await axios.get(`Clients/${clientId}`);
if (data) addressId.value = data.defaultAddressFk;
} catch (error) {
console.error(error);
}
};
const clientAddressesList = async (value) => {
let filter = {
include: [
{
relation: 'province',
scope: {
fields: ['name'],
},
},
{
relation: 'agencyMode',
scope: {
fields: ['name'],
},
},
],
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`Clients/${value}/addresses`, { params });
if (data) addresses.value = data;
};
const addressId = computed({
get: () => formModelRef.value?.formData?.addressFk,
set: (val) => {
if (val != formModelRef.value?.formData?.addressFk) {
formModelRef.value.formData.addressFk = val;
onChangeAddress(val);
getShipped({
landed: formModelRef.value?.formData?.landed,
addressFk: val,
agencyModeFk: formModelRef.value?.formData?.agencyModeFk,
warehouseFk: formModelRef.value?.formData?.warehouseFk,
});
}
},
});
const clientId = computed({
get: () => formModelRef.value?.formData?.clientFk,
set: (val) => {
formModelRef.value.formData.clientFk = val;
formModelRef.value.formData.addressFk = null;
if (!val) return;
getClientDefaultAddress(val);
clientAddressesList(val);
},
});
const landed = computed({
get: () => formModelRef.value?.formData?.landed,
set: (val) => {
formModelRef.value.formData.landed = val;
getShipped({
landed: val,
addressFk: formModelRef.value?.formData?.addressFk,
agencyModeFk: formModelRef.value?.formData?.agencyModeFk,
warehouseFk: formModelRef.value?.formData?.warehouseFk,
});
},
});
const agencyModeId = computed({
get: () => formModelRef.value?.formData?.agencyModeFk,
set: (val) => {
if (val != formModelRef.value?.formData?.agencyModeFk) {
formModelRef.value.formData.agencyModeFk = val;
if (!val) return;
const agencyMode = agenciesOptions.value.find((a) => a.id == val);
formModelRef.value.formData.warehouseFk = agencyMode.warehouseFk;
getLanded({
shipped: formModelRef.value?.formData?.shipped,
addressFk: formModelRef.value?.formData?.addressFk,
agencyModeFk: val,
warehouseFk: formModelRef.value?.formData?.warehouseFk,
});
}
},
});
const zoneId = computed({
get: () => formModelRef.value?.formData?.zoneFk,
set: (val) => {
if (val != formModelRef.value.formData.zoneFk) {
formModelRef.value.formData.zoneFk = val;
onChangeZone(val);
}
},
});
const warehouseId = computed({
get: () => formModelRef.value?.formData?.warehouseFk,
set: (val) => {
if (val != formModelRef.value.formData.warehouseFk) {
formModelRef.value.formData.warehouseFk = val;
getShipped({
landed: formModelRef.value.formData.landed,
addressFk: formModelRef.value.formData.addressFk,
agencyModeFk: formModelRef.value.formData.agencyModeFk,
warehouseFk: val,
}).then(() => {
if (zoneId.value == null) formModelRef.value.formData.agencyModeFk = null;
});
}
},
});
const shipped = computed({
get: () => formModelRef.value?.formData?.shipped,
set: (val) => {
if (
new Date(formModelRef.value?.formData?.shipped).toDateString() !=
val.toDateString()
)
val.setHours(0, 0, 0, 0);
formModelRef.value.formData.shipped = val;
getLanded({
shipped: val,
addressFk: formModelRef.value?.formData?.addressFk,
agencyModeFk: formModelRef.value?.formData?.agencyModeFk,
warehouseFk: formModelRef.value?.formData?.warehouseFk,
});
},
});
const onFormModelInit = () => {
if (formModelRef.value.formData.clientFk)
clientAddressesList(formModelRef.value.formData.clientFk);
};
const redirectToCustomerAddress = () => {
router.push({
name: 'CustomerAddressEditCard',
params: { id: clientId.value, addressId: addressId.value },
});
};
const isFormInvalid = (formData) => {
const isFormInvalid = () => {
return (
!formData.clientFk ||
!formData.addressFk ||
!formData.agencyModeFk ||
!formData.companyFk ||
!formData.shipped ||
!formData.landed ||
!formData.zoneFk
!formData.value.clientFk ||
!formData.value.addressFk ||
!formData.value.agencyModeFk ||
!formData.value.companyFk ||
!formData.value.shipped ||
!formData.value.landed ||
!formData.value.zoneFk
);
};
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 submit = async () => {
try {
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 { data } = await axios.post(
`tickets/${formData.value.id}/componentUpdate`,
params
);
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 submitWithNegatives = async () => {
formData.value.withWarningAccept = true;
submit();
};
const onNextStep = async () => {
if (step.value === 1) {
const formData = formModelRef.value.formData;
if (isFormInvalid(formData))
if (isFormInvalid())
return notify(t('basicData.someFieldsAreInvalid'), 'negative');
if (!formData.sale || formModelRef.value.hasChanges) {
const params = {
landed: formData.landed,
addressId: formData.addressFk,
agencyModeId: formData.agencyModeFk,
zoneId: formData.zoneFk,
warehouseId: formData.warehouseFk,
shipped: formData.shipped,
};
const { data } = await axios.post(
`tickets/${formData.id}/priceDifference`,
params
);
formData.sale = data;
await getPriceDifference();
stepperRef.value.next();
}
} else if (step.value === 2) {
if (haveNegatives.value && !formData.value.withoutNegatives)
openConfirmationModal(
t('basicData.negativesConfirmTitle'),
t('basicData.negativesConfirmMessage'),
submitWithNegatives
);
else submit();
}
};
onBeforeMount(async () => await getTicketData());
</script>
<template>
<FetchData
url="Clients"
:filter="{
fields: ['id', 'name'],
order: 'id',
}"
@on-fetch="(data) => (clientsOptions = data)"
auto-load
/>
<FetchData
url="Warehouses"
@on-fetch="(data) => (warehousesOptions = data)"
auto-load
/>
<FetchData
url="Companies"
:filter="{
fields: ['id', 'code'],
order: 'code ASC',
}"
@on-fetch="(data) => (companiesOptions = data)"
auto-load
/>
<FetchData
ref="agencyFetchRef"
url="AgencyModes/byWarehouse"
:filter="agencyByWarehouseFilter"
@on-fetch="(data) => (agenciesOptions = data)"
auto-load
/>
<FetchData
ref="zonesFetchRef"
url="Zones/includingExpired"
:filter="zonesFilter"
@on-fetch="(data) => (zonesOptions = data)"
auto-load
/>
<QStepper
Review

Revisamos el stepper porque:

  1. Propuesta de mejora para colocar los botones
  2. si pulso sobre siguiente se llama a priceDifferences, pero si pulso en diferencia de precio
Revisamos el stepper porque: 1. Propuesta de mejora para colocar los botones 2. si pulso sobre siguiente se llama a priceDifferences, pero si pulso en diferencia de precio ❌
Review

Mejora de organización en los botones y removí la navegación vía header para no generar inconvenientes, porque probablemente se necesite refactorizar algo para implementarlo.

Commit: 4de347d0e8

Mejora de organización en los botones y removí la navegación vía header para no generar inconvenientes, porque probablemente se necesite refactorizar algo para implementarlo. Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/4de347d0e8f180a05035282ddf863fd8d5b3918b
v-model="step"
ref="stepperRef"
@ -373,177 +159,22 @@ const onNextStep = async () => {
header-nav
animated
keep-alive
style="max-width: 800px; margin: auto"
>
<QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
<FormModel
ref="formModelRef"
:url="`Tickets/${route.params.id}`"
:url-update="`Tickets/${route.params.id}`"
:filter="filter"
model="Ticket"
auto-load
:default-actions="false"
@on-fetch="onFormModelInit()"
>
<template #form="{ data }">
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
:label="t('basicData.client')"
v-model="clientId"
option-value="id"
option-label="name"
:options="clientsOptions"
hide-selected
map-options
:required="true"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
>#{{ scope.opt?.id }}
{{ scope.opt?.name }}</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnSelect
:label="t('basicData.warehouse')"
v-model="warehouseId"
option-value="id"
option-label="name"
:options="warehousesOptions"
hide-selected
map-options
:required="true"
<TicketBasicDataForm
v-if="initialDataLoaded"
@update-form="($event) => (formData = $event)"
:form-data="formData"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
:label="t('basicData.address')"
v-model="addressId"
option-value="id"
option-label="nickname"
:options="addresses"
hide-selected
map-options
:required="true"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
:class="{
'color-vn-label': !scope.opt?.isActive,
}"
>
{{
`${
!scope.opt?.isActive
? t('basicData.inactive')
: ''
} `
}}
<span> {{ scope.opt?.nickname }}</span>
<span
v-if="
scope.opt?.province ||
scope.opt?.city ||
scope.opt?.street
"
>, {{ scope.opt?.street }},
{{ scope.opt?.city }},
{{ scope.opt?.province?.name }} -
{{ scope.opt?.agencyMode?.name }}</span
>
</QItemLabel>
</QItemSection>
</QItem>
</template>
<template #append>
<QIcon
name="edit"
color="primary"
size="sm"
class="fill-icon cursor-pointer"
@click.stop="redirectToCustomerAddress()"
>
<QTooltip>{{ t('basicData.editAddress') }}</QTooltip>
</QIcon>
</template>
</VnSelect>
<VnInput :label="t('basicData.alias')" v-model="data.nickname" />
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
:label="t('basicData.company')"
v-model="data.companyFk"
option-value="id"
option-label="code"
:options="companiesOptions"
hide-selected
map-options
:required="true"
/>
<VnSelect
:label="t('basicData.agency')"
v-model="agencyModeId"
option-value="id"
option-label="name"
:options="agenciesOptions"
hide-selected
map-options
:required="true"
@focus="agencyFetchRef.fetch()"
/>
<VnSelect
:label="t('basicData.zone')"
v-model="zoneId"
option-value="id"
option-label="name"
:options="zonesOptions"
hide-selected
map-options
:required="true"
@focus="zonesFetchRef.fetch()"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
>{{ scope.opt?.name }} - Max.
{{ toTimeFormat(scope.opt?.hour) }}
h.</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnInputDate
:label="t('basicData.shipped')"
v-model="data.shipped"
:required="true"
/>
<VnInputTime
:label="t('basicData.shippedHour')"
v-model="data.shipped"
/>
<VnInputDate
:label="t('basicData.landed')"
v-model="data.landed"
:required="true"
/>
</VnRow>
</template>
</FormModel>
</QStep>
<QStep :name="2" :title="t('basicData.priceDifference')">
<BasicDataTable :ticket-data="formModelRef.formData" />
<BasicDataTable
:form-data="formData"
v-model:haveNegatives="haveNegatives"
@update-form="($event) => (formData = $event)"
/>
</QStep>
<template #navigation>
<QStepperNavigation>
<QBtn
@ -562,5 +193,4 @@ const onNextStep = async () => {
</QStepperNavigation>
</template>
</QStepper>
<pre v-if="formModelRef">{{ formModelRef.formData }}</pre>
</template>

View File

@ -32,3 +32,5 @@ basicData:
withoutNegativesInfo: Clone this ticket with the changes and only sales availables
negativesConfirmTitle: Edit basic data
negativesConfirmMessage: Negatives are going to be generated, are you sure you want to advance all the lines?
chooseAnOption: Choose an option
unroutedTicket: The ticket has been unrouted

View File

@ -32,5 +32,7 @@ basicData:
withoutNegativesInfo: Clonar este ticket con los cambios y solo ventas disponibles
negativesConfirmTitle: Editar datos básicos
negativesConfirmMessage: Se van a generar negativos, ¿seguro que quieres adelantar todas las líneas?
chooseAnOption: Elige una opción
unroutedTicket: El ticket ha sido desenrutado
Search ticket: Buscar ticket
You can search by ticket id or alias: Puedes buscar por id o alias del ticket