Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into dev
gitea/salix/dev This commit has test failures Details

This commit is contained in:
Carlos Jimenez Ruiz 2019-05-29 13:07:23 +02:00
commit cfcadc4f28
43 changed files with 409 additions and 102 deletions

View File

@ -1,3 +1,4 @@
{ {
"name": "Dms", "name": "Dms",
"description": "Documental Managment system", "description": "Documental Managment system",
@ -22,6 +23,12 @@
"description": { "description": {
"type": "string" "type": "string"
}, },
"hardCopyNumber": {
"type": "Number"
},
"hasFile": {
"type": "boolean"
},
"created": { "created": {
"type": "Date" "type": "Date"
} }

View File

@ -20,6 +20,10 @@
"path": { "path": {
"type": "string", "type": "string",
"required": true "required": true
},
"code": {
"type": "string",
"required": true
} }
}, },
"relations": { "relations": {

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` ( `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ( 'ClientDms', 'remove', 'WRITE', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` ( `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ( 'ClientDms', '*', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,19 @@
ALTER TABLE `vn2008`.`clientes_gestdoc`
DROP FOREIGN KEY `clientes_gestdoc_ibfk_3`;
ALTER TABLE `vn2008`.`clientes_gestdoc`
DROP PRIMARY KEY,
ADD PRIMARY KEY (`gest_doc_id`);
ALTER TABLE `vn2008`.`clientes_gestdoc`
DROP INDEX `fk_clientes_gestdoc_1_idx` ;
ALTER TABLE `vn2008`.`clientes_gestdoc`
ADD INDEX `fk_clientes_gestdoc_1_idx` (`Id_Cliente` ASC);
ALTER TABLE `vn2008`.`clientes_gestdoc`
ADD CONSTRAINT `fk_clientes_gestdoc_3`
FOREIGN KEY (`Id_Cliente`)
REFERENCES `vn2008`.`Clientes` (`id_cliente`)
ON DELETE RESTRICT
ON UPDATE CASCADE;

View File

@ -0,0 +1,9 @@
ALTER TABLE `vn2008`.`clientes_gestdoc`
ADD INDEX `fk_clientes_gestdoc_1_idx` (`Id_Cliente` ASC);
ALTER TABLE `vn2008`.`clientes_gestdoc`
ADD CONSTRAINT `fk_clientes_gestdoc_3`
FOREIGN KEY (`Id_Cliente`)
REFERENCES `vn2008`.`Clientes` (`id_cliente`)
ON DELETE RESTRICT
ON UPDATE CASCADE;

View File

@ -654,7 +654,7 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
(11, 1, 16, 'Ranged weapon longbow 2m', 2, 9.10, 0, 0, 0, CURDATE()), (11, 1, 16, 'Ranged weapon longbow 2m', 2, 9.10, 0, 0, 0, CURDATE()),
(12, 4, 16, 'Melee weapon heavy shield 1x0.5m', 20, 3.06, 0, 0, 0, CURDATE()), (12, 4, 16, 'Melee weapon heavy shield 1x0.5m', 20, 3.06, 0, 0, 0, CURDATE()),
(13, 2, 8, 'Melee weapon combat fist 15cm', 15, 1.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), (13, 2, 8, 'Melee weapon combat fist 15cm', 15, 1.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(14, 1, 8, 'Ranged weapon longbow 2m', 10, 2.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), (14, 1, 8, 'Ranged weapon longbow 2m', 10, 9.28, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(15, 1, 19, 'Ranged weapon longbow 2m', 10, 1.50, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 DAY)), (15, 1, 19, 'Ranged weapon longbow 2m', 10, 1.50, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(16, 2, 20, 'Melee weapon combat fist 15cm', 15, 1.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 DAY)), (16, 2, 20, 'Melee weapon combat fist 15cm', 15, 1.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(17, 2, 22, 'Melee weapon combat fist 15cm', 30, 2.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 DAY)), (17, 2, 22, 'Melee weapon combat fist 15cm', 30, 2.30, 0, 0, 0, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
@ -1457,8 +1457,9 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `c
INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `workerFk`, `warehouseFk`, `companyFk`, `hardCopyNumber`, `hasFile`, `reference`, `description`, `created`) INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `workerFk`, `warehouseFk`, `companyFk`, `hardCopyNumber`, `hasFile`, `reference`, `description`, `created`)
VALUES VALUES
(1, 14, '1.pdf', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()), (1, 14, '1.pdf', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()),
(2, 5, '2.pdf', 5, 1, 442, 1, TRUE, 'Client:101', 'Client:101 dms for the client', CURDATE()); (2, 5, '2.pdf', 5, 1, 442, 1, TRUE, 'Client:101', 'Client:101 dms for the client', CURDATE()),
(3, 5, '3.pdf', 5, 1, 442, NULL, TRUE, 'Client: 101', 'Client:101 readme', CURDATE());
INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`) INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
VALUES VALUES
@ -1466,4 +1467,5 @@ INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
INSERT INTO `vn`.`clientDms`(`clientFk`, `dmsFk`) INSERT INTO `vn`.`clientDms`(`clientFk`, `dmsFk`)
VALUES VALUES
(101, 2); (101, 2),
(101, 3);

View File

@ -45,7 +45,7 @@ describe('Claim detail', () => {
.waitToGetProperty(selectors.claimDetail.totalClaimed, 'innerText'); .waitToGetProperty(selectors.claimDetail.totalClaimed, 'innerText');
expect(claimedQuantity).toEqual('10'); expect(claimedQuantity).toEqual('10');
expect(totalClaimed).toContain('29.50'); expect(totalClaimed).toContain('99.30');
}); });
it('should delete the second item from the claim', async() => { it('should delete the second item from the claim', async() => {

View File

@ -22,6 +22,7 @@ module.exports = Self => {
Self.clone = async id => { Self.clone = async id => {
const models = Self.app.models; const models = Self.app.models;
const transaction = await Self.beginTransaction({}); const transaction = await Self.beginTransaction({});
const options = {transaction};
// Find original zone // Find original zone
const zone = await models.Zone.findOne({ const zone = await models.Zone.findOne({
@ -35,22 +36,36 @@ module.exports = Self => {
'bonus', 'bonus',
'isVolumetric'], 'isVolumetric'],
where: {id} where: {id}
}); }, options);
const hour = zone.hour;
const offset = hour.getTimezoneOffset() * 60000;
hour.setTime(hour.getTime() + offset);
// Find all original included geolocations // Find all original included geolocations
const includedGeo = await models.ZoneIncluded.find({ const includedGeo = await models.ZoneIncluded.find({
fields: ['geoFk', 'isIncluded'], fields: ['geoFk', 'isIncluded'],
where: {zoneFk: id} where: {zoneFk: id}
}); }, options);
// Find all original selected days
const calendarDays = await models.ZoneCalendar.find({
where: {zoneFk: id}
}, options);
try { try {
const newZone = await Self.create(zone, {transaction}); const newZone = await Self.create(zone, options);
const newIncludedGeo = includedGeo.map(included => { const newIncludedGeo = includedGeo.map(included => {
included.zoneFk = newZone.id; included.zoneFk = newZone.id;
return included; return included;
}); });
const newCalendayDays = calendarDays.map(day => {
day.zoneFk = newZone.id;
return day;
});
await models.ZoneIncluded.create(newIncludedGeo, {transaction}); await models.ZoneIncluded.create(newIncludedGeo, options);
await models.ZoneCalendar.create(newCalendayDays, options);
await transaction.commit(); await transaction.commit();
return newZone; return newZone;

View File

@ -48,6 +48,6 @@
<vn-confirm <vn-confirm
vn-id="delete-zone" vn-id="delete-zone"
on-response="$ctrl.returnDialog(response)" on-response="$ctrl.returnDialog(response)"
question="Delete zone" question="Are you sure you want to delete this zone?"
message="Are you sure you want to delete this zone?"> message="This zone will be removed">
</vn-confirm> </vn-confirm>

View File

@ -1,2 +1,2 @@
Do you want to clone this zone?: ¿Seguro que quieres eliminar esta zona? Do you want to clone this zone?: ¿Seguro que quieres clonar esta zona?
All it's properties will be copied: Todas sus propiedades serán copiadas All it's properties will be copied: Todas sus propiedades serán copiadas

View File

@ -4,8 +4,8 @@ Hour: Hora (ETD)
ETD: Tiempo de salida estimado ETD: Tiempo de salida estimado
Price: Precio Price: Precio
Locations: Localizaciones Locations: Localizaciones
Delete zone: Eliminar zona This zone will be removed: La zona será eliminada
Are you sure you want to delete this zone?: ¿Estás seguro de querer eliminar esta zona? Are you sure you want to delete this zone?: ¿Seguro de que quieres eliminar esta zona?
Zones: Zonas Zones: Zonas
New zone: Nueva zona New zone: Nueva zona
Volumetric: Volumétrico Volumetric: Volumétrico

View File

@ -26,7 +26,7 @@
value="{{$ctrl.summary.price | currency: 'EUR': 2}}"> value="{{$ctrl.summary.price | currency: 'EUR': 2}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Bonus" <vn-label-value label="Bonus"
value="{{$ctrl.summary.price | currency: 'EUR': 2}}"> value="{{$ctrl.summary.bonus | currency: 'EUR': 2}}">
</vn-label-value> </vn-label-value>
<vn-vertical> <vn-vertical>
<vn-check label="Volumetric" disabled="true" <vn-check label="Volumetric" disabled="true"

View File

@ -22,7 +22,7 @@ module.exports = Self => {
} }
}); });
Self.createWithInsurance = async (data, ctx) => { Self.createWithInsurance = async(data, ctx) => {
let transaction = await Self.beginTransaction({}); let transaction = await Self.beginTransaction({});
try { try {

View File

@ -0,0 +1,35 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('removes', {
description: 'Delete an client dms',
accessType: 'WRITE',
accepts: {
arg: 'dmsId',
type: 'number',
required: true,
description: 'dms identifier',
},
returns: {
type: 'string',
root: true
},
http: {
path: `/removes`,
verb: 'POST'
}
});
Self.removes = async dmsId => {
if (!dmsId)
throw new UserError('There is nothing to delete');
let targetClientDms = await Self.app.models.ClientDms.findOne({where: {dmsFk: dmsId}});
let targetDms = await Self.app.models.Dms.findById(dmsId);
let trashDmsType = await Self.app.models.DmsType.findOne({where: {code: 'trash'}});
await targetClientDms.destroy();
await targetDms.updateAttribute('dmsTypeFk', trashDmsType.id);
};
};

View File

@ -0,0 +1,29 @@
const app = require('vn-loopback/server/server');
describe('Client dms stuff', () => {
let dmsToRestore;
let dmsTypeToRestore;
afterAll(async done => {
await app.models.ClientDms.create(dmsToRestore);
await dmsTypeToRestore.save();
done();
});
it('should delete a dms from a client and update the dmsType to trash', async() => {
const dmsId = 2;
dmsToRestore = await app.models.ClientDms.findOne({where: {dmsFk: dmsId}});
dmsTypeToRestore = await app.models.Dms.findById(dmsToRestore.dmsFk);
await app.models.ClientDms.removes(dmsId);
let destroyedDms = await app.models.ClientDms.findOne({where: {dmsFk: dmsId}});
let alteredDmsType = await app.models.Dms.findById(dmsId);
expect(destroyedDms).toBeNull();
expect(alteredDmsType.dmsTypeFk).toEqual(13);
});
});

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/dms/removes')(Self);
};

View File

@ -1,25 +1,24 @@
{ {
"name": "ClientDms", "name": "ClientDms",
"base": "Loggable", "base": "Loggable",
"log": { "log": {
"model": "ClientLog", "model":"ClientLog",
"relation": "ticket", "relation": "client",
"showField": "dmsFk" "showField": "dmsFk"
}, },
"options": { "options": {
"mysql": { "mysql": {
"table": "clientDms" "table": "clientDms"
} }
}, },
"properties": { "properties": {
"clientFk": { "dmsFk": {
"type": "Number", "type": "Number",
"id": true, "id": true,
"required": true "required": true
}, },
"dmsFk": { "clientFk": {
"type": "Number", "type": "Number",
"id": true,
"required": true "required": true
} }
}, },
@ -35,4 +34,5 @@
"foreignKey": "dmsFk" "foreignKey": "dmsFk"
} }
} }
} }

View File

@ -0,0 +1,74 @@
<vn-crud-model
vn-id="model"
url="/client/api/ClientDms"
link="{clientFk: $ctrl.$stateParams.id}"
filter="::$ctrl.filter"
limit="20"
data="$ctrl.clientDms">
</vn-crud-model>
<vn-vertical>
<vn-card pad-large>
<vn-vertical>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="dmsFk" default-order="DESC" number>File</vn-th>
<vn-th>Description</vn-th>
<vn-th>Reference</vn-th>
<vn-th number>Hard copy</vn-th>
<vn-th>Worker</vn-th>
<vn-th>Created</vn-th>
<vn-th></vn-th>
<vn-th></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="document in $ctrl.clientDms">
<vn-td number>{{::document.dmsFk}}</vn-td>
<vn-td title = "{{::document.dms.description}}">
{{::document.dms.description}}</vn-td>
</vn-td>
<vn-td>{{::document.dms.reference}}</vn-td>
<vn-td number>{{::document.dms.hardCopyNumber | dashIfEmpty}}</vn-td>
<vn-td>
<span class="link"
ng-click="$ctrl.showWorkerDescriptor($event, document.dms.workerFk)">
{{::document.dms.worker.user.nickname | dashIfEmpty}}
</span>
</vn-td>
<vn-td>{{::document.dms.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
<vn-td center>
<vn-icon-button
vn-tooltip="Remove file"
icon="delete"
ng-click="$ctrl.showDeleteConfirm(document.dmsFk)"
tabindex="-1">
</vn-icon-button>
</vn-td>
<vn-td center>
<a
target="_blank"
href="api/dms/{{::document.dmsFk}}/download?access_token={{::$ctrl.accessToken}}">
<vn-icon-button
icon="cloud_download"
title="{{'Download file' | translate}}">
</vn-icon-button>
</a>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-vertical>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>
<vn-worker-descriptor-popover
vn-id="workerDescriptor">
</vn-worker-descriptor-popover>
<vn-confirm
vn-id="confirm"
message="This file will be deleted"
question="Are you sure?"
on-response="$ctrl.deleteDms(response)">
</vn-confirm>

View File

@ -0,0 +1,71 @@
import ngModule from '../module';
import './style.scss';
class Controller {
constructor($stateParams, $scope, vnToken, $http, vnApp, $translate) {
this.$stateParams = $stateParams;
this.$ = $scope;
this.accessToken = vnToken.token;
this.$http = $http;
this.vnApp = vnApp;
this.$translate = $translate;
this.filter = {
include: {
relation: 'dms',
scope: {
fields: ['dmsTypeFk', 'workerFk', 'file', 'created', 'description', 'reference', 'hardCopyNumber'],
include: [{
relation: 'dmsType',
scope: {
fields: ['name']
}
},
{
relation: 'worker',
scope: {
fields: ['userFk'],
include: {
relation: 'user',
scope: {
fields: ['nickname']
}
},
}
}]
},
}
};
}
showWorkerDescriptor(event, workerFk) {
event.preventDefault();
event.stopImmediatePropagation();
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.workerFk = workerFk;
this.$.workerDescriptor.show();
}
showDeleteConfirm(dmsId) {
this.selectedDms = dmsId;
this.$.confirm.show();
}
deleteDms(response) {
if (response === 'ACCEPT') {
let dmsId = this.selectedDms;
let query = `/client/api/ClientDms/removes`;
this.$http.post(query, {dmsId}).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.model.refresh();
});
}
}
}
Controller.$inject = ['$stateParams', '$scope', 'vnToken', '$http', 'vnApp', '$translate'];
ngModule.component('vnClientDms', {
template: require('./index.html'),
controller: Controller,
});

View File

@ -0,0 +1,9 @@
Type: Tipo
File management: Gestión documental
File: Fichero
Hard copy: Copia
This file will be deleted: Este fichero va a ser borrado
Are you sure?: Estas seguro?
File deleted: Fichero eliminado
Remove file: Eliminar fichero
Download file: Descargar fichero

View File

@ -0,0 +1,6 @@
vn-client-risk-index {
.totalBox {
display: table;
float: right;
}
}

View File

@ -35,4 +35,5 @@ import './sample/create';
import './web-payment'; import './web-payment';
import './log'; import './log';
import './sms'; import './sms';
import './dms';

View File

@ -24,7 +24,8 @@
{"state": "client.card.creditInsurance.index", "icon": "icon-solunion"}, {"state": "client.card.creditInsurance.index", "icon": "icon-solunion"},
{"state": "client.card.contact", "icon": "contact_phone"}, {"state": "client.card.contact", "icon": "contact_phone"},
{"state": "client.card.sample.index", "icon": "mail"}, {"state": "client.card.sample.index", "icon": "mail"},
{"state": "client.card.webPayment", "icon": "icon-onlinepayment"} {"state": "client.card.webPayment", "icon": "icon-onlinepayment"},
{"state": "client.card.dms", "icon": "cloud_download"}
] ]
} }
], ],
@ -314,6 +315,12 @@
"state": "client.card.log", "state": "client.card.log",
"component": "vn-client-log", "component": "vn-client-log",
"description": "Log" "description": "Log"
},
{
"url": "/dms",
"state": "client.card.dms",
"component": "vn-client-dms",
"description": "File management"
} }
] ]
} }

View File

@ -1,15 +1,19 @@
let UserError = require('vn-loopback/util/user-error'); let UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('updateDiscount', { Self.remoteMethod('updateDiscount', {
description: 'Changes the discount of a sale', description: 'Changes the discount of a sale',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'params', arg: 'ticketFk',
type: 'object', type: 'number',
required: true, required: true,
description: 'sale ID, newDiscount, price', description: 'ticket id',
http: {source: 'body'} }, {
arg: 'sales',
type: ['object'],
required: true,
description: 'sale ID, newDiscount, price, ticket',
}], }],
returns: { returns: {
type: 'string', type: 'string',
@ -21,12 +25,16 @@ module.exports = Self => {
} }
}); });
Self.updateDiscount = async(ctx, params) => { Self.updateDiscount = async(ticketFk, sales) => {
if (isNaN(params.editLines[0].discount)) const validDiscounts = sales.every(sale => {
return !isNaN(sale.discount);
});
if (!validDiscounts)
throw new UserError(`The value should be a number`); throw new UserError(`The value should be a number`);
let model = Self.app.models; let model = Self.app.models;
let ticket = await model.Ticket.findById(params.editLines[0].ticketFk, { let ticket = await model.Ticket.findById(ticketFk, {
include: { include: {
relation: 'client', relation: 'client',
scope: { scope: {
@ -38,25 +46,27 @@ module.exports = Self => {
if (ticket.refFk) if (ticket.refFk)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
let componentToUse; let manaDiscount;
let buyerDiscount = await model.ComponentRate.findOne({where: {code: 'buyerDiscount'}});
let usesMana = await model.WorkerMana.findOne({where: {workerFk: ticket.client().salesPersonFk}, fields: 'amount'}); let usesMana = await model.WorkerMana.findOne({where: {workerFk: ticket.client().salesPersonFk}, fields: 'amount'});
let componentId = buyerDiscount.id;
if (usesMana) {
manaDiscount = await model.ComponentRate.findOne({where: {code: 'mana'}});
componentId = manaDiscount.id;
}
if (usesMana) for (let i = 0; i < sales.length; i++) {
componentToUse = 37; let currentLine = await model.Sale.findOne({where: {id: sales[i].id}, fields: 'price'});
else let value = ((-currentLine.price * sales[i].discount) / 100);
componentToUse = 34;
for (let i = 0; i < params.editLines.length; i++) { await model.SaleComponent.upsert({saleFk: sales[i].id, value: value, componentFk: componentId});
let currentLine = await model.Sale.findOne({where: {id: params.editLines[i].id}, fields: 'price'});
let value = ((-currentLine.price * params.editLines[i].discount) / 100);
await model.SaleComponent.upsert({saleFk: params.editLines[i].id, value: value, componentFk: componentToUse});
await model.Sale.update({id: params.editLines[i].id}, {discount: params.editLines[i].discount}); await model.Sale.update({id: sales[i].id}, {discount: sales[i].discount});
} }
if (usesMana) { if (usesMana) {
query = ` query = `call vn.manaSpellersRequery(?)`;
call vn.manaSpellersRequery(?)`;
await Self.rawSql(query, [ticket.client().salesPersonFk]); await Self.rawSql(query, [ticket.client().salesPersonFk]);
} }
}; };

View File

@ -1,14 +1,14 @@
let UserError = require('vn-loopback/util/user-error'); let UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('updatePrice', { Self.remoteMethod('updatePrice', {
description: 'Changes the discount of a sale', description: 'Changes the discount of a sale',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'params', arg: 'params',
type: 'object', type: 'object',
required: true, required: true,
description: 'sale ID, newPrice', description: 'sale ID, newPrice, ticketFk',
http: {source: 'body'} http: {source: 'body'}
}], }],
returns: { returns: {
@ -21,10 +21,51 @@ module.exports = Self => {
} }
}); });
Self.getTicket = async params => { Self.updatePrice = async params => {
if (!params.price) params.price = 0;
let model = Self.app.models;
let manaDiscount;
let buyerDiscount = await model.ComponentRate.findOne({where: {code: 'buyerDiscount'}});
let ticket = await getTicket(params);
let usesMana = await model.WorkerMana.findOne({where: {workerFk: ticket[0].client().salesPersonFk}, fields: 'amount'});
let currentLine = await Self.app.models.Sale.findOne({where: {id: params.id}});
let componentId = buyerDiscount.id;
if (usesMana) {
manaDiscount = await model.ComponentRate.findOne({where: {code: 'mana'}});
componentId = manaDiscount.id;
}
let value = (params.price - currentLine.price);
let saleComponent = await Self.app.models.SaleComponent.findOne({
where: {
componentFk: componentId,
saleFk: params.id
}
});
if (saleComponent) {
saleComponent.updateAttributes({value: saleComponent.value + value}).catch(() => {
throw new UserError(`Enter a valid number`);
});
} else {
await Self.app.models.SaleComponent.create({
saleFk: params.id,
componentFk: componentId,
value: value
});
}
await currentLine.updateAttributes({price: params.price});
query = `call vn.manaSpellersRequery(?)`;
await Self.rawSql(query, [ticket[0].client().salesPersonFk]);
};
async function getTicket(params) {
let model = Self.app.models; let model = Self.app.models;
let thisTicketIsEditable = await model.Ticket.isEditable(params.ticketFk); let thisTicketIsEditable = await model.Ticket.isEditable(params.ticketFk);
if (!thisTicketIsEditable) if (!thisTicketIsEditable)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
@ -40,48 +81,5 @@ module.exports = Self => {
}], }],
fields: ['id', 'clientFk'] fields: ['id', 'clientFk']
}); });
}; }
Self.updatePrice = async params => {
if (isNaN(params.price))
throw new UserError(`The value should be a number`);
if (!params.price) params.price = 0;
let model = Self.app.models;
let ticket = await Self.getTicket(params);
let usesMana = await model.WorkerMana.findOne({where: {workerFk: ticket[0].client().salesPersonFk}, fields: 'amount'});
let currentLine = await Self.app.models.Sale.findOne({where: {id: params.id}});
let componentToUse;
if (usesMana)
componentToUse = 37;
else
componentToUse = 34;
let value = (params.price - currentLine.price);
let saleComponent = await Self.app.models.SaleComponent.findOne({
where: {
componentFk: componentToUse,
saleFk: params.id
}
});
if (saleComponent)
saleComponent.updateAttributes({value: saleComponent.value + value});
else {
await Self.app.models.SaleComponent.create({
saleFk: params.id,
componentFk: componentToUse,
value: value
});
}
await currentLine.updateAttributes({price: params.price});
query = `call vn.manaSpellersRequery(?)`;
await Self.rawSql(query, [ticket[0].client().salesPersonFk]);
};
}; };

View File

@ -26,6 +26,9 @@
}, },
"componentTypeRate": { "componentTypeRate": {
"type": "Number" "type": "Number"
},
"code": {
"type": "String"
} }
}, },
"relations": { "relations": {

View File

@ -2,16 +2,15 @@
<h5>MANÁ: {{$ctrl.mana | currency: 'EUR':0}}</h5> <h5>MANÁ: {{$ctrl.mana | currency: 'EUR':0}}</h5>
</vn-horizontal> </vn-horizontal>
<div pad-medium> <div pad-medium>
<vn-textfield <vn-input-number
vn-focus vn-focus
label="Discount" label="Discount"
model="$ctrl.newDiscount" model="$ctrl.newDiscount"
type="text"
on-change="$ctrl.updateDiscount()"> on-change="$ctrl.updateDiscount()">
<t-right-icons> <t-right-icons>
<span class="filter">%</span> <span class="filter">%</span>
</t-right-icons> </t-right-icons>
</vn-textfield> </vn-input-number>
<div class="simulator"> <div class="simulator">
<p class="simulatorTitle" translate>New price</p> <p class="simulatorTitle" translate>New price</p>
<p>{{($ctrl.edit[0].quantity * $ctrl.edit[0].price) <p>{{($ctrl.edit[0].quantity * $ctrl.edit[0].price)

View File

@ -38,12 +38,15 @@ class Controller {
let modified = false; let modified = false;
for (let i = 0; i < this.edit.length; i++) { for (let i = 0; i < this.edit.length; i++) {
if (this.newDiscount != this.edit[0].discount || this.bulk || !this.newDiscount) { if (this.newDiscount != this.edit[0].discount || this.bulk || !this.newDiscount) {
editLines.push({id: this.edit[i].id, discount: this.newDiscount, ticketFk: this.$state.params.id}); editLines.push({id: this.edit[i].id, discount: this.newDiscount});
modified = true; modified = true;
} }
} }
if (modified) { if (modified) {
this.$http.post(`/ticket/api/Sales/updateDiscount`, {editLines}).then(() => { const ticketId = parseInt(this.$state.params.id);
const params = {ticketFk: ticketId, sales: editLines};
this.$http.post(`/ticket/api/Sales/updateDiscount`, params).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.clear(); this.clear();
modified = false; modified = false;
@ -53,7 +56,7 @@ class Controller {
this.onHide(); this.onHide();
} else } else
this.vnApp.showError(this.$translate.instant('There is no changes to save')); this.vnApp.showError(this.$translate.instant('There are no changes to save'));
} }
clear() { clear() {

View File

@ -69,7 +69,7 @@ describe('Ticket', () => {
spyOn(controller.vnApp, 'showError'); spyOn(controller.vnApp, 'showError');
controller.updateDiscount(); controller.updateDiscount();
expect(controller.vnApp.showError).toHaveBeenCalledWith('There is no changes to save'); expect(controller.vnApp.showError).toHaveBeenCalledWith('There are no changes to save');
}); });
}); });

View File

@ -173,16 +173,17 @@
<h5>MANÁ: {{$ctrl.mana | currency: 'EUR':0}}</h5> <h5>MANÁ: {{$ctrl.mana | currency: 'EUR':0}}</h5>
</vn-horizontal> </vn-horizontal>
<div pad-medium> <div pad-medium>
<vn-textfield <vn-input-number
vn-focus vn-focus
label="Price" label="Price"
model="$ctrl.editedPrice" model="$ctrl.editedPrice"
type="text" type="text"
step="0.01"
on-change="$ctrl.updatePrice()"> on-change="$ctrl.updatePrice()">
<t-right-icons> <t-right-icons>
<span class="filter"></span> <span class="filter"></span>
</t-right-icons> </t-right-icons>
</vn-textfield> </vn-input-number>
<div class="simulator"> <div class="simulator">
<p class="simulatorTitle" translate>New price</p> <p class="simulatorTitle" translate>New price</p>
<p>{{($ctrl.sale.quantity * $ctrl.editedPrice) <p>{{($ctrl.sale.quantity * $ctrl.editedPrice)