Added model fields
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Joan Sanchez 2022-05-31 13:36:27 +02:00
parent a5e833af2c
commit c369453bfc
18 changed files with 377 additions and 366 deletions

View File

@ -1,3 +1,3 @@
INSERT INTO salix.defaultViewConfig (tableCode, columns)
VALUES ('clientsDetail', '{"id":true,"phone":true,"city":true,"socialName":true,"salesPersonFk":true,"email":true}');
VALUES ('clientsDetail', '{"id":true,"phone":true,"city":true,"socialName":true,"salesPersonFk":true,"email":true,"name":false,"fi":false,"credit":false,"creditInsurance":false,"mobile":false,"street":false,"countryFk":false,"provinceFk":false,"postcode":false,"created":false,"businessTypeFk":false,"payMethodFk":false,"sageTaxTypeFk":false,"sageTransactionTypeFk":false,"isActive":false,"isVies":false,"isTaxDataChecked":false,"isEqualizated":false,"isFreezed":false,"hasToInvoice":false,"hasToInvoiceByAddress":false,"isToBeMailed":false,"hasLcr":false,"hasCoreVnl":false,"hasSepaVnl":false}');

View File

@ -318,6 +318,8 @@ export default class SmartTable extends Component {
for (let column of columns) {
const field = column.getAttribute('field');
const cell = document.createElement('td');
cell.setAttribute('centered', '');
if (field) {
let input;
let options;
@ -346,6 +348,23 @@ export default class SmartTable extends Component {
on-change="$ctrl.searchByColumn('${field}')"
clear-disabled="true"
/>`)(this.$inputsScope);
} else if (options && options.checkbox) {
input = this.$compile(`
<vn-check
class="dense"
name="${field}"
ng-model="searchProps['${field}']"
on-change="$ctrl.searchByColumn('${field}')"
triple-state="true"
/>`)(this.$inputsScope);
} else if (options && options.datepicker) {
input = this.$compile(`
<vn-date-picker
class="dense"
name="${field}"
ng-model="searchProps['${field}']"
on-change="$ctrl.searchByColumn('${field}')"
/>`)(this.$inputsScope);
} else {
input = this.$compile(`
<vn-textfield
@ -372,13 +391,12 @@ export default class SmartTable extends Component {
searchByColumn(field) {
const searchCriteria = this.$inputsScope.searchProps[field];
const emptySearch = searchCriteria == '' || null;
const emptySearch = searchCriteria === '' || searchCriteria == null;
const filters = this.filterSanitizer(field);
if (filters && filters.userFilter)
this.model.userFilter = filters.userFilter;
if (!emptySearch)
this.addFilter(field, this.$inputsScope.searchProps[field]);
else this.model.refresh();

View File

@ -224,5 +224,7 @@
"The agency is already assigned to another autonomous": "La agencia ya está asignada a otro autónomo",
"date in the future": "Fecha en el futuro",
"reference duplicated": "Referencia duplicada",
"This ticket is already a refund": "Este ticket ya es un abono"
"This ticket is already a refund": "Este ticket ya es un abono",
"isWithoutNegatives": "isWithoutNegatives",
"routeFk": "routeFk"
}

View File

@ -4,7 +4,7 @@ const buildFilter = require('vn-loopback/util/filter').buildFilter;
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
module.exports = Self => {
Self.remoteMethodCtx('detailFilter', {
Self.remoteMethodCtx('extendedListFilter', {
description: 'Find all instances of the model matched by filter from the data source.',
accessType: 'READ',
accepts: [
@ -13,128 +13,84 @@ module.exports = Self => {
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
},
{
arg: 'tags',
type: ['object'],
description: 'List of tags to filter with',
},
{
arg: 'search',
type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by name`,
},
{
arg: 'id',
type: 'integer',
description: 'Item id',
},
{
arg: 'categoryFk',
type: 'integer',
description: 'Category id',
},
{
arg: 'typeFk',
type: 'integer',
description: 'Type id',
},
{
arg: 'isActive',
type: 'boolean',
description: 'Whether the item is or not active',
},
{
arg: 'buyerFk',
type: 'integer',
description: 'The buyer of the item',
},
{
arg: 'supplierFk',
type: 'integer',
description: 'The supplier of the item',
},
{
arg: 'description',
arg: 'name',
type: 'string',
description: 'The item description',
description: 'The client name',
},
{
arg: 'stemMultiplier',
type: 'integer',
description: 'The item multiplier',
arg: 'salesPersonFk',
type: 'number',
},
{
arg: 'landed',
type: 'date',
description: 'The item last buy landed date',
arg: 'fi',
type: 'string',
description: 'The client fiscal id',
},
{
arg: 'isFloramondo',
type: 'boolean',
description: 'Whether the the item is or not floramondo',
}
arg: 'socialName',
type: 'string',
},
{
arg: 'city',
type: 'string',
},
{
arg: 'postcode',
type: 'string',
},
{
arg: 'provinceFk',
type: 'number',
},
{
arg: 'email',
type: 'string',
},
{
arg: 'phone',
type: 'string',
},
],
returns: {
type: ['object'],
root: true
},
http: {
path: `/detailFilter`,
path: `/extendedListFilter`,
verb: 'GET'
}
});
Self.detailFilter = async(ctx, filter, options) => {
Self.extendedListFilter = async(ctx, filter, options) => {
const conn = Self.dataSource.connector;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
let codeWhere;
if (ctx.args.search) {
const items = await Self.app.models.ItemBarcode.find({
where: {code: ctx.args.search},
fields: ['itemFk']
}, myOptions);
const itemIds = [];
for (const item of items)
itemIds.push(item.itemFk);
codeWhere = {'i.id': {inq: itemIds}};
}
const where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return /^\d+$/.test(value)
? {or: [{'i.id': value}, codeWhere]}
: {or: [
{'i.name': {like: `%${value}%`}},
{'i.longName': {like: `%${value}%`}},
codeWhere]};
case 'id':
case 'isActive':
case 'typeFk':
case 'isFloramondo':
return {[`i.${param}`]: value};
case 'multiplier':
return {'i.stemMultiplier': value};
case 'categoryFk':
return {'ic.id': value};
case 'buyerFk':
return {'it.workerFk': value};
case 'supplierFk':
return {'s.id': value};
case 'origin':
return {'ori.code': value};
case 'intrastat':
return {'intr.description': value};
case 'landed':
return {'lb.landed': value};
? {'c.id': {inq: value}}
: {'c.name': {like: `%${value}%`}};
case 'name':
case 'salesPersonFk':
case 'fi':
case 'socialName':
case 'city':
case 'postcode':
case 'provinceFk':
case 'email':
case 'phone':
param = `c.${param}`;
return {[param]: value};
}
});
@ -175,6 +131,8 @@ module.exports = Self => {
u.name AS salesPerson,
bt.code AS businessTypeFk,
bt.description AS businessType,
pm.id AS payMethodFk,
pm.name AS payMethod,
sti.CodigoIva AS sageTaxTypeFk,
sti.Iva AS sageTaxType,
stt.CodigoTransaccion AS sageTransactionTypeFk,
@ -184,6 +142,7 @@ module.exports = Self => {
LEFT JOIN country ct ON ct.id = c.countryFk
LEFT JOIN province p ON p.id = c.provinceFk
LEFT JOIN businessType bt ON bt.code = c.businessTypeFk
LEFT JOIN payMethod pm ON pm.id = c.payMethodFk
LEFT JOIN sage.TiposIva sti ON sti.CodigoIva = c.taxTypeSageFk
LEFT JOIN sage.TiposTransacciones stt ON stt.CodigoTransaccion = c.transactionTypeSageFk

View File

@ -31,7 +31,7 @@ module.exports = Self => {
require('../methods/client/createReceipt')(Self);
require('../methods/client/updatePortfolio')(Self);
require('../methods/client/checkDuplicated')(Self);
require('../methods/client/detailFilter')(Self);
require('../methods/client/extendedListFilter')(Self);
// Validations

View File

@ -1,113 +0,0 @@
import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';
class Controller extends Section {
constructor($element, $) {
super($element, $);
this.smartTableOptions = {
activeButtons: {
search: true,
shownColumns: true,
},
columns: [
{
field: 'category',
autocomplete: {
url: 'ItemCategories',
valueField: 'name',
}
},
{
field: 'origin',
autocomplete: {
url: 'Origins',
showField: 'code',
valueField: 'code'
}
},
{
field: 'typeFk',
autocomplete: {
url: 'ItemTypes',
}
},
{
field: 'intrastat',
autocomplete: {
url: 'Intrastats',
showField: 'description',
valueField: 'description'
}
},
{
field: 'buyerFk',
autocomplete: {
url: 'Workers/activeWithRole',
where: `{role: {inq: ['logistic', 'buyer']}}`,
searchFunction: '{firstName: $search}',
showField: 'nickname',
valueField: 'id',
}
},
{
field: 'active',
searchable: false
},
{
field: 'landed',
searchable: false
},
]
};
}
exprBuilder(param, value) {
switch (param) {
case 'category':
return {'ic.name': value};
case 'buyerFk':
return {'it.workerFk': value};
case 'grouping':
return {'b.grouping': value};
case 'packing':
return {'b.packing': value};
case 'origin':
return {'ori.code': value};
case 'typeFk':
return {'i.typeFk': value};
case 'intrastat':
return {'intr.description': value};
case 'name':
return {'i.name': {like: `%${value}%`}};
case 'producer':
return {'pr.name': {like: `%${value}%`}};
case 'id':
case 'size':
case 'subname':
case 'isActive':
case 'density':
case 'stemMultiplier':
case 'stems':
return {[`i.${param}`]: value};
}
}
onCloneAccept(itemFk) {
return this.$http.post(`Items/${itemFk}/clone`)
.then(res => {
this.$state.go('item.card.tags', {id: res.data.id});
});
}
preview(client) {
this.clientSelected = client;
this.$.preview.show();
}
}
ngModule.vnComponent('vnClientDetail', {
template: require('./index.html'),
controller: Controller
});

View File

@ -1,2 +0,0 @@
picture: Foto
Buy requests: Peticiones de compra

View File

@ -1,32 +0,0 @@
@import "variables";
vn-item-product {
display: block;
.id {
background-color: $color-main;
color: $color-font-dark;
margin-bottom: 0;
}
.image {
height: 112px;
width: 112px;
& > img {
max-height: 100%;
max-width: 100%;
border-radius: 3px;
}
}
vn-label-value:first-of-type section{
margin-top: 9px;
}
}
table {
img {
border-radius: 50%;
width: 50px;
height: 50px;
}
}

View File

@ -1,12 +1,13 @@
<vn-crud-model
vn-id="model"
url="Clients/detailFilter"
url="Clients/extendedListFilter"
limit="20"
auto-load="true">
</vn-crud-model>
<vn-portal slot="topbar">
<vn-searchbar
vn-focus
panel="vn-client-search-panel"
placeholder="Search client"
info="Search client by id or name"
auto-state="false"
@ -34,7 +35,7 @@
<span translate>Social name</span>
</th>
<th field="fi">
<span translate>Fiscal ID</span>
<span translate>Tax number</span>
</th>
<th field="salesPersonFk">
<span translate>Salesperson</span>
@ -75,43 +76,46 @@
<th field="businessTypeFk">
<span translate>Business type</span>
</th>
<th field="sageTransactionTypeFk">
<th field="payMethodFk">
<span translate>Billing data</span>
</th>
<th field="sageTaxTypeFk">
<span translate>Sage tax type</span>
</th>
<th field="sageTransactionTypeFk">
<span translate>Sage tr. type</span>
</th>
<th field="isActive">
<th field="isActive" centered>
<span translate>Active</span>
</th>
<th field="isVies">
<th field="isVies" centered>
<span translate>Vies</span>
</th>
<th field="isTaxDataChecked">
<span translate>Tax data checked</span>
<th field="isTaxDataChecked" centered>
<span translate>Verified data</span>
</th>
<th field="isEqualizated">
<span translate>Tax equalized</span>
<th field="isEqualizated" centered>
<span translate>Is equalizated</span>
</th>
<th field="isFreezed">
<th field="isFreezed" centered>
<span translate>Freezed</span>
</th>
<th field="hasToInvoice">
<th field="hasToInvoice" centered>
<span translate>Invoice</span>
</th>
<th field="hasToInvoiceByAddress">
<th field="hasToInvoiceByAddress" centered>
<span translate>Invoice by address</span>
</th>
<th field="isToBeMailed">
<th field="isToBeMailed" centered>
<span translate>Mailing</span>
</th>
<th field="hasLcr">
<th field="hasLcr" centered>
<span translate>Received LCR</span>
</th>
<th field="hasCoreVnl">
<th field="hasCoreVnl" centered>
<span translate>Received core VNL</span>
</th>
<th field="hasSepaVnl">
<th field="hasSepaVnl" centered>
<span translate>Received B2B VNL</span>
</th>
<th></th>
@ -124,11 +128,11 @@
params: {id: client.id}
}">
<td>
<vn-icon-button ng-show="client.isActive == false"
<vn-icon-button ng-show="::client.isActive == false"
vn-tooltip="Client inactive"
icon="icon-disabled">
</vn-icon-button>
<vn-icon-button ng-show="client.isActive && client.isFreezed == true"
<vn-icon-button ng-show="::client.isActive && client.isFreezed == true"
vn-tooltip="Client frozen"
icon="icon-frozen">
</vn-icon-button>
@ -162,116 +166,97 @@
<td>{{::client.email | dashIfEmpty}}</td>
<td>{{::client.created | date:'dd/MM/yyyy'}}</td>
<td>{{::client.businessType | dashIfEmpty}}</td>
<td>{{::client.payMethod | dashIfEmpty}}</td>
<td>{{::client.sageTaxType | dashIfEmpty}}</td>
<td>{{::client.sageTransactionType | dashIfEmpty}}</td>
<td>
<vn-check
disabled="true"
ng-model="::client.isActive">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.isActive,
'alert': !client.isActive,
}">
{{ ::client.isActive ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.isVies">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.isVies,
'alert': !client.isVies,
}">
{{ ::client.isVies ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.isTaxDataChecked">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.isTaxDataChecked,
'alert': !client.isTaxDataChecked,
}">
{{ ::client.isTaxDataChecked ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.isEqualizated">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.isEqualizated,
'alert': !client.isEqualizated,
}">
{{ ::client.isEqualizated ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.isFreezed">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.isFreezed,
'alert': !client.isFreezed,
}">
{{ ::client.isFreezed ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.hasToInvoice">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.hasToInvoice,
'alert': !client.hasToInvoice,
}">
{{ ::client.hasToInvoice ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.hasToInvoiceByAddress">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.hasToInvoiceByAddress,
'alert': !client.hasToInvoiceByAddress,
}">
{{ ::client.hasToInvoiceByAddress ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.isToBeMailed">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.isToBeMailed,
'alert': !client.isToBeMailed,
}">
{{ ::client.isToBeMailed ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.hasLcr">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.hasLcr,
'alert': !client.hasLcr,
}">
{{ ::client.hasLcr ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.hasCoreVnl">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.hasCoreVnl,
'alert': !client.hasCoreVnl,
}">
{{ ::client.hasCoreVnl ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<td>
<vn-check
disabled="true"
ng-model="::client.hasSepaVnl">
</vn-check>
<td centered>
<vn-chip ng-class="::{
'success': client.hasSepaVnl,
'alert': !client.hasSepaVnl,
}">
{{ ::client.hasSepaVnl ? 'Yes' : 'No' | translate}}
</vn-chip>
</td>
<!-- <td vn-fetched-tags>
<div>
<vn-one title="{{::item.name}}">{{::item.name}}</vn-one>
<vn-one ng-if="::item.subName">
<h3 title="{{::item.subName}}">{{::item.subName}}</h3>
</vn-one>
</div>
<vn-fetched-tags
max-length="6"
item="item"
tabindex="-1">
</vn-fetched-tags>
</td>
<td>{{::item.stems}}</td>
<td>{{::item.size}}</td>
<td title="{{::item.typeName}}">
{{::item.typeName}}
</td>
<td title="{{::item.category}}">
{{::item.category}}
</td>
<td title="{{::item.intrastat}}">
{{::item.intrastat}}
</td>
<td>{{::item.origin}}</td>
<td title="{{::item.userName}}">
<span
class="link"
vn-click-stop="workerDescriptor.show($event, item.buyerFk)">
{{::item.userName}}
</span>
</td>
<td>{{::item.density}}</td>
<td>{{::item.stemMultiplier}}</td>
<td>
<vn-check
disabled="true"
ng-model="::item.isActive">
</vn-check>
</td>
<td>{{::item.producer | dashIfEmpty}}</td>
<td shrink-date>{{::item.landed | date:'dd/MM/yyyy'}}</td> -->
<td shrink>
<vn-horizontal class="buttons">
<vn-icon-button vn-anchor="{state: 'ticket.index', params: {q: {clientFk: client.id} } }"
@ -291,7 +276,7 @@
</slot-table>
</smart-table>
</vn-card>
<a ui-sref="item.create" vn-tooltip="New item" vn-bind="+" fixed-bottom-right>
<a ui-sref="client.create" vn-tooltip="New client" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>
<vn-client-descriptor-popover

View File

@ -0,0 +1,184 @@
import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';
class Controller extends Section {
constructor($element, $) {
super($element, $);
this.smartTableOptions = {
activeButtons: {
search: true,
shownColumns: true,
},
columns: [
{
field: 'socialName',
autocomplete: {
url: 'Clients',
showField: 'socialName',
valueField: 'socialName',
}
},
{
field: 'created',
datepicker: true
},
{
field: 'countryFk',
autocomplete: {
url: 'Countries',
showField: 'country',
}
},
{
field: 'provinceFk',
autocomplete: {
url: 'Provinces'
}
},
{
field: 'salesPersonFk',
autocomplete: {
url: 'Workers/activeWithInheritedRole',
where: `{role: 'salesPerson'}`,
searchFunction: '{firstName: $search}',
showField: 'nickname',
valueField: 'id',
}
},
{
field: 'businessTypeFk',
autocomplete: {
url: 'BusinessTypes',
valueField: 'code',
showField: 'description',
}
},
{
field: 'payMethodFk',
autocomplete: {
url: 'PayMethods',
}
},
{
field: 'sageTaxTypeFk',
autocomplete: {
url: 'SageTaxTypes',
showField: 'vat',
}
},
{
field: 'sageTransactionTypeFk',
autocomplete: {
url: 'SageTransactionTypes',
showField: 'transaction',
}
},
{
field: 'isActive',
checkbox: true
},
{
field: 'isVies',
checkbox: true
},
{
field: 'isTaxDataChecked',
checkbox: true
},
{
field: 'isEqualizated',
checkbox: true
},
{
field: 'isFreezed',
checkbox: true
},
{
field: 'hasToInvoice',
checkbox: true
},
{
field: 'hasToInvoiceByAddress',
checkbox: true
},
{
field: 'isToBeMailed',
checkbox: true
},
{
field: 'hasSepaVnl',
checkbox: true
},
{
field: 'hasLcr',
checkbox: true
},
{
field: 'hasCoreVnl',
checkbox: true
}
]
};
}
exprBuilder(param, value) {
switch (param) {
case 'created':
return {'c.created': {
between: this.dateRange(value)}
};
case 'id':
case 'name':
case 'socialName':
case 'fi':
case 'credit':
case 'creditInsurance':
case 'phone':
case 'mobile':
case 'street':
case 'city':
case 'postcode':
case 'email':
case 'isActive':
case 'isVies':
case 'isTaxDataChecked':
case 'isEqualizated':
case 'isFreezed':
case 'hasToInvoice':
case 'hasToInvoiceByAddress':
case 'isToBeMailed':
case 'hasSepaVnl':
case 'hasLcr':
case 'hasCoreVnl':
case 'countryFk':
case 'provinceFk':
case 'salesPersonFk':
case 'businessTypeFk':
case 'payMethodFk':
case 'sageTaxTypeFk':
case 'sageTransactionTypeFk':
return {[`c.${param}`]: value};
}
}
dateRange(value) {
const minHour = new Date(value);
minHour.setHours(0, 0, 0, 0);
const maxHour = new Date(value);
maxHour.setHours(23, 59, 59, 59);
return [minHour, maxHour];
}
preview(client) {
this.clientSelected = client;
this.$.preview.show();
}
}
ngModule.vnComponent('vnClientExtendedList', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,3 @@
Mailing: Env. emails
Sage tr. type: Tipo tr. sage
Yes:

View File

@ -0,0 +1,6 @@
@import "variables";
vn-chip.success,
vn-chip.alert {
color: $color-font-bg
}

View File

@ -47,4 +47,4 @@ import './consumption-search-panel';
import './defaulter';
import './notification';
import './unpaid';
import './detail';
import './extended-list';

View File

@ -33,6 +33,7 @@ Search client by id or name: Buscar clientes por identificador o nombre
# Sections
Clients: Clientes
Extended list: Listado extendido
Defaulter: Morosos
New client: Nuevo cliente
Fiscal data: Datos fiscales

View File

@ -7,7 +7,7 @@
"menus": {
"main": [
{"state": "client.index", "icon": "person"},
{"state": "client.detail", "icon": "person"},
{"state": "client.extendedList", "icon": "person"},
{"state": "client.notification", "icon": "campaign"},
{"state": "client.defaulter", "icon": "icon-defaulter"}
],
@ -384,10 +384,10 @@
"description": "Unpaid"
},
{
"url": "/detail",
"state": "client.detail",
"component": "vn-client-detail",
"description": "Detail"
"url": "/extended-list",
"state": "client.extendedList",
"component": "vn-client-extended-list",
"description": "Extended list"
}
]
}

View File

@ -1,7 +1,7 @@
Client id: Id cliente
Tax number: NIF/CIF
Name: Nombre
Social name: Razon social
Social name: Razón social
Town/City: Ciudad
Postcode: Código postal
Email: E-mail

View File

@ -53,7 +53,7 @@ export default class Controller extends Section {
},
{
field: 'shippedDate',
searchable: false
datepicker: true
},
{
field: 'theoreticalHour',