Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into dev
This commit is contained in:
commit
d06d5cd9c8
|
@ -0,0 +1,15 @@
|
|||
CREATE TABLE `vn`.`device` (
|
||||
`id` INT NOT NULL,
|
||||
`sn` VARCHAR(50) NULL,
|
||||
`model` VARCHAR(50) NULL,
|
||||
`userFk` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `device_fk1_idx` (`userFk` ASC),
|
||||
CONSTRAINT `device_fk1`
|
||||
FOREIGN KEY (`userFk`)
|
||||
REFERENCES `account`.`user` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION);
|
||||
|
||||
ALTER TABLE `vn`.`device`
|
||||
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT ;
|
|
@ -1468,4 +1468,6 @@ INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
|
|||
INSERT INTO `vn`.`clientDms`(`clientFk`, `dmsFk`)
|
||||
VALUES
|
||||
(101, 2),
|
||||
(101, 3);
|
||||
(101, 3);
|
||||
|
||||
INSERT INTO `vn`.`device` (`sn`, `model`, `userFk`) VALUES ('aaa', 'android', '9');
|
|
@ -4,11 +4,24 @@ module.exports = Self => {
|
|||
Self.remoteMethod('new', {
|
||||
description: 'Create a new order and returns the new ID',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'params',
|
||||
type: 'object',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
accepts: [
|
||||
{
|
||||
arg: 'landed',
|
||||
description: 'The landed for the order',
|
||||
type: 'date',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'addressId',
|
||||
description: 'The address for the order',
|
||||
type: 'number',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'agencyModeId',
|
||||
description: 'The agencyMode for the order',
|
||||
type: 'number',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'number',
|
||||
root: true
|
||||
|
@ -19,9 +32,9 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.new = async params => {
|
||||
Self.new = async(landed, addressId, agencyModeId) => {
|
||||
let address = await Self.app.models.Address.findOne({
|
||||
where: {id: params.addressFk},
|
||||
where: {id: addressId},
|
||||
fields: ['clientFk'],
|
||||
include: [
|
||||
{relation: 'client',
|
||||
|
@ -44,9 +57,9 @@ module.exports = Self => {
|
|||
|
||||
query = `CALL vn.orderListCreate(?, ?, ?, ?);`;
|
||||
[result] = await Self.rawSql(query, [
|
||||
params.landed,
|
||||
params.agencyModeFk,
|
||||
params.addressFk,
|
||||
landed,
|
||||
agencyModeId,
|
||||
addressId,
|
||||
'SALIX'
|
||||
]);
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@ module.exports = Self => {
|
|||
where: {id: ticketFk}
|
||||
});
|
||||
|
||||
let orderID = await Self.app.models.Order.new({
|
||||
addressFk: ticket.addressFk,
|
||||
landed: ticket.landed,
|
||||
agencyModeFk: ticket.agencyModeFk
|
||||
});
|
||||
let landed = ticket.landed;
|
||||
let addressFk = ticket.addressFk;
|
||||
let agencyModeFk = ticket.agencyModeFk;
|
||||
|
||||
let orderID = await Self.app.models.Order.new(landed, addressFk, agencyModeFk);
|
||||
|
||||
return orderID;
|
||||
};
|
||||
|
|
|
@ -12,9 +12,11 @@ describe('order new()', () => {
|
|||
|
||||
it('should throw an error if the client is frozen', async() => {
|
||||
let error;
|
||||
let params = {addressFk: 121};
|
||||
let landed = new Date();
|
||||
let addressFk = 121;
|
||||
let agencyModeFk = 1;
|
||||
|
||||
await app.models.Order.new(params)
|
||||
await app.models.Order.new(landed, addressFk, agencyModeFk)
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
|
@ -24,9 +26,11 @@ describe('order new()', () => {
|
|||
|
||||
it('should throw an error if the client isnt frozen and isnt active', async() => {
|
||||
let error;
|
||||
let params = {addressFk: 6};
|
||||
let landed = new Date();
|
||||
let addressFk = 6;
|
||||
let agencyModeFk = 1;
|
||||
|
||||
await app.models.Order.new(params)
|
||||
await app.models.Order.new(landed, addressFk, agencyModeFk)
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
|
@ -35,13 +39,11 @@ describe('order new()', () => {
|
|||
});
|
||||
|
||||
it('should create a new order for the user with id 105 when all conditions are met', async() => {
|
||||
let params = {
|
||||
landed: new Date(),
|
||||
agencyModeFk: 1,
|
||||
addressFk: 125
|
||||
};
|
||||
let landed = new Date();
|
||||
let addressFk = 125;
|
||||
let agencyModeFk = 1;
|
||||
|
||||
orderId = await app.models.Order.new(params);
|
||||
orderId = await app.models.Order.new(landed, addressFk, agencyModeFk);
|
||||
|
||||
let highestOrderIdInFixtures = 3;
|
||||
|
||||
|
|
|
@ -31,5 +31,6 @@
|
|||
label="Agency"
|
||||
show-field="agency"
|
||||
value-field="id"
|
||||
rule="Order.agencyModeFk"
|
||||
field="$ctrl.order.agencyModeFk">
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -96,8 +96,8 @@ class Controller {
|
|||
createOrder() {
|
||||
let params = {
|
||||
landed: this.order.landed,
|
||||
addressFk: this.order.addressFk,
|
||||
agencyModeFk: this.order.agencyModeFk
|
||||
addressId: this.order.addressFk,
|
||||
agencyModeId: this.order.agencyModeFk
|
||||
};
|
||||
this.$http.post(`order/api/Orders/new`, params).then(res => {
|
||||
this.vnApp.showSuccess(this.translate.instant('Data saved!'));
|
||||
|
|
|
@ -1,121 +1,73 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
// #1489 updatePrice backTest
|
||||
xdescribe('sale updatePrice()', () => {
|
||||
it('should set price to 0 if the params price is undefined', async() => {
|
||||
let params = {
|
||||
price: undefined,
|
||||
id: 13,
|
||||
ticketFk: 8
|
||||
};
|
||||
await app.models.Sale.updatePrice(params);
|
||||
let saleUpdated = await app.models.Sale.findById(params.id);
|
||||
describe('sale updatePrice()', () => {
|
||||
let originalSale;
|
||||
let originalSalesPersonMana;
|
||||
let createdSaleComponent;
|
||||
let saleId = 13;
|
||||
|
||||
expect(saleUpdated.price).toEqual(0);
|
||||
afterAll(async done => {
|
||||
originalSale.save();
|
||||
createdSaleComponent.destroy();
|
||||
originalSalesPersonMana.save();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should set price as a decimal number', async() => {
|
||||
let params = {
|
||||
price: 5.5,
|
||||
id: 13,
|
||||
ticketFk: 8
|
||||
};
|
||||
await app.models.Sale.updatePrice(params);
|
||||
let saleUpdated = await app.models.Sale.findById(params.id);
|
||||
beforeAll(async done => {
|
||||
originalSale = await app.models.Sale.findById(saleId);
|
||||
originalSalesPersonMana = await app.models.WorkerMana.findById(18);
|
||||
|
||||
expect(saleUpdated.price).toEqual(5.5);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should now set price as a decimal number in a string', async() => {
|
||||
let params = {
|
||||
price: '5.5',
|
||||
id: 13,
|
||||
ticketFk: 8
|
||||
};
|
||||
await app.models.Sale.updatePrice(params);
|
||||
let saleUpdated = await app.models.Sale.findById(params.id);
|
||||
it('should throw an error if the ticket is not editable', async() => {
|
||||
let immutableSaleId = 1;
|
||||
let price = 5;
|
||||
|
||||
expect(saleUpdated.price).toEqual(5.5);
|
||||
await app.models.Sale.updatePrice(immutableSaleId, price)
|
||||
.catch(response => {
|
||||
expect(response).toEqual(new Error(`The sales of this ticket can't be modified`));
|
||||
error = response;
|
||||
});
|
||||
|
||||
expect(error).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return 0 if the price is an empty string', async() => {
|
||||
let params = {
|
||||
price: '',
|
||||
id: 13,
|
||||
ticketFk: 8
|
||||
};
|
||||
await app.models.Sale.updatePrice(params);
|
||||
let saleUpdated = await app.models.Sale.findById(params.id);
|
||||
let price = '';
|
||||
|
||||
await app.models.Sale.updatePrice(saleId, price);
|
||||
let saleUpdated = await app.models.Sale.findById(saleId);
|
||||
|
||||
expect(saleUpdated.price).toEqual(0);
|
||||
});
|
||||
|
||||
it('should now set price as a decimal number in a string', async() => {
|
||||
let price = '8';
|
||||
|
||||
it('should este crea mana', async() => {
|
||||
let params = {
|
||||
price: 5.5,
|
||||
id: 13,
|
||||
ticketFk: 8
|
||||
};
|
||||
await app.models.Sale.updatePrice(params);
|
||||
let saleUpdated = await app.models.Sale.findById(params.id);
|
||||
await app.models.Sale.updatePrice(saleId, price);
|
||||
let saleUpdated = await app.models.Sale.findById(saleId);
|
||||
|
||||
expect(saleUpdated.price).toEqual(5.5);
|
||||
expect(saleUpdated.price).toEqual(8);
|
||||
});
|
||||
|
||||
it('should este no crea el mana', async() => {
|
||||
let params = {
|
||||
price: 5.5,
|
||||
id: 13,
|
||||
ticketFk: 8
|
||||
};
|
||||
let todosLosComponentes = await app.models.SaleComponent.find({where: {saleFk: 13}});
|
||||
it('should set price as a decimal number and check the sale has the mana component', async() => {
|
||||
let price = 5.5;
|
||||
let manaComponentId = 37;
|
||||
|
||||
expect(todosLosComponentes[0].value).toEqual('');
|
||||
expect(todosLosComponentes[1].value).toEqual('');
|
||||
expect(todosLosComponentes[2].value).toEqual('');
|
||||
expect(todosLosComponentes[3].value).toEqual('');
|
||||
expect(todosLosComponentes[4].value).toEqual('');
|
||||
|
||||
await app.models.Sale.updatePrice(params);
|
||||
todosLosComponentes = await app.models.SaleComponent.find({where: {saleFk: 13}});
|
||||
let saleUpdated = await app.models.Sale.findById(params.id);
|
||||
await app.models.Sale.updatePrice(saleId, price);
|
||||
let saleUpdated = await app.models.Sale.findById(saleId);
|
||||
createdSaleComponent = await app.models.SaleComponent.findOne({where: {saleFk: saleId, componentFk: manaComponentId}});
|
||||
|
||||
expect(saleUpdated.price).toEqual(5.5);
|
||||
|
||||
expect(todosLosComponentes[0].value).toEqual('');
|
||||
expect(todosLosComponentes[1].value).toEqual('');
|
||||
expect(todosLosComponentes[2].value).toEqual('');
|
||||
expect(todosLosComponentes[3].value).toEqual('');
|
||||
expect(todosLosComponentes[4].value).toEqual('');
|
||||
expect(createdSaleComponent.value).toEqual(4.200);
|
||||
});
|
||||
// 2 let componentToUse;
|
||||
// if (usesMana)
|
||||
// componentToUse = 37;
|
||||
// 3else
|
||||
// componentToUse = 34;
|
||||
|
||||
// 4 if (saleComponent)
|
||||
// saleComponent.updateAttributes({value: saleComponent.value + value});
|
||||
// 5 else {
|
||||
// await Self.app.models.SaleComponent.create({
|
||||
// saleFk: params.id,
|
||||
// componentFk: componentToUse,
|
||||
// value: value
|
||||
// });
|
||||
// }
|
||||
it('should check that the mana of salesPerson changed', async() => {
|
||||
let updatedSalesPersonMana = await app.models.WorkerMana.findById(18);
|
||||
|
||||
// it(`should throw an error if the price is undefined`, async() => {
|
||||
// let error;
|
||||
|
||||
// let params = {ticketFk: 1, price: undefined};
|
||||
|
||||
// await app.models.Sale.updatePrice(params)
|
||||
// .catch(response => {
|
||||
// expect(response).toEqual(new Error('The value should be a number'));
|
||||
// error = response;
|
||||
// });
|
||||
|
||||
// expect(error).toBeDefined();
|
||||
// });
|
||||
expect(updatedSalesPersonMana.amount).not.toEqual(originalSalesPersonMana.amount);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,84 +2,94 @@ let UserError = require('vn-loopback/util/user-error');
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('updatePrice', {
|
||||
description: 'Changes the discount of a sale',
|
||||
description: 'Changes the price of a sale',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'params',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'sale ID, newPrice, ticketFk',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
description: 'The sale id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
arg: 'newPrice',
|
||||
description: 'The new price',
|
||||
type: 'number',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'string',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/updatePrice`,
|
||||
path: `/:id/updatePrice`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.updatePrice = async params => {
|
||||
if (!params.price) params.price = 0;
|
||||
Self.updatePrice = async(id, newPrice) => {
|
||||
let $ = Self.app.models;
|
||||
let transaction = await Self.beginTransaction({});
|
||||
let options = {transaction};
|
||||
|
||||
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 thisTicketIsEditable = await model.Ticket.isEditable(params.ticketFk);
|
||||
if (!thisTicketIsEditable)
|
||||
throw new UserError(`The sales of this ticket can't be modified`);
|
||||
|
||||
return await model.Ticket.find({
|
||||
where: {
|
||||
id: params.ticketFk
|
||||
},
|
||||
include: [{
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['salesPersonFk']
|
||||
try {
|
||||
let filter = {
|
||||
fields: ['id', 'ticketFk', 'price'],
|
||||
include: {
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['salesPersonFk']
|
||||
}
|
||||
},
|
||||
fields: ['id', 'clientFk']
|
||||
}
|
||||
}
|
||||
}],
|
||||
fields: ['id', 'clientFk']
|
||||
});
|
||||
}
|
||||
};
|
||||
let sale = await $.Sale.findById(id, filter, options);
|
||||
|
||||
let isEditable = await $.Ticket.isEditable(sale.ticketFk);
|
||||
if (!isEditable)
|
||||
throw new UserError(`The sales of this ticket can't be modified`);
|
||||
|
||||
let salesPerson = sale.ticket().client().salesPersonFk;
|
||||
let usesMana = await $.WorkerMana.findOne({where: {workerFk: salesPerson}, fields: 'amount'}, options);
|
||||
let componentCode = usesMana ? 'mana' : 'buyerDiscount';
|
||||
|
||||
let discount = await $.ComponentRate.findOne({where: {code: componentCode}}, options);
|
||||
let componentId = discount.id;
|
||||
let componentValue = newPrice - sale.price;
|
||||
|
||||
let where = {
|
||||
componentFk: componentId,
|
||||
saleFk: id
|
||||
};
|
||||
let saleComponent = await $.SaleComponent.findOne({where}, options);
|
||||
|
||||
if (saleComponent) {
|
||||
await $.SaleComponent.updateAll(where, {
|
||||
value: saleComponent.value + componentValue
|
||||
}, options);
|
||||
} else {
|
||||
await $.SaleComponent.create({
|
||||
saleFk: id,
|
||||
componentFk: componentId,
|
||||
value: componentValue
|
||||
}, options);
|
||||
}
|
||||
|
||||
await sale.updateAttributes({price: newPrice}, options);
|
||||
|
||||
query = `call vn.manaSpellersRequery(?)`;
|
||||
await Self.rawSql(query, [salesPerson], options);
|
||||
|
||||
await transaction.commit();
|
||||
} catch (error) {
|
||||
await transaction.rollback();
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ describe('ticket getSalesPersonMana()', () => {
|
|||
it('should get the mana of a salesperson of a given ticket', async() => {
|
||||
let mana = await app.models.Ticket.getSalesPersonMana(1);
|
||||
|
||||
expect(mana).toEqual(221);
|
||||
expect(mana).toEqual(222);
|
||||
});
|
||||
|
||||
it('should return 0 if the given ticket does not exists', async() => {
|
||||
|
|
|
@ -11,7 +11,12 @@
|
|||
"type": "Number"
|
||||
},
|
||||
"saleFk": {
|
||||
"id": true
|
||||
"type": "Number",
|
||||
"id": 2
|
||||
},
|
||||
"componentFk": {
|
||||
"type": "Number",
|
||||
"id": 1
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -260,7 +260,7 @@ class Controller {
|
|||
|
||||
updatePrice() {
|
||||
if (this.editedPrice != this.sale.price) {
|
||||
this.$http.post(`/api/Sales/updatePrice`, {id: this.edit.id, price: this.editedPrice, ticketFk: this.ticket.id}).then(() => {
|
||||
this.$http.post(`/api/Sales/${this.edit.id}/updatePrice`, {newPrice: this.editedPrice}).then(() => {
|
||||
this.sale.price = this.edit.price;
|
||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||
this.$scope.model.refresh();
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Author : Enrique Blasco BLanquer
|
||||
Date: 27 de mayo de 2019
|
||||
*/
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('checkUuid', {
|
||||
description: 'Check UUID from user',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'uuid,model',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: [{
|
||||
type: 'Object',
|
||||
root: true
|
||||
}],
|
||||
http: {
|
||||
path: `/checkUuid`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.checkUuid = async(ctx, data) => {
|
||||
const myUserId = ctx.req.accessToken.userId;
|
||||
// 1 Check is a registered user with a uuid
|
||||
let deviceUser = await Self.findOne({where: {userFk: myUserId, sn: data.uuid}});
|
||||
|
||||
if (deviceUser != null)
|
||||
return {'state': true, 'mng': ''};
|
||||
else {
|
||||
// 2 If it does not exist it can be for two reasons:
|
||||
// 2.1 It is the first time that the application enters so we have to register a new user associated with the user
|
||||
// 2.2 Has the user associated with a different uuid, so we deny access.
|
||||
|
||||
let device = await Self.findOne({where: {userFk: myUserId}});
|
||||
if (device != null) {
|
||||
// The device is already registered by another user, access is denied
|
||||
return {'state': false, 'mng': 'Ya estas regisgtrado en otro dispositivo, contacta con los dioses de informática.'};
|
||||
} else {
|
||||
// Check that the device is free
|
||||
let aDevice = await Self.findOne({where: {sn: data.uuid}});
|
||||
if (aDevice != null)
|
||||
return {'state': false, 'mng': 'El dispositivo esta siendo usado por otro usuario'};
|
||||
else {
|
||||
// It's the first time you access the application, insert
|
||||
/* await Self.rawSql('INSERT INTO vn2008.device (sn, model) VALUES (?,?);', [data.uuid, data.model]);*/
|
||||
await Self.create({
|
||||
sn: data.uuid,
|
||||
model: data.model,
|
||||
userFk: myUserId
|
||||
});
|
||||
|
||||
return {'state': true, 'mng': 'Nuevo dispositivo registrado'};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('device checkUuid()', () => {
|
||||
it('should return an state equal to false', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 9}}};
|
||||
let data = {'uuid': '123', 'model': 'ihpne kike molon'};
|
||||
let result = await app.models.Device.checkUuid(ctx, data);
|
||||
|
||||
expect(result.name).toBeFalsy();
|
||||
});
|
||||
});
|
|
@ -4,7 +4,7 @@ describe('workerMana getCurrentWorkerMana()', () => {
|
|||
it('should get the mana of the logged worker', async() => {
|
||||
let mana = await app.models.WorkerMana.getCurrentWorkerMana({req: {accessToken: {userId: 18}}});
|
||||
|
||||
expect(mana).toEqual(221);
|
||||
expect(mana).toEqual(222);
|
||||
});
|
||||
|
||||
it('should return 0 if the user doesnt uses mana', async() => {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Author : Enrique Blasco BLanquer
|
||||
Date: 27 de mayo de 2019
|
||||
*/
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('addAutoTime', {
|
||||
description: 'Adds a new hour registry by app in manual 0',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'timed',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: [{
|
||||
type: 'Object',
|
||||
root: true
|
||||
}],
|
||||
http: {
|
||||
path: `/addAutoTime`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.addAutoTime = async(ctx, data) => {
|
||||
const myUserId = ctx.req.accessToken.userId;
|
||||
|
||||
// get all worked time control, needed to calculate order
|
||||
let hours = await Self.rawSql(`SELECT * FROM vn.workerTimeControl
|
||||
WHERE userFk = ?
|
||||
AND DATE(timed) = CURDATE()
|
||||
ORDER BY timed DESC LIMIT 1`, [myUserId]);
|
||||
|
||||
// 1 get next order
|
||||
let order = 0;
|
||||
if (hours.length > 0)
|
||||
order = hours[hours.length - 1].order;
|
||||
|
||||
// 2 create element in db
|
||||
return Self.create({
|
||||
userFk: myUserId,
|
||||
timed: data.timed,
|
||||
order: order + 1,
|
||||
manual: 0
|
||||
});
|
||||
};
|
||||
};
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Author : Enrique Blasco BLanquer
|
||||
Date: 28 de mayo de 2019
|
||||
*/
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('getHoursWorked', {
|
||||
description: 'Get worked hours in current week, month and year',
|
||||
accessType: 'WRITE',
|
||||
returns: [{
|
||||
type: 'Object',
|
||||
root: true
|
||||
}],
|
||||
http: {
|
||||
path: `/getHoursWorked`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getHoursWorked = async(ctx, data) => {
|
||||
let totalHours = 0; // total hours worked in one year
|
||||
let totalMinutes = 0; // total minutes worked in one year
|
||||
let totalHoursMonth = 0; // total hours worked in one month
|
||||
let totalMinutesMonth = 0; // total minutes worked in one month
|
||||
let totalHoursWeek = 0; // total hours worked in one week
|
||||
let totalMinutesWeek = 0; // total minutes worked in one week
|
||||
const myUserId = ctx.req.accessToken.userId; // user id
|
||||
let today = new Date(); // needed to calculate total hours worked to current date
|
||||
let fromDate = today.getFullYear() + '-01-01'; // from date, current year
|
||||
let toDate = today.getFullYear() + '-12-31'; // to date, current year
|
||||
|
||||
|
||||
// 1 hours worked in a year
|
||||
let hoursYear = await Self.rawSql(`SELECT wtc.userFk, DATE(wtc.timed) dated,
|
||||
UNIX_TIMESTAMP(MIN(timed))timedStart,
|
||||
SEC_TO_TIME(SUM(if( mod(wtc.order,2)=1,
|
||||
UNIX_TIMESTAMP(timed) *-1,
|
||||
UNIX_TIMESTAMP(timed)))) timeWorkDay
|
||||
FROM vn.workerTimeControl wtc
|
||||
WHERE wtc.timed BETWEEN ? AND ? AND userFk = ?
|
||||
GROUP BY wtc.userFk,dated ORDER BY dated DESC`, [fromDate, toDate, myUserId]);
|
||||
|
||||
|
||||
// 2 Get days of week
|
||||
let week = [];
|
||||
// Starting Monday not Sunday
|
||||
let current = new Date();
|
||||
current.setDate((current.getDate() - current.getDay() + 1));
|
||||
for (let i = 0; i < 7; i++) {
|
||||
week.push(
|
||||
new Date(current)
|
||||
);
|
||||
current.setDate(current.getDate() + 1);
|
||||
}
|
||||
|
||||
// 3 I have all timed control for one year... NOW I CALCULATE TOTAL HOURS IN YEAR, MONTH, WEEK, Let's GO!
|
||||
for (hour of hoursYear) {
|
||||
if (parseInt(hour.timeWorkDay.split(':')[0]) > 0) {
|
||||
// YEAR
|
||||
totalHours += parseInt(hour.timeWorkDay.split(':')[0]);
|
||||
totalMinutes += parseInt(hour.timeWorkDay.split(':')[1]);
|
||||
// If it exceeds 5 hours we add 20 minutes of breakfast.
|
||||
if (parseInt(hour.timeWorkDay.split(':')[0]) >= 5)
|
||||
totalMinutes += 20;
|
||||
// MONTH
|
||||
|
||||
if ((new Date(hour.dated)).getMonth() == today.getMonth()) {
|
||||
totalHoursMonth += parseInt(hour.timeWorkDay.split(':')[0]);
|
||||
totalMinutesMonth += parseInt(hour.timeWorkDay.split(':')[1]);
|
||||
// If it exceeds 5 hours we add 20 minutes of breakfast.
|
||||
if (parseInt(hour.timeWorkDay.split(':')[0]) >= 5)
|
||||
totalMinutesMonth += 20;
|
||||
}
|
||||
// WEEK
|
||||
for (day of week) {
|
||||
let dayOfWeek = new Date(day);
|
||||
let dayOfCurrentWeek = new Date(hour.dated);
|
||||
if (dayOfWeek.getMonth() == dayOfCurrentWeek.getMonth() && dayOfWeek.getDate() == dayOfCurrentWeek.getDate()) {
|
||||
totalHoursWeek += parseInt(hour.timeWorkDay.split(':')[0]);
|
||||
totalMinutesWeek += parseInt(hour.timeWorkDay.split(':')[1]);
|
||||
// If it exceeds 5 hours we add 20 minutes of breakfast.
|
||||
if (parseInt(hour.timeWorkDay.split(':')[0]) >= 5)
|
||||
totalMinutesWeek += 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TOTAL WORKED HOURS IN THE YEAR
|
||||
totalHours += totalMinutes / 60;
|
||||
totalHours = decimalToHour(totalHours);
|
||||
|
||||
// TOTAL WORKED HOURS IN THE MONTH
|
||||
totalHoursMonth += totalMinutesMonth / 60;
|
||||
totalHoursMonth = decimalToHour(totalHoursMonth);
|
||||
|
||||
// TOTAL WORKED HOURS IN THE WEEK
|
||||
totalHoursWeek += totalMinutesWeek / 60;
|
||||
totalHoursWeek = decimalToHour(totalHoursWeek);
|
||||
|
||||
return {
|
||||
'totalWorekdYear': totalHours,
|
||||
'totalWorekdMonth': totalHoursMonth,
|
||||
'totalWorkedWeek': totalHoursWeek
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
function to calculate hours and minutes from decimal value
|
||||
*/
|
||||
function decimalToHour(value) {
|
||||
let decimalTime = parseFloat(value);
|
||||
decimalTime = decimalTime * 60 * 60;
|
||||
let hoursDay = Math.floor((decimalTime / (60 * 60)));
|
||||
decimalTime = decimalTime - (hoursDay * 60 * 60);
|
||||
let minutesDay = Math.floor((decimalTime / 60));
|
||||
return hoursDay + ':' + minutesDay;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Author : Enrique Blasco BLanquer
|
||||
Date: 29 de mayo de 2019
|
||||
*/
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('getWorkedWeek', {
|
||||
description: 'get worked week info',
|
||||
accessType: 'WRITE',
|
||||
returns: [{
|
||||
type: 'Object',
|
||||
root: true
|
||||
}],
|
||||
http: {
|
||||
path: `/getWorkedWeek`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getWorkedWeek = async(ctx, data) => {
|
||||
const myUserId = ctx.req.accessToken.userId; // user id
|
||||
let lastDate = new Date('1986-09-24'); // reference date
|
||||
let diff = 0; // difference of value between two dates
|
||||
let total = 0; // total hours
|
||||
|
||||
// 1 Get days of week
|
||||
let week = [];
|
||||
// 2 Starting Monday not Sunday
|
||||
let current = new Date();
|
||||
current.setDate((current.getDate() - current.getDay() + 1));
|
||||
for (let i = 0; i < 7; i++) {
|
||||
week.push(
|
||||
new Date(current)
|
||||
);
|
||||
current.setDate(current.getDate() + 1);
|
||||
}
|
||||
|
||||
let fromDate = week[0].getFullYear() + '-' + (week[0].getMonth() + 1) + '-' + week[0].getDate();
|
||||
let toDate = week[week.length - 1].getFullYear() + '-' + (week[week.length - 1].getMonth() + 1) + '-' + week[week.length - 1].getDate();
|
||||
|
||||
|
||||
// 3 hours worked in a current week
|
||||
let hoursWeek = await Self.rawSql(`SELECT wtc.timed ,wtc.order
|
||||
FROM vn.workerTimeControl wtc
|
||||
WHERE userFk = ?
|
||||
AND DATE(timed) BETWEEN ? AND ? ORDER BY timed DESC;`, [myUserId, fromDate, toDate]);
|
||||
|
||||
// 4 treat data
|
||||
let isFirst = true;
|
||||
for (let i = hoursWeek.length - 1; i >= 0; i--) {
|
||||
let d = new Date(hoursWeek[i].timed);
|
||||
if (isFirst) {
|
||||
lastDate = d;
|
||||
isFirst = false;
|
||||
} else {
|
||||
if (lastDate.getDate() === d.getDate()) {
|
||||
diff += Math.abs(d.getTime() - lastDate.getTime());
|
||||
lastDate = d;
|
||||
} else {
|
||||
total += diff;
|
||||
diff = 0;
|
||||
lastDate = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
total += diff;
|
||||
|
||||
// 5 calculate hours and minutes
|
||||
let decimalTime = total / 1000 / 3600;
|
||||
decimalTime = decimalTime * 60 * 60;
|
||||
let hours = Math.floor((decimalTime / (60 * 60)));
|
||||
decimalTime = decimalTime - (hours * 60 * 60);
|
||||
let minutes = Math.floor((decimalTime / 60));
|
||||
|
||||
return {'timeds': hoursWeek, 'totalWorked': hours + ':' + minutes};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('workerTimeControl addAutoTime()', () => {
|
||||
it('should return an undefined value', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 9}}};
|
||||
let data = {'timed': new Date()};
|
||||
let result = await app.models.WorkerTimeControl.addAutoTime(ctx, data);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('workerTimeControl getHoursWorked()', () => {
|
||||
it('should return an totalWorkedYear to be defined', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 9}}};
|
||||
let result = await app.models.WorkerTimeControl.getHoursWorked(ctx, null);
|
||||
|
||||
expect(result.totalWorekdYear).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('workerTimeControl getWorkedWeek()', () => {
|
||||
it('should return an timeds to be defined', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 9}}};
|
||||
let result = await app.models.WorkerTimeControl.getWorkedWeek(ctx, null);
|
||||
|
||||
expect(result.timeds).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Author : Enrique Blasco BLanquer
|
||||
Date: 28 de mayo de 2019
|
||||
*/
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('getWorkerInfo', {
|
||||
description: 'Get worker info (name, isWorking, total worked hours ...)',
|
||||
accessType: 'WRITE',
|
||||
returns: [{
|
||||
type: 'Object',
|
||||
root: true
|
||||
}],
|
||||
http: {
|
||||
path: `/getWorkerInfo`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getWorkerInfo = async(ctx, data) => {
|
||||
let prevHour = new Date(); // default value to start work
|
||||
let diff = 0; // difference of value between two dates
|
||||
let isOdd = true; // determine if timed is odd or not in db
|
||||
const myUserId = ctx.req.accessToken.userId; // get user id
|
||||
|
||||
|
||||
// 1 get name and photo for the user
|
||||
let [user] = await Self.rawSql(`SELECT u.name, t.Foto FROM vn.user u INNER JOIN vn2008.Trabajadores t ON u.id = t.user_id WHERE id = ?;`, [myUserId]);
|
||||
// 2 get all jornaly work time registered
|
||||
let workedHours = await Self.rawSql(`SELECT * FROM vn.workerTimeControl WHERE userFk = ? AND DATE(timed) = CURDATE() ORDER BY timed ASC;`, [myUserId]);
|
||||
let today = new Date();
|
||||
// 3 get the number of hours to work in one day
|
||||
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
|
||||
let [hoursForDay] = await Self.rawSql(`SELECT cl.hours_week AS hoursWeek,
|
||||
GROUP_CONCAT(DISTINCT LEFT(j.start,2) ORDER BY j.start ASC SEPARATOR '-') start ,
|
||||
GROUP_CONCAT(DISTINCT LEFT(j.end,2) ORDER BY j.end ASC SEPARATOR '-') end,
|
||||
CAST(IFNULL((SUM(TIME_TO_SEC(j.end))-SUM(TIME_TO_SEC(j.start)))/3600,if(cl.hours_week=40
|
||||
AND DAYOFWEEK(t.dated) IN(2,3,4,5,6),8,0)) AS DECIMAL(10,2)) workingHours
|
||||
FROM vn.time t
|
||||
LEFT JOIN postgresql.business b ON t.dated BETWEEN b.date_start AND ifnull(b.date_end,? )
|
||||
LEFT JOIN postgresql.profile AS pr ON b.client_id = pr.profile_id
|
||||
LEFT JOIN postgresql.person AS p ON pr.person_id = p.person_id
|
||||
LEFT JOIN vn.worker AS w ON p.id_trabajador = w.id
|
||||
LEFT JOIN postgresql.business_labour AS bl ON b.business_id = bl.business_id
|
||||
LEFT JOIN postgresql.calendar_labour_type AS cl ON bl.calendar_labour_type_id = cl.calendar_labour_type_id
|
||||
LEFT JOIN postgresql.journey AS j ON j.business_id = b.business_id and j.day_id=WEEKDAY(t.dated)+1
|
||||
WHERE t.dated BETWEEN ? AND ? AND userFk = ?
|
||||
GROUP BY w.userFk,dated`, [date, date, date, myUserId]);
|
||||
|
||||
// 4 Add all the hours and see the total worked
|
||||
for (hour of workedHours) {
|
||||
if (!isOdd)
|
||||
diff += Math.abs((new Date(hour.timed)).getTime() - prevHour.getTime());
|
||||
else
|
||||
prevHour = new Date(hour.timed);
|
||||
|
||||
isOdd = !isOdd;
|
||||
}
|
||||
|
||||
// 5 calculate hours and minutes from a number value
|
||||
let decimalTime = diff / 1000 / 3600;
|
||||
decimalTime = decimalTime * 60 * 60;
|
||||
let hours = Math.floor((decimalTime / (60 * 60)));
|
||||
decimalTime = decimalTime - (hours * 60 * 60);
|
||||
let minutes = Math.floor((decimalTime / 60));
|
||||
|
||||
// 6 default total hours
|
||||
let totalHours = '7:40';
|
||||
let hoursWeek = 40;
|
||||
|
||||
// 7 Get the hours you have to work today and the hours to work in a week
|
||||
if (hoursForDay != null) {
|
||||
// If it exceeds 5 hours we take 20 minutes of breakfast.
|
||||
if (hoursForDay.workingHours > 5)
|
||||
hoursForDay.workingHours -= 20 * 0.016666;
|
||||
let decimalTime = parseFloat(hoursForDay.workingHours);
|
||||
decimalTime = decimalTime * 60 * 60;
|
||||
let hoursDay = Math.floor((decimalTime / (60 * 60)));
|
||||
decimalTime = decimalTime - (hoursDay * 60 * 60);
|
||||
let minutesDay = Math.floor((decimalTime / 60));
|
||||
totalHours = hoursDay + ':' + minutesDay;
|
||||
}
|
||||
|
||||
|
||||
// 8 return value
|
||||
if (hoursForDay != null)
|
||||
hoursWeek = hoursForDay.hoursWeek;
|
||||
return {
|
||||
'name': user.name,
|
||||
'hours': hours,
|
||||
'minutes': minutes,
|
||||
'today': today,
|
||||
'isWorking': !isOdd,
|
||||
'lastDate': prevHour,
|
||||
'totalHours': totalHours,
|
||||
'hoursWeek': hoursWeek
|
||||
};
|
||||
};
|
||||
};
|
|
@ -46,5 +46,8 @@
|
|||
},
|
||||
"WorkerTimeControl": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Device": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
require('../methods/device/checkUuid')(Self);
|
||||
|
||||
Self.rewriteDbError(function(err) {
|
||||
if (err.code === 'ER_DUP_ENTRY')
|
||||
return new UserError(``);
|
||||
return err;
|
||||
});
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "Device",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "device"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number"
|
||||
},
|
||||
"sn": {
|
||||
"type": "String"
|
||||
},
|
||||
"model": {
|
||||
"type": "String"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"user": {
|
||||
"type": "belongsTo",
|
||||
"model": "Account",
|
||||
"foreignKey": "userFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,9 @@ const UserError = require('vn-loopback/util/user-error');
|
|||
module.exports = Self => {
|
||||
require('../methods/worker-time-control/filter')(Self);
|
||||
require('../methods/worker-time-control/addTime')(Self);
|
||||
require('../methods/worker-time-control/addAutoTime')(Self);
|
||||
require('../methods/worker-time-control/getHoursWorked')(Self);
|
||||
require('../methods/worker-time-control/getWorkedWeek')(Self);
|
||||
|
||||
Self.rewriteDbError(function(err) {
|
||||
if (err.code === 'ER_DUP_ENTRY')
|
||||
|
|
|
@ -2,4 +2,5 @@ module.exports = Self => {
|
|||
require('../methods/worker/filter')(Self);
|
||||
require('../methods/worker/mySubordinates')(Self);
|
||||
require('../methods/worker/isSubordinate')(Self);
|
||||
require('../methods/worker/getWorkerInfo')(Self);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue