Merge branch 'dev' into test
gitea/salix/test This commit looks good
Details
gitea/salix/test This commit looks good
Details
This commit is contained in:
commit
2e325310d8
|
@ -31,4 +31,3 @@ rules:
|
|||
curly: [error, multi-or-nest]
|
||||
indent: [error, 4]
|
||||
arrow-parens: [error, as-needed]
|
||||
jasmine/no-focused-tests: 0
|
|
@ -131,6 +131,7 @@ pipeline {
|
|||
stage('Database') {
|
||||
when { anyOf {
|
||||
branch 'test'
|
||||
branch 'master'
|
||||
}}
|
||||
steps {
|
||||
configFileProvider([
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('160', 'TicketServiceType', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
DROP function IF EXISTS `vn`.`clientGetSalesPerson`;
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `vn`.`clientGetSalesPerson`(vClientFk INT, vDated DATE) RETURNS int(11)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Dado un id cliente y una fecha, devuelve su comercial para ese dia, teniendo
|
||||
* en cuenta la jerarquía de las tablas: 1º la de sharingClient, 2º la de
|
||||
* sharingCart y tercero la de clientes.
|
||||
*
|
||||
* @param vClientFk El id del cliente
|
||||
* @param vDated Fecha a comprobar
|
||||
* @return El id del comercial para la fecha dada
|
||||
**/
|
||||
DECLARE vSalesperson INT DEFAULT NULL;
|
||||
DECLARE vSubstitute INT DEFAULT NULL;
|
||||
DECLARE vLoop BOOLEAN;
|
||||
|
||||
-- Obtiene el comercial original y el de sharingClient
|
||||
|
||||
SELECT c.salesPersonFk, s.workerFk
|
||||
INTO vSalesperson, vSubstitute
|
||||
FROM client c
|
||||
LEFT JOIN sharingClient s
|
||||
ON c.id = s.clientFk
|
||||
AND vDated BETWEEN s.started AND s.ended
|
||||
WHERE c.id = vClientFk
|
||||
ORDER BY s.id
|
||||
LIMIT 1;
|
||||
|
||||
-- Si no hay ninguno en sharingClient busca en sharingCart
|
||||
|
||||
IF vSubstitute IS NOT NULL
|
||||
THEN
|
||||
SET vSalesperson = vSubstitute;
|
||||
ELSEIF vSalesperson IS NOT NULL
|
||||
THEN
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.stack;
|
||||
CREATE TEMPORARY TABLE tmp.stack
|
||||
(INDEX (substitute))
|
||||
ENGINE = MEMORY
|
||||
SELECT vSalesperson substitute;
|
||||
|
||||
l: LOOP
|
||||
SELECT workerSubstitute INTO vSubstitute
|
||||
FROM sharingCart
|
||||
WHERE vDated BETWEEN started AND ended
|
||||
AND workerFk = vSalesperson
|
||||
ORDER BY id
|
||||
LIMIT 1;
|
||||
|
||||
IF vSubstitute IS NULL THEN
|
||||
LEAVE l;
|
||||
END IF;
|
||||
|
||||
SELECT COUNT(*) > 0 INTO vLoop
|
||||
FROM tmp.stack WHERE substitute = vSubstitute;
|
||||
|
||||
IF vLoop THEN
|
||||
LEAVE l;
|
||||
END IF;
|
||||
|
||||
INSERT INTO tmp.stack SET
|
||||
substitute = vSubstitute;
|
||||
|
||||
SET vSalesperson = vSubstitute;
|
||||
END LOOP;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.stack;
|
||||
END IF;
|
||||
|
||||
RETURN vSalesperson;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `vn2008`.`Greuges` CHANGE COLUMN `Fecha` `Fecha` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ;
|
|
@ -0,0 +1,9 @@
|
|||
ALTER TABLE `vn2008`.`Facturas`
|
||||
DROP FOREIGN KEY `invoice_bank_id`;
|
||||
ALTER TABLE `vn2008`.`Facturas`
|
||||
CHANGE COLUMN `Id_Banco` `Id_Banco` INT(11) NULL DEFAULT NULL ;
|
||||
ALTER TABLE `vn2008`.`Facturas`
|
||||
ADD CONSTRAINT `invoice_bank_id`
|
||||
FOREIGN KEY (`Id_Banco`)
|
||||
REFERENCES `vn2008`.`Bancos` (`Id_Banco`)
|
||||
ON UPDATE CASCADE;
|
|
@ -0,0 +1,17 @@
|
|||
ALTER TABLE `vn2008`.`Colas`
|
||||
DROP FOREIGN KEY `Colas_ibfk_1`,
|
||||
DROP FOREIGN KEY `Colas_ibfk_2`,
|
||||
DROP FOREIGN KEY `Colas_ibfk_3`,
|
||||
DROP FOREIGN KEY `Colas_ibfk_5`;
|
||||
ALTER TABLE `vn2008`.`Colas`
|
||||
CHANGE COLUMN `Id_Impresora` `Id_Impresora` TINYINT(3) UNSIGNED NULL DEFAULT NULL ,
|
||||
CHANGE COLUMN `Id_Prioridad` `Id_Prioridad` TINYINT(3) UNSIGNED NULL DEFAULT NULL ;
|
||||
ALTER TABLE `vn2008`.`Colas`
|
||||
ADD CONSTRAINT `Colas_ibfk_4`
|
||||
FOREIGN KEY (`Id_Impresora`)
|
||||
REFERENCES `vn2008`.`Impresoras` (`Id_Impresora`)
|
||||
ON UPDATE CASCADE,
|
||||
ADD CONSTRAINT `Colas_ibfk_3`
|
||||
FOREIGN KEY (`Id_Prioridad`)
|
||||
REFERENCES `vn2008`.`Prioridades` (`Id_Prioridad`)
|
||||
ON UPDATE CASCADE;
|
|
@ -0,0 +1,14 @@
|
|||
CREATE
|
||||
ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`sharingCart` AS
|
||||
SELECT
|
||||
`s`.`id` AS `id`,
|
||||
`s`.`Id_Trabajador` AS `workerFk`,
|
||||
`s`.`datSTART` AS `started`,
|
||||
`s`.`datEND` AS `ended`,
|
||||
`s`.`Id_Suplente` AS `workerSubstitute`,
|
||||
`s`.`odbc_date` AS `created`
|
||||
FROM
|
||||
`vn2008`.`sharingcart` `s`
|
|
@ -0,0 +1,13 @@
|
|||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`sharingClient` AS
|
||||
SELECT
|
||||
`s`.`id` AS `id`,
|
||||
`s`.`Id_Trabajador` AS `workerFk`,
|
||||
`s`.`datSTART` AS `started`,
|
||||
`s`.`datEND` AS `ended`,
|
||||
`s`.`Id_Cliente` AS `clientFk`
|
||||
FROM
|
||||
`vn2008`.`sharingclient` `s`;
|
|
@ -440,9 +440,12 @@ INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped
|
|||
|
||||
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
|
||||
VALUES
|
||||
( 1, 1 , 1, 'ready' ),
|
||||
( 2, 2 , 2, 'do it fast please'),
|
||||
( 3, 3 , 3, '');
|
||||
(1, 1 , 1, 'ready' ),
|
||||
(2, 2 , 2, 'do it fast please'),
|
||||
(3, 3 , 3, 'Faster faster fasteeeeeer!!!'),
|
||||
(4, 4 , 3, 'Deliver before 8am'),
|
||||
(5, 13 , 3, 'You can run from the disappointments you are trying to forget. But its only when you embrace your past that you truly move forward. Maybe I never get to go home again, but I found my way there. And I am glad I did.'),
|
||||
(6, 14, 3, 'Careful, armed warhead');
|
||||
|
||||
INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `created`)
|
||||
VALUES
|
||||
|
@ -973,6 +976,14 @@ INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`)
|
|||
VALUES
|
||||
(1,DATE_ADD(CURDATE(),INTERVAL -1 MONTH));
|
||||
|
||||
INSERT INTO `vn2008`.`Estados` (`Id_Estado`, `Estado`)
|
||||
VALUES
|
||||
('1', 'En Espera');
|
||||
|
||||
INSERT INTO `vn2008`.`Informes` (`Id_Informe`, `Informe`)
|
||||
VALUES
|
||||
('30', 'Generar factura PDF');
|
||||
|
||||
INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`)
|
||||
VALUES
|
||||
( 1, 'AGENCY', 'Agencia'),
|
||||
|
@ -1317,3 +1328,11 @@ INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `user`, `password`, `title`)
|
|||
VALUES
|
||||
('1', 'https://websms.xtratelecom.es/api_php/server.wsdl', 'VERDINATURA', '182wbOKu', 'Verdnatura');
|
||||
|
||||
INSERT INTO `vn`.`sharingClient`(`id`, `workerFk`, `started`, `ended`, `clientFk`)
|
||||
VALUES
|
||||
(1, 19, DATE_ADD(CURDATE(), INTERVAL -5 DAY), DATE_ADD(CURDATE(), INTERVAL +15 DAY), 101),
|
||||
(2, 18, DATE_ADD(CURDATE(), INTERVAL -5 DAY), DATE_ADD(CURDATE(), INTERVAL +15 DAY), 106);
|
||||
|
||||
INSERT INTO `vn`.`sharingCart`(`id`, `workerFk`, `started`, `ended`, `workerSubstitute`, `created`)
|
||||
VALUES
|
||||
(1, 18, DATE_ADD(CURDATE(), INTERVAL -5 DAY), DATE_ADD(CURDATE(), INTERVAL +15 DAY), 19, DATE_ADD(CURDATE(), INTERVAL -5 DAY));
|
|
@ -455,7 +455,7 @@ export default {
|
|||
},
|
||||
ticketService: {
|
||||
addServiceButton: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(3) > vn-icon-button > button > vn-icon',
|
||||
firstDescriptionInput: 'vn-ticket-service vn-autocomplete[label="Documentos"]',
|
||||
firstDescriptionAutocomplete: 'vn-ticket-service vn-autocomplete[field="service.description"]',
|
||||
firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input',
|
||||
firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input',
|
||||
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
|
||||
|
|
|
@ -13,8 +13,7 @@ describe('Ticket services path', () => {
|
|||
|
||||
it('should edit the first service', async() => {
|
||||
const result = await nightmare
|
||||
.clearInput(selectors.ticketService.firstDescriptionInput)
|
||||
.write(selectors.ticketService.firstDescriptionInput, 'my service')
|
||||
.autocompleteSearch(selectors.ticketService.firstDescriptionAutocomplete, 'Documentos')
|
||||
.clearInput(selectors.ticketService.firstQuantityInput)
|
||||
.write(selectors.ticketService.firstQuantityInput, 99)
|
||||
.clearInput(selectors.ticketService.firstPriceInput)
|
||||
|
@ -29,9 +28,9 @@ describe('Ticket services path', () => {
|
|||
it('should confirm the service description was edited correctly', async() => {
|
||||
const result = await nightmare
|
||||
.reloadSection('ticket.card.service')
|
||||
.waitToGetProperty(selectors.ticketService.firstDescriptionInput, 'value');
|
||||
.waitToGetProperty(`${selectors.ticketService.firstDescriptionAutocomplete} input`, 'value');
|
||||
|
||||
expect(result).toEqual('my service');
|
||||
expect(result).toEqual('Documentos');
|
||||
});
|
||||
|
||||
it('should confirm the service quantity was edited correctly', async() => {
|
||||
|
@ -55,7 +54,7 @@ describe('Ticket services path', () => {
|
|||
expect(result).toEqual('General VAT');
|
||||
});
|
||||
|
||||
fit('should delete the service', async() => {
|
||||
it('should delete the service', async() => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.ticketService.fistDeleteServiceButton)
|
||||
.waitForNumberOfElements(selectors.ticketService.serviceLine, 0)
|
|
@ -48,7 +48,7 @@ vn-drop-down {
|
|||
}
|
||||
}
|
||||
& > .list {
|
||||
max-height: 12.8em;
|
||||
max-height: 20em;
|
||||
overflow: auto;
|
||||
|
||||
ul {
|
||||
|
|
|
@ -44,11 +44,12 @@ export default class InputNumber extends Input {
|
|||
* @param {Number} value - Value
|
||||
*/
|
||||
set value(value) {
|
||||
if (!this.hasOwnProperty('_value') && value)
|
||||
this.hasValue = !(value === null || value === undefined || value === '');
|
||||
|
||||
if (!this.hasOwnProperty('_value') && this.hasValue)
|
||||
this.input.value = value;
|
||||
|
||||
this._value = value;
|
||||
this.hasValue = !(value === null || value === undefined || value === '');
|
||||
|
||||
if (this.hasValue)
|
||||
this.element.classList.add('not-empty');
|
||||
|
|
|
@ -120,7 +120,6 @@ export default class Popover extends Component {
|
|||
if (!(this.parent && this._shown)) return;
|
||||
|
||||
let margin = 10;
|
||||
let scrollbarSize = 10;
|
||||
|
||||
let style = this.popover.style;
|
||||
style.width = '';
|
||||
|
@ -135,11 +134,12 @@ export default class Popover extends Component {
|
|||
let arrowRect = this.arrow.getBoundingClientRect();
|
||||
let clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
||||
|
||||
let arrowHeight = Math.sqrt(Math.pow(arrowRect.height, 2) * 2) / 2;
|
||||
let arrowHeight = Math.floor(arrowRect.height / 2);
|
||||
let arrowOffset = arrowHeight + margin / 2;
|
||||
|
||||
let endMargin = margin + scrollbarSize;
|
||||
let maxRight = window.innerWidth - endMargin;
|
||||
let maxBottom = window.innerHeight - endMargin;
|
||||
let docEl = document.documentElement;
|
||||
let maxRight = Math.min(window.innerWidth, docEl.clientWidth) - margin;
|
||||
let maxBottom = Math.min(window.innerHeight, docEl.clientHeight) - margin;
|
||||
let maxWith = maxRight - margin;
|
||||
let maxHeight = maxBottom - margin - arrowHeight;
|
||||
|
||||
|
@ -149,9 +149,9 @@ export default class Popover extends Component {
|
|||
let left = parentRect.left + parentRect.width / 2 - width / 2;
|
||||
left = clamp(left, margin, maxRight - width);
|
||||
|
||||
let top = parentRect.top + parentRect.height + arrowHeight;
|
||||
let top = parentRect.top + parentRect.height + arrowOffset;
|
||||
let showTop = top + height > maxBottom;
|
||||
if (showTop) top = parentRect.top - height - arrowHeight;
|
||||
if (showTop) top = parentRect.top - height - arrowOffset;
|
||||
top = Math.max(top, margin);
|
||||
|
||||
if (showTop)
|
||||
|
|
|
@ -8,8 +8,14 @@
|
|||
pointer>
|
||||
</vn-icon>
|
||||
</t-left-icons>
|
||||
<t-right-icons>
|
||||
<vn-icon
|
||||
<t-right-icons vn-horizontal>
|
||||
<vn-icon vn-one
|
||||
ng-if="$ctrl.info"
|
||||
icon="info_outline"
|
||||
vn-tooltip = "{{$ctrl.info}}"
|
||||
pointer>
|
||||
</vn-icon>
|
||||
<vn-icon vn-one
|
||||
ng-if="$ctrl.panel"
|
||||
ng-click="$ctrl.openPanel($event)"
|
||||
icon="keyboard_arrow_down"
|
||||
|
|
|
@ -19,9 +19,10 @@ import {buildFilter} from 'vn-loopback/util/filter';
|
|||
export default class Controller extends Component {
|
||||
constructor($element, $scope, $compile, $state, $transitions) {
|
||||
super($element, $scope);
|
||||
this.$element = $element;
|
||||
this.$compile = $compile;
|
||||
this.$state = $state;
|
||||
|
||||
this.$scope = $scope;
|
||||
let criteria = {to: this.$state.current.name};
|
||||
this.deregisterCallback = $transitions.onSuccess(criteria,
|
||||
() => this.onStateChange());
|
||||
|
@ -218,7 +219,8 @@ ngModule.component('vnSearchbar', {
|
|||
model: '<?',
|
||||
exprBuilder: '&?',
|
||||
paramBuilder: '&?',
|
||||
autoLoad: '<?'
|
||||
autoLoad: '<?',
|
||||
info: '@?'
|
||||
},
|
||||
controller: Controller
|
||||
});
|
||||
|
|
|
@ -3,9 +3,16 @@
|
|||
vn-td-editable {
|
||||
text {
|
||||
border-bottom: 1px solid rgba(0,0,0,.12);
|
||||
min-height: 15px;
|
||||
cursor: pointer;
|
||||
display: block
|
||||
}
|
||||
|
||||
text::after {
|
||||
overflow: hidden;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
outline: none;
|
||||
position: relative;
|
||||
|
|
|
@ -23,7 +23,7 @@ vn-textfield {
|
|||
.leftIcons, .rightIcons, .suffix {
|
||||
display: flex;
|
||||
color: $color-font-secondary;
|
||||
|
||||
|
||||
.material-icons {
|
||||
font-size: 20px !important
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ export default class Textfield extends Input {
|
|||
this.type = $attrs.type;
|
||||
this.showActions = false;
|
||||
this.hasInfo = Boolean($attrs.info);
|
||||
this.info = $attrs.info || null;
|
||||
this.hasFocus = false;
|
||||
this.hasMouseIn = false;
|
||||
|
||||
|
@ -90,6 +89,7 @@ ngModule.component('vnTextfield', {
|
|||
type: '@?',
|
||||
vnTabIndex: '@?',
|
||||
onChange: '&',
|
||||
onClear: '&'
|
||||
onClear: '&',
|
||||
info: '@?'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -80,5 +80,6 @@
|
|||
"We weren't able to send this SMS": "No hemos podido enviar el SMS",
|
||||
"This client can't be invoiced": "Este cliente no puede ser facturado",
|
||||
"This ticket can't be invoiced": "Este ticket no puede ser facturado",
|
||||
"That item is not available on that day": "That item is not available on that day"
|
||||
"That item is not available on that day": "That item is not available on that day",
|
||||
"That item doesn't exists": "That item doesn't exists"
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
panel="vn-zone-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
info="Search zone by id or name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
|
|
|
@ -9,4 +9,5 @@ Are you sure you want to delete this zone?: ¿Estás seguro de querer eliminar e
|
|||
Zones: Zonas
|
||||
New zone: Nueva zona
|
||||
Volumetric: Volumétrico
|
||||
Clone: Clonar
|
||||
Clone: Clonar
|
||||
Search zone by id or name: Buscar zonas por identificador o nombre
|
|
@ -5,6 +5,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search zone by id or name"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('filter', {
|
||||
description: 'Find all instances of the model matched by filter from the data source.',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'tags',
|
||||
type: ['Object'],
|
||||
description: 'List of tags to filter with',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
description: `If it's and integer searchs by id, otherwise it searchs by client name`,
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'client',
|
||||
type: 'String',
|
||||
description: 'The worker name',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'id',
|
||||
type: 'Integer',
|
||||
description: 'The claim id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'clientFk',
|
||||
type: 'Integer',
|
||||
description: 'The client id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'claimStateFk',
|
||||
type: 'Integer',
|
||||
description: 'The claim state id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'workerFk',
|
||||
type: 'Integer',
|
||||
description: 'The worker id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'created',
|
||||
type: 'Date',
|
||||
description: 'The to date filter',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/filter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {'cl.id': value}
|
||||
: {
|
||||
or: [
|
||||
{'c.name': {like: `%${value}%`}}
|
||||
]
|
||||
};
|
||||
case 'client':
|
||||
return {'c.name': {like: `%${value}%`}};
|
||||
case 'id':
|
||||
return {'cl.id': value};
|
||||
case 'clientFk':
|
||||
return {'c.id': value};
|
||||
case 'claimStateFk':
|
||||
return {'cl.claimStateFk': value};
|
||||
case 'workerFk':
|
||||
return {'cl.workerFk': value};
|
||||
case 'created':
|
||||
return {'cl.created': value};
|
||||
}
|
||||
});
|
||||
|
||||
filter = mergeFilters(ctx.args.filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`SELECT cl.id, c.name, u.nickName, cs.description, cl.created
|
||||
FROM claim cl
|
||||
LEFT JOIN client c ON c.id = cl.clientFk
|
||||
LEFT JOIN worker w ON w.id = cl.workerFk
|
||||
LEFT JOIN account.user u ON u.id = w.userFk
|
||||
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk`
|
||||
);
|
||||
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
let itemsIndex = stmts.push(stmt) - 1;
|
||||
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
return itemsIndex === 0 ? result : result[itemsIndex];
|
||||
};
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('claim filter()', () => {
|
||||
it('should return 1 result filtering by id', async() => {
|
||||
let result = await app.models.Claim.filter({args: {filter: {}, search: 1}});
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].id).toEqual(1);
|
||||
});
|
||||
|
||||
it('should return 1 result filtering by string', async() => {
|
||||
let result = await app.models.Claim.filter({args: {filter: {}, search: 'Tony Stark'}});
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].id).toEqual(4);
|
||||
});
|
||||
|
||||
it('should return 4 results filtering by worker id', async() => {
|
||||
let result = await app.models.Claim.filter({args: {filter: {}, workerFk: 18}});
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
expect(result[0].id).toEqual(1);
|
||||
expect(result[1].id).toEqual(2);
|
||||
expect(result[2].id).toEqual(3);
|
||||
expect(result[3].id).toEqual(4);
|
||||
});
|
||||
});
|
|
@ -41,7 +41,7 @@ module.exports = Self => {
|
|||
let notModifiable = ['id', 'responsibility', 'isChargedToMana'];
|
||||
let changedFields = diff(oldClaim, params);
|
||||
let changedFieldsPicked = pick(changedFields, notModifiable);
|
||||
let statesViables = ['Gestionado', 'Pendiente', 'Anulado'];
|
||||
let statesViables = ['Gestionado', 'Pendiente', 'Anulado', 'Mana'];
|
||||
let oldState = await models.ClaimState.findOne({where: {id: oldClaim.claimStateFk}});
|
||||
let newState = await models.ClaimState.findOne({where: {id: params.claimStateFk}});
|
||||
let canChangeState = statesViables.includes(oldState.description)
|
||||
|
|
|
@ -3,4 +3,5 @@ module.exports = Self => {
|
|||
require('../methods/claim/createFromSales')(Self);
|
||||
require('../methods/claim/updateClaim')(Self);
|
||||
require('../methods/claim/regularizeClaim')(Self);
|
||||
require('../methods/claim/filter')(Self);
|
||||
};
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
"claimStateFk": {
|
||||
"type": "Number"
|
||||
},
|
||||
"clientFk": {
|
||||
"type": "Number"
|
||||
},
|
||||
"workerFk": {
|
||||
"type": "Number"
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
vn-one
|
||||
label="Responsability"
|
||||
value="$ctrl.claim.responsibility"
|
||||
max="5"
|
||||
max="$ctrl.maxResponsibility"
|
||||
min="1"
|
||||
step="1"
|
||||
vn-acl="salesAssistant"
|
||||
|
@ -191,4 +191,10 @@
|
|||
</vn-item-descriptor-popover>
|
||||
<vn-ticket-descriptor-popover
|
||||
vn-id="ticketDescriptor">
|
||||
</vn-ticket-descriptor-popover>
|
||||
</vn-ticket-descriptor-popover>
|
||||
<vn-confirm
|
||||
vn-id="update-greuge"
|
||||
question="Insert greuges on client card"
|
||||
message="Do you want to insert greuges?"
|
||||
on-response="$ctrl.onUpdateGreugeResponse(response)">
|
||||
</vn-confirm>
|
|
@ -23,6 +23,7 @@ class Controller {
|
|||
]
|
||||
};
|
||||
this.resolvedState = 3;
|
||||
this.maxResponsibility = 5;
|
||||
}
|
||||
|
||||
openAddSalesDialog() {
|
||||
|
@ -135,9 +136,29 @@ class Controller {
|
|||
this.$http.post(query, data).then(() => {
|
||||
this.card.reload();
|
||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||
if (this.claim.responsibility >= Math.ceil(this.maxResponsibility) / 2)
|
||||
this.$.updateGreuge.show();
|
||||
});
|
||||
}
|
||||
|
||||
onUpdateGreugeResponse(response) {
|
||||
if (response !== 'ACCEPT')
|
||||
return;
|
||||
let greugeTypeFreight = 7;
|
||||
let query = `claim/api/Greuges/`;
|
||||
let data = {
|
||||
clientFk: this.claim.clientFk,
|
||||
description: `claim: ${this.claim.id}`,
|
||||
amount: 11,
|
||||
greugeTypeFk: greugeTypeFreight,
|
||||
ticketFk: this.claim.ticketFk
|
||||
};
|
||||
|
||||
this.$http.post(query, data).then(() => {
|
||||
this.card.reload();
|
||||
this.vnApp.showSuccess(this.$translate.instant('Greuge inserted!'));
|
||||
});
|
||||
}
|
||||
// Item Descriptor
|
||||
showDescriptor(event, itemFk) {
|
||||
this.quicklinks = {
|
||||
|
|
|
@ -158,5 +158,37 @@ describe('claim', () => {
|
|||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onUpdateGreugeResponse()', () => {
|
||||
it('should do nothing', () => {
|
||||
spyOn(controller.card, 'reload');
|
||||
spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
controller.onUpdateGreugeResponse('CANCEL');
|
||||
|
||||
expect(controller.card.reload).not.toHaveBeenCalledWith();
|
||||
expect(controller.vnApp.showSuccess).not.toHaveBeenCalledWith('Greuge inserted!');
|
||||
});
|
||||
|
||||
it('should perform a insert into greuges', () => {
|
||||
spyOn(controller.card, 'reload');
|
||||
spyOn(controller.vnApp, 'showSuccess');
|
||||
controller.claim.clientFk = 101;
|
||||
controller.claim.id = 11;
|
||||
let data = {
|
||||
clientFk: 101,
|
||||
description: `claim: ${controller.claim.id}`,
|
||||
amount: 11,
|
||||
greugeTypeFk: 7,
|
||||
ticketFk: controller.claim.ticketFk
|
||||
};
|
||||
$httpBackend.expect('POST', `claim/api/Greuges/`, data).respond();
|
||||
controller.onUpdateGreugeResponse('ACCEPT');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.card.reload).toHaveBeenCalledWith();
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Greuge inserted!');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,4 +5,7 @@ Import claim: Importar reclamacion
|
|||
Imports claim details: Importa detalles de la reclamacion
|
||||
Import ticket: Importar ticket
|
||||
Imports ticket lines: Importa las lineas de un ticket
|
||||
Regularize: Regularizar
|
||||
Regularize: Regularizar
|
||||
Do you want to insert greuges?: Desea insertar greuges?
|
||||
Insert greuges on client card: Insertar greuges en la ficha del cliente
|
||||
Greuge inserted: Greuge insertado
|
|
@ -1,19 +1,17 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/claim/api/Claims"
|
||||
filter="::$ctrl.filter"
|
||||
url="/claim/api/Claims/filter"
|
||||
limit="20"
|
||||
data="claims"
|
||||
auto-load="false">
|
||||
order="claimStateFk ASC, created DESC">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-claim-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
auto-load="true"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search claim by id or client name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
|
@ -38,7 +36,7 @@
|
|||
<vn-td number>{{::claim.id}}</vn-td>
|
||||
<vn-td expand>
|
||||
<span class="link" ng-click="$ctrl.showClientDescriptor($event, claim.client.id)">
|
||||
{{::claim.client.name}}
|
||||
{{::claim.name}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td center>{{::claim.created | dateTime:'dd/MM/yyyy'}}</vn-td>
|
||||
|
@ -46,12 +44,12 @@
|
|||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, claim.worker.user.id)">
|
||||
{{::claim.worker.user.nickname}}
|
||||
{{::claim.nickName}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span class="chip {{::$ctrl.stateColor(claim)}}">
|
||||
{{::claim.claimState.description}}
|
||||
{{::claim.description}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
|
|
|
@ -4,58 +4,10 @@ export default class Controller {
|
|||
constructor($scope) {
|
||||
this.$ = $scope;
|
||||
this.ticketSelected = null;
|
||||
|
||||
this.filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
fields: ['userFk'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['nickname']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'claimState',
|
||||
scope: {
|
||||
fields: ['description']
|
||||
}
|
||||
}
|
||||
],
|
||||
order: 'claimStateFk ASC, created DESC'
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {id: value}
|
||||
: {client: {like: `%${value}%`}};
|
||||
case 'client':
|
||||
return {[param]: {like: `%${value}%`}};
|
||||
case 'created':
|
||||
return {created: {between: [value, value]}};
|
||||
case 'id':
|
||||
case 'clientFk':
|
||||
case 'workerFk':
|
||||
case 'claimStateFk':
|
||||
return {[param]: value};
|
||||
}
|
||||
}
|
||||
|
||||
stateColor(claim) {
|
||||
switch (claim.claimState.description) {
|
||||
switch (claim.description) {
|
||||
case 'Pendiente':
|
||||
return 'warning';
|
||||
case 'Gestionado':
|
||||
|
@ -91,6 +43,13 @@ export default class Controller {
|
|||
onDescriptorLoad() {
|
||||
this.$.popover.relocate();
|
||||
}
|
||||
|
||||
onSearch(params) {
|
||||
if (params)
|
||||
this.$.model.applyFilter(null, params);
|
||||
else
|
||||
this.$.model.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope'];
|
||||
|
|
|
@ -10,4 +10,5 @@ Claim Id: Id reclamación
|
|||
Created: Creado
|
||||
Send Pickup order: Enviar orden de recogida
|
||||
Show Pickup order: Ver orden de recogida
|
||||
Search claim by id or client name: Buscar reclamaciones por identificador o nombre de cliente
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search claim by id or client name"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -6,11 +6,11 @@ module.exports = Self => {
|
|||
Self.remoteMethodCtx('send', {
|
||||
description: 'Sends SMS to a destination phone',
|
||||
accepts: [{
|
||||
arg: 'recipientFk',
|
||||
arg: 'destinationFk',
|
||||
type: 'Integer'
|
||||
},
|
||||
{
|
||||
arg: 'recipient',
|
||||
arg: 'destination',
|
||||
type: 'String',
|
||||
required: true,
|
||||
},
|
||||
|
@ -20,7 +20,7 @@ module.exports = Self => {
|
|||
required: true,
|
||||
}],
|
||||
returns: {
|
||||
type: 'boolean',
|
||||
type: 'Object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
@ -29,7 +29,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.send = async(ctx, recipientFk, recipient, message) => {
|
||||
Self.send = async(ctx, destinationFk, destination, message) => {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const smsConfig = await Self.app.models.SmsConfig.findOne();
|
||||
const soapClient = await soap.createClientAsync(smsConfig.uri);
|
||||
|
@ -37,7 +37,7 @@ module.exports = Self => {
|
|||
user: smsConfig.user,
|
||||
pass: smsConfig.password,
|
||||
src: smsConfig.title,
|
||||
dst: recipient,
|
||||
dst: destination,
|
||||
msg: message
|
||||
};
|
||||
|
||||
|
@ -61,18 +61,21 @@ module.exports = Self => {
|
|||
console.error(e);
|
||||
}
|
||||
|
||||
const statusCode = status.codigo[0];
|
||||
const statusDescription = status.descripcion[0];
|
||||
|
||||
const newSms = {
|
||||
senderFk: userId,
|
||||
destinationFk: recipientFk || null,
|
||||
destination: recipient,
|
||||
destinationFk: destinationFk || null,
|
||||
destination: destination,
|
||||
message: message,
|
||||
statusCode: status.codigo,
|
||||
status: status.descripcion
|
||||
statusCode: statusCode,
|
||||
status: statusDescription
|
||||
};
|
||||
|
||||
const sms = Self.create(newSms);
|
||||
const sms = await Self.create(newSms);
|
||||
|
||||
if (status.codigo != 200)
|
||||
if (statusCode != 200)
|
||||
throw new UserError(`We weren't able to send this SMS`);
|
||||
|
||||
return sms;
|
||||
|
|
|
@ -8,7 +8,7 @@ const app = require('vn-loopback/server/server');
|
|||
describe('sms send()', () => {
|
||||
it('should should return the expected message and status code', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 1}}};
|
||||
let result = await app.models.Sms.send(ctx, null, 'Invalid', 'My SMS Body');
|
||||
let result = await app.models.Sms.send(ctx, 101, 'Invalid', 'My SMS Body');
|
||||
|
||||
expect(result.statusCode).toEqual(200);
|
||||
expect(result.status).toEqual('Envio en procesamiento');
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"name": "Sms",
|
||||
"description": "Sms sent to client",
|
||||
"base": "VnModel",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model":"ClientLog",
|
||||
"relation": "recipient"
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "sms"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
panel="vn-client-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
info="Search client by id or name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
|
|
|
@ -27,6 +27,7 @@ Client inactive: Cliente inactivo
|
|||
Client not checked: Cliente no comprobado
|
||||
Credit insurance: Crédito asegurado
|
||||
Web Account inactive: Sin acceso Web
|
||||
Search client by id or name: Buscar clientes por identificador o nombre
|
||||
|
||||
# Sections
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search client by id or name"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<h5 pad-small-v translate>Send SMS</h5>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one
|
||||
label="Recipient"
|
||||
model="$ctrl.sms.recipient">
|
||||
label="Destination"
|
||||
model="$ctrl.sms.destination">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal >
|
||||
|
|
|
@ -18,11 +18,7 @@ class Controller extends Component {
|
|||
|
||||
onResponse(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
let params = {
|
||||
recipient: this.sms.recipient,
|
||||
message: this.sms.message
|
||||
};
|
||||
this.$http.post(`/client/api/Sms/send`, params).then(res => {
|
||||
this.$http.post(`/client/api/Sms/send`, this.sms).then(res => {
|
||||
this.vnApp.showMessage(this.$translate.instant('SMS sent!'));
|
||||
|
||||
if (res.data) this.emit('send', {response: res.data});
|
||||
|
|
|
@ -17,8 +17,8 @@ describe('Client', () => {
|
|||
|
||||
describe('onResponse()', () => {
|
||||
it('should perform a POST query and show a success snackbar', () => {
|
||||
let params = {recipient: 111111111, message: 'My SMS'};
|
||||
controller.sms = {recipient: 111111111, message: 'My SMS'};
|
||||
let params = {destinationFk: 101, destination: 111111111, message: 'My SMS'};
|
||||
controller.sms = {destinationFk: 101, destination: 111111111, message: 'My SMS'};
|
||||
|
||||
spyOn(controller.vnApp, 'showMessage');
|
||||
$httpBackend.when('POST', `/client/api/Sms/send`, params).respond(200, params);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Send SMS: Enviar SMS
|
||||
Recipient: Destinatario
|
||||
Destination: Destinatario
|
||||
Message: Mensaje
|
||||
SMS sent!: ¡SMS enviado!
|
|
@ -15,6 +15,7 @@
|
|||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
auto-load="true"
|
||||
info="Search invoices by reference"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
Invoice out: Facturas
|
||||
Invoice out: Facturas
|
||||
Search invoices by reference: Buscar facturas por referencia
|
|
@ -5,6 +5,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search invoices by reference"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
vn-three
|
||||
panel="vn-item-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search items by id, name or barcode"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
<vn-icon-menu
|
||||
|
|
|
@ -44,6 +44,7 @@ Shipped: F. envío
|
|||
stems: Tallos
|
||||
Compression: Compresión
|
||||
Density: Densidad
|
||||
Search items by id, name or barcode: Buscar articulos por identificador, nombre o codigo de barras
|
||||
|
||||
# Sections
|
||||
Items: Artículos
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search items by id, name or barcode"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<vn-searchbar
|
||||
panel="vn-order-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search orders by id"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
|
|
|
@ -19,4 +19,5 @@ Order: Orden
|
|||
Price: Precio
|
||||
Ascendant: Ascendente
|
||||
Descendant: Descendente
|
||||
Created from: Creado desde
|
||||
Created from: Creado desde
|
||||
Search orders by id: Buscar en la cesta por identificador
|
|
@ -5,6 +5,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search orders by id"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -6,6 +6,15 @@
|
|||
<a translate-attr="{title: 'Preview'}" ui-sref="route.card.summary({id: $ctrl.route.id})">
|
||||
<vn-icon icon="desktop_windows"></vn-icon>
|
||||
</a>
|
||||
<vn-icon-menu
|
||||
vn-id="more-button"
|
||||
icon="more_vert"
|
||||
show-filter="false"
|
||||
value-field="callback"
|
||||
translate-fields="['name']"
|
||||
data="$ctrl.moreOptions"
|
||||
on-change="$ctrl.onMoreChange(value)">
|
||||
</vn-icon-menu>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="attributes">
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($, $http, vnApp, $translate) {
|
||||
this.$http = $http;
|
||||
this.vnApp = vnApp;
|
||||
this.$translate = $translate;
|
||||
this.$ = $;
|
||||
this.moreOptions = [
|
||||
{callback: this.showRouteReport, name: 'Show route report'},
|
||||
{callback: this.sendRouteReport, name: 'Send route report'}
|
||||
];
|
||||
}
|
||||
set quicklinks(value = {}) {
|
||||
this._quicklinks = Object.assign(value, this._quicklinks);
|
||||
}
|
||||
|
@ -8,9 +18,25 @@ class Controller {
|
|||
get quicklinks() {
|
||||
return this._quicklinks;
|
||||
}
|
||||
|
||||
onMoreChange(callback) {
|
||||
callback.call(this);
|
||||
}
|
||||
|
||||
showRouteReport() {
|
||||
let url = `/api/report/rpt-route?routeFk=${this.route.id}`;
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
sendRouteReport() {
|
||||
let url = `/api/email/driver-route?routeFk=${this.route.id}`;
|
||||
this.$http.post(url).then(() => {
|
||||
this.vnApp.showSuccess(this.$translate.instant('Report sent'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$state'];
|
||||
Controller.$inject = ['$scope', '$http', 'vnApp', '$translate'];
|
||||
|
||||
ngModule.component('vnRouteDescriptor', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
Volume exceded: Volumen excedido
|
||||
Volume: Volumen
|
||||
Volume: Volumen
|
||||
Send route report: Enviar informe de ruta
|
||||
Show route report: Ver informe de ruta
|
|
@ -14,6 +14,7 @@
|
|||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
auto-load="true"
|
||||
info="Search routes by id"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
Routes: Rutas
|
||||
Routes: Rutas
|
||||
Search routes by id: Buscar rutas por identificador
|
|
@ -5,6 +5,7 @@
|
|||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
info="Search routes by id"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -31,15 +31,16 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.confirm = async ctx => {
|
||||
const models = Self.app.models;
|
||||
let transaction = await Self.beginTransaction({});
|
||||
let options = {transaction: transaction};
|
||||
|
||||
try {
|
||||
let item = await Self.app.models.Item.findById(ctx.args.itemFk);
|
||||
let item = await models.Item.findById(ctx.args.itemFk);
|
||||
if (!item)
|
||||
throw new UserError(`That item doesn't exists`);
|
||||
|
||||
let request = await Self.app.models.TicketRequest.findById(ctx.args.id, {
|
||||
let request = await models.TicketRequest.findById(ctx.args.id, {
|
||||
include: {relation: 'ticket'}
|
||||
});
|
||||
|
||||
|
@ -60,15 +61,19 @@ module.exports = Self => {
|
|||
|
||||
|
||||
if (request.saleFk) {
|
||||
let sale = await Self.app.models.Sale.findById(request.saleFk);
|
||||
sale.updateAttributes({itemFk: ctx.args.itemFk, quantity: ctx.args.quantity, description: item.description}, options);
|
||||
let sale = await models.Sale.findById(request.saleFk);
|
||||
sale.updateAttributes({
|
||||
itemFk: ctx.args.itemFk,
|
||||
quantity: ctx.args.quantity,
|
||||
description: item.description
|
||||
}, options);
|
||||
} else {
|
||||
params = {
|
||||
ticketFk: request.ticketFk,
|
||||
itemFk: ctx.args.itemFk,
|
||||
quantity: ctx.args.quantity
|
||||
};
|
||||
sale = await Self.app.models.Sale.create(params, options);
|
||||
sale = await models.Sale.create(params, options);
|
||||
request.updateAttributes({saleFk: sale.id, itemFk: sale.itemFk}, options);
|
||||
}
|
||||
|
||||
|
@ -76,6 +81,14 @@ module.exports = Self => {
|
|||
params = [sale.id];
|
||||
await Self.rawSql(query, params, options);
|
||||
|
||||
const message = `Se ha comprado ${params.quantity} unidades de "${item.description}" (#${params.itemFk}) `
|
||||
+ `para el ticket #${params.ticketFk}`;
|
||||
|
||||
await models.Message.send(ctx, {
|
||||
recipientFk: request.requesterFk,
|
||||
message: message
|
||||
}, options);
|
||||
|
||||
await transaction.commit();
|
||||
} catch (error) {
|
||||
await transaction.rollback();
|
||||
|
|
|
@ -2,14 +2,14 @@ const UserError = require('vn-loopback/util/user-error');
|
|||
|
||||
module.exports = function(Self) {
|
||||
Self.remoteMethodCtx('makeInvoice', {
|
||||
description: 'Change property isEqualizated in all client addresses',
|
||||
description: 'Make out an invoice from a ticket id',
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Client id',
|
||||
description: 'Ticket id',
|
||||
http: {source: 'path'}
|
||||
}
|
||||
],
|
||||
|
@ -53,7 +53,7 @@ module.exports = function(Self) {
|
|||
query = `CALL vn.invoiceOutMake(?, ?, @invoiceId);
|
||||
SELECT @invoiceId AS invoiceId;`;
|
||||
result = await Self.rawSql(query, [serial, null], options);
|
||||
let invoice = result[1].invoiceId;
|
||||
let invoice = result[1][0].invoiceId;
|
||||
|
||||
if (serial != 'R' && invoice) {
|
||||
query = `CALL vn.invoiceOutBooking(?)`;
|
||||
|
@ -62,9 +62,11 @@ module.exports = function(Self) {
|
|||
|
||||
let user = await Self.app.models.Worker.findOne({where: {userFk: userId}});
|
||||
|
||||
query = `INSERT INTO vn2008.Colas(Id_Informe,Cola,Id_Trabajador) VALUES (?, ?, ?)`;
|
||||
query = `INSERT INTO printServerQueue(reportFk, param1, workerFk) VALUES (?, ?, ?)`;
|
||||
await Self.rawSql(query, [3, invoice, user.id], options);
|
||||
await options.transaction.commit();
|
||||
|
||||
return {invoiceFk: invoice, serial};
|
||||
} catch (e) {
|
||||
options.transaction.rollback();
|
||||
throw e;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue