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
gitea/salix-front/pipeline/pr-master This commit looks good
Details
This commit is contained in:
commit
a64575c7cc
|
@ -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)"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
>
|
||||
|
|
|
@ -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 = [];
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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) },
|
||||
});
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
/>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -271,6 +271,7 @@ onMounted(() => (stateStore.rightDrawer = false));
|
|||
:label="t('purchaseRequest.price')"
|
||||
type="number"
|
||||
min="0"
|
||||
step="any"
|
||||
/>
|
||||
</template>
|
||||
</VnTable>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -73,6 +73,7 @@ const columns = computed(() => [
|
|||
inWhere: true,
|
||||
attrs: {
|
||||
url: 'AgencyModes',
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
columnField: {
|
||||
|
|
Loading…
Reference in New Issue