#7717 fix OrderCatalog #558
|
@ -26,7 +26,10 @@ const url = computed(() => {
|
||||||
if (props.baseUrl) return `${props.baseUrl}/${route.params.id}`;
|
if (props.baseUrl) return `${props.baseUrl}/${route.params.id}`;
|
||||||
return props.customUrl;
|
return props.customUrl;
|
||||||
});
|
});
|
||||||
|
const searchRightDataKey = computed(() => {
|
||||||
|
if (!props.searchDataKey) return route.name;
|
||||||
|
return props.searchDataKey;
|
||||||
|
});
|
||||||
const arrayData = useArrayData(props.dataKey, {
|
const arrayData = useArrayData(props.dataKey, {
|
||||||
url: url.value,
|
url: url.value,
|
||||||
filter: props.filter,
|
filter: props.filter,
|
||||||
|
@ -62,10 +65,9 @@ if (props.baseUrl) {
|
||||||
<slot name="searchbar" v-if="props.searchDataKey">
|
<slot name="searchbar" v-if="props.searchDataKey">
|
||||||
<VnSearchbar :data-key="props.searchDataKey" v-bind="props.searchbarProps" />
|
<VnSearchbar :data-key="props.searchDataKey" v-bind="props.searchbarProps" />
|
||||||
</slot>
|
</slot>
|
||||||
<slot v-else name="searchbar" />
|
|
||||||
<RightMenu>
|
<RightMenu>
|
||||||
<template #right-panel v-if="props.filterPanel">
|
<template #right-panel v-if="props.filterPanel">
|
||||||
<component :is="props.filterPanel" :data-key="props.searchDataKey" />
|
<component :is="props.filterPanel" :data-key="searchRightDataKey" />
|
||||||
</template>
|
</template>
|
||||||
</RightMenu>
|
</RightMenu>
|
||||||
<QPageContainer>
|
<QPageContainer>
|
||||||
|
|
|
@ -111,6 +111,7 @@ watch(
|
||||||
|
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
async function search(evt) {
|
async function search(evt) {
|
||||||
|
try {
|
||||||
if (evt && $props.disableSubmitEvent) return;
|
if (evt && $props.disableSubmitEvent) return;
|
||||||
|
|
||||||
store.filter.where = {};
|
store.filter.where = {};
|
||||||
|
@ -123,9 +124,10 @@ async function search(evt) {
|
||||||
userParams.value = newParams;
|
userParams.value = newParams;
|
||||||
|
|
||||||
if (!$props.showAll && !Object.values(filter).length) store.data = [];
|
if (!$props.showAll && !Object.values(filter).length) store.data = [];
|
||||||
|
|
||||||
isLoading.value = false;
|
|
||||||
emit('search');
|
emit('search');
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reload() {
|
async function reload() {
|
||||||
|
@ -140,6 +142,7 @@ async function reload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clearFilters() {
|
async function clearFilters() {
|
||||||
|
try {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
store.userParamsChanged = true;
|
store.userParamsChanged = true;
|
||||||
arrayData.reset(['skip', 'filter.skip', 'page']);
|
arrayData.reset(['skip', 'filter.skip', 'page']);
|
||||||
|
@ -159,10 +162,11 @@ async function clearFilters() {
|
||||||
if (!$props.showAll) {
|
if (!$props.showAll) {
|
||||||
store.data = [];
|
store.data = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoading.value = false;
|
|
||||||
emit('clear');
|
emit('clear');
|
||||||
emit('update:modelValue', userParams.value);
|
emit('update:modelValue', userParams.value);
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagsList = computed(() => {
|
const tagsList = computed(() => {
|
||||||
|
|
|
@ -104,9 +104,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function search() {
|
async function search() {
|
||||||
const staticParams = Object.entries(store.userParams).filter(
|
const staticParams = Object.entries(store.userParams);
|
||||||
([key, value]) => value && (props.staticParams || []).includes(key)
|
|
||||||
);
|
|
||||||
arrayData.reset(['skip', 'page']);
|
arrayData.reset(['skip', 'page']);
|
||||||
|
|
||||||
if (props.makeFetch)
|
if (props.makeFetch)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// parsing JSON safely
|
||||||
|
function parseJSON(str, fallback) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(str ?? '{}');
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error parsing JSON:', e);
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default function (route, param) {
|
||||||
|
// catch route query params
|
||||||
|
const params = parseJSON(route?.query?.params, {});
|
||||||
|
|
||||||
|
// extract and parse filter from params
|
||||||
|
const { filter: filterStr = '{}' } = params;
|
||||||
|
const where = parseJSON(filterStr, {})?.where;
|
||||||
|
if (where && where[param] !== undefined) {
|
||||||
|
return where[param];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import dashIfEmpty from './dashIfEmpty';
|
||||||
import dateRange from './dateRange';
|
import dateRange from './dateRange';
|
||||||
import toHour from './toHour';
|
import toHour from './toHour';
|
||||||
import dashOrCurrency from './dashOrCurrency';
|
import dashOrCurrency from './dashOrCurrency';
|
||||||
|
import getParamWhere from './getParamWhere';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
toLowerCase,
|
toLowerCase,
|
||||||
|
@ -26,4 +27,5 @@ export {
|
||||||
toPercentage,
|
toPercentage,
|
||||||
dashIfEmpty,
|
dashIfEmpty,
|
||||||
dateRange,
|
dateRange,
|
||||||
|
getParamWhere,
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,6 +93,7 @@ globals:
|
||||||
since: Since
|
since: Since
|
||||||
from: From
|
from: From
|
||||||
to: To
|
to: To
|
||||||
|
notes: Notes
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Login
|
logIn: Login
|
||||||
summary: Summary
|
summary: Summary
|
||||||
|
|
|
@ -93,6 +93,7 @@ globals:
|
||||||
since: Desde
|
since: Desde
|
||||||
from: Desde
|
from: Desde
|
||||||
to: Hasta
|
to: Hasta
|
||||||
|
notes: Notas
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Inicio de sesión
|
logIn: Inicio de sesión
|
||||||
summary: Resumen
|
summary: Resumen
|
||||||
|
|
|
@ -19,7 +19,7 @@ const props = defineProps({
|
||||||
<VnFilterPanel
|
<VnFilterPanel
|
||||||
:data-key="props.dataKey"
|
:data-key="props.dataKey"
|
||||||
:search-button="true"
|
:search-button="true"
|
||||||
:unremovable-params="['from', 'to']"
|
:un-removable-params="['from', 'to']"
|
||||||
:hidden-tags="['from', 'to']"
|
:hidden-tags="['from', 'to']"
|
||||||
>
|
>
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -7,6 +7,7 @@ import { useState } from 'composables/useState';
|
||||||
import FormModel from 'components/FormModel.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
|
|
||||||
|
@ -15,7 +16,6 @@ const route = useRoute();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const ORDER_MODEL = 'order';
|
const ORDER_MODEL = 'order';
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const isNew = Boolean(!route.params.id);
|
const isNew = Boolean(!route.params.id);
|
||||||
const clientList = ref([]);
|
const clientList = ref([]);
|
||||||
const agencyList = ref([]);
|
const agencyList = ref([]);
|
||||||
|
@ -64,13 +64,6 @@ const fetchOrderDetails = (order) => {
|
||||||
fetchAgencyList(order?.landed, order?.addressFk);
|
fetchAgencyList(order?.landed, order?.addressFk);
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderMapper = (order) => {
|
|
||||||
return {
|
|
||||||
addressId: order.addressFk,
|
|
||||||
agencyModeId: order.agencyModeFk,
|
|
||||||
landed: new Date(order.landed).toISOString(),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const orderFilter = {
|
const orderFilter = {
|
||||||
|
|||||||
include: [
|
include: [
|
||||||
{ relation: 'agencyMode', scope: { fields: ['name'] } },
|
{ relation: 'agencyMode', scope: { fields: ['name'] } },
|
||||||
|
@ -106,10 +99,6 @@ const onClientChange = async (clientId) => {
|
||||||
console.error('Error al cambiar el cliente:', error);
|
console.error('Error al cambiar el cliente:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function onDataSaved({ id }) {
|
|
||||||
await router.push({ path: `/order/${id}/catalog` });
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -117,9 +106,8 @@ async function onDataSaved({ id }) {
|
||||||
<div class="q-pa-md">
|
<div class="q-pa-md">
|
||||||
<FormModel
|
<FormModel
|
||||||
:url="`Orders/${route.params.id}`"
|
:url="`Orders/${route.params.id}`"
|
||||||
@on-data-saved="onDataSaved"
|
:url-update="`Orders/${route.params.id}/updateBasicData`"
|
||||||
:model="ORDER_MODEL"
|
:model="ORDER_MODEL"
|
||||||
:mapper="orderMapper"
|
|
||||||
:filter="orderFilter"
|
:filter="orderFilter"
|
||||||
@on-fetch="fetchOrderDetails"
|
@on-fetch="fetchOrderDetails"
|
||||||
auto-load
|
auto-load
|
||||||
|
@ -180,8 +168,6 @@ async function onDataSaved({ id }) {
|
||||||
() => fetchAgencyList(data.landed, data.addressFk)
|
() => fetchAgencyList(data.landed, data.addressFk)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
|
||||||
<VnRow>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('order.form.agencyModeFk')"
|
:label="t('order.form.agencyModeFk')"
|
||||||
v-model="data.agencyModeFk"
|
v-model="data.agencyModeFk"
|
||||||
|
@ -189,9 +175,29 @@ async function onDataSaved({ id }) {
|
||||||
option-value="agencyModeFk"
|
option-value="agencyModeFk"
|
||||||
option-label="agencyMode"
|
option-label="agencyMode"
|
||||||
hide-selected
|
hide-selected
|
||||||
:disable="!agencyList?.length"
|
:disable="!agencyList?.length && data.isConfirmed === 1"
|
||||||
>
|
clearable
|
||||||
</VnSelect>
|
emit-value
|
||||||
|
map-options
|
||||||
|
:model-value="
|
||||||
|
!data.isConfirmed &&
|
||||||
|
agencyList?.length &&
|
||||||
|
agencyList.some(
|
||||||
|
(agency) => agency.agencyModeFk === data.agency_id
|
||||||
|
)
|
||||||
|
? data.agencyModeFk
|
||||||
|
: null
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow>
|
||||||
|
<VnInput
|
||||||
|
:label="t('globals.notes')"
|
||||||
|
type="textarea"
|
||||||
|
v-model="data.note"
|
||||||
|
fill-input
|
||||||
|
autogrow
|
||||||
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormModel>
|
</FormModel>
|
|
@ -1,16 +1,35 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import VnCard from 'components/common/VnCard.vue';
|
import VnCard from 'components/common/VnCard.vue';
|
||||||
import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
|
import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
|
||||||
import OrderFilter from './OrderFilter.vue';
|
import OrderFilter from './OrderFilter.vue';
|
||||||
import OrderSearchbar from './OrderSearchbar.vue';
|
import OrderSearchbar from './OrderSearchbar.vue';
|
||||||
|
import OrderCatalogFilter from './OrderCatalogFilter.vue';
|
||||||
|
const config = {
|
||||||
|
OrderCatalog: OrderCatalogFilter,
|
||||||
|
};
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const routeName = computed(() => route.name);
|
||||||
|
const customRouteRedirectName = computed(() => {
|
||||||
alexm
commented
Esto para que hace falta? Esto para que hace falta?
jon
commented
Para eliminar el duplicado de la searchbar, ya que la searchbar de catalog es distinta al del resto del módulo Para eliminar el duplicado de la searchbar, ya que la searchbar de catalog es distinta al del resto del módulo
|
|||||||
|
const route = config[routeName.value];
|
||||||
|
if (route) return null;
|
||||||
|
return 'OrderList';
|
||||||
|
});
|
||||||
|
const customFilterPanel = computed(() => {
|
||||||
|
const filterPanel = config[routeName.value] ?? OrderFilter;
|
||||||
|
return filterPanel;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnCard
|
<VnCard
|
||||||
data-key="Order"
|
data-key="Order"
|
||||||
base-url="Orders"
|
base-url="Orders"
|
||||||
:descriptor="OrderDescriptor"
|
:descriptor="OrderDescriptor"
|
||||||
:filter-panel="OrderFilter"
|
:filter-panel="customFilterPanel"
|
||||||
search-data-key="OrderList"
|
:search-data-key="customRouteRedirectName"
|
||||||
>
|
>
|
||||||
<template #searchbar>
|
<template #searchbar>
|
||||||
<OrderSearchbar />
|
<OrderSearchbar />
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
import axios from 'axios';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import CatalogItem from 'components/ui/CatalogItem.vue';
|
import CatalogItem from 'components/ui/CatalogItem.vue';
|
||||||
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
|
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
|
||||||
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const tags = ref([]);
|
||||||
|
|
||||||
onMounted(() => (stateStore.rightDrawer = true));
|
onMounted(() => {
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
checkOrderConfirmation();
|
||||||
|
});
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
|
|
||||||
const catalogParams = {
|
const catalogParams = {
|
||||||
|
@ -19,7 +26,12 @@ const catalogParams = {
|
||||||
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
|
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
|
||||||
};
|
};
|
||||||
|
|
||||||
const tags = ref([]);
|
async function checkOrderConfirmation() {
|
||||||
|
const response = await axios.get(`Orders/${route.params.id}`);
|
||||||
|
if (response.data.isConfirmed === 1) {
|
||||||
|
router.push(`/order/${route.params.id}/line`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function extractTags(items) {
|
function extractTags(items) {
|
||||||
const resultTags = [];
|
const resultTags = [];
|
||||||
|
@ -52,6 +64,15 @@ function extractValueTags(items) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<VnSearchbar
|
||||||
|
data-key="OrderCatalogList"
|
||||||
|
:user-params="catalogParams"
|
||||||
|
:static-params="['orderFk', 'orderBy']"
|
||||||
|
:redirect="false"
|
||||||
|
url="Orders/CatalogFilter"
|
||||||
|
:label="t('Search items')"
|
||||||
|
:info="t('You can search items by name or id')"
|
||||||
|
/>
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<QScrollArea class="fit text-grey-8">
|
<QScrollArea class="fit text-grey-8">
|
||||||
<OrderCatalogFilter
|
<OrderCatalogFilter
|
||||||
|
@ -68,7 +89,6 @@ function extractValueTags(items) {
|
||||||
url="Orders/CatalogFilter"
|
url="Orders/CatalogFilter"
|
||||||
:limit="50"
|
:limit="50"
|
||||||
:user-params="catalogParams"
|
:user-params="catalogParams"
|
||||||
auto-load
|
|
||||||
@on-fetch="extractTags"
|
@on-fetch="extractTags"
|
||||||
:update-router="false"
|
:update-router="false"
|
||||||
>
|
>
|
||||||
|
@ -106,3 +126,8 @@ function extractValueTags(items) {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
You can search items by name or id: Puedes buscar items por nombre o id
|
||||||
|
</i18n>
|
|
@ -7,8 +7,8 @@ import FetchData from 'components/FetchData.vue';
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
|
import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
|
||||||
import { useValidator } from 'src/composables/useValidator';
|
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
jsegarra
commented
useValidator no se usa en la template ni en script-setup useValidator no se usa en la template ni en script-setup
|
|||||||
|
import getParamWhere from 'src/filters/getParamWhere';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -27,19 +27,26 @@ const props = defineProps({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const categoryList = ref(null);
|
const categoryList = ref(null);
|
||||||
const selectedCategoryFk = ref(null);
|
const selectedCategoryFk = ref(getParamWhere(route, 'categoryFk'));
|
||||||
const typeList = ref(null);
|
const typeList = ref([]);
|
||||||
const selectedTypeFk = ref(null);
|
const selectedTypeFk = ref(null);
|
||||||
const validationsStore = useValidator();
|
|
||||||
const selectedOrder = ref(null);
|
|
||||||
const selectedOrderField = ref(null);
|
|
||||||
const moreFields = ref([]);
|
|
||||||
const moreFieldsOrder = ref([]);
|
|
||||||
const selectedTag = ref(null);
|
const selectedTag = ref(null);
|
||||||
const tagValues = ref([{}]);
|
const tagValues = ref([{}]);
|
||||||
const tagOptions = ref([]);
|
const tagOptions = ref([]);
|
||||||
|
const vnFilterPanelRef = ref();
|
||||||
|
const orderByList = ref([
|
||||||
|
{ id: 'relevancy DESC, name', name: t('params.relevancy'), priority: 999 },
|
||||||
|
{ id: 'showOrder, price', name: t('params.colorAndPrice'), priority: 999 },
|
||||||
|
{ id: 'name', name: t('params.name'), priority: 999 },
|
||||||
|
{ id: 'price', name: t('params.price'), priority: 999 },
|
||||||
|
]);
|
||||||
|
const orderWayList = ref([
|
||||||
|
{ id: 'ASC', name: t('params.ASC') },
|
||||||
|
{ id: 'DESC', name: t('params.DESC') },
|
||||||
|
]);
|
||||||
|
const orderBySelected = ref('relevancy DESC, name');
|
||||||
|
const orderWaySelected = ref('ASC');
|
||||||
|
|
||||||
const createValue = (val, done) => {
|
const createValue = (val, done) => {
|
||||||
if (val.length > 2) {
|
if (val.length > 2) {
|
||||||
|
@ -72,7 +79,7 @@ const selectCategory = (params, category, search) => {
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadTypes = async (categoryFk) => {
|
const loadTypes = async (categoryFk = selectedCategoryFk.value) => {
|
||||||
const { data } = await axios.get(`Orders/${route.params.id}/getItemTypeAvailable`, {
|
const { data } = await axios.get(`Orders/${route.params.id}/getItemTypeAvailable`, {
|
||||||
params: { itemCategoryId: categoryFk },
|
params: { itemCategoryId: categoryFk },
|
||||||
});
|
});
|
||||||
|
@ -84,7 +91,14 @@ const selectedCategory = computed(() =>
|
||||||
(category) => category?.id === selectedCategoryFk.value
|
(category) => category?.id === selectedCategoryFk.value
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
function filterFn(val, update) {
|
||||||
|
update(() => {
|
||||||
|
const needle = val.toLowerCase();
|
||||||
|
tagOptions.value = props.tagValue.filter(
|
||||||
|
(v) => v.toLowerCase().indexOf(needle) > -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
const selectedType = computed(() => {
|
const selectedType = computed(() => {
|
||||||
return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
|
return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
|
||||||
});
|
});
|
||||||
|
@ -95,7 +109,8 @@ function exprBuilder(param, value) {
|
||||||
case 'typeFk':
|
case 'typeFk':
|
||||||
return { [param]: value };
|
return { [param]: value };
|
||||||
case 'search':
|
case 'search':
|
||||||
return { 'i.name': { like: `%${value}%` } };
|
if (/^\d+$/.test(value)) return { 'i.id': value };
|
||||||
|
else return { 'i.name': { like: `%${value}%` } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,36 +147,6 @@ const removeTagChip = (selection, params, search) => {
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOrderChange = (value, params) => {
|
|
||||||
const tagObj = JSON.parse(params.orderBy);
|
|
||||||
tagObj.way = value.name;
|
|
||||||
params.orderBy = JSON.stringify(tagObj);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onOrderFieldChange = (value, params) => {
|
|
||||||
const tagObj = JSON.parse(params.orderBy);
|
|
||||||
switch (value) {
|
|
||||||
case 'Relevancy':
|
|
||||||
tagObj.name = value + ' DESC, name';
|
|
||||||
params.orderBy = JSON.stringify(tagObj);
|
|
||||||
break;
|
|
||||||
case 'ColorAndPrice':
|
|
||||||
tagObj.name = 'showOrder, price';
|
|
||||||
params.orderBy = JSON.stringify(tagObj);
|
|
||||||
break;
|
|
||||||
case 'Name':
|
|
||||||
tagObj.name = 'name';
|
|
||||||
params.orderBy = JSON.stringify(tagObj);
|
|
||||||
break;
|
|
||||||
case 'Price':
|
|
||||||
tagObj.name = 'price';
|
|
||||||
params.orderBy = JSON.stringify(tagObj);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const _moreFields = ['ASC', 'DESC'];
|
|
||||||
const _moreFieldsTypes = ['Relevancy', 'ColorAndPrice', 'Name', 'Price'];
|
|
||||||
const setCategoryList = (data) => {
|
const setCategoryList = (data) => {
|
||||||
categoryList.value = (data || [])
|
categoryList.value = (data || [])
|
||||||
.filter((category) => category.display)
|
.filter((category) => category.display)
|
||||||
|
@ -169,8 +154,8 @@ const setCategoryList = (data) => {
|
||||||
...category,
|
...category,
|
||||||
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
||||||
}));
|
}));
|
||||||
moreFields.value = useLang(_moreFields);
|
|
||||||
moreFieldsOrder.value = useLang(_moreFieldsTypes);
|
selectedCategoryFk.value && loadTypes();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCategoryClass = (category, params) => {
|
const getCategoryClass = (category, params) => {
|
||||||
|
@ -179,27 +164,22 @@ const getCategoryClass = (category, params) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const useLang = (values) => {
|
function addOrder(value, field, params) {
|
||||||
const { models } = validationsStore;
|
let { orderBy } = params;
|
||||||
const properties = models.Item?.properties || {};
|
orderBy = JSON.parse(orderBy);
|
||||||
return values.map((name) => {
|
orderBy[field] = value;
|
||||||
let prop = properties[name];
|
params.orderBy = JSON.stringify(orderBy);
|
||||||
const label = t(`params.${name}`);
|
vnFilterPanelRef.value.search();
|
||||||
return {
|
}
|
||||||
name,
|
|
||||||
label,
|
|
||||||
type: prop ? prop.type : null,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData url="ItemCategories" limit="30" auto-load @on-fetch="setCategoryList" />
|
<FetchData url="ItemCategories" limit="30" auto-load @on-fetch="setCategoryList" />
|
||||||
<VnFilterPanel
|
<VnFilterPanel
|
||||||
|
ref="vnFilterPanelRef"
|
||||||
:data-key="props.dataKey"
|
:data-key="props.dataKey"
|
||||||
:hidden-tags="['orderFk', 'orderBy']"
|
:hidden-tags="['orderFk', 'orderBy']"
|
||||||
:unremovable-params="['orderFk', 'orderBy']"
|
:un-removable-params="['orderFk', 'orderBy']"
|
||||||
:expr-builder="exprBuilder"
|
:expr-builder="exprBuilder"
|
||||||
:custom-tags="['tagGroups']"
|
:custom-tags="['tagGroups']"
|
||||||
@remove="clearFilter"
|
@remove="clearFilter"
|
||||||
|
@ -289,33 +269,29 @@ const useLang = (values) => {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
<QItem class="q-my-md">
|
|
||||||
<QItemSection>
|
|
||||||
<VnSelect
|
|
||||||
:label="t('Order')"
|
|
||||||
v-model="selectedOrder"
|
|
||||||
:options="moreFields"
|
|
||||||
option-label="label"
|
|
||||||
option-value="way"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
@update:model-value="(value) => onOrderChange(value, params)"
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem class="q-mb-md">
|
<QItem class="q-mb-md">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Order by')"
|
:label="t('Order by')"
|
||||||
v-model="selectedOrderField"
|
v-model="orderBySelected"
|
||||||
:options="moreFieldsOrder"
|
:options="orderByList"
|
||||||
option-label="label"
|
|
||||||
option-value="name"
|
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
@update:model-value="(value) => onOrderFieldChange(value, params)"
|
@update:model-value="(value) => addOrder(value, 'field', params)"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-md">
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('Order')"
|
||||||
|
v-model="orderWaySelected"
|
||||||
|
:options="orderWayList"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
@update:model-value="(value) => addOrder(value, 'way', params)"
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
@ -352,7 +328,7 @@ const useLang = (values) => {
|
||||||
v-if="!selectedTag"
|
v-if="!selectedTag"
|
||||||
:label="t('params.value')"
|
:label="t('params.value')"
|
||||||
v-model="value.value"
|
v-model="value.value"
|
||||||
:options="tagValue || []"
|
:options="tagOptions || []"
|
||||||
option-value="value"
|
option-value="value"
|
||||||
option-label="value"
|
option-label="value"
|
||||||
dense
|
dense
|
||||||
|
@ -362,6 +338,8 @@ const useLang = (values) => {
|
||||||
use-input
|
use-input
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
@new-value="createValue"
|
@new-value="createValue"
|
||||||
|
@filter="filterFn"
|
||||||
|
@update:model-value="applyTagFilter(params, searchFn)"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-else-if="selectedTag === 1"
|
v-else-if="selectedTag === 1"
|
||||||
|
@ -377,6 +355,7 @@ const useLang = (values) => {
|
||||||
use-input
|
use-input
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
@new-value="createValue"
|
@new-value="createValue"
|
||||||
|
@update:model-value="applyTagFilter(params, searchFn)"
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-else
|
v-else
|
||||||
|
@ -386,6 +365,7 @@ const useLang = (values) => {
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
|
@keyup.enter="applyTagFilter(params, searchFn)"
|
||||||
/>
|
/>
|
||||||
<QIcon
|
<QIcon
|
||||||
name="delete"
|
name="delete"
|
||||||
|
@ -400,7 +380,7 @@ const useLang = (values) => {
|
||||||
@click="tagValues.push({})"
|
@click="tagValues.push({})"
|
||||||
/>
|
/>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<!-- <QItem>
|
||||||
<QItemSection class="q-py-sm">
|
<QItemSection class="q-py-sm">
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('Search')"
|
:label="t('Search')"
|
||||||
|
@ -414,7 +394,7 @@ const useLang = (values) => {
|
||||||
@click.stop="applyTagFilter(params, searchFn)"
|
@click.stop="applyTagFilter(params, searchFn)"
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem> -->
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
</template>
|
</template>
|
||||||
</VnFilterPanel>
|
</VnFilterPanel>
|
||||||
|
@ -477,10 +457,10 @@ en:
|
||||||
order: Order
|
order: Order
|
||||||
ASC: Ascendant
|
ASC: Ascendant
|
||||||
DESC: Descendant
|
DESC: Descendant
|
||||||
Relevancy: Relevancy
|
relevancy: Relevancy
|
||||||
ColorAndPrice: Color and price
|
colorAndPrice: Color and price
|
||||||
Name: Name
|
name: Name
|
||||||
Price: Price
|
price: Price
|
||||||
es:
|
es:
|
||||||
params:
|
params:
|
||||||
type: Tipo
|
type: Tipo
|
||||||
|
@ -490,10 +470,10 @@ es:
|
||||||
order: Orden
|
order: Orden
|
||||||
ASC: Ascendiente
|
ASC: Ascendiente
|
||||||
DESC: Descendiente
|
DESC: Descendiente
|
||||||
Relevancy: Relevancia
|
relevancy: Relevancia
|
||||||
ColorAndPrice: Color y precio
|
colorAndPrice: Color y precio
|
||||||
Name: Nombre
|
name: Nombre
|
||||||
Price: Precio
|
price: Precio
|
||||||
Order: Orden
|
Order: Orden
|
||||||
Order by: Ordenar por
|
Order by: Ordenar por
|
||||||
Plant: Planta
|
Plant: Planta
|
||||||
|
|
|
@ -5,10 +5,12 @@ import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import useNotify from 'composables/useNotify';
|
import useNotify from 'composables/useNotify';
|
||||||
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
const emit = defineEmits(['added']);
|
||||||
|
const route = useRoute();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
prices: {
|
prices: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -16,9 +18,8 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['added']);
|
|
||||||
|
|
||||||
const fields = ref((props.prices || []).map((item) => ({ ...item, quantity: 0 })));
|
const fields = ref((props.prices || []).map((item) => ({ ...item, quantity: 0 })));
|
||||||
|
const descriptorData = useArrayData('orderData');
|
||||||
|
|
||||||
const addToOrder = async () => {
|
const addToOrder = async () => {
|
||||||
const items = (fields.value || []).filter((item) => Number(item.quantity) > 0);
|
const items = (fields.value || []).filter((item) => Number(item.quantity) > 0);
|
||||||
|
@ -28,19 +29,20 @@ const addToOrder = async () => {
|
||||||
});
|
});
|
||||||
notify(t('globals.dataSaved'), 'positive');
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
emit('added');
|
emit('added');
|
||||||
|
descriptorData.fetch({});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container order-catalog-item q-pb-md">
|
<div class="container order-catalog-item q-pa-md">
|
||||||
<QForm @submit="addToOrder">
|
<QForm @submit="addToOrder">
|
||||||
<QMarkupTable class="shadow-0">
|
<QMarkupTable class="shadow-0">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="item in fields" :key="item.warehouse">
|
<tr v-for="item in fields" :key="item.warehouse">
|
||||||
<td class="text-bold q-py-lg">
|
<td class="text-bold q-pr-md td" style="width: 35%">
|
||||||
{{ item.warehouse }}
|
{{ item.warehouse }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="text-right" style="width: 35%">
|
||||||
<span
|
<span
|
||||||
class="link"
|
class="link"
|
||||||
@click="
|
@click="
|
||||||
|
@ -75,8 +77,11 @@ const addToOrder = async () => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.container {
|
// .container {
|
||||||
max-width: 448px;
|
// max-width: 768px;
|
||||||
width: 100%;
|
// width: 100%;
|
||||||
|
// }
|
||||||
|
.td {
|
||||||
|
width: 200px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -4,13 +4,13 @@ import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
|
|
||||||
import useCardDescription from 'src/composables/useCardDescription';
|
import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
|
||||||
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
|
||||||
const DEFAULT_ITEMS = 0;
|
const DEFAULT_ITEMS = 0;
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ const $props = defineProps({
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const data = ref(useCardDescription());
|
||||||
|
const getTotalRef = ref();
|
||||||
|
|
||||||
const entityId = computed(() => {
|
const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
|
@ -57,11 +59,11 @@ const filter = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const data = ref(useCardDescription());
|
|
||||||
const setData = (entity) => {
|
const setData = (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
|
getTotalRef.value && getTotalRef.value.fetch();
|
||||||
data.value = useCardDescription(entity?.client?.name, entity?.id);
|
data.value = useCardDescription(entity?.client?.name, entity?.id);
|
||||||
state.set('OrderDescriptor', entity);
|
state.set('orderData', entity);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConfirmationValue = (isConfirmed) => {
|
const getConfirmationValue = (isConfirmed) => {
|
||||||
|
@ -69,13 +71,17 @@ const getConfirmationValue = (isConfirmed) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const total = ref(null);
|
const total = ref(null);
|
||||||
|
|
||||||
|
function ticketFilter(order) {
|
||||||
|
return JSON.stringify({ id: order.id });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
ref="getTotalRef"
|
||||||
:url="`Orders/${entityId}/getTotal`"
|
:url="`Orders/${entityId}/getTotal`"
|
||||||
@on-fetch="(response) => (total = response)"
|
@on-fetch="(response) => (total = response)"
|
||||||
auto-load
|
|
||||||
/>
|
/>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
|
@ -120,7 +126,7 @@ const total = ref(null);
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="{
|
:to="{
|
||||||
name: 'TicketList',
|
name: 'TicketList',
|
||||||
query: { params: JSON.stringify({ orderFk: entity.id }) },
|
query: { table: ticketFilter(entity) },
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('order.summary.orderTicketList') }}</QTooltip>
|
<QTooltip>{{ t('order.summary.orderTicketList') }}</QTooltip>
|
||||||
|
|
|
@ -21,15 +21,13 @@ const salesPersonFilter = {
|
||||||
fields: ['id', 'nickname'],
|
fields: ['id', 'nickname'],
|
||||||
};
|
};
|
||||||
const salesPersonList = ref(null);
|
const salesPersonList = ref(null);
|
||||||
const sourceFilter = { fields: ['value'] };
|
const sourceList = ref([]);
|
||||||
const sourceList = ref(null);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
url="AgencyModes/isActive"
|
url="AgencyModes/isActive"
|
||||||
:filter="agencyFilter"
|
:filter="agencyFilter"
|
||||||
limit="30"
|
|
||||||
sort-by="name ASC"
|
sort-by="name ASC"
|
||||||
auto-load
|
auto-load
|
||||||
@on-fetch="(data) => (agencyList = data)"
|
@on-fetch="(data) => (agencyList = data)"
|
||||||
|
@ -37,7 +35,6 @@ const sourceList = ref(null);
|
||||||
<FetchData
|
<FetchData
|
||||||
url="Workers/search"
|
url="Workers/search"
|
||||||
:filter="salesPersonFilter"
|
:filter="salesPersonFilter"
|
||||||
limit="30"
|
|
||||||
sort-by="nickname ASC"
|
sort-by="nickname ASC"
|
||||||
@on-fetch="(data) => (salesPersonList = data)"
|
@on-fetch="(data) => (salesPersonList = data)"
|
||||||
:params="{ departmentCodes: ['VT'] }"
|
:params="{ departmentCodes: ['VT'] }"
|
||||||
|
@ -45,8 +42,7 @@ const sourceList = ref(null);
|
||||||
/>
|
/>
|
||||||
<FetchData
|
<FetchData
|
||||||
url="Orders/getSourceValues"
|
url="Orders/getSourceValues"
|
||||||
:filter="sourceFilter"
|
:filter="{ fields: ['value'] }"
|
||||||
limit="30"
|
|
||||||
sort-by="value ASC"
|
sort-by="value ASC"
|
||||||
@on-fetch="(data) => (sourceList = data)"
|
@on-fetch="(data) => (sourceList = data)"
|
||||||
auto-load
|
auto-load
|
||||||
|
@ -59,56 +55,34 @@ const sourceList = ref(null);
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ params }">
|
<template #body="{ params }">
|
||||||
<QItem>
|
<div class="q-px-md q-gutter-y-sm">
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
<VnInput
|
||||||
is-outlined
|
|
||||||
:label="t('customerId')"
|
:label="t('customerId')"
|
||||||
v-model="params.clientFk"
|
v-model="params.clientFk"
|
||||||
lazy-rules
|
lazy-rules
|
||||||
>
|
dense
|
||||||
<template #prepend>
|
outlined
|
||||||
<QIcon name="badge" size="sm"></QIcon>
|
rounded
|
||||||
</template>
|
/>
|
||||||
</VnInput>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection v-if="agencyList">
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('agency')"
|
:label="t('agency')"
|
||||||
v-model="params.agencyModeFk"
|
v-model="params.agencyModeFk"
|
||||||
:options="agencyList"
|
:options="agencyList"
|
||||||
option-value="id"
|
:input-debounce="0"
|
||||||
option-label="name"
|
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
use-input
|
|
||||||
:input-debounce="0"
|
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
<QItemSection v-else>
|
|
||||||
<QSkeleton type="QInput" class="full-width" />
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection v-if="salesPersonList">
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('salesPerson')"
|
:label="t('salesPerson')"
|
||||||
v-model="params.workerFk"
|
v-model="params.workerFk"
|
||||||
:options="salesPersonList"
|
url="Workers/search"
|
||||||
option-value="id"
|
:filter="{ departmentCodes: ['VT'] }"
|
||||||
option-label="name"
|
sort-by="nickname ASC"
|
||||||
|
option-label="nickname"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
use-input
|
|
||||||
:input-debounce="0"
|
|
||||||
>
|
>
|
||||||
<template #option="{ itemProps, opt }">
|
<template #option="{ itemProps, opt }">
|
||||||
<QItem v-bind="itemProps">
|
<QItem v-bind="itemProps">
|
||||||
|
@ -121,13 +95,6 @@ const sourceList = ref(null);
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
</QItemSection>
|
|
||||||
<QItemSection v-else>
|
|
||||||
<QSkeleton type="QInput" class="full-width" />
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
v-model="params.from"
|
v-model="params.from"
|
||||||
:label="t('fromLanded')"
|
:label="t('fromLanded')"
|
||||||
|
@ -135,10 +102,6 @@ const sourceList = ref(null);
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
v-model="params.to"
|
v-model="params.to"
|
||||||
:label="t('toLanded')"
|
:label="t('toLanded')"
|
||||||
|
@ -146,61 +109,34 @@ const sourceList = ref(null);
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('orderId')"
|
:label="t('orderId')"
|
||||||
v-model="params.orderFk"
|
v-model="params.orderFk"
|
||||||
lazy-rules
|
lazy-rules
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection v-if="sourceList">
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('application')"
|
:label="t('application')"
|
||||||
v-model="params.sourceApp"
|
v-model="params.sourceApp"
|
||||||
:options="sourceList"
|
:options="sourceList"
|
||||||
option-label="value"
|
option-label="value"
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
use-input
|
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
:input-debounce="0"
|
:input-debounce="0"
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
<QItemSection v-else>
|
|
||||||
<QSkeleton type="QInput" class="full-width" />
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
v-model="params.myTeam"
|
v-model="params.myTeam"
|
||||||
:label="t('myTeam')"
|
:label="t('myTeam')"
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
v-model="params.isConfirmed"
|
v-model="params.isConfirmed"
|
||||||
:label="t('isConfirmed')"
|
:label="t('isConfirmed')"
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox v-model="params.showEmpty" :label="t('showEmpty')" />
|
<QCheckbox v-model="params.showEmpty" :label="t('showEmpty')" />
|
||||||
</QItemSection>
|
</div>
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
</VnFilterPanel>
|
</VnFilterPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, watch } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
|
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
|
||||||
import axios from 'axios';
|
|
||||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import FetchData from 'src/components/FetchData.vue';
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
import VnImg from 'src/components/ui/VnImg.vue';
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const descriptorData = useArrayData('orderData');
|
||||||
const componentKey = ref(0);
|
const componentKey = ref(0);
|
||||||
const tableLinesRef = ref();
|
const tableLinesRef = ref();
|
||||||
const order = ref();
|
const order = ref();
|
||||||
|
@ -25,6 +28,8 @@ const orderSummary = ref({
|
||||||
total: null,
|
total: null,
|
||||||
vat: null,
|
vat: null,
|
||||||
});
|
});
|
||||||
|
const getTotalRef = ref();
|
||||||
|
const getVATRef = ref();
|
||||||
|
|
||||||
const lineFilter = ref({
|
const lineFilter = ref({
|
||||||
include: [
|
include: [
|
||||||
|
@ -59,6 +64,13 @@ const lineFilter = ref({
|
||||||
fields: ['id', 'name'],
|
fields: ['id', 'name'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
relation: 'order',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'isConfirmed'],
|
||||||
|
where: { id: route.params.id },
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
where: { orderFk: route.params.id },
|
where: { orderFk: route.params.id },
|
||||||
});
|
});
|
||||||
|
@ -104,6 +116,7 @@ const columns = computed(() => [
|
||||||
component: null,
|
component: null,
|
||||||
},
|
},
|
||||||
format: (row) => row?.item?.name,
|
format: (row) => row?.item?.name,
|
||||||
|
columnClass: 'expand',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -147,7 +160,6 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
label: t('lines.amount'),
|
label: t('lines.amount'),
|
||||||
format: (row) => toCurrency(row.amount),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'right',
|
align: 'right',
|
||||||
|
@ -155,8 +167,9 @@ const columns = computed(() => [
|
||||||
name: 'tableActions',
|
name: 'tableActions',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
title: t('delete'),
|
title: t('Delete'),
|
||||||
icon: 'delete',
|
icon: 'delete',
|
||||||
|
show: (row) => !row.order.isConfirmed,
|
||||||
action: (row) => confirmRemove(row),
|
action: (row) => confirmRemove(row),
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
},
|
},
|
||||||
|
@ -185,6 +198,9 @@ async function remove(item) {
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
tableLinesRef.value.reload();
|
tableLinesRef.value.reload();
|
||||||
alexm marked this conversation as resolved
Outdated
alexm
commented
Crec que vaig ficar una cosa per a que detectara els canvis del filter, comprova si encara cal este codi Crec que vaig ficar una cosa per a que detectara els canvis del filter, comprova si encara cal este codi
jon
commented
He probado a eliminarlo y sin el watch solo cambia lo que muestra el descriptor He probado a eliminarlo y sin el watch solo cambia lo que muestra el descriptor
|
|||||||
|
descriptorData.fetch({});
|
||||||
|
getTotalRef.value.fetch();
|
||||||
|
getVATRef.value.fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function confirmOrder() {
|
async function confirmOrder() {
|
||||||
|
@ -193,7 +209,22 @@ async function confirmOrder() {
|
||||||
message: t('globals.confirm'),
|
message: t('globals.confirm'),
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
|
router.push({
|
||||||
|
name: 'TicketList',
|
||||||
|
query: {
|
||||||
|
table: JSON.stringify({ clientFk: descriptorData.store.data.clientFk }),
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => router.currentRoute.value.params.id,
|
||||||
|
() => {
|
||||||
|
lineFilter.value.where.orderFk = router.currentRoute.value.params.id;
|
||||||
|
|
||||||
|
tableLinesRef.value.reload();
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -204,44 +235,36 @@ async function confirmOrder() {
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
ref="getTotalRef"
|
||||||
:key="componentKey"
|
:key="componentKey"
|
||||||
:url="`Orders/${route.params.id}/getTotal`"
|
:url="`Orders/${route.params.id}/getTotal`"
|
||||||
@on-fetch="(data) => (orderSummary.total = data)"
|
@on-fetch="(data) => (orderSummary.total = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
ref="getVATRef"
|
||||||
:key="componentKey"
|
:key="componentKey"
|
||||||
:url="`Orders/${route.params.id}/getVAT`"
|
:url="`Orders/${route.params.id}/getVAT`"
|
||||||
@on-fetch="(data) => (orderSummary.vat = data)"
|
@on-fetch="(data) => (orderSummary.vat = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<QDrawer side="right" :width="270" v-model="stateStore.rightDrawer">
|
<QDrawer side="right" :width="270" v-model="stateStore.rightDrawer">
|
||||||
<QCard class="order-lines-summary q-pa-lg">
|
<QCard
|
||||||
|
class="order-lines-summary q-pa-lg"
|
||||||
|
v-if="orderSummary.vat && orderSummary.total"
|
||||||
|
>
|
||||||
<p class="header text-right block">
|
<p class="header text-right block">
|
||||||
{{ t('summary') }}
|
{{ t('summary') }}
|
||||||
</p>
|
</p>
|
||||||
<VnLv
|
<VnLv
|
||||||
v-if="orderSummary.vat && orderSummary.total"
|
|
||||||
:label="t('subtotal') + ': '"
|
:label="t('subtotal') + ': '"
|
||||||
:value="toCurrency(orderSummary.total - orderSummary.vat)"
|
:value="toCurrency(orderSummary.total - orderSummary.vat)"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv :label="t('VAT') + ': '" :value="toCurrency(orderSummary?.vat)" />
|
||||||
v-if="orderSummary.vat"
|
<VnLv :label="t('total') + ': '" :value="toCurrency(orderSummary?.total)" />
|
||||||
:label="t('VAT') + ': '"
|
|
||||||
:value="toCurrency(orderSummary?.vat)"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
v-if="orderSummary.total"
|
|
||||||
:label="t('total') + ': '"
|
|
||||||
:value="toCurrency(orderSummary?.total)"
|
|
||||||
/>
|
|
||||||
</QCard>
|
</QCard>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
<QPage :key="componentKey" class="column items-center">
|
|
||||||
<div class="order-list full-width">
|
|
||||||
<div v-if="!orderSummary.total" class="no-result">
|
|
||||||
{{ t('globals.noResults') }}
|
|
||||||
</div>
|
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableLinesRef"
|
ref="tableLinesRef"
|
||||||
data-key="OrderLines"
|
data-key="OrderLines"
|
||||||
|
@ -267,15 +290,25 @@ async function confirmOrder() {
|
||||||
</div>
|
</div>
|
||||||
<FetchedTags :item="row?.item" :max-length="6" />
|
<FetchedTags :item="row?.item" :max-length="6" />
|
||||||
</template>
|
</template>
|
||||||
|
<template #column-amount="{ row }">
|
||||||
|
{{ toCurrency(row.quantity * row.price) }}
|
||||||
|
</template>
|
||||||
|
<template #column-tableActions="{ row }">
|
||||||
|
<QIcon
|
||||||
|
v-if="row.order?.isConfirmed === 0"
|
||||||
|
name="delete"
|
||||||
|
icon="delete"
|
||||||
|
@click="confirmRemove(row)"
|
||||||
|
class="cursor-pointer"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
</div>
|
|
||||||
<QPageSticky :offset="[20, 20]" v-if="!order?.isConfirmed" style="z-index: 2">
|
<QPageSticky :offset="[20, 20]" v-if="!order?.isConfirmed" style="z-index: 2">
|
||||||
<QBtn fab icon="check" color="primary" @click="confirmOrder()" />
|
<QBtn fab icon="check" color="primary" @click="confirmOrder()" />
|
||||||
<QTooltip>
|
<QTooltip>
|
||||||
{{ t('confirm') }}
|
{{ t('confirm') }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QPageSticky>
|
</QPageSticky>
|
||||||
</QPage>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
|
@ -180,9 +180,10 @@ const detailsColumns = ref([
|
||||||
<ItemDescriptorProxy :id="props.row.item?.id" />
|
<ItemDescriptorProxy :id="props.row.item?.id" />
|
||||||
</span>
|
</span>
|
||||||
</QTd>
|
</QTd>
|
||||||
<QTd key="description" :props="props" class="description">
|
<QTd key="description" :props="props">
|
||||||
|
<div class="description">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<span>{{ props.row.item.name }}</span>
|
{{ props.row.item.name }}
|
||||||
<span
|
<span
|
||||||
v-if="props.row.item.subName"
|
v-if="props.row.item.subName"
|
||||||
class="subName"
|
class="subName"
|
||||||
|
@ -190,6 +191,7 @@ const detailsColumns = ref([
|
||||||
{{ props.row.item.subName }}
|
{{ props.row.item.subName }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<FetchedTags :item="props.row.item" :max-length="5" />
|
<FetchedTags :item="props.row.item" :max-length="5" />
|
||||||
</QTd>
|
</QTd>
|
||||||
<QTd key="quantity" :props="props">
|
<QTd key="quantity" :props="props">
|
||||||
|
@ -228,24 +230,13 @@ const detailsColumns = ref([
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
height: auto;
|
padding-top: 15px;
|
||||||
padding-top: 12px;
|
padding-bottom: 15px;
|
||||||
padding-bottom: 12px;
|
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subName {
|
.subName {
|
||||||
|
margin-left: 5%;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--vn-label-color);
|
color: var(--vn-label-color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { dashIfEmpty } from 'src/filters';
|
||||||
|
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
|
import ItemDescriptorProxy from 'pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const volumeSummary = ref(null);
|
||||||
|
const volumeRef = ref();
|
||||||
|
const volumes = ref([]);
|
||||||
|
const volumeFilter = ref({
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'item',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
where: { orderFk: route.params.id },
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'itemFk',
|
||||||
|
label: t('item'),
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: t('globals.description'),
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'quantity',
|
||||||
|
label: t('quantity'),
|
||||||
alexm
commented
Crec que vaig ficar una cosa per a que detectara els canvis del filter, comprova si encara cal este codi Crec que vaig ficar una cosa per a que detectara els canvis del filter, comprova si encara cal este codi
|
|||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'volume',
|
||||||
|
label: t('volume'),
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const loadVolumes = async (rows) => {
|
||||||
|
if (!rows) return;
|
||||||
|
const { data } = await axios.get(`Orders/${route.params.id}/getVolumes`);
|
||||||
|
rows.forEach((order) => {
|
||||||
|
(data.volumes || []).forEach((volume) => {
|
||||||
|
if (order.itemFk === volume.itemFk) order.volume = volume.volume;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
volumes.value = rows;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FetchData
|
||||||
|
:url="`Orders/${route.params.id}/getTotalVolume`"
|
||||||
|
@on-fetch="(data) => (volumeSummary = data)"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<QCard v-if="volumeSummary" class="order-volume-summary q-pa-lg">
|
||||||
|
<VnLv :label="t('total')" :value="`${volumeSummary?.totalVolume} m³`" />
|
||||||
|
<VnLv
|
||||||
|
:label="t('boxes')"
|
||||||
|
:value="`${dashIfEmpty(volumeSummary?.totalBoxes)} U`"
|
||||||
|
/>
|
||||||
|
</QCard>
|
||||||
|
<VnTable
|
||||||
|
ref="volumeRef"
|
||||||
|
data-key="OrderCatalogVolume"
|
||||||
|
url="OrderRows"
|
||||||
|
:columns="columns"
|
||||||
|
auto-load
|
||||||
|
:user-filter="volumeFilter"
|
||||||
|
order="itemFk"
|
||||||
|
@on-fetch="(data) => loadVolumes(data)"
|
||||||
|
:right-search="false"
|
||||||
|
:column-search="false"
|
||||||
|
>
|
||||||
|
<template #column-itemFk="{ row }">
|
||||||
|
<span class="link">
|
||||||
|
{{ row.itemFk }}
|
||||||
|
<ItemDescriptorProxy :id="row.itemFk" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-description="{ row }">
|
||||||
|
<FetchedTags :item="row.item" :max-length="5" />
|
||||||
|
</template>
|
||||||
|
<template #column-volume="{ rowIndex }">
|
||||||
|
{{ volumes?.[rowIndex]?.volume }}
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.order-volume-summary {
|
||||||
|
.vn-label-value {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 2%;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--vn-label-color);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
summary: Summary
|
||||||
|
total: Total
|
||||||
|
boxes: Boxes
|
||||||
|
item: Item
|
||||||
|
quantity: Quantity
|
||||||
|
volume: m³ per quantity
|
||||||
|
es:
|
||||||
|
summary: Resumen
|
||||||
|
total: Total
|
||||||
|
boxes: Cajas
|
||||||
|
item: Artículo
|
||||||
|
quantity: Cantidad
|
||||||
|
volume: m³ por cantidad
|
||||||
|
</i18n>
|
|
@ -3,19 +3,21 @@ import axios from 'axios';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
|
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
|
||||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
|
||||||
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import OrderSearchbar from './Card/OrderSearchbar.vue';
|
||||||
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
|
import OrderFilter from './Card/OrderFilter.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const clientList = ref([]);
|
|
||||||
const agencyList = ref([]);
|
const agencyList = ref([]);
|
||||||
const selectedAddress = ref();
|
const addressesList = ref([]);
|
||||||
|
const clientId = ref();
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
|
@ -29,7 +31,7 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'clientName',
|
name: 'clientFk',
|
||||||
label: t('module.customer'),
|
label: t('module.customer'),
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
|
@ -41,20 +43,26 @@ const columns = computed(() => [
|
||||||
columnField: {
|
columnField: {
|
||||||
component: null,
|
component: null,
|
||||||
},
|
},
|
||||||
|
format: (row) => row?.clientName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'name',
|
name: 'salesPersonFk',
|
||||||
label: t('module.salesPerson'),
|
label: t('module.salesPerson'),
|
||||||
|
columnFilter: {
|
||||||
component: 'select',
|
component: 'select',
|
||||||
|
inWhere: true,
|
||||||
attrs: {
|
attrs: {
|
||||||
url: 'Workers/activeWithInheritedRole',
|
url: 'Workers/activeWithInheritedRole',
|
||||||
fields: ['id', 'name'],
|
fields: ['id', 'name'],
|
||||||
where: { role: 'salesPerson' },
|
where: { role: 'salesPerson' },
|
||||||
|
useLike: false,
|
||||||
|
optionValue: 'id',
|
||||||
|
optionLabel: 'name',
|
||||||
|
optionFilter: 'firstName',
|
||||||
},
|
},
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
},
|
||||||
|
format: (row) => row?.name,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -92,18 +100,22 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'agencyName',
|
name: 'agencyModeFk',
|
||||||
label: t('module.agency'),
|
label: t('module.agency'),
|
||||||
|
format: (row) => row?.agencyName,
|
||||||
|
columnFilter: {
|
||||||
component: 'select',
|
component: 'select',
|
||||||
cardVisible: true,
|
|
||||||
attrs: {
|
attrs: {
|
||||||
url: 'Agencies',
|
url: 'agencyModes',
|
||||||
fields: ['id', 'name'],
|
fields: ['id', 'name'],
|
||||||
|
find: {
|
||||||
|
value: 'agencyModeFk',
|
||||||
|
label: 'agencyName',
|
||||||
},
|
},
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'total',
|
name: 'total',
|
||||||
|
@ -125,22 +137,36 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
async function fetchClientAddress(id, data) {
|
async function fetchClientAddress(id, formData) {
|
||||||
const clientData = await axios.get(`Clients/${id}`);
|
const { data } = await axios.get(`Clients/${id}`, {
|
||||||
selectedAddress.value = clientData.data.defaultAddressFk;
|
params: { filter: { include: { relation: 'addresses' } } },
|
||||||
data.addressId = selectedAddress.value;
|
});
|
||||||
|
addressesList.value = data.addresses;
|
||||||
|
formData.addressId = data.defaultAddressFk;
|
||||||
|
fetchAgencies(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchAgencies({ landed, addressId }) {
|
||||||
|
if (!landed || !addressId) return (agencyList.value = []);
|
||||||
|
|
||||||
|
const { data } = await axios.get('Agencies/landsThatDay', {
|
||||||
|
params: { addressFk: addressId, landed },
|
||||||
|
});
|
||||||
|
agencyList.value = data;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnSearchbar
|
<OrderSearchbar />
|
||||||
data-key="OrderList"
|
<RightMenu>
|
||||||
:label="t('Search order')"
|
<template #right-panel>
|
||||||
:info="t('You can search orders by reference')"
|
<OrderFilter data-key="OrderList" />
|
||||||
/>
|
</template>
|
||||||
|
</RightMenu>
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="OrderList"
|
data-key="OrderList"
|
||||||
url="Orders/filter"
|
url="Orders/filter"
|
||||||
|
:order="['landed DESC', 'clientFk ASC', 'id DESC']"
|
||||||
:create="{
|
:create="{
|
||||||
urlCreate: 'Orders/new',
|
urlCreate: 'Orders/new',
|
||||||
title: 'Create Order',
|
title: 'Create Order',
|
||||||
|
@ -152,36 +178,49 @@ async function fetchClientAddress(id, data) {
|
||||||
addressId: null,
|
addressId: null,
|
||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
|
:user-params="{ showEmpty: false }"
|
||||||
|
:right-search="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
redirect="order"
|
redirect="order"
|
||||||
auto-load
|
|
||||||
>
|
>
|
||||||
<template #more-create-dialog="{ data }">
|
<template #more-create-dialog="{ data }">
|
||||||
<VnSelect
|
<VnSelect
|
||||||
url="Clients"
|
url="Clients"
|
||||||
v-model="data.id"
|
:include="{ relation: 'addresses' }"
|
||||||
|
v-model="clientId"
|
||||||
:label="t('module.customer')"
|
:label="t('module.customer')"
|
||||||
:options="clientList"
|
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
@update:model-value="(id) => fetchClientAddress(id, data)"
|
@update:model-value="(id) => fetchClientAddress(id, data)"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
url="Clients"
|
v-model="data.addressId"
|
||||||
v-model="selectedAddress"
|
:options="addressesList"
|
||||||
:label="t('module.address')"
|
:label="t('module.address')"
|
||||||
:options="selectedAddress"
|
option-value="id"
|
||||||
option-value="defaultAddressFk"
|
option-label="nickname"
|
||||||
option-label="street"
|
@update:model-value="() => fetchAgencies(data)"
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>
|
||||||
|
{{ scope.opt?.nickname }}: {{ scope.opt?.street }},
|
||||||
|
{{ scope.opt?.city }}</QItemLabel
|
||||||
|
>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
<VnInputDate
|
||||||
|
v-model="data.landed"
|
||||||
|
:label="t('module.landed')"
|
||||||
|
@update:model-value="() => fetchAgencies(data)"
|
||||||
/>
|
/>
|
||||||
<VnInputDate v-model="data.landed" :label="t('module.landed')" />
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
url="Agencies"
|
|
||||||
v-model="data.agencyModeId"
|
v-model="data.agencyModeId"
|
||||||
:label="t('module.agency')"
|
:label="t('module.agency')"
|
||||||
:options="agencyList"
|
:options="agencyList"
|
||||||
option-value="id"
|
option-value="agencyModeFk"
|
||||||
option-label="name"
|
option-label="agencyMode"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
|
||||||
import CardList from 'components/ui/CardList.vue';
|
|
||||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
|
||||||
|
|
||||||
import { dashIfEmpty } from 'src/filters';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const { t } = useI18n();
|
|
||||||
const volumeSummary = ref(null);
|
|
||||||
|
|
||||||
const loadVolumes = async (rows) => {
|
|
||||||
const { data } = await axios.get(`Orders/${route.params.id}/getVolumes`);
|
|
||||||
(rows || []).forEach((order) => {
|
|
||||||
(data.volumes || []).forEach((volume) => {
|
|
||||||
if (order.itemFk === volume.itemFk) {
|
|
||||||
order.volume = volume.volume;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<FetchData
|
|
||||||
:url="`Orders/${route.params.id}/getTotalVolume`"
|
|
||||||
@on-fetch="(data) => (volumeSummary = data)"
|
|
||||||
auto-load
|
|
||||||
/>
|
|
||||||
<QPage class="column items-center q-pa-md">
|
|
||||||
<div class="vn-card-list">
|
|
||||||
<div
|
|
||||||
v-if="!volumeSummary?.totalVolume && !volumeSummary?.totalBoxes"
|
|
||||||
class="no-result"
|
|
||||||
>
|
|
||||||
{{ t('globals.noResults') }}
|
|
||||||
</div>
|
|
||||||
<QCard v-else class="order-volume-summary q-pa-lg">
|
|
||||||
<p class="header text-right block">
|
|
||||||
{{ t('summary') }}
|
|
||||||
</p>
|
|
||||||
<VnLv :label="t('total')" :value="`${volumeSummary?.totalVolume} m³`" />
|
|
||||||
<VnLv
|
|
||||||
:label="t('boxes')"
|
|
||||||
:value="`${dashIfEmpty(volumeSummary?.totalBoxes)} U`"
|
|
||||||
/>
|
|
||||||
</QCard>
|
|
||||||
<VnPaginate
|
|
||||||
data-key="OrderCatalogVolume"
|
|
||||||
url="OrderRows"
|
|
||||||
:limit="20"
|
|
||||||
auto-load
|
|
||||||
:filter="{
|
|
||||||
include: {
|
|
||||||
relation: 'item',
|
|
||||||
},
|
|
||||||
where: { orderFk: route.params.id },
|
|
||||||
}"
|
|
||||||
order="itemFk"
|
|
||||||
@on-fetch="(data) => loadVolumes(data)"
|
|
||||||
>
|
|
||||||
<template #body="{ rows }">
|
|
||||||
<div class="catalog-list q-mt-xl">
|
|
||||||
<CardList
|
|
||||||
v-for="row in rows"
|
|
||||||
:key="row.id"
|
|
||||||
:id="row.id"
|
|
||||||
:title="row?.item?.name"
|
|
||||||
class="cursor-inherit"
|
|
||||||
>
|
|
||||||
<template #list-items>
|
|
||||||
<div class="q-mb-sm">
|
|
||||||
<FetchedTags :item="row.item" :max-length="5" />
|
|
||||||
</div>
|
|
||||||
<VnLv :label="t('item')" :value="row.item.id" />
|
|
||||||
<VnLv :label="t('subName')">
|
|
||||||
<template #value>
|
|
||||||
<span class="text-uppercase">
|
|
||||||
{{ row.item.subName }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</VnLv>
|
|
||||||
<VnLv :label="t('quantity')" :value="row.quantity" />
|
|
||||||
<VnLv :label="t('volume')" :value="row.volume" />
|
|
||||||
</template>
|
|
||||||
</CardList>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</VnPaginate>
|
|
||||||
</div>
|
|
||||||
</QPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.order-volume-summary {
|
|
||||||
.vn-label-value {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 2%;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
color: var(--vn-label-color);
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.header {
|
|
||||||
color: $primary;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
font-size: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-result {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--vn-label-color);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<i18n>
|
|
||||||
en:
|
|
||||||
summary: Summary
|
|
||||||
total: Total
|
|
||||||
boxes: Boxes
|
|
||||||
item: Item
|
|
||||||
subName: Subname
|
|
||||||
quantity: Quantity
|
|
||||||
volume: m³ per quantity
|
|
||||||
es:
|
|
||||||
summary: Resumen
|
|
||||||
total: Total
|
|
||||||
boxes: Cajas
|
|
||||||
item: Artículo
|
|
||||||
subName: Subname
|
|
||||||
quantity: Cantidad
|
|
||||||
volume: m³ por cantidad
|
|
||||||
</i18n>
|
|
|
@ -63,7 +63,7 @@ export default {
|
||||||
title: 'basicData',
|
title: 'basicData',
|
||||||
icon: 'vn:settings',
|
icon: 'vn:settings',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Order/Card/OrderForm.vue'),
|
component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'OrderCatalog',
|
name: 'OrderCatalog',
|
||||||
|
@ -72,7 +72,7 @@ export default {
|
||||||
title: 'catalog',
|
title: 'catalog',
|
||||||
icon: 'vn:basket',
|
icon: 'vn:basket',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Order/OrderCatalog.vue'),
|
component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'OrderVolume',
|
name: 'OrderVolume',
|
||||||
|
@ -81,7 +81,7 @@ export default {
|
||||||
title: 'volume',
|
title: 'volume',
|
||||||
icon: 'vn:volume',
|
icon: 'vn:volume',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Order/OrderVolume.vue'),
|
component: () => import('src/pages/Order/Card/OrderVolume.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'OrderLines',
|
name: 'OrderLines',
|
||||||
|
@ -90,7 +90,7 @@ export default {
|
||||||
title: 'lines',
|
title: 'lines',
|
||||||
icon: 'vn:lines',
|
icon: 'vn:lines',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Order/OrderLines.vue'),
|
component: () => import('src/pages/Order/Card/OrderLines.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
esta función está sin uso