regularize claim #656

This commit is contained in:
Joan Sanchez 2018-10-08 07:31:55 +02:00
parent b649ee71d9
commit f7e042320d
15 changed files with 328 additions and 25 deletions

View File

@ -88,7 +88,12 @@
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Regularizar" vn-acl="administrative, salesAssistant"></vn-submit>
{{$ctrl.resolvedStateText}}
<vn-button
label="Regularize"
ng-click="$ctrl.regularize()"
disabled="$ctrl.claim.claimStateFk == $ctrl.resolvedState">
</vn-button>
</vn-button-bar>
<!-- WIP
<a ng-click="$ctrl.openAddSalesDialog()" vn-tooltip="New item" vn-bind="+" fixed-bottom-right>

View File

@ -22,6 +22,7 @@ class Controller {
{relation: 'claimBeggining'}
]
};
this.resolvedState = 3;
}
openAddSalesDialog() {
@ -118,6 +119,15 @@ class Controller {
this.$.model.refresh();
});
}
regularize() {
let data = {claimFk: this.$stateParams.id};
let query = `/claim/api/Claims/regularizeClaim`;
this.$http.post(query, data).then(() => {
this.card.reload();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
}
}
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
@ -127,5 +137,8 @@ ngModule.component('vnClaimAction', {
controller: Controller,
bindings: {
claim: '<'
},
require: {
card: '^vnClaimCard'
}
});

View File

@ -31,6 +31,7 @@ describe('claim', () => {
hide: () => {},
show: () => {}
};
controller.card = {reload: () => {}};
}));
describe('openAddSalesDialog()', () => {
@ -135,7 +136,7 @@ describe('claim', () => {
});
describe('importTicketLines()', () => {
it('should perform a post quer', () => {
it('should perform a post query', () => {
spyOn(controller.$.model, 'refresh');
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.lastTicketsPopover, 'hide');
@ -149,5 +150,20 @@ describe('claim', () => {
expect(controller.$.lastTicketsPopover.hide).toHaveBeenCalledWith();
});
});
describe('regularize()', () => {
it('should perform a post query and reload the claim card', () => {
spyOn(controller.card, 'reload');
spyOn(controller.vnApp, 'showSuccess');
let data = {claimFk: $state.params.id};
$httpBackend.expect('POST', `/claim/api/Claims/regularizeClaim`, data).respond({});
controller.regularize();
$httpBackend.flush();
expect(controller.card.reload).toHaveBeenCalledWith();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
});
});

View File

@ -4,4 +4,5 @@ Total claimed: Total Reclamado
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
Imports ticket lines: Importa las lineas de un ticket
Regularize: Regularizar

View File

@ -73,4 +73,4 @@ Tracking: Revisión
Sale checked: Control clientes
Components: Componentes
Sale tracking: Líneas preparadas
Pictures: Imágenes
Pictures: Fotos

View File

@ -0,0 +1,156 @@
module.exports = Self => {
Self.remoteMethodCtx('regularizeClaim', {
description: 'Imports lines from claimBeginning to a new ticket with specific shipped, landed dates, agency and company',
accessType: 'WRITE',
accepts: [{
arg: 'params',
type: 'object',
http: {source: 'body'}
}],
returns: {
type: ['Object'],
root: true
},
http: {
path: `/regularizeClaim`,
verb: 'POST'
}
});
Self.regularizeClaim = async (ctx, params) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const resolvedState = 3;
const claimEnds = await models.ClaimEnd.find({
include: {
relation: 'claimDestination',
fields: ['addressFk']
},
where: {claimFk: params.claimFk}
});
let transaction = await Self.beginTransaction({});
try {
for (let i = 0; i < claimEnds.length; i++) {
const claimEnd = claimEnds[i];
const destination = claimEnd.claimDestination();
const addressFk = destination && destination.addressFk;
if (!addressFk)
continue;
let sale = await getSale(claimEnd.saleFk);
let ticketFk = await getTicketId({
addressFk: addressFk,
companyFk: sale.ticket().companyFk,
warehouseFk: sale.ticket().warehouseFk
}, transaction);
let address = await models.Address.findOne({
where: {id: addressFk}
});
if (!ticketFk) {
ticketFk = await createTicket({
clientFk: address.clientFk,
addressFk: addressFk,
warehouseFk: sale.ticket().warehouseFk,
companyFk: sale.ticket().companyFk,
userId: userId
}, transaction);
}
await models.Sale.create({
ticketFk: ticketFk,
itemFk: sale.itemFk,
concept: sale.concept,
quantity: -sale.quantity,
price: sale.price,
discount: 100
}, {transaction: transaction});
await sendMessage(ctx, {
itemFk: sale.itemFk,
ticketFk: sale.ticketFk,
workerFk: sale.item().itemType().workerFk,
quantity: sale.quantity,
concept: sale.concept,
nickname: address.nickname
}, transaction);
}
let claim = await Self.findById(params.claimFk);
claim = await claim.updateAttributes({
claimStateFk: resolvedState
}, {transaction: transaction});
await transaction.commit();
return claim;
} catch (e) {
await transaction.rollback();
throw e;
}
};
async function getSale(saleFk) {
return await Self.app.models.Sale.findOne({
include: [
{
relation: 'ticket',
scope: {fields: ['warehouseFk', 'companyFk']}
},
{
relation: 'item',
scope: {
fields: ['typeFk'],
include: {
relation: 'itemType',
scope: {fields: ['workerFk']}
}
}
}],
where: {id: saleFk}
});
}
async function getTicketId(params, transaction) {
const currentDate = new Date();
currentDate.setHours(0, 0, 0, 0);
let ticket = await Self.app.models.Ticket.findOne({
where: {
addressFk: params.addressFk,
companyFk: params.companyFk,
warehouseFk: params.warehouseFk,
shipped: currentDate,
landed: currentDate
}
}, {transaction: transaction});
return ticket && ticket.id;
}
async function createTicket(params, transaction) {
return await Self.app.models.Ticket.new({
shipped: new Date(),
landed: new Date(),
clientFk: params.clientFk,
warehouseFk: params.warehouseFk,
companyFk: params.companyFk,
addressFk: params.addressFk,
userId: params.userId
}, {transaction: transaction});
}
async function sendMessage(ctx, params, transaction) {
const message = `Envio ${params.quantity} unidades de "${params.concept}" (#${params.itemFk}) a `
+ `"${params.nickname}" provenientes del ticket #${params.ticketFk}`;
await Self.app.models.Message.send(ctx, {
recipientFk: params.workerFk,
message: message
}, {transaction: transaction});
}
};

View File

@ -0,0 +1,45 @@
const app = require(`${servicesDir}/claim/server/server`);
describe('regularizeClaim()', () => {
const claimFk = 1;
const pendentState = 1;
const resolvedState = 3;
const trashDestination = 2;
const trashAddress = 12;
let claimEnds = [];
let trashTicket;
afterAll(async() => {
let claim = await app.models.Claim.findById(claimFk);
await claim.updateAttributes({claimStateFk: pendentState});
await app.models.Ticket.destroyById(trashTicket.id);
claimEnds.forEach(async line => {
await line.destroy();
});
});
it('should change claim state to resolved', async() => {
let ctx = {req: {accessToken: {userId: 18}}};
let params = {claimFk: claimFk};
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
});
claimEnds.forEach(async claimEnd => {
claimEnd.updateAttributes({claimDestinationFk: trashDestination});
});
let claimBefore = await app.models.Claim.findById(params.claimFk);
await app.models.Claim.regularizeClaim(ctx, params);
let claimAfter = await app.models.Claim.findById(params.claimFk);
trashTicket = await app.models.Ticket.findOne({where: {addressFk: 12}});
expect(trashTicket.addressFk).toEqual(trashAddress);
expect(claimBefore.claimStateFk).toEqual(pendentState);
expect(claimAfter.claimStateFk).toEqual(resolvedState);
});
});

View File

@ -18,6 +18,13 @@
"required": true
}
},
"relations": {
"address": {
"type": "belongsTo",
"model": "Address",
"foreignKey": "addressFk"
}
},
"acls": [
{
"accessType": "READ",

View File

@ -2,4 +2,5 @@ module.exports = Self => {
require('../methods/claim/getSummary')(Self);
require('../methods/claim/createFromSales')(Self);
require('../methods/claim/updateClaim')(Self);
require('../methods/claim/regularizeClaim')(Self);
};

View File

@ -71,13 +71,15 @@ module.exports = function(Self) {
let customer = insurance.classification().customer();
if (!customer.salesPerson()) return;
let salesPerson = customer.salesPerson().user().name;
let salesPersonId = customer.salesPerson().user().id;
let grade = data.grade ? `(Grado ${data.grade})` : '(Sin grado)';
let message = {
message: `He cambiado el crédito asegurado del cliente "${customer.name}" a ${data.credit}${grade}`
let params = {
recipientFk: salesPersonId,
message: `He cambiado el crédito asegurado del `
+ `cliente "${customer.name}" a ${data.credit}${grade}`
};
Self.app.models.Message.send(salesPerson, message, ctx);
Self.app.models.Message.send(ctx, params);
};
// Update from transaction misses ctx accessToken.

View File

@ -51,5 +51,6 @@
"You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo",
"Warehouse cannot be blank": "El almacén no puede quedar en blanco",
"Agency cannot be blank": "La agencia no puede quedar en blanco",
"You don't have enough privileges to do that": "No tienes permisos para para hacer esto"
"You don't have enough privileges to do that": "No tienes permisos para para hacer esto",
"This address doesn't exist": "This address doesn't exist"
}

View File

@ -1,18 +1,12 @@
module.exports = Self => {
Self.remoteMethod('send', {
Self.remoteMethodCtx('send', {
description: 'Send message to user',
accessType: 'WRITE',
accepts: [{
arg: 'recipient',
type: 'string',
required: true,
description: 'The user/alias name',
http: {source: 'path'}
}, {
arg: 'data',
type: 'object',
required: true,
description: 'Message data',
description: 'recipientFk, message',
http: {source: 'body'}
}, {
arg: 'context',
@ -31,10 +25,23 @@ module.exports = Self => {
}
});
Self.send = async(recipient, data, ctx) => {
let query = `SELECT vn.messageSendWithUser(?, ?, ?) AS sent`;
let [result] = await Self.rawSql(query, [ctx.req.accessToken.userId, recipient, data.message]);
Self.send = async(ctx, data, transaction) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const sender = await models.Account.findById(userId, transaction);
const recipient = await models.Account.findById(data.recipientFk, transaction);
return result;
await Self.create({
sender: sender.name,
recipient: recipient.name,
message: data.message
}, transaction);
return await models.MessageInbox.create({
sender: sender.name,
recipient: recipient.name,
finalRecipient: recipient.name,
message: data.message
}, transaction);
};
};

View File

@ -3,9 +3,12 @@ const app = require(`${servicesDir}/client/server/server`);
describe('message send()', () => {
it('should call the send method and return the response', async() => {
let ctx = {req: {accessToken: {userId: 1}}};
await app.models.Message.send('salesPerson', {message: 'I changed something'}, ctx)
.then(response => {
expect(response.sent).toEqual(1);
});
let params = {
recipientFk: 1,
message: 'I changed something'
};
let response = await app.models.Message.send(ctx, params, {transaction: 'You'});
expect(response.message).toEqual(params.message);
});
});

View File

@ -0,0 +1,43 @@
{
"name": "MessageInbox",
"base": "VnModel",
"options": {
"mysql": {
"table": "messageInbox"
}
},
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
},
"sender": {
"type": "String",
"required": true
},
"recipient": {
"type": "String",
"required": true
},
"finalRecipient": {
"type": "String",
"required": true
},
"message": {
"type": "String"
}
},
"relations": {
"remitter": {
"type": "belongsTo",
"model": "User",
"foreignKey": "sender"
},
"receptor": {
"type": "belongsTo",
"model": "User",
"foreignKey": "recipient"
}
}
}

View File

@ -123,6 +123,9 @@
"Message": {
"dataSource": "vn"
},
"MessageInbox": {
"dataSource": "vn"
},
"WorkerMana": {
"dataSource": "bs"
},