Merge branch 'master' of https://gitea.verdnatura.es/verdnatura/salix-front into Hotfix-ZoneLocationsTree
gitea/salix-front/pipeline/pr-master This commit looks good Details

This commit is contained in:
Jon Elias 2024-11-18 09:48:02 +01:00
commit a64575c7cc
25 changed files with 282 additions and 167 deletions

View File

@ -38,7 +38,7 @@ const onDataSaved = (dataSaved) => {
@on-fetch="(data) => (warehousesOptions = data)"
auto-load
url="Warehouses"
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
/>
<FetchData
@on-fetch="(data) => (temperaturesOptions = data)"

View File

@ -247,6 +247,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
}
function updateStateParams() {
if (!route?.path) return;
const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);

View File

@ -5,7 +5,7 @@ import { useRoute } from 'vue-router';
import { useAcl } from 'src/composables/useAcl';
import axios from 'axios';
import { useQuasar } from 'quasar';
import FetchData from 'components/FetchData.vue';
import { getClientRisk } from '../composables/getClientRisk';
import { toCurrency, toDate, toDateHourMin } from 'src/filters';
import { useState } from 'composables/useState';
@ -16,7 +16,7 @@ import { useVnConfirm } from 'composables/useVnConfirm';
import VnTable from 'components/VnTable/VnTable.vue';
import VnInput from 'components/common/VnInput.vue';
import VnSubToolbar from 'components/ui/VnSubToolbar.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnFilter from 'components/VnTable/VnFilter.vue';
import CustomerNewPayment from 'src/pages/Customer/components/CustomerNewPayment.vue';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
@ -25,7 +25,7 @@ const { openConfirmationModal } = useVnConfirm();
const { sendEmail, openReport } = usePrintService();
const { t } = useI18n();
const { hasAny } = useAcl();
const currentBalance = ref({});
const quasar = useQuasar();
const route = useRoute();
const state = useState();
@ -33,28 +33,53 @@ const stateStore = useStateStore();
const user = state.getUser();
const clientRisk = ref([]);
const companies = ref([]);
const tableRef = ref();
const companyId = ref(user.value.companyFk);
const companyId = ref();
const companyUser = ref(user.value.companyFk);
const balances = ref([]);
const vnFilterRef = ref({});
const filter = computed(() => {
return {
clientId: route.params.id,
companyId: companyId.value ?? user.value.companyFk,
companyId: companyId.value ?? companyUser.value,
};
});
const companyFilterColumn = {
align: 'left',
name: 'companyId',
label: t('Company'),
component: 'select',
attrs: {
url: 'Companies',
optionLabel: 'code',
optionValue: 'id',
sortBy: 'code',
},
columnFilter: {
event: {
remove: () => (companyId.value = null),
'update:modelValue': (newCompanyFk) => {
if (!newCompanyFk) return;
vnFilterRef.value.addFilter(newCompanyFk);
companyUser.value = newCompanyFk;
},
blur: () => !companyId.value && (companyId.value = companyUser.value),
},
},
visible: false,
};
const columns = computed(() => [
{
align: 'right',
align: 'left',
name: 'payed',
label: t('Date'),
format: ({ payed }) => toDate(payed),
cardVisible: true,
},
{
align: 'right',
align: 'left',
name: 'created',
label: t('Creation date'),
format: ({ created }) => toDateHourMin(created),
@ -65,7 +90,12 @@ const columns = computed(() => [
label: t('Employee'),
columnField: {
component: 'userLink',
attrs: ({ row }) => ({ workerId: row.workerFk, name: row.userName }),
attrs: ({ row }) => {
return {
workerId: row.workerFk,
name: row.userName,
};
},
},
cardVisible: true,
},
@ -77,13 +107,13 @@ const columns = computed(() => [
class: 'extend',
},
{
align: 'right',
align: 'left',
name: 'bankFk',
label: t('Bank'),
cardVisible: true,
},
{
align: 'right',
align: 'left',
name: 'debit',
label: t('Debit'),
format: ({ debit }) => debit && toCurrency(debit),
@ -136,20 +166,37 @@ const columns = computed(() => [
onBeforeMount(() => {
stateStore.rightDrawer = true;
companyId.value = companyUser.value;
});
async function getCurrentBalance(data) {
currentBalance.value[companyId.value] = {
amount: 0,
code: companies.value.find((c) => c.id === companyId.value)?.code,
async function getClientRisks() {
const filter = {
where: { clientFk: route.params.id, companyFk: companyUser.value },
};
const { data } = await getClientRisk(filter);
clientRisk.value = data;
return clientRisk.value;
}
for (const balance of data) {
currentBalance.value[balance.companyFk] = {
code: balance.company.code,
amount: balance.amount,
};
async function getCurrentBalance() {
const currentBalance = (await getClientRisks()).find((balance) => {
return balance.companyFk === companyId.value;
});
return currentBalance && currentBalance.amount;
}
async function onFetch(data) {
balances.value = [];
for (const [index, balance] of data.entries()) {
if (index === 0) {
balance.balance = await getCurrentBalance();
continue;
}
const previousBalance = data[index - 1];
balance.balance =
previousBalance?.balance - (previousBalance?.debit - previousBalance?.credit);
}
balances.value = data;
}
const showNewPaymentDialog = () => {
@ -169,43 +216,25 @@ const showBalancePdf = ({ id }) => {
</script>
<template>
<FetchData
url="Companies"
auto-load
@on-fetch="(data) => (companies = data)"
></FetchData>
<FetchData
v-if="companies.length > 0"
url="clientRisks"
:filter="{
include: { relation: 'company', scope: { fields: ['code'] } },
where: { clientFk: route.params.id },
}"
auto-load
@on-fetch="getCurrentBalance"
></FetchData>
<VnSubToolbar class="q-mb-md">
<template #st-data>
<div class="column justify-center q-px-md q-py-sm">
<span class="text-bold">{{ t('Total by company') }}</span>
<div class="row justify-center">
{{ currentBalance[companyId]?.code }}:
{{ toCurrency(currentBalance[companyId]?.amount) }}
<div class="row justify-center" v-if="clientRisk?.length">
{{ clientRisk[0].company.code }}:
{{ toCurrency(clientRisk[0].amount) }}
</div>
</div>
</template>
<template #st-actions>
<div>
<VnSelect
:label="t('Company')"
<VnFilter
ref="vnFilterRef"
v-model="companyId"
data-key="CustomerBalance"
:options="companies"
option-label="code"
option-value="id"
></VnSelect>
:column="companyFilterColumn"
search-url="balance"
/>
</div>
</template>
</VnSubToolbar>
@ -219,6 +248,7 @@ const showBalancePdf = ({ id }) => {
:right-search="false"
:is-editable="false"
:column-search="false"
@on-fetch="onFetch"
:disable-option="{ card: true }"
auto-load
>

View File

@ -37,6 +37,9 @@ const entityId = computed(() => {
const data = ref(useCardDescription());
const setData = (entity) => (data.value = useCardDescription(entity?.name, entity?.id));
const debtWarning = computed(() => {
return customer.value?.debt > customer.value?.credit ? 'negative' : 'primary';
});
</script>
<template>
@ -111,7 +114,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
v-if="customer.debt > customer.credit"
name="vn:risk"
size="xs"
color="primary"
:color="debtWarning"
>
<QTooltip>{{ t('customer.card.hasDebt') }}</QTooltip>
</QIcon>

View File

@ -8,9 +8,6 @@ import { useQuasar } from 'quasar';
import useNotify from 'src/composables/useNotify';
import VnSmsDialog from 'src/components/common/VnSmsDialog.vue';
import TicketCreateDialog from 'src/pages/Ticket/TicketCreateDialog.vue';
import OrderCreateDialog from 'src/pages/Order/Card/OrderCreateDialog.vue';
import { ref } from 'vue';
const $props = defineProps({
customer: {
@ -28,7 +25,7 @@ const showSmsDialog = () => {
quasar.dialog({
component: VnSmsDialog,
componentProps: {
phone: $props.customer.phone || $props.customer.mobile,
phone: $props.customer.mobile || $props.customer.phone,
promise: sendSms,
},
});
@ -44,13 +41,38 @@ const sendSms = async (payload) => {
}
};
const ticketCreateFormDialog = ref(null);
const openTicketCreateForm = () => {
ticketCreateFormDialog.value.show();
const query = {
table: {
clientFk: $props.customer.id,
},
createForm: {
clientId: $props.customer.id,
addressId: $props.customer.defaultAddressFk,
},
};
openWindow('ticket', query);
};
const orderCreateFormDialog = ref(null);
const openOrderCreateForm = () => {
orderCreateFormDialog.value.show();
const query = {
table: {
clientFk: $props.customer.id,
},
createForm: {
clientFk: $props.customer.id,
addressId: $props.customer.defaultAddressFk,
},
};
openWindow('order', query);
};
const openWindow = (type, { createForm, table }) => {
window.open(
`/#/${type}/list?createForm=${JSON.stringify(createForm)}&table=${JSON.stringify(
table
)}`,
'_blank'
);
};
</script>
@ -58,17 +80,11 @@ const openOrderCreateForm = () => {
<QItem v-ripple clickable @click="openTicketCreateForm()">
<QItemSection>
{{ t('globals.pageTitles.createTicket') }}
<QDialog ref="ticketCreateFormDialog">
<TicketCreateDialog />
</QDialog>
</QItemSection>
</QItem>
<QItem v-ripple clickable @click="openOrderCreateForm()">
<QItemSection>
{{ t('globals.pageTitles.createOrder') }}
<QDialog ref="orderCreateFormDialog">
<OrderCreateDialog :client-fk="customer.id" />
</QDialog>
</QItemSection>
</QItem>
<QItem v-ripple clickable>

View File

@ -11,6 +11,20 @@ defineProps({
required: true,
},
});
const handleSalesModelValue = (val) => ({
or: [
{ id: val },
{ name: val },
{ nickname: { like: '%' + val + '%' } },
{ code: { like: `${val}%` } },
],
});
const exprBuilder = (param, value) => {
return {
and: [{ active: { neq: false } }, handleSalesModelValue(value)],
};
};
</script>
<template>
@ -52,14 +66,18 @@ defineProps({
<QItem class="q-mb-sm">
<QItemSection>
<VnSelect
url="Workers/activeWithInheritedRole"
:filter="{ where: { role: 'salesPerson' } }"
url="Workers/search"
:params="{
departmentCodes: ['VT'],
}"
auto-load
:label="t('Salesperson')"
:expr-builder="exprBuilder"
v-model="params.salesPersonFk"
@update:model-value="searchFn()"
option-value="id"
option-label="name"
sort-by="nickname ASC"
emit-value
map-options
use-input
@ -68,7 +86,18 @@ defineProps({
outlined
rounded
:input-debounce="0"
/>
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }},{{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template></VnSelect
>
</QItemSection>
</QItem>
<QItem class="q-mb-sm">

View File

@ -68,7 +68,6 @@ const columns = computed(() => [
fields: ['id', 'name'],
where: { role: 'salesPerson' },
optionFilter: 'firstName',
useLike: false,
},
create: false,
columnField: {
@ -429,9 +428,10 @@ function handleLocation(data, location) {
:params="{
departmentCodes: ['VT', 'shopping'],
}"
:fields="['id', 'nickname']"
:fields="['id', 'nickname', 'code']"
sort-by="nickname ASC"
:use-like="false"
option-label="nickname"
option-value="id"
emit-value
auto-load
>

View File

@ -23,6 +23,7 @@ const incoterms = ref([]);
const customsAgents = ref([]);
const observationTypes = ref([]);
const notes = ref([]);
let originalNotes = [];
const deletes = ref([]);
onBeforeMount(() => {
@ -42,7 +43,8 @@ const getData = async (observations) => {
});
if (data.length) {
notes.value = data
originalNotes = data;
notes.value = originalNotes
.map((observation) => {
const type = observationTypes.value.find(
(type) => type.id === observation.observationTypeFk
@ -81,14 +83,24 @@ const deleteNote = (id, index) => {
};
const onDataSaved = async () => {
let payload = {};
const creates = notes.value.filter((note) => note.$isNew);
if (creates.length) {
payload.creates = creates;
}
if (deletes.value.length) {
payload.deletes = deletes.value;
}
let payload = {
creates: notes.value.filter((note) => note.$isNew),
deletes: deletes.value,
updates: notes.value
.filter((note) =>
originalNotes.some(
(oNote) =>
oNote.id === note.id &&
(note.description !== oNote.description ||
note.observationTypeFk !== oNote.observationTypeFk)
)
)
.map((note) => ({
data: note,
where: { id: note.id },
})),
};
await axios.post('AddressObservations/crud', payload);
notes.value = [];
deletes.value = [];

View File

@ -184,16 +184,17 @@ const getItemPackagingType = (ticketSales) => {
:disable-option="{ card: true, table: true }"
class="full-width"
:disable-infinite-scroll="true"
redirect="ticket"
>
<template #column-nickname="{ row }">
<span class="link">
<span class="link" @click.stop>
{{ row.nickname }}
<CustomerDescriptorProxy :id="row.clientFk" />
</span>
</template>
<template #column-routeFk="{ row }">
<span class="link">
<span class="link" @click.stop>
{{ row.routeFk }}
<RouteDescriptorProxy :id="row.routeFk" />
</span>
@ -210,7 +211,7 @@ const getItemPackagingType = (ticketSales) => {
<span v-else> {{ toCurrency(row.totalWithVat) }}</span>
</template>
<template #column-state="{ row }">
<span v-if="row.invoiceOut">
<span v-if="row.invoiceOut" @click.stop>
<span :class="{ link: row.invoiceOut.ref }">
{{ row.invoiceOut.ref }}
<InvoiceOutDescriptorProxy :id="row.invoiceOut.id" />

View File

@ -0,0 +1,12 @@
import axios from 'axios';
export async function getClientRisk(_filter) {
const filter = {
..._filter,
include: { relation: 'company', scope: { fields: ['code'] } },
};
return await axios(`ClientRisks`, {
params: { filter: JSON.stringify(filter) },
});
}

View File

@ -99,7 +99,7 @@ const travelDialogRef = ref(false);
const tableRef = ref();
const travel = ref(null);
const userParams = ref({
dated: Date.vnNew(),
dated: Date.vnNew().toJSON(),
});
const filter = ref({
@ -219,6 +219,7 @@ function round(value) {
data-key="StockBoughts"
url="StockBoughts/getStockBought"
save-url="StockBoughts/crud"
search-url="StockBoughts"
order="reserve DESC"
:right-search="false"
:is-editable="true"
@ -281,6 +282,7 @@ function round(value) {
display: flex;
flex-direction: column;
align-items: center;
min-width: 35%;
}
.text-negative {
color: $negative !important;
@ -297,5 +299,5 @@ function round(value) {
Date: Fecha
View more details: Ver más detalles
Reserve some space: Reservar espacio
This buyer has already made a reservation for this date: Este comprador ya ha hecho una reserva para esta fecha
This buyer has already made a reservation for this date: Este comprador ya ha hecho una reserva para esta fecha
</i18n>

View File

@ -18,7 +18,7 @@ const $props = defineProps({
required: true,
},
});
const customUrl = `StockBoughts/getStockBoughtDetail?workerFk=${$props.workerFk}&date=${$props.dated}`;
const customUrl = `StockBoughts/getStockBoughtDetail?workerFk=${$props.workerFk}&dated=${$props.dated}`;
const columns = [
{
align: 'left',

View File

@ -27,7 +27,7 @@ onMounted(async () => {
<VnFilterPanel
:data-key="props.dataKey"
:search-button="true"
search-url="table"
search-url="StockBoughts"
@set-user-params="setUserParams"
>
<template #tags="{ tag, formatFn }">
@ -36,12 +36,19 @@ onMounted(async () => {
<span>{{ formatFn(tag.value) }}</span>
</div>
</template>
<template #body="{ params }">
<template #body="{ params, searchFn }">
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate
id="date"
v-model="params.dated"
@update:model-value="
(value) => {
params.dated = value;
setUserParams(params);
searchFn();
}
"
:label="t('Date')"
is-outlined
/>

View File

@ -17,21 +17,6 @@ const props = defineProps({
});
const itemTypeWorkersOptions = ref([]);
const exprBuilder = (param, value) => {
switch (param) {
case 'name':
return { 'i.name': { like: `%${value}%` } };
case 'itemFk':
case 'warehouseFk':
case 'rate2':
case 'rate3':
param = `fp.${param}`;
return { [param]: value };
case 'minPrice':
param = `i.${param}`;
return { [param]: value };
}
};
</script>
<template>
@ -66,7 +51,7 @@ const exprBuilder = (param, value) => {
url="Warehouses"
auto-load
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
:label="t('components.itemsFilterPanel.warehouseFk')"
:label="t('globals.warehouse')"
v-model="params.warehouseFk"
option-label="name"
option-value="id"

View File

@ -1,7 +1,7 @@
<script setup>
import axios from 'axios';
import { useI18n } from 'vue-i18n';
import { computed, ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
@ -14,7 +14,6 @@ import OrderFilter from './Card/OrderFilter.vue';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import { toDateTimeFormat } from 'src/filters/date';
import { onMounted } from 'vue';
import { useRoute } from 'vue-router';
const { t } = useI18n();
@ -142,8 +141,13 @@ const columns = computed(() => [
],
},
]);
async function fetchClientAddress(id, formData) {
onMounted(() => {
if (!route.query.createForm) return;
const clientId = route.query.createForm;
const id = JSON.parse(clientId);
fetchClientAddress(id.clientFk);
});
async function fetchClientAddress(id, formData = {}) {
const { data } = await axios.get(`Clients/${id}`, {
params: { filter: { include: { relation: 'addresses' } } },
});
@ -170,13 +174,6 @@ const getDateColor = (date) => {
if (comparation == 0) return 'bg-warning';
if (comparation < 0) return 'bg-success';
};
onMounted(() => {
if (!route.query.createForm) return;
const clientId = route.query.createForm;
const id = JSON.parse(clientId);
fetchClientAddress(id.clientFk, id);
});
</script>
<template>
<OrderSearchbar />
@ -194,7 +191,7 @@ onMounted(() => {
urlCreate: 'Orders/new',
title: t('module.cerateOrder'),
onDataSaved: (url) => {
tableRef.redirect(url);
tableRef.redirect(`${url}/catalog`);
},
formInitialData: {
active: true,

View File

@ -271,6 +271,7 @@ onMounted(() => (stateStore.rightDrawer = false));
:label="t('purchaseRequest.price')"
type="number"
min="0"
step="any"
/>
</template>
</VnTable>

View File

@ -22,7 +22,6 @@ import { useVnConfirm } from 'composables/useVnConfirm';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnUsesMana from 'src/components/ui/VnUsesMana.vue';
const route = useRoute();
const router = useRouter();
@ -779,9 +778,6 @@ watch(
:label="t('ticketSale.discount')"
type="number"
/>
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
<VnUsesMana :mana-code="manaCode" />
</div>
</TicketEditManaProxy>
</template>
<span v-else>{{ toPercentage(row.discount / 100) }}</span>

View File

@ -19,7 +19,6 @@ import VnTitle from 'src/components/common/VnTitle.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue';
const route = useRoute();
@ -87,10 +86,6 @@ async function changeState(value) {
function toTicketUrl(section) {
return '#/ticket/' + entityId.value + '/' + section;
}
function isOnTicketCard() {
const currentPath = route.path;
return currentPath.startsWith('/ticket');
}
</script>
<template>

View File

@ -1,7 +1,7 @@
<script setup>
import axios from 'axios';
import { computed, ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
import { useStateStore } from 'stores/useStateStore';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
@ -24,6 +24,8 @@ import { toTimeFormat } from 'src/filters/date';
import InvoiceOutDescriptorProxy from '../InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { viewSummary } = useSummaryDialog();
const tableRef = ref();
@ -40,16 +42,18 @@ from.setDate(from.getDate() - 7);
const to = Date.vnNew();
to.setHours(23, 59, 0, 0);
to.setDate(to.getDate() + 1);
const userParams = {
from: null,
to: null,
};
// Método para inicializar las variables desde la query string
onMounted(() => {
initializeFromQuery();
stateStore.rightDrawer = true;
if (!route.query.createForm) return;
onClientSelected(JSON.parse(route.query.createForm));
});
const initializeFromQuery = () => {
const query = route.query.table ? JSON.parse(route.query.table) : {};
// Asigna los valores a las variables correspondientes
from.value = query.from || from.toISOString();
to.value = query.to || to.toISOString();
Object.assign(userParams, { from, to });
@ -206,13 +210,19 @@ const columns = computed(() => [
{
title: t('ticketList.summary'),
icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row.id, TicketSummary),
action: (row, evt) => {
if (evt && evt.ctrlKey) {
const url = router.resolve({
params: { id: row.id },
name: 'TicketCard',
}).href;
window.open(url, '_blank');
} else viewSummary(row.id, TicketSummary);
},
},
],
},
]);
function redirectToLines(id) {
const url = `#/ticket/${id}/sale`;
window.open(url, '_blank');
@ -302,11 +312,6 @@ const getDateColor = (date) => {
if (comparation < 0) return 'bg-success';
};
onMounted(() => {
initializeFromQuery();
stateStore.rightDrawer = true;
});
async function makeInvoice(ticket) {
const ticketsIds = ticket.map((item) => item.id);
const { data } = await axios.post(`Tickets/invoiceTicketsAndPdf`, { ticketsIds });
@ -472,7 +477,7 @@ function setReference(data) {
urlCreate: 'Tickets/new',
title: t('ticketList.createTicket'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
formInitialData: { clientId: null },
}"
default-mode="table"
:order="['shippedDate DESC', 'shippedHour ASC', 'zoneLanding ASC', 'id']"
@ -574,17 +579,17 @@ function setReference(data) {
</span>
</template>
<template #column-stateFk="{ row }">
<span v-if="getColor(row)">
<QChip :class="getColor(row)" dense square>
{{ row.state }}
</QChip>
</span>
<span v-else-if="row.state === 'Entregado'">
<span v-if="row.refFk">
<span class="link" @click.stop>
{{ row.refFk }}
<InvoiceOutDescriptorProxy :id="row.invoiceOutId" />
</span>
</span>
<span v-else-if="getColor(row)">
<QChip :class="getColor(row)" dense square>
{{ row.state }}
</QChip>
</span>
<span v-else>
{{ row.state }}
</span>
@ -616,6 +621,7 @@ function setReference(data) {
option-value="id"
option-label="name"
hide-selected
required
@update:model-value="(client) => onClientSelected(data)"
:sort-by="'id ASC'"
>
@ -635,7 +641,7 @@ function setReference(data) {
</VnRow>
<VnRow>
<VnSelect
url="Addresses"
required
:label="t('ticket.create.address')"
v-model="data.addressId"
:options="addressesOptions"
@ -680,6 +686,7 @@ function setReference(data) {
option-value="id"
option-label="name"
hide-selected
required
@update:model-value="() => fetchAvailableAgencies(data)"
/>
</div>
@ -693,7 +700,6 @@ function setReference(data) {
option-value="agencyModeFk"
option-label="agencyMode"
hide-selected
:disable="!data.clientId || !data.landed || !data.warehouseId"
/>
</div>
</VnRow>
@ -829,7 +835,14 @@ function setReference(data) {
</QTooltip>
</QPageSticky>
</template>
<style scoped>
.disabled,
.disabled *,
[disabled],
[disabled] * {
cursor: pointer !important;
}
</style>
<i18n>
es:
Search ticket: Buscar ticket

View File

@ -205,8 +205,10 @@ const onThermographCreated = async (data) => {
}"
sort-by="thermographFk ASC"
option-label="thermographFk"
option-filter-value="thermographFk"
:disable="viewAction === 'edit'"
:tooltip="t('New thermograph')"
:roles-allowed-to-create="['logistic']"
>
<template #form>
<CreateThermographForm

View File

@ -20,12 +20,13 @@ function notIsLocations(ifIsFalse, ifIsTrue) {
<template>
<VnCard
data-key="zone"
base-url="Zones"
:base-url="notIsLocations('Zones', undefined)"
:descriptor="ZoneDescriptor"
:filter-panel="ZoneFilterPanel"
:search-data-key="notIsLocations('ZoneList', 'ZoneLocations')"
:filter-panel="notIsLocations(ZoneFilterPanel, undefined)"
:search-data-key="notIsLocations('ZoneList', undefined)"
:custom-url="`Zones/${route.params?.id}/getLeaves`"
:searchbar-props="{
url: 'Zones',
url: notIsLocations('Zones', 'ZoneLocations'),
label: notIsLocations(t('list.searchZone'), t('list.searchLocation')),
info: t('list.searchInfo'),
whereFilter: notIsLocations((value) => {

View File

@ -5,6 +5,7 @@ import VnInput from 'src/components/common/VnInput.vue';
import { useState } from 'src/composables/useState';
import axios from 'axios';
import { useArrayData } from 'composables/useArrayData';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
const props = defineProps({
rootLabel: {
@ -33,22 +34,23 @@ const state = useState();
const treeRef = ref();
const expanded = ref([]);
const arrayData = useArrayData('ZoneLocations', {
url: `Zones/${route.params.id}/getLeaves`,
const datakey = 'ZoneLocations';
const url = computed(() => `Zones/${route.params.id}/getLeaves`);
const arrayData = useArrayData(datakey, {
url: url.value,
});
const { store } = arrayData;
const storeData = computed(() => store.data);
const nodes = ref([
{
id: null,
name: props.rootLabel,
sons: true,
tickable: false,
noTick: true,
children: [{}],
},
]);
const defaultNode = {
id: null,
name: props.rootLabel,
sons: true,
tickable: false,
noTick: true,
children: [{}],
};
const nodes = ref([defaultNode]);
const _tickedNodes = computed({
get: () => props.tickedNodes,
@ -229,6 +231,7 @@ onUnmounted(() => {
<QBtn color="primary" icon="search" dense flat @click="reFetch()" />
</template>
</VnInput>
<VnSearchbar :data-key="datakey" :url="url" :redirect="false" />
<QTree
ref="treeRef"
:nodes="nodes"

View File

@ -96,7 +96,7 @@ watch(
sort-by="code, townFk"
option-value="geoFk"
option-label="code"
:filter-options="['code', 'geoFk']"
:filter-options="['code']"
hide-selected
dense
outlined
@ -105,11 +105,14 @@ watch(
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection v-if="opt.code">
<QItemLabel>{{ opt.code }}</QItemLabel>
<QItemLabel caption
>{{ opt.town?.province?.name }},
{{ opt.town?.province?.country?.name }}</QItemLabel
>
<QItemLabel>
{{ `${opt.code}, ${opt.town?.name}` }}
</QItemLabel>
<QItemLabel caption>
{{
`${opt.town?.province?.name}, ${opt.town?.province?.country?.name}`
}}
</QItemLabel>
</QItemSection>
</QItem>
</template>

View File

@ -22,7 +22,12 @@ const agencies = ref([]);
</script>
<template>
<FetchData url="agencies" @on-fetch="(data) => (agencies = data)" auto-load />
<FetchData
url="AgencyModes"
:filter="{ fields: ['id', 'name'] }"
@on-fetch="(data) => (agencies = data)"
auto-load
/>
<VnFilterPanel
:data-key="props.dataKey"
:search-button="true"

View File

@ -73,6 +73,7 @@ const columns = computed(() => [
inWhere: true,
attrs: {
url: 'AgencyModes',
fields: ['id', 'name'],
},
},
columnField: {