feat: refs #8441 add VehicleInvoiceIn component with invoice management functionality #1567

Open
jtubau wants to merge 67 commits from 8441-createVehicleInvoiceInSection into dev
133 changed files with 1235 additions and 1205 deletions
Showing only changes of commit 430cddb554 - Show all commits

2
Jenkinsfile vendored
View File

@ -120,6 +120,8 @@ pipeline {
def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs')
sh 'docker login --username $CREDS_USR --password $CREDS_PSW $REGISTRY'
sh "docker-compose ${env.COMPOSE_PARAMS} pull back"
sh "docker-compose ${env.COMPOSE_PARAMS} pull db"
sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {

View File

@ -32,6 +32,18 @@ pnpm run test:front
pnpm run test:e2e
```
### Run e2e parallel
```bash
pnpm run test:e2e:parallel
```
### View e2e parallel report
```bash
pnpm run test:e2e:summary
```
### Build the app for production
```bash

View File

@ -25,6 +25,8 @@ RUN apt-get update \
libnss3 \
libxss1 \
libxtst6 \
mesa-vulkan-drivers \
vulkan-tools \
xauth \
xvfb \
&& apt-get clean \

View File

@ -13,7 +13,7 @@
"format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
"test:e2e": "cypress open",
"test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
"test:e2e:parallel": "bash ./test/cypress/cypressParallel.sh",
"test:e2e:parallel": "bash ./test/cypress/run.sh",
"test:e2e:summary": "bash ./test/cypress/summary.sh",
"test": "echo \"See package.json => scripts for available tests.\" && exit 0",
"test:front": "vitest",
@ -56,6 +56,7 @@
"eslint-plugin-cypress": "^4.1.0",
"eslint-plugin-vue": "^9.32.0",
"husky": "^8.0.0",
"junit-merge": "^2.0.0",
"mocha": "^11.1.0",
"postcss": "^8.4.23",
"prettier": "^3.4.2",

View File

@ -91,6 +91,9 @@ devDependencies:
husky:
specifier: ^8.0.0
version: 8.0.3
junit-merge:
specifier: ^2.0.0
version: 2.0.0
mocha:
specifier: ^11.1.0
version: 11.1.0
@ -4860,6 +4863,10 @@ packages:
universalify: 2.0.1
dev: true
/fs-readdir-recursive@1.1.0:
resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==}
dev: true
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@ -5640,6 +5647,16 @@ packages:
verror: 1.10.0
dev: true
/junit-merge@2.0.0:
resolution: {integrity: sha512-qwENzBWcdHPazNqPO0fKyFIqEyaSKyO0iyBeIU4Y/scjkXYpwTi88P2S/PWecqgMhzG2MOCwXk8QB9ucvXeIPw==}
hasBin: true
dependencies:
commander: 2.20.3
fs-readdir-recursive: 1.1.0
mkdirp: 0.5.6
xmldoc: 1.3.0
dev: true
/keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
dependencies:
@ -6037,7 +6054,6 @@ packages:
hasBin: true
dependencies:
minimist: 1.2.8
dev: false
/mlly@1.7.4:
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
@ -7253,6 +7269,10 @@ packages:
resolution: {integrity: sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==}
dev: true
/sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
dev: true
/scheduler@0.25.0:
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
dev: true
@ -8689,6 +8709,12 @@ packages:
engines: {node: '>=4.0'}
dev: true
/xmldoc@1.3.0:
resolution: {integrity: sha512-y7IRWW6PvEnYQZNZFMRLNJw+p3pezM4nKYPfr15g4OOW9i8VpeydycFuipE2297OvZnh3jSb2pxOt9QpkZUVng==}
dependencies:
sax: 1.4.1
dev: true
/xunit-viewer@10.6.1(@babel/runtime@7.26.9)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.3)(codemirror@6.0.1)(react-dom@19.0.0)(react@19.0.0):
resolution: {integrity: sha512-ZMprLPVhCQJf2KD56tv2hlOjc4T+KnUe1E9DkEBHnuliOq7IOXWJf61pxyBMo/7H83B7Ln0DIeWNMMbx/3I7Jg==}
hasBin: true

View File

@ -188,7 +188,7 @@ const selectItem = ({ id }) => {
>
<template #body-cell-id="{ row }">
<QTd auto-width @click.stop>
<QBtn flat color="blue">{{ row.id }}</QBtn>
<QBtn flat class="link">{{ row.id }}</QBtn>
<ItemDescriptorProxy :id="row.id" />
</QTd>
</template>

View File

@ -196,7 +196,7 @@ const selectTravel = ({ id }) => {
>
<template #body-cell-id="{ row }">
<QTd auto-width @click.stop data-cy="travelFk-travel-form">
<QBtn flat color="blue">{{ row.id }}</QBtn>
<QBtn flat class="link">{{ row.id }}</QBtn>
<TravelDescriptorProxy :id="row.id" />
</QTd>
</template>

View File

@ -77,6 +77,7 @@ watch(
function findMatches(search, item) {
const matches = [];
function findRoute(search, item) {
if (!item?.children) return;
for (const child of item.children) {
if (search?.indexOf(child.name) > -1) {
matches.push(child);
@ -92,7 +93,7 @@ function findMatches(search, item) {
}
function addChildren(module, route, parent) {
const menus = route?.meta?.menu ?? route?.menus?.[props.source]; //backwards compatible
const menus = route?.meta?.menu;
if (!menus) return;
const matches = findMatches(menus, route);
@ -107,11 +108,7 @@ function getRoutes() {
main: getMainRoutes,
card: getCardRoutes,
};
try {
handleRoutes[props.source]();
} catch (error) {
throw new Error(`Method is not defined`);
}
handleRoutes[props.source]();
}
function getMainRoutes() {
const modules = Object.assign([], navigation.getModules().value);
@ -122,7 +119,6 @@ function getMainRoutes() {
);
if (!moduleDef) continue;
item.children = [];
addChildren(item.module, moduleDef, item.children);
}
@ -132,21 +128,16 @@ function getMainRoutes() {
function getCardRoutes() {
const currentRoute = route.matched[1];
const currentModule = toLowerCamel(currentRoute.name);
let moduleDef = routes.find((route) => toLowerCamel(route.name) === currentModule);
let moduleDef;
if (!moduleDef) return;
if (!moduleDef?.menus) moduleDef = betaGetRoutes();
addChildren(currentModule, moduleDef, items.value);
}
function betaGetRoutes() {
let menuRoute;
let index = route.matched.length - 1;
while (!menuRoute && index > 0) {
if (route.matched[index]?.meta?.menu) menuRoute = route.matched[index];
while (!moduleDef && index > 0) {
if (route.matched[index]?.meta?.menu) moduleDef = route.matched[index];
index--;
}
return menuRoute;
if (!moduleDef) return;
addChildren(currentModule, moduleDef, items.value);
}
async function togglePinned(item, event) {

View File

@ -28,6 +28,17 @@ defineProps({ row: { type: Object, required: true } });
{{ t('ticketSale.reserved') }}
</QTooltip>
</QIcon>
<QIcon
v-if="row?.isDeleted"
color="primary"
name="vn:deletedTicket"
size="xs"
data-cy="ticketDeletedIcon"
>
<QTooltip>
{{ t('Ticket deleted') }}
</QTooltip>
</QIcon>
<QIcon
v-if="row?.hasRisk"
name="vn:risk"

View File

@ -6,6 +6,7 @@ import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputTime from 'components/common/VnInputTime.vue';
import VnCheckbox from 'components/common/VnCheckbox.vue';
import VnColumn from 'components/VnTable/VnColumn.vue';
const $props = defineProps({
@ -106,7 +107,7 @@ const components = {
},
},
checkbox: {
component: markRaw(QCheckbox),
component: markRaw(VnCheckbox),
event: updateEvent,
attrs: {
class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',

View File

@ -920,12 +920,24 @@ const rowCtrlClickFunction = computed(() => {
:row-index="index"
>
<VnColumn
:column="col"
:column="{
...col,
disable:
col?.component ===
'checkbox'
? true
: false,
}"
:row="row"
:is-editable="false"
v-model="row[col.name]"
component-prop="columnField"
:show-label="true"
:show-label="
col?.component ===
'checkbox'
? false
: true
"
/>
</slot>
</span>

View File

@ -15,10 +15,7 @@ vi.mock('src/router/modules', () => ({
meta: {
title: 'customers',
icon: 'vn:client',
},
menus: {
main: ['CustomerList', 'CustomerCreate'],
card: ['CustomerBasicData'],
menu: ['CustomerList', 'CustomerCreate'],
},
children: [
{
@ -50,14 +47,6 @@ vi.mock('src/router/modules', () => ({
],
},
},
{
path: 'create',
name: 'CustomerCreate',
meta: {
title: 'createCustomer',
icon: 'vn:addperson',
},
},
],
},
],
@ -98,7 +87,7 @@ vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
icon: 'vn:client',
moduleName: 'Customer',
keyBinding: 'c',
menu: 'customer',
menu: ['customer'],
},
},
],
@ -260,15 +249,6 @@ describe('Leftmenu as main', () => {
});
});
it('should handle a single matched route with a menu', () => {
const route = {
matched: [{ meta: { menu: 'customer' } }],
};
const result = vm.betaGetRoutes();
expect(result.meta.menu).toEqual(route.matched[0].meta.menu);
});
it('should get routes for main source', () => {
vm.props.source = 'main';
vm.getRoutes();
@ -351,8 +331,9 @@ describe('addChildren', () => {
it('should handle routes with no meta menu', () => {
const route = {
meta: {},
menus: {},
meta: {
menu: [],
},
};
const parent = [];

View File

@ -54,7 +54,7 @@ const $props = defineProps({
default: 'table',
},
redirect: {
type: Boolean,
type: [String, Boolean],
default: true,
},
arrayData: {

View File

@ -186,7 +186,7 @@ function fetchData([data]) {
ref="vnPaginateRef"
class="show"
v-bind="$attrs"
search-url="notes"
:search-url="false"
@on-fetch="
newNote.text = '';
newNote.observationTypeFk = null;

View File

@ -9,6 +9,8 @@ export function getColAlign(col) {
case 'number':
align = 'right';
break;
case 'time':
case 'date':
case 'checkbox':
align = 'center';
break;

View File

@ -15,6 +15,7 @@ body.body--light {
--vn-empty-tag: #acacac;
--vn-black-text-color: black;
--vn-text-color-contrast: white;
--vn-link-color: #1e90ff;
background-color: var(--vn-page-color);
@ -38,6 +39,7 @@ body.body--dark {
--vn-empty-tag: #2d2d2d;
--vn-black-text-color: black;
--vn-text-color-contrast: black;
--vn-link-color: #66bfff;
background-color: var(--vn-page-color);
@ -49,7 +51,7 @@ a {
}
.link {
color: $color-link;
color: var(--vn-link-color);
cursor: pointer;
&--white {
@ -58,14 +60,14 @@ a {
}
.tx-color-link {
color: $color-link !important;
color: var(--vn-link-color) !important;
}
.tx-color-font {
color: $color-link !important;
color: var(--vn-link-color) !important;
}
.header-link {
color: $color-link !important;
color: var(--vn-link-color) !important;
cursor: pointer;
border-bottom: solid $primary;
border-width: 2px;

View File

@ -24,7 +24,6 @@ $alert: $negative;
$white: #fff;
$dark: #3d3d3d;
// custom
$color-link: #66bfff;
$color-spacer-light: #a3a3a31f;
$color-spacer: #7979794d;
$border-thin-light: 1px solid $color-spacer-light;

View File

@ -99,7 +99,6 @@ globals:
file: File
selectFile: Select a file
copyClipboard: Copy on clipboard
salesPerson: SalesPerson
send: Send
code: Code
since: Since
@ -158,7 +157,9 @@ globals:
changeState: Change state
raid: 'Raid {daysInForward} days'
isVies: Vies
department: Department
noData: No data available
vehicle: Vehicle
pageTitles:
logIn: Login
addressEdit: Update address
@ -346,7 +347,6 @@ globals:
params:
description: Description
clientFk: Client id
salesPersonFk: Sales person
warehouseFk: Warehouse
provinceFk: Province
stateFk: State
@ -531,6 +531,7 @@ ticket:
customerCard: Customer card
ticketList: Ticket List
newOrder: New Order
ticketClaimed: Claimed ticket
boxing:
expedition: Expedition
created: Created
@ -603,7 +604,6 @@ worker:
balance: Balance
medical: Medical
list:
department: Department
schedule: Schedule
newWorker: New worker
summary:
@ -862,7 +862,6 @@ components:
mine: For me
hasMinPrice: Minimum price
# LatestBuysFilter
salesPersonFk: Buyer
supplierFk: Supplier
from: From
to: To

View File

@ -103,7 +103,6 @@ globals:
file: Fichero
selectFile: Seleccione un fichero
copyClipboard: Copiar en portapapeles
salesPerson: Comercial
send: Enviar
code: Código
since: Desde
@ -163,6 +162,8 @@ globals:
raid: 'Redada {daysInForward} días'
isVies: Vies
noData: Datos no disponibles
department: Departamento
vehicle: Vehículo
pageTitles:
logIn: Inicio de sesión
addressEdit: Modificar consignatario
@ -349,7 +350,6 @@ globals:
params:
description: Descripción
clientFk: Id cliente
salesPersonFk: Comercial
warehouseFk: Almacén
provinceFk: Provincia
stateFk: Estado
@ -531,13 +531,13 @@ ticket:
state: Estado
shipped: Enviado
landed: Entregado
salesPerson: Comercial
total: Total
card:
customerId: ID cliente
customerCard: Ficha del cliente
ticketList: Listado de tickets
newOrder: Nuevo pedido
ticketClaimed: Ticket reclamado
boxing:
expedition: Expedición
created: Creado
@ -622,8 +622,6 @@ invoiceOut:
errors:
downloadCsvFailed: Error al descargar CSV
order:
field:
salesPersonFk: Comercial
form:
clientFk: Cliente
addressFk: Dirección
@ -691,7 +689,6 @@ worker:
formation: Formación
medical: Mutua
list:
department: Departamento
schedule: Horario
newWorker: Nuevo trabajador
summary:
@ -949,7 +946,6 @@ components:
hasMinPrice: Precio mínimo
wareHouseFk: Almacén
# LatestBuysFilter
salesPersonFk: Comprador
supplierFk: Proveedor
visible: Visible
active: Activo

View File

@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const route = useRoute();
const { t } = useI18n();
@ -27,13 +28,10 @@ const entityId = computed(() => $props.id || route.params.id);
<template #body="{ entity: alias }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<router-link
:to="{ name: 'AliasBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnTitle
:url="`#/account/alias/${entityId}/basic-data`"
:text="t('globals.summary.basicData')"
/>
</QCardSection>
<VnLv :label="t('role.id')" :value="alias.id" />
<VnLv :label="t('role.description')" :value="alias.description" />

View File

@ -5,6 +5,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import filter from './AccountFilter.js';
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const $props = defineProps({ id: { type: Number, default: 0 } });
@ -26,13 +27,10 @@ const entityId = computed(() => $props.id || route.params.id);
<template #body="{ entity }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<router-link
:to="{ name: 'AccountBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ $t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnTitle
:url="`#/account/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
</QCardSection>
<VnLv :label="$t('account.card.nickname')" :value="entity.name" />
<VnLv :label="$t('account.card.role')" :value="entity.role?.name" />

View File

@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const route = useRoute();
const { t } = useI18n();
@ -29,13 +30,10 @@ const entityId = computed(() => $props.id || route.params.id);
<template #body="{ entity }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<a
class="header header-link"
:href="`#/VnUser/${entityId}/basic-data`"
>
{{ t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</a>
<VnTitle
:url="`#/account/role/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
</QCardSection>
<VnLv :label="t('role.id')" :value="entity.id" />
<VnLv :label="t('globals.name')" :value="entity.name" />

View File

@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
import { toDateHourMinSec, toPercentage } from 'src/filters';
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
@ -65,12 +66,12 @@ onMounted(async () => {
</template>
</VnLv>
<VnLv :label="t('claim.created')" :value="toDateHourMinSec(entity.created)" />
<VnLv :label="t('claim.commercial')">
<VnLv :label="t('globals.department')">
<template #value>
<VnUserLink
:name="entity.client?.salesPersonUser?.name"
:worker-id="entity.client?.salesPersonFk"
/>
<span class="link">
{{ entity?.client?.department?.name || '-' }}
<DepartmentDescriptorProxy :id="entity?.client?.departmentFk" />
</span>
</template>
</VnLv>
<VnLv

View File

@ -14,7 +14,7 @@ export default {
relation: 'client',
scope: {
include: [
{ relation: 'salesPersonUser' },
{ relation: 'department' },
{
relation: 'claimsRatio',
scope: {

View File

@ -117,7 +117,7 @@ const selected = ref([]);
const mana = ref(0);
async function fetchMana() {
const ticketId = claim.value.ticketFk;
const response = await axios.get(`Tickets/${ticketId}/getSalesPersonMana`);
const response = await axios.get(`Tickets/${ticketId}/getDepartmentMana`);
mana.value = response.data;
}

View File

@ -19,6 +19,7 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import ClaimDescriptorMenu from './ClaimDescriptorMenu.vue';
const route = useRoute();
@ -252,13 +253,15 @@ function claimUrl(section) {
</VnLv>
<VnLv
v-if="$route.name != 'ClaimSummary'"
:label="t('globals.salesPerson')"
:label="t('customer.summary.team')"
>
<template #value>
<VnUserLink
:name="claim.client?.salesPersonUser?.name"
:worker-id="claim.client?.salesPersonFk"
/>
<span class="link">
{{ claim?.client?.department?.name || '-' }}
<DepartmentDescriptorProxy
:id="claim?.client?.departmentFk"
/>
</span>
</template>
</VnLv>
<VnLv v-if="$route.name != 'ClaimSummary'" :label="t('claim.attendedBy')">
@ -271,7 +274,7 @@ function claimUrl(section) {
</VnLv>
<VnLv v-if="$route.name != 'ClaimSummary'" :label="t('claim.customer')">
<template #value>
<span class="link cursor-pointer">
<span class="link">
{{ claim.client?.name }}
<CustomerDescriptorProxy :id="claim.clientFk" />
</span>

View File

@ -80,7 +80,7 @@ const columns = [
:right-search="false"
:column-search="false"
:disable-option="{ card: true, table: true }"
search-url="actions"
:search-url="false"
:filter="{ where: { claimFk: $props.id } }"
:columns="columns"
:limit="0"

View File

@ -44,15 +44,14 @@ const props = defineProps({
is-outlined
/>
<VnSelect
:label="t('Salesperson')"
v-model="params.salesPersonFk"
url="Workers/activeWithInheritedRole"
:filter="{ where: { role: 'salesPerson' } }"
:use-like="false"
option-filter="firstName"
dense
outlined
dense
rounded
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
<VnSelect
:label="t('claim.attendedBy')"
@ -126,7 +125,6 @@ en:
search: Contains
clientFk: Customer
clientName: Customer
salesPersonFk: Salesperson
attenderFk: Attender
claimResponsibleFk: Responsible
claimStateFk: State
@ -139,7 +137,6 @@ es:
search: Contiene
clientFk: Cliente
clientName: Cliente
salesPersonFk: Comercial
attenderFk: Asistente
claimResponsibleFk: Responsable
claimStateFk: Estado
@ -148,6 +145,5 @@ es:
itemFk: Artículo
zoneFk: Zona
Client Name: Nombre del cliente
Salesperson: Comercial
Item: Artículo
</i18n>

View File

@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
import { toDate } from 'filters/index';
import ClaimFilter from './ClaimFilter.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import ClaimSummary from './Card/ClaimSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
@ -48,6 +49,20 @@ const columns = computed(() => [
},
columnClass: 'expand',
},
{
align: 'left',
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Departments',
},
create: true,
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
align: 'left',
label: t('claim.attendedBy'),
@ -152,6 +167,12 @@ const STATE_COLOR = {
<CustomerDescriptorProxy :id="row.clientFk" />
</span>
</template>
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ row.departmentName || '-' }}
<DepartmentDescriptorProxy :id="row?.departmentFk" />
</span>
</template>
<template #column-attendedBy="{ row }">
<span @click.stop>
<VnUserLink :name="row.workerName" :worker-id="row.workerFk" />

View File

@ -8,7 +8,6 @@ import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import { getDifferences, getUpdatedValues } from 'src/filters';
const route = useRoute();
@ -37,7 +36,7 @@ const exprBuilder = (param, value) => {
function onBeforeSave(formData, originalData) {
return getUpdatedValues(
Object.keys(getDifferences(formData, originalData)),
formData
formData,
);
}
</script>
@ -119,16 +118,11 @@ function onBeforeSave(formData, originalData) {
/>
</VnRow>
<VnRow>
<VnSelectWorker
:label="t('customer.summary.salesPerson')"
v-model="data.salesPersonFk"
:params="{
departmentCodes: ['VT', 'shopping'],
}"
:has-avatar="true"
:rules="validate('client.salesPersonFk')"
:expr-builder="exprBuilder"
emit-value
<VnSelect
:label="t('globals.department')"
v-model="data.departmentFk"
url="Departments"
:fields="['id', 'name']"
/>
<VnSelect
v-model="data.contactChannelFk"
@ -160,7 +154,7 @@ function onBeforeSave(formData, originalData) {
<QIcon name="info" class="cursor-pointer">
<QTooltip>{{
t(
'In case of a company succession, specify the grantor company'
'In case of a company succession, specify the grantor company',
)
}}</QTooltip>
</QIcon>

View File

@ -3,14 +3,14 @@ import { onMounted, ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
import { toCurrency, toDate } from 'src/filters';
import useCardDescription from 'src/composables/useCardDescription';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import { useState } from 'src/composables/useState';
const state = useState();
@ -84,14 +84,10 @@ const debtWarning = computed(() => {
:value="toCurrency(entity.debt)"
:info="t('customer.summary.riskInfo')"
/>
<VnLv :label="t('customer.summary.salesPerson')">
<VnLv :label="t('globals.department')">
<template #value>
<VnUserLink
v-if="entity.salesPersonUser"
:name="entity.salesPersonUser.name"
:worker-id="entity.salesPersonFk"
/>
<span v-else>{{ dashIfEmpty(entity.salesPersonUser) }}</span>
<span class="link" v-text="entity.department?.name" />
<DepartmentDescriptorProxy :id="entity.department?.id" />
</template>
</VnLv>
<VnLv

View File

@ -86,12 +86,12 @@ const tableColumnComponents = {
},
file: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
props: () => ({ flat: true }),
event: ({ row }) => downloadFile(row.dmsFk),
},
employee: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
props: () => ({ flat: true }),
event: () => {},
},
created: {
@ -214,8 +214,17 @@ const toCustomerFileManagementCreate = () => {
v-bind="tableColumnComponents[props.col.name].props(props)"
>
<template v-if="props.col.name !== 'original'">
{{ props.value }}
<span
:class="{
link:
props.col.name === 'employee' ||
props.col.name === 'file',
}"
>
{{ props.value }}
</span>
</template>
<WorkerDescriptorProxy
:id="props.row.dms.workerFk"
v-if="props.col.name === 'employee'"

View File

@ -2,7 +2,6 @@
import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { toCurrency, toPercentage, toDate, dashOrCurrency } from 'src/filters';
import CardSummary from 'components/ui/CardSummary.vue';
@ -13,6 +12,8 @@ import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryT
import VnTitle from 'src/components/common/VnTitle.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
const route = useRoute();
const { t } = useI18n();
const grafanaUrl = 'https://grafana.verdnatura.es';
@ -106,16 +107,12 @@ const sumRisk = ({ clientRisks }) => {
{{ t('globals.params.email') }}
<VnLinkMail email="entity.email"></VnLinkMail> </template
></VnLv>
<VnLv
:label="t('customer.summary.salesPerson')"
:value="entity?.salesPersonUser?.name"
>
<VnLv :label="t('globals.department')">
<template #value>
<VnUserLink
:name="entity.salesPersonUser?.name"
:worker-id="entity.salesPersonFk"
/> </template
></VnLv>
<span class="link" v-text="entity.department?.name" />
<DepartmentDescriptorProxy :id="entity?.department?.id" />
</template>
</VnLv>
<VnLv
:label="t('customer.summary.contactChannel')"
:value="entity?.contactChannel?.name"

View File

@ -1,146 +0,0 @@
<script setup>
import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnLocation from 'src/components/common/VnLocation.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
const { t } = useI18n();
const initialData = reactive({
active: true,
isEqualizated: false,
});
const workersOptions = ref([]);
const businessTypesOptions = ref([]);
function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {};
data.postcode = code;
data.city = town;
data.provinceFk = provinceFk;
data.countryFk = countryFk;
}
</script>
<template>
<FetchData
@on-fetch="(data) => (workersOptions = data)"
auto-load
url="Workers/search?departmentCodes"
/>
<FetchData
@on-fetch="(data) => (businessTypesOptions = data)"
auto-load
url="BusinessTypes"
/>
<QPage>
<VnSubToolbar />
<FormModel
:form-initial-data="initialData"
model="client"
url-create="Clients/createWithUser"
>
<template #form="{ data, validate }">
<VnRow>
<QInput :label="t('Comercial name')" v-model="data.name" />
<VnSelect
:label="t('Salesperson')"
:options="workersOptions"
hide-selected
option-label="name"
option-value="id"
v-model="data.salesPersonFk"
/>
</VnRow>
<VnRow>
<VnSelect
:label="t('Business type')"
:options="businessTypesOptions"
hide-selected
option-label="description"
option-value="code"
v-model="data.businessTypeFk"
/>
<QInput v-model="data.fi" :label="t('Tax number')" />
</VnRow>
<VnRow>
<QInput
:label="t('Business name')"
:rules="validate('client.socialName')"
v-model="data.socialName"
/>
</VnRow>
<VnRow>
<QInput
:label="t('Street')"
:rules="validate('client.street')"
v-model="data.street"
/>
</VnRow>
<VnRow>
<VnLocation
:rules="validate('Worker.postcode')"
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
v-model="data.location"
@update:model-value="(location) => handleLocation(data, location)"
>
</VnLocation>
</VnRow>
<VnRow>
<QInput v-model="data.userName" :label="t('Web user')" />
<QInput
:label="t('Email')"
:rules="validate('client.email')"
clearable
type="email"
v-model="data.email"
>
<template #append>
<QIcon name="info" class="cursor-info">
<QTooltip max-width="400px">{{
t('customer.basicData.youCanSaveMultipleEmails')
}}</QTooltip>
</QIcon>
</template>
</QInput>
</VnRow>
<QCheckbox
:label="t('Is equalizated')"
v-model="initialData.isEqualizated"
/>
</template>
</FormModel>
</QPage>
</template>
<style lang="scss" scoped>
.card {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-gap: 20px;
}
</style>
<i18n>
es:
Comercial name: Nombre comercial
Salesperson: Comercial
Business type: Tipo de negocio
Tax number: NIF / CIF
Business name: Razón social
Street: Dirección fiscal
Postcode: Código postal
City: Población
Province: Provincia
Country: País
Web user: Usuario web
Email: Email
Is equalizated: Recargo de equivalencia
</i18n>

View File

@ -3,7 +3,6 @@ import { useI18n } from 'vue-i18n';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n();
defineProps({
@ -65,22 +64,15 @@ const exprBuilder = (param, value) => {
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnSelectWorker
:label="t('Salesperson')"
v-model="params.salesPersonFk"
:params="{
departmentCodes: ['VT'],
}"
:expr-builder="exprBuilder"
@update:model-value="searchFn()"
emit-value
map-options
use-input
hide-selected
dense
<VnSelect
outlined
dense
rounded
:input-debounce="0"
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
</QItemSection>
</QItem>
@ -164,7 +156,6 @@ en:
params:
search: Contains
fi: FI
salesPersonFk: Salesperson
provinceFk: Province
isActive: Is active
city: City
@ -191,7 +182,6 @@ es:
sageTaxTypeFk: Tipo de impuesto Sage
sageTransactionTypeFk: Tipo de impuesto Sage
payMethodFk: Forma de pago
salesPersonFk: Comercial
provinceFk: Provincia
city: Ciudad
phone: Teléfono
@ -201,7 +191,6 @@ es:
name: Nombre
postcode: CP
FI: NIF
Salesperson: Comercial
Province: Provincia
City: Ciudad
Phone: Teléfono

View File

@ -10,7 +10,6 @@ import CustomerFilter from './CustomerFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import VnLocation from 'src/components/common/VnLocation.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n();
@ -73,30 +72,17 @@ const columns = computed(() => [
},
{
align: 'left',
name: 'salesPersonFk',
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'),
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name', 'firstName'],
where: { role: 'salesPerson' },
optionFilter: 'firstName',
url: 'Departments',
},
columnFilter: {
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name', 'firstName'],
where: { role: 'salesPerson' },
optionLabel: 'firstName',
optionValue: 'id',
},
},
create: false,
create: true,
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.salesPerson),
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
align: 'left',
@ -155,6 +141,9 @@ const columns = computed(() => [
inWhere: true,
},
columnClass: 'expand',
attrs: {
uppercase: true,
},
},
{
align: 'left',
@ -446,36 +435,6 @@ function handleLocation(data, location) {
redirect="customer"
>
<template #more-create-dialog="{ data }">
<VnSelectWorker
:label="t('customer.summary.salesPerson')"
v-model="data.salesPersonFk"
:params="{
departmentCodes: ['VT', 'shopping'],
}"
:has-avatar="true"
:id-value="data.salesPersonFk"
emit-value
auto-load
>
<template #prepend>
<VnAvatar
:worker-id="data.salesPersonFk"
color="primary"
:title="title"
/>
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt?.nickname }},
{{ scope.opt?.code }}</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelectWorker>
<VnLocation
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
v-model="data.location"

View File

@ -32,28 +32,6 @@ const columns = computed(() => [
},
},
},
{
align: 'left',
name: 'isWorker',
label: t('Is worker'),
},
{
align: 'left',
name: 'salesPersonFk',
label: t('Salesperson'),
columnFilter: {
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
where: { role: 'salesPerson' },
useLike: false,
optionValue: 'id',
optionLabel: 'name',
optionFilter: 'firstName',
},
},
},
{
align: 'left',
name: 'departmentFk',
@ -153,6 +131,11 @@ const columns = computed(() => [
label: t('Has recovery'),
name: 'hasRecovery',
},
{
align: 'left',
name: 'isWorker',
label: t('customer.params.isWorker'),
},
]);
const viewAddObservation = (rowsSelected) => {
@ -167,7 +150,6 @@ const viewAddObservation = (rowsSelected) => {
function exprBuilder(param, value) {
switch (param) {
case 'salesPersonFk':
case 'creditInsurance':
case 'countryFk':
return { [`c.${param}`]: value };
@ -176,7 +158,7 @@ function exprBuilder(param, value) {
case 'workerFk':
return { [`co.${param}`]: value };
case 'departmentFk':
return { [`wd.${param}`]: value };
return { [`c.${param}`]: value };
case 'amount':
case 'clientFk':
return { [`d.${param}`]: value };
@ -241,12 +223,6 @@ function exprBuilder(param, value) {
<template #column-observation="{ row }">
<VnInput type="textarea" v-model="row.observation" readonly dense rows="2" />
</template>
<template #column-salesPersonFk="{ row }">
<span class="link" @click.stop>
{{ row.salesPersonName }}
<WorkerDescriptorProxy :id="row.salesPersonFk" />
</span>
</template>
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ row.departmentName }}
@ -265,8 +241,6 @@ function exprBuilder(param, value) {
es:
Add observation: Añadir observación
Client: Cliente
Is worker: Es trabajador
Salesperson: Comercial
Department: Departamento
Country: País
P. Method: F. Pago
@ -281,5 +255,5 @@ es:
Credit I.: Crédito A.
Credit insurance: Crédito asegurado
From: Desde
Has recovery: Tiene recobro
Has recovery: Recobro
</i18n>

View File

@ -15,19 +15,12 @@ const props = defineProps({
},
});
const salespersons = ref();
const countries = ref();
const authors = ref();
const departments = ref();
</script>
<template>
<FetchData
:filter="{ where: { role: 'salesPerson' } }"
@on-fetch="(data) => (salespersons = data)"
auto-load
url="Workers/activeWithInheritedRole"
/>
<FetchData @on-fetch="(data) => (countries = data)" auto-load url="Countries" />
<FetchData
@on-fetch="(data) => (authors = data)"
@ -62,29 +55,6 @@ const departments = ref();
@update:model-value="searchFn()"
/>
</QItem>
<QItem class="q-mb-sm">
<QItemSection v-if="salespersons">
<VnSelect
:input-debounce="0"
:label="t('Salesperson')"
:options="salespersons"
dense
emit-value
hide-selected
map-options
option-label="name"
option-value="id"
outlined
rounded
use-input
v-model="params.salesPersonFk"
@update:model-value="searchFn()"
/>
</QItemSection>
<QItemSection v-else>
<QSkeleton class="full-width" type="QInput" />
</QItemSection>
</QItem>
<QItem class="q-mb-sm">
<QItemSection v-if="departments">
<VnSelect
@ -219,7 +189,6 @@ const departments = ref();
en:
params:
clientFk: Client
salesPersonFk: Salesperson
countryFk: Country
paymentMethod: P. Method
balance: Balance D.
@ -230,7 +199,6 @@ en:
es:
params:
clientFk: Cliente
salesPersonFk: Comercial
countryFk: País
paymentMethod: F. Pago
balance: Saldo V.
@ -239,7 +207,6 @@ es:
credit: Crédito A.
defaulterSinced: Desde
Client: Cliente
Salesperson: Comercial
Departments: Departamentos
Country: País
P. Method: F. Pago

View File

@ -69,17 +69,16 @@ const columns = computed(() => [
},
{
align: 'left',
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'),
name: 'salesPersonFk',
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
where: { role: 'salesPerson' },
optionFilter: 'firstName',
useLike: false,
url: 'Departments',
},
visible: false,
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
]);
</script>
@ -96,7 +95,7 @@ const columns = computed(() => [
</VnSubToolbar>
<VnTable
:data-key="dataKey"
url="Clients"
url="Clients/filter"
:table="{
'row-key': 'id',
selection: 'multiple',
@ -127,7 +126,6 @@ const columns = computed(() => [
es:
Identifier: Identificador
Social name: Razón social
Salesperson: Comercial
Phone: Teléfono
City: Población
Email: Email

View File

@ -20,7 +20,7 @@ customer:
name: Name
contact: Contact
mobile: Mobile
salesPerson: Sales person
team: Team
contactChannel: Contact channel
socialName: Social name
fiscalId: Fiscal ID
@ -78,7 +78,6 @@ customer:
id: Identifier
socialName: Social name
fi: Tax number
salesPersonFk: Salesperson
creditInsurance: Credit insurance
phone: Phone
street: Street

View File

@ -20,7 +20,7 @@ customer:
name: Nombre
contact: Contacto
mobile: Móvil
salesPerson: Comercial
team: Equipo
contactChannel: Canal de contacto
socialName: Razón social
fiscalId: NIF/CIF
@ -78,7 +78,6 @@ customer:
id: Identificador
socialName: Razón social
fi: NIF / CIF
salesPersonFk: Comercial
creditInsurance: Crédito asegurado
phone: Teléfono
street: Dirección fiscal

View File

@ -20,14 +20,21 @@ const tagValues = ref([]);
</script>
<template>
<FetchData
url="TicketRequests/getItemTypeWorker"
auto-load
:filter="{ fields: ['id', 'nickname'], order: 'nickname ASC' }"
@on-fetch="(data) => (itemTypeWorkersOptions = data)"
/>
<ItemsFilterPanel :data-key="dataKey" :custom-tags="['tags']">
<template #body="{ params, searchFn }">
<QItem class="q-my-md">
<QItemSection>
<VnSelect
:label="t('components.itemsFilterPanel.salesPersonFk')"
v-model="params.salesPersonFk"
url="TicketRequests/getItemTypeWorker"
:label="t('components.itemsFilterPanel.buyerFk')"
v-model="params.buyerFk"
:options="itemTypeWorkersOptions"
option-value="id"
option-label="nickname"
:fields="['id', 'nickname']"
sort-by="nickname ASC"

View File

@ -46,6 +46,11 @@ function ticketFilter(invoice) {
<InvoiceOutDescriptorMenu :invoice-out-data="entity" :menu-ref="menuRef" />
</template>
<template #body="{ entity }">
<VnLv
v-if="entity.externalRef"
:label="t('invoiceOut.externalRef')"
:value="entity.externalRef"
/>
<VnLv :label="t('invoiceOut.card.issued')" :value="toDate(entity.issued)" />
<VnLv :label="t('globals.amount')" :value="toCurrency(entity.amount)" />
<VnLv v-if="entity.client" :label="t('globals.client')">

View File

@ -7,6 +7,7 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
const { t } = useI18n();
const props = defineProps({
@ -30,7 +31,7 @@ const states = ref();
<QItem>
<QItemSection>
<VnInput
:label="t('Customer ID')"
:label="t('globals.params.clientFk')"
v-model="params.clientFk"
is-outlined
/>
@ -38,13 +39,17 @@ const states = ref();
</QItem>
<QItem>
<QItemSection>
<VnInput v-model="params.fi" :label="t('FI')" is-outlined />
<VnInput
v-model="params.fi"
:label="t('globals.params.fi')"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputNumber
:label="t('Amount')"
:label="t('globals.amount')"
v-model="params.amount"
is-outlined
data-cy="InvoiceOutFilterAmountBtn"
@ -54,7 +59,7 @@ const states = ref();
<QItem>
<QItemSection>
<QInput
:label="t('Min')"
:label="t('invoiceOut.params.min')"
dense
lazy-rules
outlined
@ -65,7 +70,7 @@ const states = ref();
</QItemSection>
<QItemSection>
<QInput
:label="t('Max')"
:label="t('invoiceOut.params.max')"
dense
lazy-rules
outlined
@ -78,7 +83,7 @@ const states = ref();
<QItem>
<QItemSection>
<QCheckbox
:label="t('Has PDF')"
:label="t('invoiceOut.params.hasPdf')"
toggle-indeterminate
v-model="params.hasPdf"
/>
@ -88,14 +93,31 @@ const states = ref();
<QItemSection>
<VnInputDate
v-model="params.created"
:label="t('Created')"
:label="t('invoiceOut.params.created')"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate v-model="params.dued" :label="t('Dued')" is-outlined />
<VnInputDate
v-model="params.dued"
:label="t('invoiceOut.params.dued')"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
rounded
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
</QItemSection>
</QItem>
</template>

View File

@ -8,7 +8,7 @@ import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { usePrintService } from 'src/composables/usePrintService';
import VnTable from 'src/components/VnTable/VnTable.vue';
import InvoiceOutSummary from './Card/InvoiceOutSummary.vue';
import { toCurrency, toDate } from 'src/filters/index';
import { toCurrency, toDate, dashIfEmpty } from 'src/filters/index';
import { QBtn } from 'quasar';
import axios from 'axios';
import InvoiceOutFilter from './InvoiceOutFilter.vue';
@ -16,6 +16,7 @@ import VnRow from 'src/components/ui/VnRow.vue';
import VnRadio from 'src/components/common/VnRadio.vue';
import VnInput from 'src/components/common/VnInput.vue';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from '../Worker/Department/Card/DepartmentDescriptorProxy.vue';
import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n();
@ -54,6 +55,14 @@ const columns = computed(() => [
name: 'id',
},
},
{
align: 'left',
name: 'issued',
label: t('invoiceOut.summary.issued'),
component: 'date',
format: (row) => toDate(row.issued),
columnField: { component: null },
},
{
align: 'left',
name: 'ref',
@ -86,6 +95,20 @@ const columns = computed(() => [
component: null,
},
},
{
align: 'left',
name: 'departmentFk',
label: t('customer.summary.team'),
cardVisible: true,
component: 'select',
attrs: {
url: 'Departments',
},
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
align: 'left',
name: 'companyFk',
@ -229,6 +252,12 @@ watchEffect(selectedRows);
<CustomerDescriptorProxy :id="row.clientFk" />
</span>
</template>
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ dashIfEmpty(row.departmentName) }}
<DepartmentDescriptorProxy :id="row?.departmentFk" />
</span>
</template>
<template #more-create-dialog="{ data }">
<div class="row q-col-gutter-xs col-span-2">
<div class="col-12">

View File

@ -8,7 +8,7 @@ import { useInvoiceOutGlobalStore } from 'src/stores/invoiceOutGlobal.js';
import { useArrayData } from 'src/composables/useArrayData';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import TicketDescriptorProxy from '../Ticket/Card/TicketDescriptorProxy.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import DepartmentDescriptorProxy from '../Worker/Department/Card/DepartmentDescriptorProxy.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import InvoiceOutNegativeBasesFilter from './InvoiceOutNegativeBasesFilter.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
@ -115,18 +115,16 @@ const columns = computed(() => [
},
{
align: 'left',
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'),
name: 'workerName',
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
where: { role: 'salesPerson' },
url: 'Departments',
},
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.workerName),
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
]);
@ -198,10 +196,10 @@ const downloadCSV = async () => {
<TicketDescriptorProxy :id="row.ticketFk" />
</span>
</template>
<template #column-workerName="{ row }">
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ row.workerName }}
<WorkerDescriptorProxy :id="row.comercialId" />
{{ row.departmentName }}
<DepartmentDescriptorProxy :id="row.departmentFk" />
</span>
</template>
<template #moreFilterPanel="{ params }">

View File

@ -129,12 +129,15 @@ const props = defineProps({
</QItem>
<QItem>
<QItemSection>
<VnSelectWorker
:label="t('invoiceOut.negativeBases.comercial')"
v-model="params.workerName"
option-value="name"
is-outlined
@update:model-value="searchFn()"
<VnSelect
outlined
dense
rounded
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
</QItemSection>
</QItem>

View File

@ -1,6 +1,7 @@
invoiceOut:
search: Search invoice
searchInfo: You can search by invoice reference
externalRef: External Ref.
params:
id: ID
company: Company
@ -12,7 +13,6 @@ invoiceOut:
isActive: Active
hasToInvoice: Has to invoice
hasVerifiedData: Verified data
workerName: Worker
isTaxDataChecked: Verified data
amount: Amount
clientFk: Client
@ -26,6 +26,7 @@ invoiceOut:
max: Max
hasPdf: Has PDF
search: Contains
departmentFk: Department
card:
issued: Issued
customerCard: Customer card

View File

@ -1,6 +1,7 @@
invoiceOut:
search: Buscar factura emitida
searchInfo: Puedes buscar por referencia de la factura
externalRef: Ref. externa
params:
id: ID
company: Empresa
@ -12,7 +13,6 @@ invoiceOut:
isActive: Activo
hasToInvoice: Debe facturar
hasVerifiedData: Datos verificados
workerName: Comercial
isTaxDataChecked: Datos comprobados
amount: Importe
clientFk: Cliente
@ -26,6 +26,7 @@ invoiceOut:
max: Max
hasPdf: Tiene PDF
search: Contiene
departmentFk: Departamento
card:
issued: Fecha emisión
customerCard: Ficha del cliente

View File

@ -3,6 +3,7 @@ import { ref, computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import { useStateStore } from 'stores/useStateStore';
import { toCurrency } from 'filters/index';
import useNotify from 'src/composables/useNotify.js';
@ -61,6 +62,7 @@ const columns = computed(() => [
columnClass: 'expand',
},
{
align: 'left',
label: t('item.buyRequest.requester'),
name: 'requesterName',
component: 'select',
@ -77,6 +79,19 @@ const columns = computed(() => [
},
columnClass: 'shrink',
},
{
align: 'left',
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Departments',
},
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
label: t('item.buyRequest.requested'),
name: 'quantity',
@ -107,6 +122,7 @@ const columns = computed(() => [
},
columnClass: 'shrink',
},
{
label: t('globals.item'),
name: 'item',
@ -262,6 +278,12 @@ const onDenyAccept = (_, responseData) => {
<WorkerDescriptorProxy :id="row.requesterFk" />
</span>
</template>
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ row.departmentName }}
<DepartmentDescriptorProxy :id="row.departmentFk" />
</span>
</template>
<template #column-item="{ row }">
<span>

View File

@ -221,7 +221,7 @@ en:
attenderFk: Atender
clientFk: Client id
warehouseFk: Warehouse
requesterFk: Salesperson
requesterFk: Requester
from: From
to: To
mine: For me
@ -239,7 +239,7 @@ es:
attenderFk: Comprador
clientFk: Id cliente
warehouseFk: Almacén
requesterFk: Comercial
requesterFk: Solicitante
from: Desde
to: Hasta
mine: Para mi

View File

@ -7,6 +7,7 @@ import filter from './ItemTypeFilter.js';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
onUpdated(() => summaryRef.value.fetch());
@ -62,13 +63,10 @@ async function setItemTypeData(data) {
</template>
<template #body>
<QCard class="vn-one">
<router-link
:to="{ name: 'ItemTypeBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnTitle
:url="`#/item/item-type/${entityId}/basic-data`"
:text="$t('globals.summary.basicData')"
/>
<VnLv :label="t('itemType.summary.id')" :value="itemType.id" />
<VnLv :label="t('itemType.shared.code')" :value="itemType.code" />
<VnLv :label="t('itemType.shared.name')" :value="itemType.name" />

View File

@ -84,7 +84,7 @@ item:
attenderFk: Atender
clientFk: Client id
warehouseFk: Warehouse
requesterFk: Salesperson
requesterFk: Requester
from: From
to: To
mine: For me

View File

@ -93,7 +93,7 @@ item:
attenderFk: Comprador
clientFk: Id cliente
warehouseFk: Almacén
requesterFk: Comercial
requesterFk: Solicitante
from: Desde
to: Hasta
mine: Para mi

View File

@ -31,7 +31,7 @@ function exprBuilder(param, value) {
switch (param) {
case 'clientFk':
return { [`c.id`]: value };
case 'salesPersonFk':
case 'departmentFk':
return { [`c.${param}`]: value };
}
}
@ -62,25 +62,17 @@ const columns = computed(() => [
columnFilter: false,
},
{
label: t('salesClientsTable.salesPerson'),
name: 'salesPersonFk',
field: 'salesPerson',
align: 'left',
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Departments',
},
columnField: {
component: null,
},
optionFilter: 'firstName',
columnFilter: {
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
sortBy: 'nickname ASC',
where: { role: 'salesPerson' },
useLike: false,
},
},
columnClass: 'no-padding',
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
label: t('salesClientsTable.client'),
@ -128,9 +120,9 @@ const columns = computed(() => [
<VnInputDate v-model="to" :label="$t('globals.to')" dense />
</VnRow>
</template>
<template #column-salesPersonFk="{ row }">
<span class="link" :title="row.salesPerson" v-text="row.salesPerson" />
<WorkerDescriptorProxy :id="row.salesPersonFk" dense />
<template #column-departmentFk="{ row }">
<span class="link" :title="row.department" v-text="row.department" />
<WorkerDescriptorProxy :id="row.departmentFk" dense />
</template>
<template #column-clientFk="{ row }">
<span class="link" :title="row.clientName" v-text="row.clientName" />

View File

@ -1,9 +1,9 @@
<script setup>
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import { toDateFormat, toDateTimeFormat } from 'src/filters/date.js';
import { toCurrency } from 'src/filters';
@ -20,8 +20,8 @@ function exprBuilder(param, value) {
switch (param) {
case 'clientFk':
return { [`c.id`]: value };
case 'salesPersonFk':
return { [`c.salesPersonFk`]: value };
case 'departmentFk':
return { [`c.departmentFk`]: value };
}
}
@ -63,20 +63,18 @@ const columns = computed(() => [
columnFilter: false,
},
{
label: t('salesClientsTable.salesPerson'),
name: 'salesPersonFk',
align: 'left',
optionFilter: 'firstName',
columnFilter: {
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
sortBy: 'nickname ASC',
where: { role: 'salesPerson' },
useLike: false,
},
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Departments',
},
create: true,
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
label: t('salesOrdersTable.import'),
@ -184,11 +182,10 @@ const openTab = (id) =>
<CustomerDescriptorProxy :id="row.clientFk" />
</QTd>
</template>
<template #column-salesPersonFk="{ row }">
<template #column-departmentFk="{ row }">
<QTd @click.stop>
<span class="link" v-text="row.salesPerson" />
<WorkerDescriptorProxy :id="row.salesPersonFk" dense />
<span class="link" v-text="row.departmentName" />
<DepartmentDescriptorProxy :id="row.departmentFk" dense />
</QTd>
</template>
</VnTable>

View File

@ -9,7 +9,6 @@ import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import FetchData from 'src/components/FetchData.vue';
import { dateRange } from 'src/filters';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
defineProps({ dataKey: { type: String, required: true } });
const { t, te } = useI18n();
@ -113,16 +112,16 @@ const getLocale = (label) => {
</QItem>
<QItem>
<QItemSection>
<VnSelectWorker
<VnSelect
outlined
dense
rounded
:label="t('globals.params.salesPersonFk')"
v-model="params.salesPersonFk"
:params="{ departmentCodes: ['VT'] }"
:no-one="true"
>
</VnSelectWorker>
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
</QItemSection>
</QItem>
<QItem>

View File

@ -2,7 +2,7 @@
import { ref, computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
@ -49,8 +49,8 @@ function exprBuilder(param, value) {
switch (param) {
case 'stateFk':
return { 'ts.stateFk': value };
case 'salesPersonFk':
return { 'c.salesPersonFk': !value ? null : value };
case 'departmentFk':
return { 'c.departmentFk': !value ? null : value };
case 'provinceFk':
return { 'a.provinceFk': value };
case 'theoreticalHour':
@ -108,19 +108,18 @@ const columns = computed(() => [
},
},
{
label: t('salesClientsTable.salesPerson'),
name: 'salesPersonFk',
field: 'userName',
align: 'left',
columnFilter: {
component: 'select',
attrs: {
url: 'Workers/search?departmentCodes=["VT"]',
fields: ['id', 'name', 'nickname', 'code'],
sortBy: 'nickname ASC',
optionLabel: 'nickname',
},
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Departments',
},
create: true,
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
label: t('salesClientsTable.date'),
@ -437,10 +436,10 @@ const openTab = (id) => useOpenURL(`#/ticket/${id}/sale`);
<CustomerDescriptorProxy :id="row.clientFk" />
</div>
</template>
<template #column-salesPersonFk="{ row }">
<div @click.stop :title="row.userName">
<span class="link" v-text="dashIfEmpty(row.userName)" />
<WorkerDescriptorProxy :id="row.salesPersonFk" />
<template #column-departmentFk="{ row }">
<div @click.stop :title="row.departmentName">
<span class="link" v-text="dashIfEmpty(row.departmentName)" />
<DepartmentDescriptorProxy :id="row.departmentFk" />
</div>
</template>
<template #column-shippedDate="{ row }">

View File

@ -7,7 +7,6 @@ salesClientsTable:
to: To
date: Date
hour: Hour
salesPerson: Salesperson
client: Client
salesOrdersTable:
delete: Delete

View File

@ -7,7 +7,6 @@ salesClientsTable:
to: Hasta
date: Fecha
hour: Hora
salesPerson: Comercial
client: Cliente
salesOrdersTable:
delete: Eliminar

View File

@ -64,17 +64,7 @@ const orderFilter = {
{
relation: 'client',
scope: {
fields: [
'salesPersonFk',
'name',
'isActive',
'isFreezed',
'isTaxDataChecked',
],
include: {
relation: 'salesPersonUser',
scope: { fields: ['id', 'name'] },
},
fields: ['name', 'isActive', 'isFreezed', 'isTaxDataChecked'],
},
},
],
@ -167,7 +157,7 @@ const onClientChange = async (clientId) => {
!data.isConfirmed &&
agencyList?.length &&
agencyList.some(
(agency) => agency.agencyModeFk === data.agency_id
(agency) => agency.agencyModeFk === data.agency_id,
)
? data.agencyModeFk
: null

View File

@ -8,7 +8,7 @@ import filter from './OrderFilter.js';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchData from 'components/FetchData.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
const DEFAULT_ITEMS = 0;
@ -66,11 +66,11 @@ const total = ref(0);
:label="t('globals.state')"
:value="getConfirmationValue(entity.isConfirmed)"
/>
<VnLv :label="t('order.field.salesPersonFk')">
<VnLv :label="t('customer.summary.team')">
<template #value>
<span class="link">
{{ entity?.client?.salesPersonUser?.name || '-' }}
<WorkerDescriptorProxy :id="entity?.client?.salesPersonFk" />
{{ entity?.client?.department?.name || '-' }}
<DepartmentDescriptorProxy :id="entity?.client?.departmentFk" />
</span>
</template>
</VnLv>

View File

@ -10,14 +10,14 @@ export default {
relation: 'client',
scope: {
fields: [
'salesPersonFk',
'departmentFk',
'name',
'isActive',
'isFreezed',
'isTaxDataChecked',
],
include: {
relation: 'salesPersonUser',
relation: 'department',
scope: { fields: ['id', 'name'] },
},
},

View File

@ -6,7 +6,6 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'components/common/VnInput.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n();
const props = defineProps({
@ -62,15 +61,15 @@ const sourceList = ref([]);
outlined
rounded
/>
<VnSelectWorker
:label="t('globals.salesPerson')"
v-model="params.workerFk"
:params="{
departmentCodes: ['VT'],
}"
dense
<VnSelect
outlined
dense
rounded
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
<VnInputDate
v-model="params.from"
@ -125,7 +124,6 @@ en:
search: Includes
clientFk: Client
agencyModeFk: Agency
salesPersonFk: Sales Person
from: From
to: To
orderFk: Order
@ -136,7 +134,6 @@ en:
showEmpty: Show Empty
customerId: Customer ID
agency: Agency
salesPerson: Sales Person
fromLanded: From Landed
toLanded: To Landed
orderId: Order ID
@ -149,7 +146,6 @@ es:
search: Búsqueda
clientFk: Cliente
agencyModeFk: Agencia
salesPersonFk: Comercial
from: Desde
to: Hasta
orderFk: Cesta
@ -160,7 +156,6 @@ es:
showEmpty: Mostrar vacías
customerId: ID Cliente
agency: Agencia
salesPerson: Comercial
fromLanded: Desde F. entrega
toLanded: Hasta F. entrega
orderId: ID Cesta

View File

@ -10,12 +10,12 @@ import axios from 'axios';
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
import OrderFilter from './Card/OrderFilter.vue';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSection from 'src/components/common/VnSection.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import { getAddresses } from '../Customer/composables/getAddresses';
const { t } = useI18n();
@ -59,22 +59,17 @@ const columns = computed(() => [
},
{
align: 'left',
name: 'salesPersonFk',
label: t('module.salesPerson'),
columnFilter: {
component: 'select',
inWhere: true,
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
where: { role: 'salesPerson' },
useLike: false,
optionValue: 'id',
optionLabel: 'name',
optionFilter: 'firstName',
},
name: 'departmentFk',
label: t('customer.summary.team'),
component: 'select',
attrs: {
url: 'Departments',
},
format: (row) => row?.name,
create: true,
columnField: {
component: null,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
},
{
align: 'center',
@ -264,10 +259,10 @@ const isDefaultAddress = (opt, data) => {
<CustomerDescriptorProxy :id="row?.clientFk" />
</span>
</template>
<template #column-salesPersonFk="{ row }">
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ row?.name }}
<WorkerDescriptorProxy :id="row?.salesPersonFk" />
{{ row?.departmentName }}
<DepartmentDescriptorProxy :id="row?.departmentFk" />
</span>
</template>
<template #column-landed="{ row }">

View File

@ -8,7 +8,6 @@ module:
hour: Hour
agency: Agency
total: Total
salesPerson: Sales Person
address: Address
cerateOrder: Create order
lines:
@ -22,8 +21,6 @@ lines:
params:
tagGroups: Tags
order:
field:
salesPersonFk: Sales Person
form:
clientFk: Client
addressFk: Address

View File

@ -8,7 +8,6 @@ module:
hour: Hora
agency: Agencia
total: Total
salesPerson: Comercial
address: Dirección
cerateOrder: Crear cesta
lines:
@ -22,8 +21,6 @@ lines:
params:
tagGroups: Tags
order:
field:
salesPersonFk: Comercial
form:
clientFk: Cliente
addressFk: Dirección

View File

@ -2,10 +2,13 @@
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import VnTable from 'components/VnTable/VnTable.vue';
import VnSection from 'src/components/common/VnSection.vue';
import AgencySummary from 'pages/Route/Agency/Card/AgencySummary.vue';
const { t } = useI18n();
const { viewSummary } = useSummaryDialog();
const router = useRouter();
const dataKey = 'AgencyList';
function navigate(id) {
@ -40,16 +43,22 @@ const columns = computed(() => [
},
{
align: 'left',
label: t('isOwn'),
label: t('agency.isOwn'),
name: 'isOwn',
component: 'checkbox',
columnFilter: {
inWhere: true,
},
cardVisible: true,
},
{
align: 'left',
label: t('isAnyVolumeAllowed'),
label: t('agency.isAnyVolumeAllowed'),
name: 'isAnyVolumeAllowed',
component: 'checkbox',
columnFilter: {
inWhere: true,
},
cardVisible: true,
},
{
@ -58,9 +67,10 @@ const columns = computed(() => [
name: 'tableActions',
actions: [
{
title: t('Client ticket list'),
title: t('globals.pageTitles.summary'),
icon: 'preview',
action: (row) => navigate(row.id),
action: (row) => viewSummary(row?.id, AgencySummary),
isPrimary: true,
},
],
},
@ -82,7 +92,7 @@ const columns = computed(() => [
<VnTable
:data-key
:columns="columns"
is-editable="false"
:is-editable="false"
:right-search="false"
:use-model="true"
redirect="route/agency"
@ -103,11 +113,3 @@ const columns = computed(() => [
justify-content: center;
}
</style>
<i18n>
es:
isOwn: Tiene propietario
isAnyVolumeAllowed: Permite cualquier volumen
en:
isOwn: Has owner
isAnyVolumeAllowed: Allows any volume
</i18n>

View File

@ -21,7 +21,7 @@ const warehouses = ref([]);
@on-fetch="(data) => (warehouses = data)"
auto-load
/>
<FormModel :update-url="`Agencies/${routeId}`" model="Agency" auto-load>
<FormModel :url-update="`Agencies/${routeId}`" model="Agency" auto-load>
<template #form="{ data }">
<VnRow>
<VnInput v-model="data.name" :label="t('globals.name')" />

View File

@ -0,0 +1,20 @@
<script setup>
import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
import AgencySummary from './AgencySummary.vue';
const $props = defineProps({
id: {
type: Number,
required: true,
},
summary: {
type: Object,
default: null,
},
});
</script>
<template>
<QPopupProxy>
<AgencyDescriptor v-if="$props.id" :id="$props.id" :summary="AgencySummary" />
</QPopupProxy>
</template>

View File

@ -6,29 +6,31 @@ import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import VnCheckbox from 'components/common/VnCheckbox.vue';
const route = useRoute();
const $props = defineProps({ id: { type: Number, default: 0 } });
const { t } = useI18n();
const entityId = computed(() => $props.id || useRoute().params.id);
const entityId = computed(() => $props.id || route.params.id);
</script>
<template>
<div class="q-pa-md">
<CardSummary :url="`Agencies/${entityId}`" data-key="Agency">
<CardSummary :url="`Agencies/${entityId}`" data-key="Agency" module-name="Agency">
<template #header="{ entity: agency }">{{ agency.name }}</template>
<template #body="{ entity: agency }">
<QCard class="vn-one">
<VnTitle
:url="`#/agency/${entityId}/basic-data`"
:url="`#/${route.meta.moduleName.toLowerCase()}/agency/${entityId}/basic-data`"
:text="t('globals.pageTitles.basicData')"
/>
<VnLv :label="t('globals.name')" :value="agency.name" />
<QCheckbox
<VnCheckbox
:label="t('agency.isOwn')"
v-model="agency.isOwn"
:disable="true"
/>
<QCheckbox
<VnCheckbox
:label="t('agency.isAnyVolumeAllowed')"
v-model="agency.isAnyVolumeAllowed"
:disable="true"

View File

@ -80,6 +80,7 @@ async function deleteWorCenter(id) {
color="primary"
round
flat
data-cy="removeWorkCenterBtn"
/>
</QItemSection>
</QItem>

View File

@ -1,11 +1,12 @@
agency:
search: Search agency
searchInfo: You can search by name
searchInfo: You can search by name and by id
isOwn: Own
isAnyVolumeAllowed: Any volume allowed
removeItem: Agency removed successfully
notification:
removeItemError: Error removing agency
removeItem: WorkCenter removed successfully
removeItemError: Error removing work center
removeItem: Work center removed successfully
pageTitles:
agency: Agency
searchBar:

View File

@ -1,15 +1,14 @@
agency:
search: Buscar agencia
searchInfo: Puedes buscar por nombre
searchInfo: Puedes buscar por nombre y por id
isOwn: Propio
isAnyVolumeAllowed: Cualquier volumen
removeItem: Agencia eliminada correctamente
notification:
removeItemError: Error al eliminar la agencia
removeItemError: Error al eliminar la el centro de trabajo
removeItem: Centro de trabajo eliminado correctamente
pageTitles:
agency: Agencia
searchBar:
info: Puedes buscar por nombre o id
label: Buscar agencia...

View File

@ -7,6 +7,10 @@ const $props = defineProps({
type: Number,
required: true,
},
summary: {
type: Object,
default: null,
},
});
</script>
<template>

View File

@ -25,7 +25,7 @@ const emit = defineEmits(['search']);
>
<template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong>
<strong>{{ t(`route.params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span>
</div>
</template>
@ -33,6 +33,7 @@ const emit = defineEmits(['search']);
<QItem class="q-my-sm">
<QItemSection>
<VnSelectWorker
:label="t('globals.worker')"
v-model="params.workerFk"
dense
outlined
@ -44,7 +45,7 @@ const emit = defineEmits(['search']);
<QItem class="q-my-sm">
<QItemSection>
<VnSelect
:label="t('Agency')"
:label="t('globals.agency')"
v-model="params.agencyModeFk"
url="AgencyModes/isActive"
sort-by="name ASC"
@ -61,7 +62,7 @@ const emit = defineEmits(['search']);
<QItemSection>
<VnInputDate
v-model="params.from"
:label="t('From')"
:label="t('globals.from')"
is-outlined
:disable="Boolean(params.scopeDays)"
@update:model-value="params.scopeDays = null"
@ -72,7 +73,7 @@ const emit = defineEmits(['search']);
<QItemSection>
<VnInputDate
v-model="params.to"
:label="t('To')"
:label="t('globals.to')"
is-outlined
:disable="Boolean(params.scopeDays)"
@update:model-value="params.scopeDays = null"
@ -84,7 +85,7 @@ const emit = defineEmits(['search']);
<VnInput
v-model="params.scopeDays"
type="number"
:label="t('Days Onward')"
:label="t('globals.daysOnward')"
is-outlined
clearable
:disable="Boolean(params.from || params.to)"
@ -98,7 +99,7 @@ const emit = defineEmits(['search']);
<QItem class="q-my-sm">
<QItemSection>
<VnSelect
:label="t('Vehicle')"
:label="t('globals.vehicle')"
v-model="params.vehicleFk"
url="Vehicles/active"
sort-by="numberPlate ASC"
@ -120,7 +121,7 @@ const emit = defineEmits(['search']);
<QItem class="q-my-sm">
<QItemSection>
<VnSelect
:label="t('Warehouse')"
:label="t('globals.warehouse')"
v-model="params.warehouseFk"
url="Warehouses"
option-value="id"
@ -136,7 +137,7 @@ const emit = defineEmits(['search']);
<QItemSection>
<VnInput
v-model="params.description"
:label="t('Description')"
:label="t('globals.description')"
is-outlined
clearable
/>
@ -146,7 +147,7 @@ const emit = defineEmits(['search']);
<QItemSection>
<QCheckbox
v-model="params.isOk"
:label="t('Served')"
:label="t('route.filter.Served')"
toggle-indeterminate
/>
</QItemSection>
@ -154,38 +155,3 @@ const emit = defineEmits(['search']);
</template>
</VnFilterPanel>
</template>
<i18n>
en:
params:
warehouseFk: Warehouse
description: Description
m3:
scopeDays: Days Onward
vehicleFk: Vehicle
agencyModeFk: Agency
workerFk: Worker
from: From
to: To
Served: Served
es:
params:
warehouseFk: Almacén
description: Descripción
m3:
scopeDays: Días en adelante
vehicleFk: Vehículo
agencyModeFk: Agencia
workerFk: Trabajador
from: Desde
to: Hasta
Warehouse: Almacén
Description: Descripción
Vehicle: Vehículo
Agency: Agencia
Worker: Trabajador
From: Desde
To: Hasta
Served: Servida
Days Onward: Días en adelante
</i18n>

View File

@ -135,7 +135,7 @@ const ticketColumns = ref([
<template #body="{ entity }">
<QCard class="vn-max">
<VnTitle
:url="`#/route/${entityId}/basic-data`"
:url="`#/${route.meta.moduleName.toLowerCase()}/${entityId}/basic-data`"
:text="t('globals.pageTitles.basicData')"
/>
</QCard>
@ -221,7 +221,7 @@ const ticketColumns = ref([
<template #body-cell-city="{ value, row }">
<QTd auto-width>
<span
class="link cursor-pointer"
class="link"
@click="openBuscaman(entity?.route?.vehicleFk, [row])"
>
{{ value }}
@ -230,7 +230,7 @@ const ticketColumns = ref([
</template>
<template #body-cell-client="{ value, row }">
<QTd auto-width>
<span class="link cursor-pointer">
<span class="link">
{{ value }}
<CustomerDescriptorProxy :id="row?.clientFk" />
</span>
@ -238,7 +238,7 @@ const ticketColumns = ref([
</template>
<template #body-cell-ticket="{ value, row }">
<QTd auto-width class="text-center">
<span class="link cursor-pointer">
<span class="link">
{{ value }}
<TicketDescriptorProxy :id="row?.id" />
</span>

View File

@ -17,7 +17,7 @@ const onSave = (data, response) => {
</script>
<template>
<FormModel
:update-url="`Roadmaps/${$route.params?.id}`"
:url-update="`Roadmaps/${$route.params?.id}`"
:url="`Roadmaps/${$route.params?.id}`"
observe-form-changes
model="Roadmap"

View File

@ -15,6 +15,10 @@ const $props = defineProps({
required: false,
default: null,
},
summary: {
type: Object,
default: null,
},
});
const route = useRoute();
@ -26,7 +30,12 @@ const entityId = computed(() => {
</script>
<template>
<CardDescriptor :url="`Roadmaps/${entityId}`" :filter="filter" data-key="Roadmap">
<CardDescriptor
:url="`Roadmaps/${entityId}`"
:filter="filter"
data-key="Roadmap"
:summary="summary"
>
<template #body="{ entity }">
<VnLv :label="t('Roadmap')" :value="entity?.name" />
<VnLv :label="t('ETD')" :value="toDateHourMin(entity?.etd)" />

View File

@ -13,6 +13,7 @@ import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import RouteDescriptorProxy from 'pages/Route/Card/RouteDescriptorProxy.vue';
import InvoiceInDescriptorProxy from 'pages/InvoiceIn/Card/InvoiceInDescriptorProxy.vue';
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
import AgencyDescriptorProxy from 'pages/Route/Agency/Card/AgencyDescriptorProxy.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue';
import VnDms from 'components/common/VnDms.vue';
import VnTable from 'components/VnTable/VnTable.vue';
@ -236,10 +237,16 @@ onUnmounted(() => (stateStore.rightDrawer = false));
selection: 'multiple',
}"
>
<template #column-id="{ row }">
<template #column-agencyModeName="{ row }">
<span class="link" @click.stop>
{{ row.routeFk }}
<RouteDescriptorProxy :id="row.route.id" />
{{ row?.agencyModeName }}
<AgencyDescriptorProxy :id="row?.agencyModeFk" v-if="row?.agencyModeFk" />
</span>
</template>
<template #column-agencyAgreement="{ row }">
<span class="link" @click.stop>
{{ row?.agencyAgreement }}
<AgencyDescriptorProxy :id="row?.agencyFk" v-if="row?.agencyFk" />
</span>
</template>
<template #column-invoiceInFk="{ row }">

View File

@ -38,7 +38,7 @@ const routeFilter = {
};
const columns = computed(() => [
{
align: 'center',
align: 'right',
name: 'id',
label: 'Id',
chip: {
@ -46,11 +46,11 @@ const columns = computed(() => [
},
isId: true,
columnFilter: false,
width: '25px',
},
{
align: 'center',
name: 'workerFk',
label: t('route.Worker'),
label: t('globals.worker'),
create: true,
component: 'select',
attrs: {
@ -71,9 +71,8 @@ const columns = computed(() => [
format: (row, dashIfEmpty) => dashIfEmpty(row.workerUserName),
},
{
align: 'center',
name: 'agencyModeFk',
label: t('route.Agency'),
label: t('globals.agency'),
isTitle: true,
cardVisible: true,
create: true,
@ -90,9 +89,8 @@ const columns = computed(() => [
format: (row, dashIfEmpty) => dashIfEmpty(row.agencyName),
},
{
align: 'center',
name: 'vehicleFk',
label: t('route.Vehicle'),
label: t('globals.vehicle'),
cardVisible: true,
create: true,
component: 'select',
@ -111,9 +109,8 @@ const columns = computed(() => [
format: (row, dashIfEmpty) => dashIfEmpty(row.vehiclePlateNumber),
},
{
align: 'center',
name: 'dated',
label: t('route.Date'),
label: t('globals.date'),
columnFilter: false,
cardVisible: true,
create: true,
@ -122,9 +119,8 @@ const columns = computed(() => [
dated === '0000-00-00' ? dashIfEmpty(null) : toDate(dated),
},
{
align: 'center',
name: 'from',
label: t('route.From'),
label: t('globals.from'),
visible: false,
cardVisible: true,
create: true,
@ -132,9 +128,8 @@ const columns = computed(() => [
format: ({ from }) => toDate(from),
},
{
align: 'center',
name: 'to',
label: t('route.To'),
label: t('globals.to'),
visible: false,
cardVisible: true,
create: true,
@ -142,30 +137,31 @@ const columns = computed(() => [
format: ({ date }) => toDate(date),
},
{
align: 'center',
align: 'right',
name: 'm3',
label: 'm3',
cardVisible: true,
columnClass: 'shrink',
width: '50px',
},
{
align: 'center',
name: 'started',
label: t('route.hourStarted'),
component: 'time',
columnFilter: false,
format: ({ started }) => toHour(started),
width: '50px',
},
{
align: 'center',
name: 'finished',
label: t('route.hourFinished'),
component: 'time',
columnFilter: false,
format: ({ finished }) => toHour(finished),
width: '50px',
},
{
align: 'center',
align: 'right',
name: 'kmStart',
label: t('route.KmStart'),
columnClass: 'shrink',
@ -173,7 +169,7 @@ const columns = computed(() => [
visible: false,
},
{
align: 'center',
align: 'right',
name: 'kmEnd',
label: t('route.KmEnd'),
columnClass: 'shrink',
@ -181,16 +177,15 @@ const columns = computed(() => [
visible: false,
},
{
align: 'center',
align: 'left',
name: 'description',
label: t('route.Description'),
label: t('globals.description'),
isTitle: true,
create: true,
component: 'input',
field: 'description',
},
{
align: 'center',
name: 'isOk',
label: t('route.Served'),
component: 'checkbox',
@ -202,7 +197,7 @@ const columns = computed(() => [
name: 'tableActions',
actions: [
{
title: t('route.Add tickets'),
title: t('route.addTicket'),
icon: 'vn:ticketAdd',
action: (row) => openTicketsDialog(row?.id),
isPrimary: true,
@ -214,7 +209,7 @@ const columns = computed(() => [
isPrimary: true,
},
{
title: t('route.Route summary'),
title: t('route.routeSummary'),
icon: 'arrow_forward',
action: (row) => navigate(row?.id),
isPrimary: true,
@ -276,11 +271,13 @@ const openTicketsDialog = (id) => {
<QDialog v-model="confirmationDialog">
<QCard style="min-width: 350px">
<QCardSection>
<p class="text-h6 q-ma-none">{{ t('route.Select the starting date') }}</p>
<p class="text-h6 q-ma-none">
{{ t('route.extendedList.selectStartingDate') }}
</p>
</QCardSection>
<QCardSection class="q-pt-none">
<VnInputDate
:label="t('route.Starting date')"
:label="t('route.extendedList.startingDate')"
v-model="startingDate"
autofocus
/>
@ -288,7 +285,7 @@ const openTicketsDialog = (id) => {
<QCardActions align="right">
<QBtn
flat
:label="t('route.Cancel')"
:label="t('globals.cancel')"
v-close-popup
class="text-primary"
/>
@ -339,7 +336,7 @@ const openTicketsDialog = (id) => {
:disable="!selectedRows?.length"
@click="confirmationDialog = true"
>
<QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
<QTooltip>{{ t('route.extendedList.cloneSelectedRoutes') }}</QTooltip>
</QBtn>
<QBtn
icon="cloud_download"
@ -348,7 +345,9 @@ const openTicketsDialog = (id) => {
:disable="!selectedRows?.length"
@click="showRouteReport"
>
<QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
<QTooltip>{{
t('route.extendedList.downloadSelectedRoutes')
}}</QTooltip>
</QBtn>
<QBtn
icon="check"
@ -357,7 +356,7 @@ const openTicketsDialog = (id) => {
:disable="!selectedRows?.length"
@click="markAsServed()"
>
<QTooltip>{{ t('route.Mark as served') }}</QTooltip>
<QTooltip>{{ t('route.extendedList.markServed') }}</QTooltip>
</QBtn>
</template>
</VnTable>

View File

@ -7,8 +7,11 @@ import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import AgencyDescriptorProxy from 'src/pages/Route/Agency/Card/AgencyDescriptorProxy.vue';
import VehicleDescriptorProxy from 'src/pages/Route/Vehicle/Card/VehicleDescriptorProxy.vue';
import VnSection from 'src/components/common/VnSection.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import RouteTickets from './RouteTickets.vue';
const { t } = useI18n();
const { viewSummary } = useSummaryDialog();
@ -24,6 +27,12 @@ const routeFilter = {
},
],
};
function redirectToTickets(id) {
const url = `#/route/${id}/tickets`;
window.open(url, '_blank');
}
const columns = computed(() => [
{
align: 'right',
@ -34,25 +43,29 @@ const columns = computed(() => [
condition: () => true,
},
columnFilter: false,
width: '25px',
},
{
align: 'left',
name: 'workerFk',
label: t('route.Worker'),
label: t('gloabls.worker'),
component: markRaw(VnSelectWorker),
create: true,
cardVisible: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
columnFilter: false,
width: '100px',
},
{
align: 'left',
name: 'agencyName',
label: t('route.Agency'),
name: 'workerFk',
label: t('globals.worker'),
visible: false,
cardVisible: true,
},
{
label: t('route.Agency'),
name: 'agencyName',
label: t('globals.agency'),
},
{
label: t('globals.Agency'),
name: 'agencyModeFk',
component: 'select',
attrs: {
@ -68,14 +81,18 @@ const columns = computed(() => [
visible: false,
},
{
align: 'left',
name: 'vehiclePlateNumber',
label: t('route.Vehicle'),
name: 'agencyName',
label: t('globals.agency'),
visible: false,
cardVisible: true,
},
{
name: 'vehiclePlateNumber',
label: t('globals.vehicle'),
},
{
name: 'vehicleFk',
label: t('route.Vehicle'),
label: t('globals.Vehicle'),
cardVisible: true,
component: 'select',
attrs: {
@ -93,25 +110,27 @@ const columns = computed(() => [
visible: false,
},
{
align: 'left',
align: 'center',
name: 'started',
label: t('route.hourStarted'),
cardVisible: true,
columnFilter: false,
format: (row) => toHour(row.started),
format: ({ started }) => toHour(started),
width: '50px',
},
{
align: 'left',
align: 'center',
name: 'finished',
label: t('route.hourFinished'),
cardVisible: true,
columnFilter: false,
format: (row) => toHour(row.started),
format: ({ finished }) => toHour(finished),
width: '50px',
},
{
align: 'left',
name: 'description',
label: t('route.Description'),
label: t('globals.description'),
cardVisible: true,
isTitle: true,
create: true,
@ -119,7 +138,6 @@ const columns = computed(() => [
columnFilter: false,
},
{
align: 'left',
name: 'isOk',
label: t('route.Served'),
component: 'checkbox',
@ -130,6 +148,12 @@ const columns = computed(() => [
align: 'right',
name: 'tableActions',
actions: [
{
title: t('globals.pageTitles.tickets'),
icon: 'vn:ticket',
action: (row) => redirectToTickets(row?.id),
isPrimary: true,
},
{
title: t('components.smartCard.viewSummary'),
icon: 'preview',
@ -155,6 +179,7 @@ const columns = computed(() => [
</template>
<template #body>
<VnTable
:with-filters="false"
:data-key
:columns="columns"
ref="tableRef"
@ -174,6 +199,24 @@ const columns = computed(() => [
<WorkerDescriptorProxy :id="row?.workerFk" v-if="row?.workerFk" />
</span>
</template>
<template #column-agencyName="{ row }">
<span class="link" @click.stop>
{{ row?.agencyName }}
<AgencyDescriptorProxy
:id="row?.agencyModeFk"
v-if="row?.agencyModeFk"
/>
</span>
</template>
<template #column-vehiclePlateNumber="{ row }">
<span class="link" @click.stop>
{{ row?.vehiclePlateNumber }}
<VehicleDescriptorProxy
:id="row?.vehicleFk"
v-if="row?.vehicleFk"
/>
</span>
</template>
</VnTable>
</template>
</VnSection>

View File

@ -2,13 +2,11 @@
import { useI18n } from 'vue-i18n';
import { computed, ref } from 'vue';
import { dashIfEmpty } from 'src/filters';
import { toDate, toDateHourMin } from 'filters/index';
import { toDate, toDateHourMin, toCurrency } from 'filters/index';
import { useQuasar } from 'quasar';
import { useSummaryDialog } from 'composables/useSummaryDialog';
import toCurrency from 'filters/toCurrency';
import axios from 'axios';
import VnSearchbar from 'components/ui/VnSearchbar.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import RoadmapSummary from 'pages/Route/Roadmap/RoadmapSummary.vue';
@ -17,6 +15,8 @@ import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputTime from 'src/components/common/VnInputTime.vue';
import VnSection from 'src/components/common/VnSection.vue';
import RoadmapFilter from './Roadmap/RoadmapFilter.vue';
import VehicleDescriptorProxy from 'src/pages/Route/Vehicle/Card/VehicleDescriptorProxy.vue';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
const { viewSummary } = useSummaryDialog();
const { t } = useI18n();
@ -33,7 +33,7 @@ const columns = computed(() => [
{
align: 'left',
name: 'name',
label: t('Roadmap'),
label: t('route.roadmap.roadmap'),
create: true,
cardVisible: true,
columnFilter: {
@ -41,9 +41,9 @@ const columns = computed(() => [
},
},
{
align: 'left',
align: 'center',
name: 'etd',
label: t('ETD'),
label: t('route.roadmap.etd'),
component: 'date',
columnFilter: {
inWhere: true,
@ -54,7 +54,7 @@ const columns = computed(() => [
{
align: 'left',
name: 'supplierFk',
label: t('Carrier'),
label: t('route.roadmap.carrier'),
component: 'select',
attrs: {
url: 'suppliers',
@ -65,21 +65,21 @@ const columns = computed(() => [
},
{
name: 'tractorPlate',
label: t('Plate'),
label: t('route.roadmap.vehicle'),
field: (row) => row.tractorPlate,
sortable: true,
align: 'left',
},
{
name: 'price',
label: t('Price'),
field: (row) => toCurrency(row.price),
label: t('route.roadmap.price'),
format: ({ price }) => toCurrency(price),
sortable: true,
align: 'left',
align: 'right',
},
{
name: 'observations',
label: t('Observations'),
label: t('route.roadmap.observations'),
field: (row) => dashIfEmpty(row.observations),
sortable: true,
align: 'left',
@ -89,7 +89,7 @@ const columns = computed(() => [
name: 'tableActions',
actions: [
{
title: t('Ver cmr'),
title: t('route.roadmap.seeCmr'),
icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row?.id, RoadmapSummary),
@ -124,8 +124,8 @@ function confirmRemove() {
.dialog({
component: VnConfirm,
componentProps: {
title: t('Selected roadmaps will be removed'),
message: t('Are you sure you want to continue?'),
title: t('route.roadmap.selectedRoadmapsRemoved'),
message: t('route.roadmap.areYouSure'),
promise: removeSelection,
},
})
@ -157,15 +157,24 @@ function exprBuilder(param, value) {
<QCard style="min-width: 350px">
<QCardSection>
<p class="text-h6 q-ma-none">
{{ t('Select the estimated date of departure (ETD)') }}
{{ t('route.roadmap.selectEtd') }}
</p>
</QCardSection>
<QCardSection class="q-pt-none">
<VnInputDate :label="t('ETD')" v-model="etdDate" autofocus />
<VnInputDate
:label="t('route.roadmap.etd')"
v-model="etdDate"
autofocus
/>
</QCardSection>
<QCardActions align="right">
<QBtn flat :label="t('Cancel')" v-close-popup class="text-primary" />
<QBtn
flat
:label="t('globals.cancel')"
v-close-popup
class="text-primary"
/>
<QBtn color="primary" v-close-popup @click="cloneSelection">
{{ t('globals.clone') }}
</QBtn>
@ -181,7 +190,7 @@ function exprBuilder(param, value) {
:disable="!selectedRows?.length"
@click="isCloneDialogOpen = true"
>
<QTooltip>{{ t('Clone Selected Routes') }}</QTooltip>
<QTooltip>{{ t('route.roadmap.cloneSelected') }}</QTooltip>
</QBtn>
<QBtn
icon="delete"
@ -190,7 +199,7 @@ function exprBuilder(param, value) {
:disable="!selectedRows?.length"
@click="confirmRemove"
>
<QTooltip>{{ t('Delete roadmap(s)') }}</QTooltip>
<QTooltip>{{ t('route.roadmap.deleteRoadmap') }}</QTooltip>
</QBtn>
</template>
</VnSubToolbar>
@ -222,7 +231,7 @@ function exprBuilder(param, value) {
redirect="route/roadmap"
:create="{
urlCreate: 'Roadmaps',
title: t('Create routemap'),
title: t('route.roadmap.createRoadmap'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
@ -232,7 +241,10 @@ function exprBuilder(param, value) {
{{ toDateHourMin(row.etd) }}
</template>
<template #column-supplierFk="{ row }">
{{ row.supplierFk }}
<span class="link" @click.stop>
{{ row.driverName }}
<SupplierDescriptorProxy :id="row.supplierFk" />
</span>
</template>
<template #more-create-dialog="{ data }">
<VnInputDate v-model="data.etd" />
@ -251,21 +263,3 @@ function exprBuilder(param, value) {
gap: 12px;
}
</style>
<i18n>
es:
Create routemap: Crear troncal
Search roadmaps: Buscar troncales
You can search by roadmap reference: Puedes buscar por referencia del troncal
Delete roadmap(s): Eliminar troncal(es)
Selected roadmaps will be removed: Los troncales seleccionadas serán eliminados
Are you sure you want to continue?: ¿Seguro que quieres continuar?
The date can't be empty: La fecha no puede estar vacía
Clone Selected Routes: Clonar rutas seleccionadas
Create roadmap: Crear troncal
Roadmap: Troncal
Carrier: Transportista
Plate: Matrícula
Price: Precio
Observations: Observaciones
Select the estimated date of departure (ETD): Selecciona la fecha estimada de salida
</i18n>

View File

@ -37,9 +37,9 @@ const columns = computed(() => [
align: 'left',
},
{
name: 'city',
label: t('City'),
field: (row) => row?.city,
name: 'client',
label: t('Client'),
field: (row) => row?.nickname,
sortable: false,
align: 'left',
},
@ -51,9 +51,9 @@ const columns = computed(() => [
align: 'center',
},
{
name: 'client',
label: t('Client'),
field: (row) => row?.nickname,
name: 'city',
label: t('City'),
field: (row) => row?.city,
sortable: false,
align: 'left',
},

View File

@ -1,17 +1,29 @@
<script setup>
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import VnLv from 'src/components/ui/VnLv.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
const { notify } = useNotify();
const props = defineProps({
id: {
type: Number,
required: false,
default: null,
},
});
const route = useRoute();
const entityId = computed(() => props.id || route.params.id);
</script>
<template>
<CardDescriptor
:url="`Vehicles/${$route.params.id}`"
:url="`Vehicles/${entityId}`"
data-key="Vehicle"
title="numberPlate"
:to-module="{ name: 'VehicleList' }"
>
<template #menu="{ entity }">
<QItem

View File

@ -0,0 +1,20 @@
<script setup>
import VehicleDescriptor from 'pages/Route/Vehicle/Card/VehicleDescriptor.vue';
import VehicleSummary from './VehicleSummary.vue';
const $props = defineProps({
id: {
type: Number,
required: true,
},
summary: {
type: Object,
default: null,
},
});
</script>
<template>
<QPopupProxy>
<VehicleDescriptor v-if="$props.id" :id="$props.id" :summary="VehicleSummary" />
</QPopupProxy>
</template>

View File

@ -17,12 +17,13 @@ const props = defineProps({ id: { type: [Number, String], default: null } });
const invoices = ref([]);
const route = useRoute();
const entityId = computed(() => props.id || +route.params.id);
const baseLink = `#/${route.meta.moduleName.toLowerCase()}/vehicle/${entityId.value}`;
const links = {
'basic-data': `#/${route.meta.moduleName}/vehicle/${entityId.value}/basic-data`,
notes: `#/${route.meta.moduleName}/vehicle/${entityId.value}/notes`,
dms: `#/${route.meta.moduleName}/vehicle/${entityId.value}/dms`,
'invoice-in': `#/${route.meta.moduleName}/vehicle/${entityId.value}/invoice-in`,
events: `#/${route.meta.moduleName}/vehicle/${entityId.value}/events`,
'basic-data': `${baseLink}/basic-data`,
notes: `${baseLink}/notes`,
dms: `${baseLink}/dms`,
'invoice-in': `${baseLink}/invoice-in`,
events: `${baseLink}/events`,
};
</script>
<template>
@ -63,7 +64,10 @@ const links = {
<template #value>
<span class="link">
{{ entity.supplier?.name }}
<SupplierDescriptorProxy :id="entity.supplierFk" />
<SupplierDescriptorProxy
v-if="entity.supplierFk"
:id="entity.supplierFk"
/>
</span>
</template>
</VnLv>
@ -72,6 +76,7 @@ const links = {
<span class="link">
{{ entity.supplierCooler?.name }}
<SupplierDescriptorProxy
v-if="entity.supplierCoolerFk"
:id="entity.supplierCoolerFk"
/>
</span>

View File

@ -116,6 +116,7 @@ const columns = computed(() => [
title: t('components.smartCard.openSummary'),
icon: 'preview',
action: (row) => viewSummary(row.id, VehicleSummary),
isPrimary: true,
},
],
},

View File

@ -1,24 +1,56 @@
route:
filter:
Served: Served
extendedList:
selectStartingDate: Select the starting date
startingDate: Starting date
cloneSelectedRoutes: Clone selected routes
downloadSelectedRoutes: Download selected routes as PDF
markServed: Mark as served
roadmap:
roadmap: Roadmap
carrier: Carrier
vehicle: Vehicle
price: Price
observations: Observations
etd: ETD
dateCantEmpty: The date can't be empty
createRoadmap: Create roadmap
deleteRoadmap: Delete roadmap(s)
cloneSelected: Clone selected routes
selectedRoadmapsRemoved: Selected roadmaps will be removed
areYouSure: Are you sure you want to continue?
selectEtd: Select the estimated date of departure (ETD)
search: Search roadmap
searchInfo: You can search by roadmap reference
params:
id: Id
name: Name
warehouseFk: Warehouse
description: Description
m3:
scopeDays: Days Onward
vehicleFk: Vehicle
agencyModeFk: Agency
workerFk: Worker
from: From
to: To
isOk: Served
etd: ETD
tractorPlate: Plate
price: Price
observations: Observations
id: Id
name: Name
cmrFk: CMR id
hasCmrDms: Attached in gestdoc
ticketFk: Ticketd id
routeFk: Route id
clientFk: Client id
countryFk: Country
warehouseFk: Warehouse
shipped: Shipped
agencyAgreement: Agency agreement
agencyModeName: Agency route
isOwn: Own
isAnyVolumeallowed: Any volume allowed
issued: Issued
jtubau marked this conversation as resolved
Review

Creo que esta traduccion es global, o por lo menos es exactamente la misma que en invoiceIn, hazla global o mira a ver si ya está.

Creo que esta traduccion es global, o por lo menos es exactamente la misma que en invoiceIn, hazla global o mira a ver si ya está.
Worker: Worker
Agency: Agency
@ -26,25 +58,19 @@ route:
Description: Description
hourStarted: H.Start
hourFinished: H.End
dated: Dated
From: From
To: To
createRoute: Create route
Date: Date
KmStart: Km start
KmEnd: Km end
Served: Served
Clone Selected Routes: Clone selected routes
Select the starting date: Select the starting date
Stating date: Starting date
Cancel: Cancel
Mark as served: Mark as served
Download selected routes as PDF: Download selected routes as PDF
Add ticket: Add ticket
Summary: Summary
addTicket: Add ticket
routeSummary: Go to summary
Route is closed: Route is closed
Route is not served: Route is not served
search: Search route
searchInfo: You can search by route reference
dated: Dated
preview: Preview
cmr:
search: Search Cmr
searchInfo: You can search Cmr by Id

View File

@ -1,14 +1,45 @@
route:
filter:
Served: Servida
extendedList:
selectStartingDate: Seleccione la fecha de inicio
statingDate: Fecha de inicio
cloneSelectedRoutes: Clonar rutas seleccionadas
downloadSelectedRoutes: Descargar rutas seleccionadas como PDF
markServed: Marcar como servidas
roadmap:
roadmap: Troncal
carrier: Transportista
vehicle: Vehículo
price: Precio
observations: Observaciones
etd: ETD
dateCantEmpty: La fecha no puede estar vacía
createRoadmap: Crear troncal
deleteRoadmap: Eliminar troncal(es)
cloneSelected: Clonar rutas seleccionadas
jtubau marked this conversation as resolved Outdated

Poner todas las fechas con el mismo formato. F. x

Poner todas las fechas con el mismo formato. F. x
selectedRoadmapsRemoved: Los troncales seleccionadas serán eliminados
areYouSure: ¿Seguro que quieres continuar?
selectEtd: Selecciona la fecha estimada de salida
search: Buscar troncales
searchInfo: Puedes buscar por referencia del troncal
params:
id: Id
name: Troncal
warehouseFk: Almacén
description: Descripción
m3:
scopeDays: Días adelante
vehicleFk: Vehículo
agencyModeFk: Agencia
workerFk: Trabajador
from: Desde
to: Hasta
isOk: Servida
etd: ETD
tractorPlate: Matrícula
price: Precio
observations: Observaciones
id: Id
name: Troncal
cmrFk: Id CMR
hasCmrDms: Gestdoc
search: Búsqueda general
@ -20,6 +51,8 @@ route:
shipped: F. preparación
agencyModeName: Agencia Ruta
agencyAgreement: Agencia Acuerdo
isOwn: Propio
isAnyVolumeAllowed: Cualquier volumen
jtubau marked this conversation as resolved
Review

Lo mismo que en inglés

Lo mismo que en inglés
Review

esta ahí por el filtro automático de vnTable, ya que busca la traducción en moduleName.params y en este caso es route.params

esta ahí por el filtro automático de vnTable, ya que busca la traducción en moduleName.params y en este caso es route.params
issued: F. emisión
Worker: Trabajador
Agency: Agencia
@ -28,25 +61,18 @@ route:
hourStarted: H.Inicio
hourFinished: H.Fin
createRoute: Crear ruta
From: Desde
To: Hasta
Date: Fecha
KmStart: Km inicio
KmEnd: Km fin
Served: Servida
Clone Selected Routes: Clonar rutas seleccionadas
Select the starting date: Seleccione la fecha de inicio
Stating date: Fecha de inicio
Cancel: Cancelar
Mark as served: Marcar como servidas
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
Add ticket: Añadir tickets
preview: Vista previa
Summary: Resumen
addTicket: Añadir tickets
routeSummary: Ir a vista previa
Route is closed: La ruta está cerrada
Route is not served: La ruta no está servida
search: Buscar rutas
searchInfo: Puedes buscar por referencia de la ruta
dated: Fecha
preview: Vista previa
cmr:
list:
results: resultados

View File

@ -2,6 +2,7 @@
import { useI18n } from 'vue-i18n';
import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n();
const props = defineProps({
@ -46,19 +47,7 @@ const emit = defineEmits(['search']);
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnSelect
dense
outlined
rounded
:label="t('params.userFk')"
v-model="params.userFk"
url="Workers/activeWithInheritedRole"
option-value="id"
option-label="firstName"
:where="{ role: 'salesPerson' }"
sort-by="firstName ASC"
:use-like="false"
/>
<VnSelectWorker v-model="params.userFk" outlined rounded />
</QItemSection>
</QItem>
<QItem class="q-mb-md">

View File

@ -6,6 +6,7 @@ import VnLv from 'components/ui/VnLv.vue';
import VnUserLink from 'components/ui/VnUserLink.vue';
import filter from './ShelvingFilter.js';
import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const $props = defineProps({
id: {
@ -38,13 +39,10 @@ const entityId = computed(() => $props.id || route.params.id);
</template>
<template #body="{ entity }">
<QCard class="vn-one">
<RouterLink
class="header header-link"
:to="{ name: 'ShelvingBasicData', params: { id: entityId } }"
>
{{ $t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</RouterLink>
<VnTitle
:url="`#/shelving/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
<VnLv :label="$t('globals.code')" :value="entity.code" />
<VnLv
:label="$t('shelving.list.parking')"

View File

@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const $props = defineProps({
id: {
@ -28,13 +29,10 @@ const filter = {
<template #body="{ entity }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<a
class="header header-link"
:href="`#/parking/${entityId}/basic-data`"
>
{{ t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</a>
<VnTitle
:url="`#/shelving/parking/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
</QCardSection>
<VnLv :label="t('globals.code')" :value="entity.code" />
<VnLv

View File

@ -203,7 +203,7 @@ onMounted(async () => {
</QTr>
<QTr v-for="(buy, index) in row.buys" :key="index">
<QTd no-hover>
<QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
<QBtn flat class="link" dense no-caps>{{ buy.itemName }}</QBtn>
<ItemDescriptorProxy :id="buy.itemFk" />
</QTd>

View File

@ -44,8 +44,8 @@ const getPriceDifference = async () => {
shipped: ticket.value.shipped,
};
const { data } = await axios.post(
`tickets/${ticket.value.id}/priceDifference`,
params
`tickets/${formData.value.id}/priceDifference`,
params,
);
ticket.value.sale = data;
};
@ -71,8 +71,8 @@ const submit = async () => {
};
const { data } = await axios.post(
`tickets/${ticket.value.id}/componentUpdate`,
params
`tickets/${formData.value.id}/componentUpdate`,
params,
);
if (!data) return;
@ -99,7 +99,7 @@ const onNextStep = async () => {
openConfirmationModal(
t('basicData.negativesConfirmTitle'),
t('basicData.negativesConfirmMessage'),
submitWithNegatives
submitWithNegatives,
);
else submit();
}

View File

@ -3,14 +3,15 @@ import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { toDateTimeFormat } from 'src/filters/date';
import filter from './TicketFilter.js';
import FetchData from 'src/components/FetchData.vue';
import TicketProblems from 'src/components/TicketProblems.vue';
import axios from 'axios';
const $props = defineProps({
id: {
@ -31,23 +32,37 @@ const entityId = computed(() => {
return $props.id || route.params.id;
});
const problems = ref({});
const originalTicket = ref();
function ticketFilter(ticket) {
return JSON.stringify({ clientFk: ticket.clientFk });
}
async function getClaims() {
const userFilter = { where: { refundTicketFk: entityId.value } };
const { data } = await axios.get(`TicketRefunds`, {
params: { filter: JSON.stringify(userFilter) },
});
if (!data) return;
originalTicket.value = data[0]?.originalTicketFk;
}
async function getProblems() {
const { data } = await axios.get(`Tickets/${entityId.value}/getTicketProblems`);
if (!data) return;
problems.value = data[0];
}
function getInfo() {
getClaims();
getProblems();
}
</script>
<template>
<FetchData
:url="`Tickets/${entityId}/getTicketProblems`"
auto-load
@on-fetch="(data) => ([problems] = data)"
/>
<CardDescriptor
:url="`Tickets/${entityId}`"
:filter="filter"
data-key="Ticket"
:summary="$props.summary"
@on-fetch="getInfo"
width="lg-width"
>
<template #menu="{ entity }">
@ -73,12 +88,12 @@ function ticketFilter(ticket) {
</QBadge>
</template>
</VnLv>
<VnLv :label="t('globals.salesPerson')">
<VnLv :label="t('customer.summary.team')">
<template #value>
<VnUserLink
:name="entity.client?.salesPersonUser?.name"
:worker-id="entity.client?.salesPersonFk"
/>
<span class="link">
{{ entity?.client?.department?.name || '-' }}
<DepartmentDescriptorProxy :id="entity?.client?.departmentFk" />
</span>
</template>
</VnLv>
<VnLv
@ -95,7 +110,7 @@ function ticketFilter(ticket) {
</template>
<template #icons="{ entity }">
<QCardActions class="q-gutter-x-xs">
<TicketProblems :row="{ ...entity?.client, ...problems }" />
<TicketProblems :row="{ ...entity?.client, ...problems, ...entity }" />
</QCardActions>
</template>
<template #actions="{ entity }">
@ -129,6 +144,15 @@ function ticketFilter(ticket) {
>
<QTooltip>{{ t('ticket.card.newOrder') }}</QTooltip>
</QBtn>
<QBtn
v-if="originalTicket"
size="md"
icon="vn:claims"
color="primary"
:to="{ name: 'TicketCard', params: { id: originalTicket } }"
>
<QTooltip>{{ t('ticket.card.ticketClaimed') }}</QTooltip>
</QBtn>
</QCardActions>
</template>
</CardDescriptor>

View File

@ -33,7 +33,7 @@ const save = (sale = $props.sale) => {
};
const getMana = async () => {
const { data } = await axios.get(`Tickets/${route.params.id}/getSalesPersonMana`);
const { data } = await axios.get(`Tickets/${route.params.id}/getDepartmentMana`);
mana.value = data;
await getUsesMana();
};

View File

@ -12,7 +12,7 @@ export default {
fields: [
'id',
'name',
'salesPersonFk',
'departmentFk',
'phone',
'mobile',
'email',
@ -29,7 +29,7 @@ export default {
fields: ['id', 'lang'],
},
},
{ relation: 'salesPersonUser' },
{ relation: 'department' },
],
},
},

View File

@ -174,22 +174,26 @@ const getSaleTotal = (sale) => {
return price - discount;
};
const getRowUpdateInputEvents = (sale) => ({
'keyup.enter': () => {
changeQuantity(sale);
},
blur: () => {
changeQuantity(sale);
},
});
const getRowUpdateInputEvents = (sale) => {
return {
'keyup.enter': () => {
changeQuantity(sale);
},
blur: () => {
changeQuantity(sale);
},
};
};
const resetChanges = async () => {
arrayData.fetch({ append: false });
tableRef.value.reload();
selectedRows.value = [];
};
const changeQuantity = async (sale) => {
if (!sale.itemFk || sale.quantity == null || sale?.originalQuantity === sale.quantity)
return;
else sale.originalQuantity = sale.quantity;
if (!sale.id) return addSale(sale);
if (await isSalePrepared(sale)) {
@ -235,7 +239,7 @@ const addSale = async (sale) => {
notify('globals.dataSaved', 'positive');
sale.isNew = false;
arrayData.fetch({});
resetChanges();
};
const changeConcept = async (sale) => {
if (await isSalePrepared(sale)) {
@ -258,6 +262,18 @@ const DEFAULT_EDIT = {
oldQuantity: null,
};
const edit = ref({ ...DEFAULT_EDIT });
const usesMana = ref(null);
const getUsesMana = async () => {
const { data } = await axios.get('Sales/usesMana');
usesMana.value = data;
};
const getMana = async () => {
const { data } = await axios.get(`Tickets/${route.params.id}/getDepartmentMana`);
mana.value = data;
await getUsesMana();
};
const selectedValidSales = computed(() => {
if (!sales.value) return;
@ -310,7 +326,7 @@ const changeDiscount = async (sale) => {
}
};
const updateDiscounts = async (sales, newDiscount = null) => {
const updateDiscounts = async (sales, newDiscount) => {
const salesTracking = await fetchSalesTracking();
const someSaleIsPrepared = salesTracking.some((sale) =>
@ -320,12 +336,11 @@ const updateDiscounts = async (sales, newDiscount = null) => {
else updateDiscount(sales, newDiscount);
};
const updateDiscount = async (sales, newDiscount = null) => {
const saleIds = sales.map((sale) => sale.id);
const _newDiscount = newDiscount || edit.value.discount;
const updateDiscount = async (sales, newDiscount = 0) => {
const salesIds = sales.map(({ id }) => id);
const params = {
salesIds: saleIds,
newDiscount: _newDiscount,
salesIds,
newDiscount,
manaCode: manaCode.value,
};
await axios.post(`Tickets/${route.params.id}/updateDiscount`, params);
@ -474,7 +489,7 @@ const endNewRow = (row) => {
};
async function confirmUpdate(cb) {
await quasar
quasar
.dialog({
component: VnConfirm,
componentProps: {
@ -664,6 +679,7 @@ watch(
selection: 'multiple',
}"
:right-search="false"
:search-url="false"
:column-search="false"
:disable-option="{ card: true }"
auto-load
@ -703,7 +719,7 @@ watch(
</template>
<template #column-image="{ row }">
<div class="image-wrapper">
<VnImg :id="parseInt(row?.item?.id)" class="rounded" />
<VnImg v-if="row.item" :id="parseInt(row?.item?.id)" class="rounded" />
</div>
</template>
<template #column-visible="{ row }">
@ -751,7 +767,7 @@ watch(
{{ row?.item?.subName.toUpperCase() }}
</div>
</div>
<FetchedTags :item="row.item" :max-length="6" />
<FetchedTags v-if="row.item" :item="row.item" :max-length="6" />
<QPopupProxy v-if="row.id && isTicketEditable">
<VnInput
v-model="row.concept"

View File

@ -62,8 +62,6 @@ const isClaimable = computed(() => {
}
return false;
});
const hasReserves = computed(() => props.sales.some((sale) => sale.reserved == true));
const sendSms = async (params) => {
await axios.post(`Tickets/${ticket.value.id}/sendSms`, params);
notify(t('SMS sent'), 'positive');
@ -144,14 +142,6 @@ const onCreateClaimAccepted = async () => {
push({ name: 'ClaimBasicData', params: { id: data.id } });
};
const setReserved = async (reserved) => {
const params = { ticketId: ticket.value.id, sales: props.sales, reserved: reserved };
await axios.post(`Sales/reserve`, params);
props.sales.forEach((sale) => {
sale.reserved = reserved;
});
};
const createRefund = async (withWarehouse) => {
if (!props.ticket) return;
@ -252,18 +242,6 @@ const createRefund = async (withWarehouse) => {
<QItemLabel>{{ t('Mark as reserved') }}</QItemLabel>
</QItemSection>
</QItem>
<QItem
v-if="isTicketEditable && hasReserves"
clickable
v-close-popup
v-ripple
@click="setReserved(false)"
data-cy="unmarkAsReservedItem"
>
<QItemSection>
<QItemLabel>{{ t('Unmark as reserved') }}</QItemLabel>
</QItemSection>
</QItem>
<QItem clickable v-ripple data-cy="ticketSaleRefundItem">
<QItemSection>
<QItemLabel>{{ t('Refund') }}</QItemLabel>

Some files were not shown because too many files have changed in this diff Show More