Merge branch '8626-addTestCasesInRouteListTest' of https://gitea.verdnatura.es/verdnatura/salix-front into 8626-addTestCasesInRouteListTest
gitea/salix-front/pipeline/pr-dev This commit is unstable Details

This commit is contained in:
Jose Antonio Tubau 2025-03-17 10:38:18 +01:00
commit 861b535564
70 changed files with 9240 additions and 13031 deletions

2
Jenkinsfile vendored
View File

@ -120,6 +120,8 @@ pipeline {
def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs') def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs')
sh 'docker login --username $CREDS_USR --password $CREDS_PSW $REGISTRY' 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" sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { 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 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 ### Build the app for production
```bash ```bash

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -47,14 +47,6 @@ vi.mock('src/router/modules', () => ({
], ],
}, },
}, },
{
path: 'create',
name: 'CustomerCreate',
meta: {
title: 'createCustomer',
icon: 'vn:addperson',
},
},
], ],
}, },
], ],

View File

@ -99,7 +99,6 @@ globals:
file: File file: File
selectFile: Select a file selectFile: Select a file
copyClipboard: Copy on clipboard copyClipboard: Copy on clipboard
salesPerson: SalesPerson
send: Send send: Send
code: Code code: Code
since: Since since: Since
@ -158,6 +157,7 @@ globals:
changeState: Change state changeState: Change state
raid: 'Raid {daysInForward} days' raid: 'Raid {daysInForward} days'
isVies: Vies isVies: Vies
department: Department
noData: No data available noData: No data available
vehicle: Vehicle vehicle: Vehicle
pageTitles: pageTitles:
@ -347,7 +347,6 @@ globals:
params: params:
description: Description description: Description
clientFk: Client id clientFk: Client id
salesPersonFk: Sales person
warehouseFk: Warehouse warehouseFk: Warehouse
provinceFk: Province provinceFk: Province
stateFk: State stateFk: State
@ -605,7 +604,6 @@ worker:
balance: Balance balance: Balance
medical: Medical medical: Medical
list: list:
department: Department
schedule: Schedule schedule: Schedule
newWorker: New worker newWorker: New worker
summary: summary:
@ -864,7 +862,6 @@ components:
mine: For me mine: For me
hasMinPrice: Minimum price hasMinPrice: Minimum price
# LatestBuysFilter # LatestBuysFilter
salesPersonFk: Buyer
supplierFk: Supplier supplierFk: Supplier
from: From from: From
to: To to: To

View File

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

View File

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

View File

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

View File

@ -117,7 +117,7 @@ const selected = ref([]);
const mana = ref(0); const mana = ref(0);
async function fetchMana() { async function fetchMana() {
const ticketId = claim.value.ticketFk; 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; 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 ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.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'; import ClaimDescriptorMenu from './ClaimDescriptorMenu.vue';
const route = useRoute(); const route = useRoute();
@ -252,13 +253,15 @@ function claimUrl(section) {
</VnLv> </VnLv>
<VnLv <VnLv
v-if="$route.name != 'ClaimSummary'" v-if="$route.name != 'ClaimSummary'"
:label="t('globals.salesPerson')" :label="t('customer.summary.team')"
> >
<template #value> <template #value>
<VnUserLink <span class="link">
:name="claim.client?.salesPersonUser?.name" {{ claim?.client?.department?.name || '-' }}
:worker-id="claim.client?.salesPersonFk" <DepartmentDescriptorProxy
/> :id="claim?.client?.departmentFk"
/>
</span>
</template> </template>
</VnLv> </VnLv>
<VnLv v-if="$route.name != 'ClaimSummary'" :label="t('claim.attendedBy')"> <VnLv v-if="$route.name != 'ClaimSummary'" :label="t('claim.attendedBy')">

View File

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

View File

@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
import { toDate } from 'filters/index'; import { toDate } from 'filters/index';
import ClaimFilter from './ClaimFilter.vue'; import ClaimFilter from './ClaimFilter.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.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 VnUserLink from 'src/components/ui/VnUserLink.vue';
import ClaimSummary from './Card/ClaimSummary.vue'; import ClaimSummary from './Card/ClaimSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
@ -48,6 +49,20 @@ const columns = computed(() => [
}, },
columnClass: 'expand', 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', align: 'left',
label: t('claim.attendedBy'), label: t('claim.attendedBy'),
@ -152,6 +167,12 @@ const STATE_COLOR = {
<CustomerDescriptorProxy :id="row.clientFk" /> <CustomerDescriptorProxy :id="row.clientFk" />
</span> </span>
</template> </template>
<template #column-departmentFk="{ row }">
<span class="link" @click.stop>
{{ row.departmentName || '-' }}
<DepartmentDescriptorProxy :id="row?.departmentFk" />
</span>
</template>
<template #column-attendedBy="{ row }"> <template #column-attendedBy="{ row }">
<span @click.stop> <span @click.stop>
<VnUserLink :name="row.workerName" :worker-id="row.workerFk" /> <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 VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import { getDifferences, getUpdatedValues } from 'src/filters'; import { getDifferences, getUpdatedValues } from 'src/filters';
const route = useRoute(); const route = useRoute();
@ -37,7 +36,7 @@ const exprBuilder = (param, value) => {
function onBeforeSave(formData, originalData) { function onBeforeSave(formData, originalData) {
return getUpdatedValues( return getUpdatedValues(
Object.keys(getDifferences(formData, originalData)), Object.keys(getDifferences(formData, originalData)),
formData formData,
); );
} }
</script> </script>
@ -119,16 +118,11 @@ function onBeforeSave(formData, originalData) {
/> />
</VnRow> </VnRow>
<VnRow> <VnRow>
<VnSelectWorker <VnSelect
:label="t('customer.summary.salesPerson')" :label="t('globals.department')"
v-model="data.salesPersonFk" v-model="data.departmentFk"
:params="{ url="Departments"
departmentCodes: ['VT', 'shopping'], :fields="['id', 'name']"
}"
:has-avatar="true"
:rules="validate('client.salesPersonFk')"
:expr-builder="exprBuilder"
emit-value
/> />
<VnSelect <VnSelect
v-model="data.contactChannelFk" v-model="data.contactChannelFk"
@ -160,7 +154,7 @@ function onBeforeSave(formData, originalData) {
<QIcon name="info" class="cursor-pointer"> <QIcon name="info" class="cursor-pointer">
<QTooltip>{{ <QTooltip>{{
t( t(
'In case of a company succession, specify the grantor company' 'In case of a company succession, specify the grantor company',
) )
}}</QTooltip> }}</QTooltip>
</QIcon> </QIcon>

View File

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

View File

@ -2,7 +2,6 @@
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { toCurrency, toPercentage, toDate, dashOrCurrency } from 'src/filters'; import { toCurrency, toPercentage, toDate, dashOrCurrency } from 'src/filters';
import CardSummary from 'components/ui/CardSummary.vue'; 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 VnTitle from 'src/components/common/VnTitle.vue';
import VnRow from 'src/components/ui/VnRow.vue'; import VnRow from 'src/components/ui/VnRow.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue'; import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const grafanaUrl = 'https://grafana.verdnatura.es'; const grafanaUrl = 'https://grafana.verdnatura.es';
@ -106,16 +107,12 @@ const sumRisk = ({ clientRisks }) => {
{{ t('globals.params.email') }} {{ t('globals.params.email') }}
<VnLinkMail email="entity.email"></VnLinkMail> </template <VnLinkMail email="entity.email"></VnLinkMail> </template
></VnLv> ></VnLv>
<VnLv <VnLv :label="t('globals.department')">
:label="t('customer.summary.salesPerson')"
:value="entity?.salesPersonUser?.name"
>
<template #value> <template #value>
<VnUserLink <span class="link" v-text="entity.department?.name" />
:name="entity.salesPersonUser?.name" <DepartmentDescriptorProxy :id="entity?.department?.id" />
:worker-id="entity.salesPersonFk" </template>
/> </template </VnLv>
></VnLv>
<VnLv <VnLv
:label="t('customer.summary.contactChannel')" :label="t('customer.summary.contactChannel')"
:value="entity?.contactChannel?.name" :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 VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
defineProps({ defineProps({
@ -65,22 +64,15 @@ const exprBuilder = (param, value) => {
</QItem> </QItem>
<QItem class="q-mb-sm"> <QItem class="q-mb-sm">
<QItemSection> <QItemSection>
<VnSelectWorker <VnSelect
: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
outlined outlined
dense
rounded rounded
:input-debounce="0" :label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
@ -164,7 +156,6 @@ en:
params: params:
search: Contains search: Contains
fi: FI fi: FI
salesPersonFk: Salesperson
provinceFk: Province provinceFk: Province
isActive: Is active isActive: Is active
city: City city: City
@ -191,7 +182,6 @@ es:
sageTaxTypeFk: Tipo de impuesto Sage sageTaxTypeFk: Tipo de impuesto Sage
sageTransactionTypeFk: Tipo de impuesto Sage sageTransactionTypeFk: Tipo de impuesto Sage
payMethodFk: Forma de pago payMethodFk: Forma de pago
salesPersonFk: Comercial
provinceFk: Provincia provinceFk: Provincia
city: Ciudad city: Ciudad
phone: Teléfono phone: Teléfono
@ -201,7 +191,6 @@ es:
name: Nombre name: Nombre
postcode: CP postcode: CP
FI: NIF FI: NIF
Salesperson: Comercial
Province: Provincia Province: Provincia
City: Ciudad City: Ciudad
Phone: Teléfono Phone: Teléfono

View File

@ -10,7 +10,6 @@ import CustomerFilter from './CustomerFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import VnLocation from 'src/components/common/VnLocation.vue'; import VnLocation from 'src/components/common/VnLocation.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.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'; import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n(); const { t } = useI18n();
@ -73,30 +72,17 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
name: 'salesPersonFk', name: 'departmentFk',
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'), label: t('customer.summary.team'),
component: 'select', component: 'select',
attrs: { attrs: {
url: 'Workers/activeWithInheritedRole', url: 'Departments',
fields: ['id', 'name', 'firstName'],
where: { role: 'salesPerson' },
optionFilter: 'firstName',
}, },
columnFilter: { create: true,
component: 'select',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name', 'firstName'],
where: { role: 'salesPerson' },
optionLabel: 'firstName',
optionValue: 'id',
},
},
create: false,
columnField: { columnField: {
component: null, component: null,
}, },
format: (row, dashIfEmpty) => dashIfEmpty(row.salesPerson), format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
}, },
{ {
align: 'left', align: 'left',
@ -155,6 +141,9 @@ const columns = computed(() => [
inWhere: true, inWhere: true,
}, },
columnClass: 'expand', columnClass: 'expand',
attrs: {
uppercase: true,
},
}, },
{ {
align: 'left', align: 'left',
@ -446,36 +435,6 @@ function handleLocation(data, location) {
redirect="customer" redirect="customer"
> >
<template #more-create-dialog="{ data }"> <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 <VnLocation
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]" :acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
v-model="data.location" 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', align: 'left',
name: 'departmentFk', name: 'departmentFk',
@ -153,6 +131,11 @@ const columns = computed(() => [
label: t('Has recovery'), label: t('Has recovery'),
name: 'hasRecovery', name: 'hasRecovery',
}, },
{
align: 'left',
name: 'isWorker',
label: t('customer.params.isWorker'),
},
]); ]);
const viewAddObservation = (rowsSelected) => { const viewAddObservation = (rowsSelected) => {
@ -167,7 +150,6 @@ const viewAddObservation = (rowsSelected) => {
function exprBuilder(param, value) { function exprBuilder(param, value) {
switch (param) { switch (param) {
case 'salesPersonFk':
case 'creditInsurance': case 'creditInsurance':
case 'countryFk': case 'countryFk':
return { [`c.${param}`]: value }; return { [`c.${param}`]: value };
@ -176,7 +158,7 @@ function exprBuilder(param, value) {
case 'workerFk': case 'workerFk':
return { [`co.${param}`]: value }; return { [`co.${param}`]: value };
case 'departmentFk': case 'departmentFk':
return { [`wd.${param}`]: value }; return { [`c.${param}`]: value };
case 'amount': case 'amount':
case 'clientFk': case 'clientFk':
return { [`d.${param}`]: value }; return { [`d.${param}`]: value };
@ -241,12 +223,6 @@ function exprBuilder(param, value) {
<template #column-observation="{ row }"> <template #column-observation="{ row }">
<VnInput type="textarea" v-model="row.observation" readonly dense rows="2" /> <VnInput type="textarea" v-model="row.observation" readonly dense rows="2" />
</template> </template>
<template #column-salesPersonFk="{ row }">
<span class="link" @click.stop>
{{ row.salesPersonName }}
<WorkerDescriptorProxy :id="row.salesPersonFk" />
</span>
</template>
<template #column-departmentFk="{ row }"> <template #column-departmentFk="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.departmentName }} {{ row.departmentName }}
@ -265,8 +241,6 @@ function exprBuilder(param, value) {
es: es:
Add observation: Añadir observación Add observation: Añadir observación
Client: Cliente Client: Cliente
Is worker: Es trabajador
Salesperson: Comercial
Department: Departamento Department: Departamento
Country: País Country: País
P. Method: F. Pago P. Method: F. Pago
@ -281,5 +255,5 @@ es:
Credit I.: Crédito A. Credit I.: Crédito A.
Credit insurance: Crédito asegurado Credit insurance: Crédito asegurado
From: Desde From: Desde
Has recovery: Tiene recobro Has recovery: Recobro
</i18n> </i18n>

View File

@ -15,19 +15,12 @@ const props = defineProps({
}, },
}); });
const salespersons = ref();
const countries = ref(); const countries = ref();
const authors = ref(); const authors = ref();
const departments = ref(); const departments = ref();
</script> </script>
<template> <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) => (countries = data)" auto-load url="Countries" />
<FetchData <FetchData
@on-fetch="(data) => (authors = data)" @on-fetch="(data) => (authors = data)"
@ -62,29 +55,6 @@ const departments = ref();
@update:model-value="searchFn()" @update:model-value="searchFn()"
/> />
</QItem> </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"> <QItem class="q-mb-sm">
<QItemSection v-if="departments"> <QItemSection v-if="departments">
<VnSelect <VnSelect
@ -219,7 +189,6 @@ const departments = ref();
en: en:
params: params:
clientFk: Client clientFk: Client
salesPersonFk: Salesperson
countryFk: Country countryFk: Country
paymentMethod: P. Method paymentMethod: P. Method
balance: Balance D. balance: Balance D.
@ -230,7 +199,6 @@ en:
es: es:
params: params:
clientFk: Cliente clientFk: Cliente
salesPersonFk: Comercial
countryFk: País countryFk: País
paymentMethod: F. Pago paymentMethod: F. Pago
balance: Saldo V. balance: Saldo V.
@ -239,7 +207,6 @@ es:
credit: Crédito A. credit: Crédito A.
defaulterSinced: Desde defaulterSinced: Desde
Client: Cliente Client: Cliente
Salesperson: Comercial
Departments: Departamentos Departments: Departamentos
Country: País Country: País
P. Method: F. Pago P. Method: F. Pago

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { usePrintService } from 'src/composables/usePrintService'; import { usePrintService } from 'src/composables/usePrintService';
import VnTable from 'src/components/VnTable/VnTable.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import InvoiceOutSummary from './Card/InvoiceOutSummary.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 { QBtn } from 'quasar';
import axios from 'axios'; import axios from 'axios';
import InvoiceOutFilter from './InvoiceOutFilter.vue'; import InvoiceOutFilter from './InvoiceOutFilter.vue';
@ -16,7 +16,7 @@ import VnRow from 'src/components/ui/VnRow.vue';
import VnRadio from 'src/components/common/VnRadio.vue'; import VnRadio from 'src/components/common/VnRadio.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue'; import DepartmentDescriptorProxy from '../Worker/Department/Card/DepartmentDescriptorProxy.vue';
import VnSection from 'src/components/common/VnSection.vue'; import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n(); const { t } = useI18n();
@ -55,6 +55,14 @@ const columns = computed(() => [
name: 'id', name: 'id',
}, },
}, },
{
align: 'left',
name: 'issued',
label: t('invoiceOut.summary.issued'),
component: 'date',
format: (row) => toDate(row.issued),
columnField: { component: null },
},
{ {
align: 'left', align: 'left',
name: 'ref', name: 'ref',
@ -90,12 +98,12 @@ const columns = computed(() => [
{ {
align: 'left', align: 'left',
name: 'departmentFk', name: 'departmentFk',
label: t('globals.params.departmentFk'), label: t('customer.summary.team'),
cardVisible: true,
component: 'select', component: 'select',
attrs: { attrs: {
url: 'Departments', url: 'Departments',
}, },
create: true,
columnField: { columnField: {
component: null, component: null,
}, },
@ -246,7 +254,7 @@ watchEffect(selectedRows);
</template> </template>
<template #column-departmentFk="{ row }"> <template #column-departmentFk="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.departmentName || '-' }} {{ dashIfEmpty(row.departmentName) }}
<DepartmentDescriptorProxy :id="row?.departmentFk" /> <DepartmentDescriptorProxy :id="row?.departmentFk" />
</span> </span>
</template> </template>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnFilterPanel from 'components/ui/VnFilterPanel.vue'; import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
@ -46,19 +47,7 @@ const emit = defineEmits(['search']);
</QItem> </QItem>
<QItem class="q-mb-sm"> <QItem class="q-mb-sm">
<QItemSection> <QItemSection>
<VnSelect <VnSelectWorker v-model="params.userFk" outlined rounded />
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"
/>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem class="q-mb-md"> <QItem class="q-mb-md">

View File

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

View File

@ -3,10 +3,10 @@ import { ref, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue'; 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 CardDescriptor from 'components/ui/CardDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue'; import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { toDateTimeFormat } from 'src/filters/date'; import { toDateTimeFormat } from 'src/filters/date';
import filter from './TicketFilter.js'; import filter from './TicketFilter.js';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
@ -88,12 +88,12 @@ function getInfo() {
</QBadge> </QBadge>
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('globals.salesPerson')"> <VnLv :label="t('customer.summary.team')">
<template #value> <template #value>
<VnUserLink <span class="link">
:name="entity.client?.salesPersonUser?.name" {{ entity?.client?.department?.name || '-' }}
:worker-id="entity.client?.salesPersonFk" <DepartmentDescriptorProxy :id="entity?.client?.departmentFk" />
/> </span>
</template> </template>
</VnLv> </VnLv>
<VnLv <VnLv

View File

@ -33,7 +33,7 @@ const save = (sale = $props.sale) => {
}; };
const getMana = async () => { 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; mana.value = data;
await getUsesMana(); await getUsesMana();
}; };

View File

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

View File

@ -176,12 +176,10 @@ const getSaleTotal = (sale) => {
const getRowUpdateInputEvents = (sale) => { const getRowUpdateInputEvents = (sale) => {
return { return {
'keyup.enter': (evt) => { 'keyup.enter': () => {
console.error(evt);
changeQuantity(sale); changeQuantity(sale);
}, },
blur: (evt) => { blur: () => {
console.error(evt);
changeQuantity(sale); changeQuantity(sale);
}, },
}; };
@ -264,6 +262,18 @@ const DEFAULT_EDIT = {
oldQuantity: null, oldQuantity: null,
}; };
const edit = ref({ ...DEFAULT_EDIT }); 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(() => { const selectedValidSales = computed(() => {
if (!sales.value) return; if (!sales.value) return;

View File

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

View File

@ -13,9 +13,9 @@ import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
import { getUrl } from 'src/composables/getUrl'; import { getUrl } from 'src/composables/getUrl';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import VnTitle from 'src/components/common/VnTitle.vue'; import VnTitle from 'src/components/common/VnTitle.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue'; import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue'; import VnToSummary from 'src/components/ui/VnToSummary.vue';
@ -152,12 +152,14 @@ onMounted(async () => {
</QBadge> </QBadge>
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('globals.salesPerson')"> <VnLv :label="t('customer.summary.team')">
<template #value> <template #value>
<VnUserLink <span class="link">
:name="entity.client?.salesPersonUser?.name" {{ entity?.client?.department?.name || '-' }}
:worker-id="entity.client?.salesPersonFk" <DepartmentDescriptorProxy
/> :id="entity?.client?.departmentFk"
/>
</span>
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('globals.agency')" :value="entity.agencyMode?.name" /> <VnLv :label="t('globals.agency')" :value="entity.agencyMode?.name" />

View File

@ -259,7 +259,7 @@ const moveTicketsAdvance = async () => {
destinationId: ticket.id, destinationId: ticket.id,
originShipped: ticket.futureShipped, originShipped: ticket.futureShipped,
destinationShipped: ticket.shipped, destinationShipped: ticket.shipped,
salesPersonFk: ticket.workerFk, departmentFk: ticket.departmentFk,
}); });
} }
const params = { tickets: ticketsToMove }; const params = { tickets: ticketsToMove };
@ -285,7 +285,7 @@ const progressAdd = () => {
t('advanceTickets.moveTicketSuccess', { t('advanceTickets.moveTicketSuccess', {
ticketsNumber: progressLength.value - splitErrors.value.length, ticketsNumber: progressLength.value - splitErrors.value.length,
}), }),
'positive' 'positive',
); );
} }
}; };
@ -345,16 +345,16 @@ watch(
originElRef.value.setAttribute('colspan', '9'); originElRef.value.setAttribute('colspan', '9');
destinationElRef.value.textContent = `${t( destinationElRef.value.textContent = `${t(
'advanceTickets.destination' 'advanceTickets.destination',
)} ${toDateFormat(vnTableRef.value.params.dateToAdvance)}`; )} ${toDateFormat(vnTableRef.value.params.dateToAdvance)}`;
originElRef.value.textContent = `${t('advanceTickets.origin')} ${toDateFormat( originElRef.value.textContent = `${t('advanceTickets.origin')} ${toDateFormat(
vnTableRef.value.params.dateFuture vnTableRef.value.params.dateFuture,
)}`; )}`;
newRow.append(destinationElRef.value, originElRef.value); newRow.append(destinationElRef.value, originElRef.value);
head.insertBefore(newRow, firstRow); head.insertBefore(newRow, firstRow);
}, },
{ once: true, inmmediate: true } { once: true, inmmediate: true },
); );
watch( watch(
@ -362,14 +362,14 @@ watch(
() => { () => {
if (originElRef.value && destinationElRef.value) { if (originElRef.value && destinationElRef.value) {
destinationElRef.value.textContent = `${t( destinationElRef.value.textContent = `${t(
'advanceTickets.destination' 'advanceTickets.destination',
)} ${toDateFormat(vnTableRef.value.params.dateToAdvance)}`; )} ${toDateFormat(vnTableRef.value.params.dateToAdvance)}`;
originElRef.value.textContent = `${t('advanceTickets.origin')} ${toDateFormat( originElRef.value.textContent = `${t('advanceTickets.origin')} ${toDateFormat(
vnTableRef.value.params.dateFuture vnTableRef.value.params.dateFuture,
)}`; )}`;
} }
}, },
{ deep: true } { deep: true },
); );
</script> </script>
<template> <template>
@ -405,7 +405,7 @@ watch(
t(`advanceTickets.advanceTitleSubtitle`, { t(`advanceTickets.advanceTitleSubtitle`, {
selectedTickets: selectedTickets.length, selectedTickets: selectedTickets.length,
}), }),
moveTicketsAdvance moveTicketsAdvance,
) )
" "
> >
@ -423,7 +423,7 @@ watch(
t(`advanceTickets.advanceWithoutNegativeSubtitle`, { t(`advanceTickets.advanceWithoutNegativeSubtitle`, {
selectedTickets: selectedTickets.length, selectedTickets: selectedTickets.length,
}), }),
splitTickets splitTickets,
) )
" "
> >

View File

@ -97,15 +97,15 @@ const getGroupedStates = (data) => {
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelectWorker <VnSelect
:label="t('globals.salesPerson')"
v-model="params.salesPersonFk"
:params="{
departmentCodes: ['VT'],
}"
dense
outlined outlined
dense
rounded rounded
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
@ -308,7 +308,6 @@ en:
from: From from: From
shipped: Shipped shipped: Shipped
to: To to: To
salesPersonFk: Salesperson
stateFk: State stateFk: State
groupedStates: Grouped State groupedStates: Grouped State
refFk: Invoice Ref. refFk: Invoice Ref.
@ -336,7 +335,6 @@ es:
from: Desde from: Desde
shipped: F. envío shipped: F. envío
to: Hasta to: Hasta
salesPersonFk: Comercial
stateFk: Estado stateFk: Estado
groupedStates: Estado agrupado groupedStates: Estado agrupado
refFk: Ref. Factura refFk: Ref. Factura
@ -355,7 +353,6 @@ es:
Order ID: ID Pedido Order ID: ID Pedido
From: Desde From: Desde
To: Hasta To: Hasta
Salesperson: Comercial
State: Estado State: Estado
Invoice Ref.: Ref. Factura Invoice Ref.: Ref. Factura
My team: Mi equipo My team: Mi equipo

View File

@ -160,7 +160,7 @@ const moveTicketsFuture = async () => {
destinationId: ticket.futureId, destinationId: ticket.futureId,
originShipped: ticket.shipped, originShipped: ticket.shipped,
destinationShipped: ticket.futureShipped, destinationShipped: ticket.futureShipped,
salesPersonFk: ticket.salesPersonFk, departmentFk: ticket.departmentFk,
}; };
}); });

View File

@ -17,6 +17,7 @@ import TicketFilter from './TicketFilter.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue'; import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import { toTimeFormat } from 'src/filters/date'; import { toTimeFormat } from 'src/filters/date';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue'; import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
@ -99,22 +100,16 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
label: t('ticketList.salesPerson'), name: 'departmentFk',
name: 'salesPersonFk', label: t('customer.summary.team'),
component: 'select', component: 'select',
attrs: { attrs: {
url: 'Workers/activeWithInheritedRole', url: 'Departments',
fields: ['id', 'name'],
where: { role: 'salesPerson' },
optionFilter: 'firstName',
useLike: false,
}, },
columnField: { columnField: {
component: null, component: null,
}, },
columnClass: 'expand', format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
cardVisible: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.salesPerson),
}, },
{ {
align: 'left', align: 'left',
@ -519,10 +514,10 @@ function setReference(data) {
<template #column-statusIcons="{ row }"> <template #column-statusIcons="{ row }">
<TicketProblems :row="row" /> <TicketProblems :row="row" />
</template> </template>
<template #column-salesPersonFk="{ row }"> <template #column-departmentFk="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ dashIfEmpty(row.userName) }} {{ dashIfEmpty(row.departmentName) }}
<CustomerDescriptorProxy :id="row.salesPersonFk" /> <DepartmentDescriptorProxy :id="row.departmentFk" />
</span> </span>
</template> </template>
<template #column-shippedDate="{ row }"> <template #column-shippedDate="{ row }">

View File

@ -5,7 +5,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectCache from 'src/components/common/VnSelectCache.vue'; import VnSelectCache from 'src/components/common/VnSelectCache.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; 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 VnSearchbar from 'src/components/ui/VnSearchbar.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { useVnConfirm } from 'composables/useVnConfirm'; import { useVnConfirm } from 'composables/useVnConfirm';
@ -112,23 +112,17 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
name: 'id', name: 'departmentFk',
label: t('weeklyTickets.salesperson'), label: t('customer.summary.team'),
columnFilter: { component: 'select',
component: 'select', attrs: {
alias: 'u', url: 'Departments',
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
where: { role: 'salesperson' },
},
inWhere: true,
}, },
create: true,
columnField: { columnField: {
component: null, component: null,
}, },
cardVisible: true, format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
format: (row) => row.userName,
}, },
{ {
align: 'right', align: 'right',
@ -142,9 +136,9 @@ const columns = computed(() => [
openConfirmationModal( openConfirmationModal(
t('You are going to delete this weekly ticket'), t('You are going to delete this weekly ticket'),
t( t(
'This ticket will be removed from weekly tickets! Continue anyway?' 'This ticket will be removed from weekly tickets! Continue anyway?',
), ),
() => deleteWeekly(row.ticketFk) () => deleteWeekly(row.ticketFk),
), ),
isPrimary: true, isPrimary: true,
}, },
@ -219,10 +213,10 @@ onMounted(async () => {
<CustomerDescriptorProxy :id="row.clientFk" /> <CustomerDescriptorProxy :id="row.clientFk" />
</span> </span>
</template> </template>
<template #column-id="{ row }"> <template #column-departmentFk="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.userName }} {{ row.departmentName }}
<WorkerDescriptorProxy :id="row.workerFk" /> <DepartmentDescriptorProxy :id="row.departmentFk" />
</span> </span>
</template> </template>
</VnTable> </VnTable>

View File

@ -136,7 +136,6 @@ purchaseRequest:
weeklyTickets: weeklyTickets:
id: Ticket ID id: Ticket ID
shipment: Shipment shipment: Shipment
salesperson: Salesperson
search: Search weekly tickets search: Search weekly tickets
searchInfo: Search weekly tickets by id or client id searchInfo: Search weekly tickets by id or client id
ticketSaleTracking: ticketSaleTracking:
@ -172,7 +171,7 @@ tracking:
addState: Add state addState: Add state
package: package:
package: Package package: Package
added: Added added: D. Added
addPackage: Add package addPackage: Add package
removePackage: Remove package removePackage: Remove package
ticketList: ticketList:
@ -181,7 +180,6 @@ ticketList:
state: State state: State
shipped: Shipped shipped: Shipped
zone: Zone zone: Zone
salesPerson: Sales person
totalWithVat: Total with VAT totalWithVat: Total with VAT
summary: Summary summary: Summary
client: Customer client: Customer

View File

@ -58,7 +58,6 @@ basicData:
weeklyTickets: weeklyTickets:
id: ID Ticket id: ID Ticket
shipment: Salida shipment: Salida
salesperson: Comercial
search: Buscar por tickets programados search: Buscar por tickets programados
searchInfo: Buscar tickets programados por el identificador o el identificador del cliente searchInfo: Buscar tickets programados por el identificador o el identificador del cliente
advanceTickets: advanceTickets:
@ -162,7 +161,7 @@ expedition:
removeExpedition: Eliminar expedición removeExpedition: Eliminar expedición
package: package:
package: Embalaje package: Embalaje
added: Añadido added: F. Creacion
addPackage: Añadir embalaje addPackage: Añadir embalaje
removePackage: Quitar embalaje removePackage: Quitar embalaje
ticketSaleTracking: ticketSaleTracking:
@ -186,7 +185,6 @@ ticketList:
state: Estado state: Estado
shipped: F. Envío shipped: F. Envío
zone: Zona zone: Zona
salesPerson: Comercial
totalWithVat: Total con IVA totalWithVat: Total con IVA
summary: Resumen summary: Resumen
client: Cliente client: Cliente

View File

@ -121,7 +121,7 @@ const handlePhotoUpdated = (evt = false) => {
:value="entity.user?.emailUser?.email" :value="entity.user?.emailUser?.email"
copy copy
/> />
<VnLv :label="t('worker.list.department')"> <VnLv :label="t('globals.department')">
<template #value> <template #value>
<span class="link" v-text="entity.department?.department?.name" /> <span class="link" v-text="entity.department?.department?.name" />
<DepartmentDescriptorProxy :id="entity.department?.department?.id" /> <DepartmentDescriptorProxy :id="entity.department?.department?.id" />

View File

@ -51,7 +51,7 @@ onBeforeMount(async () => {
<QCard class="vn-one"> <QCard class="vn-one">
<VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" /> <VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
<VnLv :label="t('globals.name')" :value="worker.user?.nickname" /> <VnLv :label="t('globals.name')" :value="worker.user?.nickname" />
<VnLv :label="t('worker.list.department')"> <VnLv :label="t('globals.department')">
<template #value> <template #value>
<span class="link" v-text="worker.department?.department?.name" /> <span class="link" v-text="worker.department?.department?.name" />
<DepartmentDescriptorProxy <DepartmentDescriptorProxy

View File

@ -4,8 +4,8 @@ const customerCard = {
name: 'CustomerCard', name: 'CustomerCard',
path: ':id', path: ':id',
component: () => import('src/pages/Customer/Card/CustomerCard.vue'), component: () => import('src/pages/Customer/Card/CustomerCard.vue'),
redirect: { name: 'CustomerSummary' }, redirect: { name: 'CustomerSummary' },
meta: { meta: {
menu: [ menu: [
'CustomerBasicData', 'CustomerBasicData',
'CustomerFiscalData', 'CustomerFiscalData',
@ -40,8 +40,7 @@ const customerCard = {
title: 'basicData', title: 'basicData',
icon: 'vn:settings', icon: 'vn:settings',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerBasicData.vue'),
import('src/pages/Customer/Card/CustomerBasicData.vue'),
}, },
{ {
path: 'fiscal-data', path: 'fiscal-data',
@ -50,8 +49,7 @@ const customerCard = {
title: 'fiscalData', title: 'fiscalData',
icon: 'vn:dfiscales', icon: 'vn:dfiscales',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerFiscalData.vue'),
import('src/pages/Customer/Card/CustomerFiscalData.vue'),
}, },
{ {
path: 'billing-data', path: 'billing-data',
@ -60,8 +58,7 @@ const customerCard = {
title: 'billingData', title: 'billingData',
icon: 'vn:payment', icon: 'vn:payment',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerBillingData.vue'),
import('src/pages/Customer/Card/CustomerBillingData.vue'),
}, },
{ {
path: 'address', path: 'address',
@ -85,9 +82,7 @@ const customerCard = {
title: 'address-create', title: 'address-create',
}, },
component: () => component: () =>
import( import('src/pages/Customer/components/CustomerAddressCreate.vue'),
'src/pages/Customer/components/CustomerAddressCreate.vue'
),
}, },
{ {
path: ':addressId', path: ':addressId',
@ -125,8 +120,7 @@ const customerCard = {
title: 'credits', title: 'credits',
icon: 'vn:credit', icon: 'vn:credit',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerCredits.vue'),
import('src/pages/Customer/Card/CustomerCredits.vue'),
}, },
{ {
path: 'greuges', path: 'greuges',
@ -135,8 +129,7 @@ const customerCard = {
title: 'greuges', title: 'greuges',
icon: 'vn:greuge', icon: 'vn:greuge',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerGreuges.vue'),
import('src/pages/Customer/Card/CustomerGreuges.vue'),
}, },
{ {
path: 'balance', path: 'balance',
@ -145,8 +138,7 @@ const customerCard = {
title: 'balance', title: 'balance',
icon: 'balance', icon: 'balance',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerBalance.vue'),
import('src/pages/Customer/Card/CustomerBalance.vue'),
}, },
{ {
path: 'recoveries', path: 'recoveries',
@ -155,8 +147,7 @@ const customerCard = {
title: 'recoveries', title: 'recoveries',
icon: 'vn:recovery', icon: 'vn:recovery',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerRecoveries.vue'),
import('src/pages/Customer/Card/CustomerRecoveries.vue'),
}, },
{ {
path: 'web-access', path: 'web-access',
@ -165,8 +156,7 @@ const customerCard = {
title: 'webAccess', title: 'webAccess',
icon: 'vn:web', icon: 'vn:web',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerWebAccess.vue'),
import('src/pages/Customer/Card/CustomerWebAccess.vue'),
}, },
{ {
path: 'log', path: 'log',
@ -247,9 +237,7 @@ const customerCard = {
title: 'creditOpinion', title: 'creditOpinion',
}, },
component: () => component: () =>
import( import('src/pages/Customer/Card/CustomerCreditOpinion.vue'),
'src/pages/Customer/Card/CustomerCreditOpinion.vue'
),
}, },
], ],
}, },
@ -319,9 +307,7 @@ const customerCard = {
title: 'samples', title: 'samples',
}, },
component: () => component: () =>
import( import('src/pages/Customer/Card/CustomerSamples.vue'),
'src/pages/Customer/Card/CustomerSamples.vue'
),
}, },
{ {
path: 'create', path: 'create',
@ -376,9 +362,7 @@ const customerCard = {
title: 'fileManagement', title: 'fileManagement',
}, },
component: () => component: () =>
import( import('src/pages/Customer/Card/CustomerFileManagement.vue'),
'src/pages/Customer/Card/CustomerFileManagement.vue'
),
}, },
{ {
path: 'file-management', path: 'file-management',
@ -420,8 +404,7 @@ const customerCard = {
meta: { meta: {
title: 'unpaid', title: 'unpaid',
}, },
component: () => component: () => import('src/pages/Customer/Card/CustomerUnpaid.vue'),
import('src/pages/Customer/Card/CustomerUnpaid.vue'),
}, },
], ],
}, },
@ -429,7 +412,7 @@ const customerCard = {
}; };
export default { export default {
name: 'Customer', name: 'Customer',
path: '/customer', path: '/customer',
meta: { meta: {
title: 'customers', title: 'customers',
@ -469,15 +452,6 @@ export default {
customerCard, customerCard,
], ],
}, },
{
path: 'create',
name: 'CustomerCreate',
meta: {
title: 'customerCreate',
icon: 'add',
},
component: () => import('src/pages/Customer/CustomerCreate.vue'),
},
{ {
path: 'payments', path: 'payments',
name: 'CustomerPayments', name: 'CustomerPayments',

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe('ClaimAction', () => { describe.skip('ClaimAction', () => {
const claimId = 1; const claimId = 1;
const firstRow = 'tbody > :nth-child(1)'; const firstRow = 'tbody > :nth-child(1)';

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe('Client list', () => { describe.skip('Client list', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.visit('/#/customer/list', { cy.visit('/#/customer/list', {
@ -25,7 +25,7 @@ describe('Client list', () => {
'Web user': { val: `user_test_${randomInt}` }, 'Web user': { val: `user_test_${randomInt}` },
Street: { val: `C/ STREET ${randomInt}` }, Street: { val: `C/ STREET ${randomInt}` },
Email: { val: `user.test${randomInt}@cypress.com` }, Email: { val: `user.test${randomInt}@cypress.com` },
'Sales person': { val: 'salesPerson', type: 'select' }, Team: { val: 'Informatica', type: 'select' },
Location: { val: '46000', type: 'select' }, Location: { val: '46000', type: 'select' },
'Business type': { val: 'others', type: 'select' }, 'Business type': { val: 'others', type: 'select' },
}; };

View File

@ -16,9 +16,9 @@ describe('InvoiceOut negative bases', () => {
cy.get(getDescriptors('ticketFk')).click(); cy.get(getDescriptors('ticketFk')).click();
cy.get('.descriptor').should('be.visible'); cy.get('.descriptor').should('be.visible');
cy.get('.q-item > .q-item__label').should('include.text', '23'); cy.get('.q-item > .q-item__label').should('include.text', '23');
cy.get(getDescriptors('workerName')).click(); cy.get(getDescriptors('departmentFk')).click();
cy.get('.descriptor').should('be.visible'); cy.get('.descriptor').should('be.visible');
cy.get('.q-item > .q-item__label').should('include.text', '18'); cy.get('.q-item > .q-item__label').should('include.text', '155');
}); });
it('should filter and download as CSV', () => { it('should filter and download as CSV', () => {

View File

@ -12,7 +12,7 @@ describe('Login', () => {
cy.get('button[type="submit"]').click(); cy.get('button[type="submit"]').click();
cy.get('.q-notification__message').should( cy.get('.q-notification__message').should(
'have.text', 'have.text',
'Invalid username or password' 'Invalid username or password',
); );
}); });
@ -23,7 +23,7 @@ describe('Login', () => {
cy.get('button[type="submit"]').click(); cy.get('button[type="submit"]').click();
cy.get('.q-notification__message').should( cy.get('.q-notification__message').should(
'have.text', 'have.text',
'Invalid username or password' 'Invalid username or password',
); );
}); });
@ -33,7 +33,7 @@ describe('Login', () => {
cy.get('button[type="submit"]').click(); cy.get('button[type="submit"]').click();
cy.get('.q-notification__message').should( cy.get('.q-notification__message').should(
'have.text', 'have.text',
'You have successfully logged in' 'You have successfully logged in',
); );
cy.url().should('contain', '/dashboard'); cy.url().should('contain', '/dashboard');
}); });
@ -44,7 +44,7 @@ describe('Login', () => {
cy.get('button[type="submit"]').click(); cy.get('button[type="submit"]').click();
cy.get('.q-notification__message').should( cy.get('.q-notification__message').should(
'have.text', 'have.text',
'You have successfully logged in' 'You have successfully logged in',
); );
cy.url().should('contain', '/dashboard'); cy.url().should('contain', '/dashboard');
cy.get('#user').click(); cy.get('#user').click();
@ -61,14 +61,4 @@ describe('Login', () => {
cy.get('button[type="submit"]').click(); cy.get('button[type="submit"]').click();
cy.url().should('contain', '/dashboard'); cy.url().should('contain', '/dashboard');
}); });
// ticket creation is not yet implemented, use this test once it is
// it(`should get redirected to ticket creation after login since salesPerson can do it`, () => {
// cy.visit('/#/ticket/create', { failOnStatusCode: false });
// cy.url().should('contain', '/#/login?redirect=/ticket/create');
// cy.get('input[aria-label="Username"]').type('salesPerson');
// cy.get('input[aria-label="Password"]').type('nightmare');
// cy.get('button[type="submit"]').click();
// cy.url().should('contain', '/#/ticket/create');
// })
}); });

View File

@ -24,12 +24,21 @@ describe('Logout', () => {
}, },
}, },
statusMessage: 'AUTHORIZATION_REQUIRED', statusMessage: 'AUTHORIZATION_REQUIRED',
}); }).as('badRequest');
}); });
it('when token not exists', () => { it('when token not exists', () => {
const exceptionHandler = (err) => {
if (err.code === 'AUTHORIZATION_REQUIRED') return;
};
Cypress.on('uncaught:exception', exceptionHandler);
cy.get('.q-list').first().should('be.visible').click(); cy.get('.q-list').first().should('be.visible').click();
cy.wait('@badRequest');
cy.checkNotification('Authorization Required'); cy.checkNotification('Authorization Required');
Cypress.off('uncaught:exception', exceptionHandler);
}); });
}); });
}); });

View File

@ -23,7 +23,7 @@ describe('TicketSale', () => {
cy.get('[data-col-field="price"]') cy.get('[data-col-field="price"]')
.find('.q-btn > .q-btn__content') .find('.q-btn > .q-btn__content')
.should('have.text', `${price}`); .should('contain.text', `${price}`);
}); });
it('update discount', () => { it('update discount', () => {
const discount = Math.floor(Math.random() * 100) + 1; const discount = Math.floor(Math.random() * 100) + 1;
@ -152,22 +152,6 @@ describe('TicketSale', () => {
cy.checkNotification('Future ticket date not allowed'); cy.checkNotification('Future ticket date not allowed');
}); });
it('marks row as reserved', () => {
selectFirstRow();
cy.dataCy('ticketSaleMoreActionsDropdown').click();
cy.waitForElement('[data-cy="markAsReservedItem"]');
cy.dataCy('markAsReservedItem').click();
cy.dataCy('ticketSaleReservedIcon').should('exist');
});
it('unmarks row as reserved', () => {
selectFirstRow();
cy.dataCy('ticketSaleMoreActionsDropdown').click();
cy.waitForElement('[data-cy="unmarkAsReservedItem"]');
cy.dataCy('unmarkAsReservedItem').click();
cy.dataCy('ticketSaleReservedIcon').should('not.exist');
});
it('refunds row with warehouse', () => { it('refunds row with warehouse', () => {
selectFirstRow(); selectFirstRow();
cy.dataCy('ticketSaleMoreActionsDropdown').click(); cy.dataCy('ticketSaleMoreActionsDropdown').click();

View File

@ -40,6 +40,11 @@ style.innerHTML = `
`; `;
document.head.appendChild(style); document.head.appendChild(style);
// FIXME: https://redmine.verdnatura.es/issues/8771
Cypress.on('uncaught:exception', (err) => {
if (err.code === 'ERR_CANCELED') return false;
});
const waitForApiReady = (url, maxRetries = 20, delay = 1000) => { const waitForApiReady = (url, maxRetries = 20, delay = 1000) => {
let retries = 0; let retries = 0;