refs #5184 working on search panel
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Alexandre Riera 2023-03-27 14:29:22 +02:00
parent 4bc24b02f6
commit 6f2de903bc
15 changed files with 232 additions and 3 deletions

View File

@ -0,0 +1,4 @@
ALTER TABLE `vn`.`invoiceInConfig` ADD daysAgo INT UNSIGNED DEFAULT 45 COMMENT 'Días en el pasado para mostrar facturas en invoiceIn series en salix';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('InvoiceIn', 'getSerial', 'READ', 'ALLOW', 'ROLE', 'administrative');

View File

@ -2490,9 +2490,9 @@ REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issu
(9, 1009, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1242, 1, 442, 1), (9, 1009, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1242, 1, 442, 1),
(10, 1010, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1243, 1, 442, 1); (10, 1010, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1243, 1, 442, 1);
INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`) INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`, `daysAgo`)
VALUES VALUES
(1, -2, '2% retention', 2); (1, -2, '2% retention', 2, 45);
INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`) INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`)
VALUES VALUES

View File

@ -0,0 +1,34 @@
module.exports = Self => {
Self.remoteMethod('getSerial', {
description: 'Return invoiceIn serial',
accessType: 'READ',
accepts: {
arg: 'issued',
type: 'date',
required: true
},
returns: {
type: 'object',
root: true
},
http: {
path: '/getSerial',
verb: 'GET'
}
});
Self.getSerial = async(issued, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const result = await Self.rawSql(`
SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total
FROM vn.invoiceIn i
WHERE i.issued >= ?
GROUP BY i.serial`, [issued]);
return result;
};
};

View File

@ -17,6 +17,9 @@
}, },
"retentionName": { "retentionName": {
"type": "string" "type": "string"
},
"daysAgo": {
"type": "number"
} }
}, },
"relations": { "relations": {

View File

@ -6,4 +6,5 @@ module.exports = Self => {
require('../methods/invoice-in/getTotals')(Self); require('../methods/invoice-in/getTotals')(Self);
require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInPdf')(Self);
require('../methods/invoice-in/invoiceInEmail')(Self); require('../methods/invoice-in/invoiceInEmail')(Self);
require('../methods/invoice-in/getSerial')(Self);
}; };

View File

@ -13,3 +13,5 @@ import './dueDay';
import './intrastat'; import './intrastat';
import './create'; import './create';
import './log'; import './log';
import './serial';
import './serial-search-panel';

View File

@ -7,6 +7,7 @@ Foreign value: Divisa
InvoiceIn: Facturas recibidas InvoiceIn: Facturas recibidas
InvoiceIn cloned: Factura clonada InvoiceIn cloned: Factura clonada
InvoiceIn deleted: Factura eliminada InvoiceIn deleted: Factura eliminada
InvoiceIn Serial: Facturas por series
Invoice list: Listado de facturas recibidas Invoice list: Listado de facturas recibidas
InvoiceIn booked: Factura contabilizada InvoiceIn booked: Factura contabilizada
Net: Neto Net: Neto

View File

@ -12,6 +12,10 @@
{ {
"state": "invoiceIn.index", "state": "invoiceIn.index",
"icon": "icon-invoice-in" "icon": "icon-invoice-in"
},
{
"state": "invoiceIn.serial",
"icon": "icon-invoice-in"
} }
], ],
"card": [ "card": [
@ -54,6 +58,15 @@
"administrative" "administrative"
] ]
}, },
{
"url": "/serial",
"state": "invoiceIn.serial",
"component": "vn-invoice-in-serial",
"description": "InvoiceIn Serial",
"acl": [
"administrative"
]
},
{ {
"url": "/:id", "url": "/:id",
"state": "invoiceIn.card", "state": "invoiceIn.card",
@ -133,4 +146,4 @@
] ]
} }
] ]
} }

View File

@ -0,0 +1,26 @@
<vn-side-menu side="right">
<vn-horizontal class="input">
<vn-textfield
label="Days ago"
ng-model="$ctrl.filter.search"
vn-focus
ng-keydown="$ctrl.onKeyPress($event)">
</vn-textfield>
</vn-horizontal>
<vn-horizontal class="input">
<vn-textfield
label="Serial"
ng-model="$ctrl.filter.search"
ng-keydown="$ctrl.onKeyPress($event)">
</vn-textfield>
</vn-horizontal>
<div class="chips">
<vn-chip
ng-if="$ctrl.filter.search"
removable="true"
on-remove="$ctrl.removeItemFilter('search')"
class="colored">
<span>Id/Name: {{$ctrl.filter.search}}</span>
</vn-chip>
</div>
</vn-side-menu>

View File

@ -0,0 +1,41 @@
import ngModule from '../module';
import SearchPanel from 'core/components/searchbar/search-panel';
import './style.scss';
class Controller extends SearchPanel {
constructor($element, $) {
super($element, $);
const filter = {
fields: ['daysAgo']
};
this.$http.get('InvoiceInConfigs', {filter});
}
$onInit() {
this.filter = {
tags: []
};
}
removeItemFilter(param) {
this.filter[param] = null;
this.addFilters();
}
onKeyPress($event) {
if ($event.key === 'Enter')
this.addFilters();
}
addFilters() {
return this.model.addFilter({}, this.filter);
}
}
ngModule.component('vnInvoiceInSerialSearchPanel', {
template: require('./index.html'),
controller: Controller,
bindings: {
model: '<'
}
});

View File

@ -0,0 +1,24 @@
@import "variables";
vn-invoice-in-serial-search-panel vn-side-menu div {
& > .input {
padding-left: $spacing-md;
padding-right: $spacing-md;
border-color: $color-spacer;
border-bottom: $border-thin;
}
& > .horizontal {
grid-auto-flow: column;
grid-column-gap: $spacing-sm;
align-items: center;
}
& > .chips {
display: flex;
flex-wrap: wrap;
padding: $spacing-md;
overflow: hidden;
max-width: 100%;
border-color: $color-spacer;
border-top: $border-thin;
}
}

View File

@ -0,0 +1,42 @@
<vn-crud-model
vn-id="model"
url="InvoiceIns/getSerial"
limit="20"
auto-load="true"
params="{issued: '1900-01-01'}">
</vn-crud-model>
<vn-portal slot="topbar">
</vn-portal>
<vn-invoice-in-serial-search-panel
model="model">
</vn-invoice-in-serial-search-panel>
<vn-data-viewer
model="model"
class="vn-w-lg">
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="serial">Serial</vn-th>
<vn-th field="pending">Pending</vn-th>
<vn-th field="total">Total</vn-th>
<vn-th></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="invoiceIn in model.data">
<vn-td>{{::invoiceIn.serial}}</vn-td>
<vn-td>{{::invoiceIn.pending}}</vn-td>
<vn-td>{{::invoiceIn.total}}</vn-td>
<vn-td shrink>
<vn-icon-button
vn-click-stop="$ctrl.$state.go('invoiceIn.index')"
vn-tooltip="Go to InvoiceIn"
icon="icon-invoice-in">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card>
</vn-data-viewer>

View File

@ -0,0 +1,35 @@
import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
constructor($element, $) {
super($element, $);
}
exprBuilder(param, value) {
switch (param) {
case 'issued':
return {'ii.issued': {
between: this.dateRange(value)}
};
case 'serial':
return {[`ii.${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];
}
}
Controller.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnInvoiceInSerial', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,3 @@
Serial: Serie
Pending: Pendientes
Go to InvoiceIn: Ir al listado de facturas recibidas