1368-ticket_sale_refactor #327

Merged
joan merged 20 commits from 1368-ticket_sale_refactor into dev 2020-07-02 12:58:12 +00:00
13 changed files with 136 additions and 153 deletions
Showing only changes of commit b40e09a6cb - Show all commits

View File

@ -1,4 +1,5 @@
UPDATE `salix`.`ACL` SET `accessType`='WRITE' WHERE `id`='213'; UPDATE `salix`.`ACL` SET `accessType`='WRITE' WHERE `id`='213';
UPDATE `salix`.`ACL` SET `property` = 'deleteSales' WHERE (`id` = '80');
INSERT IGNORE INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('CustomsAgent', '*', '*', 'ALLOW', 'ROLE', 'employee'); INSERT IGNORE INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('CustomsAgent', '*', '*', 'ALLOW', 'ROLE', 'employee');

View File

@ -4,17 +4,15 @@ module.exports = Self => {
Self.remoteMethodCtx('createFromSales', { Self.remoteMethodCtx('createFromSales', {
description: 'Create a claim', description: 'Create a claim',
accepts: [{ accepts: [{
arg: 'claim', arg: 'ticketId',
type: 'object', type: 'Number',
required: true, required: true,
description: ' newTicketFk, clientFk, ticketCreated', description: 'The origin ticket id'
http: {source: 'body'}
}, { }, {
arg: 'sales', arg: 'sales',
type: 'object', type: ['Object'],
required: true, required: true,
description: '[sales IDs]', description: 'The claimed sales'
http: {source: 'body'}
}], }],
returns: { returns: {
type: 'object', type: 'object',
@ -26,28 +24,27 @@ module.exports = Self => {
} }
}); });
Self.createFromSales = async(ctx, params) => { Self.createFromSales = async(ctx, ticketId, sales) => {
let models = Self.app.models; const models = Self.app.models;
let userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
let tx = await Self.beginTransaction({}); const tx = await Self.beginTransaction({});
try { try {
let options = {transaction: tx}; let options = {transaction: tx};
const ticketId = params.claim.ticketFk;
const ticket = await models.Ticket.findById(ticketId, null, options); const ticket = await models.Ticket.findById(ticketId, null, options);
if (ticket.isDeleted) if (ticket.isDeleted)
throw new UserError(`You can't create a claim for a removed ticket`); throw new UserError(`You can't create a claim for a removed ticket`);
const worker = await models.Worker.findOne({ const newClaim = await Self.create({
where: {userFk: userId} ticketFk: ticketId,
clientFk: ticket.clientFk,
ticketCreated: ticket.shipped,
workerFk: userId
}, options); }, options);
const promises = [];
params.claim.workerFk = worker.id; for (const sale of sales) {
let newClaim = await Self.create(params.claim, options);
let promises = [];
for (const sale of params.sales) {
const newClaimBeginning = models.ClaimBeginning.create({ const newClaimBeginning = models.ClaimBeginning.create({
saleFk: sale.id, saleFk: sale.id,
claimFk: newClaim.id, claimFk: newClaim.id,

View File

@ -1,7 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('Claim Create', () => { describe('Claim createFromSales()', () => {
let newDate = new Date();
let createdClaimFk; let createdClaimFk;
afterAll(async done => { afterAll(async done => {
@ -10,28 +9,18 @@ describe('Claim Create', () => {
done(); done();
}); });
let newClaim = { const ticketId = 2;
ticketFk: 2, const newSale = [{
clientFk: 101,
ticketCreated: newDate
};
let newSale = [{
id: 3, id: 3,
instance: 0, instance: 0,
quantity: 10 quantity: 10
}]; }];
const ctx = {req: {accessToken: {userId: 1}}};
let params = {claim: newClaim, sales: newSale};
let ctx = {req: {accessToken: {userId: 1}}};
it('should create a new claim', async() => { it('should create a new claim', async() => {
let claim = await app.models.Claim.createFromSales(ctx, params); let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
expect(claim.ticketFk).toEqual(newClaim.ticketFk); expect(claim.ticketFk).toEqual(ticketId);
expect(claim.clientFk).toEqual(newClaim.clientFk);
expect(claim.ticketCreated).toEqual(newClaim.ticketCreated);
expect(claim.workerFk).toEqual(newClaim.workerFk);
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}}); let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}});
@ -44,7 +33,7 @@ describe('Claim Create', () => {
it('should not be able to create a claim if exists that sale', async() => { it('should not be able to create a claim if exists that sale', async() => {
let error; let error;
await app.models.Claim.createFromSales(ctx, params) await app.models.Claim.createFromSales(ctx, ticketId, newSale)
.catch(e => { .catch(e => {
error = e; error = e;

View File

@ -0,0 +1,43 @@
let UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('deleteSales', {
description: 'Deletes the selected sales',
accessType: 'WRITE',
accepts: [{
arg: 'sales',
type: ['Object'],
required: true,
description: 'The sales to remove'
},
{
arg: 'ticketId',
type: 'Number',
required: true,
description: 'The ticket id'
}],
returns: {
type: ['Object'],
root: true
},
http: {
path: `/deleteSales`,
verb: 'POST'
}
});
Self.deleteSales = async(ctx, sales, ticketId) => {
const models = Self.app.models;
const isTicketEditable = await models.Ticket.isEditable(ctx, ticketId);
if (!isTicketEditable)
throw new UserError(`The sales of this ticket can't be modified`);
const promises = [];
for (let sale of sales) {
const deletedSale = models.Sale.destroyById(sale.id);
promises.push(deletedSale);
}
return Promise.all(promises);
};
};

View File

@ -1,35 +0,0 @@
let UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('removes', {
description: 'Change the state of a ticket',
accessType: 'WRITE',
accepts: [{
arg: 'params',
type: 'object',
required: true,
description: '[sales IDs], actualTicketFk',
http: {source: 'body'}
}],
returns: {
type: 'string',
root: true
},
http: {
path: `/removes`,
verb: 'post'
}
});
Self.removes = async(ctx, params) => {
let thisTicketIsEditable = await Self.app.models.Ticket.isEditable(ctx, params.actualTicketFk);
if (!thisTicketIsEditable)
throw new UserError(`The sales of this ticket can't be modified`);
let promises = [];
for (let i = 0; i < params.sales.length; i++)
promises.push(Self.app.models.Sale.destroyById(params.sales[i].id));
return Promise.all(promises);
};
};

View File

@ -6,28 +6,43 @@ module.exports = Self => {
description: 'Change the state of a ticket', description: 'Change the state of a ticket',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'params', arg: 'ticketId',
type: 'object', type: 'Number',
required: true, required: true,
description: '[sales IDs], ticketFk, reserved', description: 'The ticket id'
http: {source: 'body'} }, {
arg: 'sales',
type: ['Object'],
required: true,
description: 'The sale to reserve'
},
{
arg: 'reserved',
type: 'Boolean',
required: true
}], }],
returns: { returns: {
type: 'string', type: ['Object'],
root: true root: true
}, },
http: { http: {
path: `/reserve`, path: `/reserve`,
verb: 'post' verb: 'POST'
} }
}); });
Self.reserve = async(ctx, params) => { Self.reserve = async(ctx, ticketId, sales, reserved) => {
let thisTicketIsEditable = await Self.app.models.Ticket.isEditable(ctx, params.ticketFk); const models = Self.app.models;
if (!thisTicketIsEditable) const isTicketEditable = await models.Ticket.isEditable(ctx, ticketId);
if (!isTicketEditable)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
for (let i = 0; i < params.sales.length; i++) const promises = [];
await Self.app.models.Sale.update({id: params.sales[i].id}, {reserved: params.reserved}); for (let sale of sales) {
const reservedSale = models.Sale.update({id: sale.id}, {reserved: reserved});
promises.push(reservedSale);
}
return Promise.all(promises);
}; };
}; };

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('sale removes()', () => { describe('sale deleteSales()', () => {
let sale; let sale;
let newsale; let newsale;
@ -16,13 +16,11 @@ describe('sale removes()', () => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let error; let error;
let params = { const sales = [{id: 1, instance: 0}, {id: 2, instance: 1}];
sales: [{id: 1, instance: 0}, {id: 2, instance: 1}], const ticketId = 2;
actualTicketFk: 2
};
try { try {
await app.models.Sale.removes(ctx, params); await app.models.Sale.deleteSales(ctx, sales, ticketId);
} catch (e) { } catch (e) {
error = e; error = e;
} }
@ -32,12 +30,11 @@ describe('sale removes()', () => {
it('should delete the sales', async() => { it('should delete the sales', async() => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let params = {
sales: [{id: newsale.id, instance: 0}],
actualTicketFk: 16
};
let res = await app.models.Sale.removes(ctx, params); const sales = [{id: newsale.id, instance: 0}];
const ticketId = 16;
let res = await app.models.Sale.deleteSales(ctx, sales, ticketId);
expect(res).toEqual([{count: 1}]); expect(res).toEqual([{count: 1}]);
}); });

View File

@ -1,6 +1,7 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('sale reserve()', () => { describe('sale reserve()', () => {
const ctx = {req: {accessToken: {userId: 9}}};
afterAll(async done => { afterAll(async done => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let params = { let params = {
@ -17,13 +18,12 @@ describe('sale reserve()', () => {
}); });
it('should throw an error if the ticket can not be modified', async() => { it('should throw an error if the ticket can not be modified', async() => {
let ctx = {req: {accessToken: {userId: 9}}};
let error; let error;
let params = {ticketFk: 2, const ticketId = 2;
sales: [{id: 5}], const sales = [{id: 5}];
reserved: false}; const reserved = false;
await app.models.Sale.reserve(ctx, params) await app.models.Sale.reserve(ctx, ticketId, sales, reserved)
.catch(response => { .catch(response => {
expect(response).toEqual(new Error(`The sales of this ticket can't be modified`)); expect(response).toEqual(new Error(`The sales of this ticket can't be modified`));
error = response; error = response;
@ -38,18 +38,13 @@ describe('sale reserve()', () => {
expect(originalTicketSales[0].reserved).toEqual(0); expect(originalTicketSales[0].reserved).toEqual(0);
expect(originalTicketSales[1].reserved).toEqual(0); expect(originalTicketSales[1].reserved).toEqual(0);
let ctx = {req: {accessToken: {userId: 9}}}; const ticketId = 11;
let params = { const sales = [{id: 7}, {id: 8}];
sales: [ const reserved = true;
{id: 7},
{id: 8}],
ticketFk: 11,
reserved: true
};
await app.models.Sale.reserve(ctx, params); await app.models.Sale.reserve(ctx, ticketId, sales, reserved);
let reservedTicketSales = await app.models.Ticket.getSales(11); const reservedTicketSales = await app.models.Ticket.getSales(ticketId);
expect(reservedTicketSales[0].reserved).toEqual(1); expect(reservedTicketSales[0].reserved).toEqual(1);
expect(reservedTicketSales[1].reserved).toEqual(1); expect(reservedTicketSales[1].reserved).toEqual(1);

View File

@ -1,12 +1,12 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('getSalesPersonMana', { Self.remoteMethod('getSalesPersonMana', {
description: 'Returns mana of a salesperson of a ticket', description: 'Returns the mana amount of a salesperson for a ticket',
accessType: 'READ', accessType: 'READ',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'number', type: 'number',
required: true, required: true,
description: 'ticket id', description: 'The ticket id',
http: {source: 'path'} http: {source: 'path'}
}], }],
returns: { returns: {
@ -18,8 +18,9 @@ module.exports = Self => {
} }
}); });
Self.getSalesPersonMana = async ticketFk => { Self.getSalesPersonMana = async ticketId => {
let ticket = await Self.app.models.Ticket.findById(ticketFk, { const models = Self.app.models;
const ticket = await models.Ticket.findById(ticketId, {
include: [{ include: [{
relation: 'client', relation: 'client',
scope: { scope: {
@ -29,10 +30,12 @@ module.exports = Self => {
fields: ['id', 'clientFk'] fields: ['id', 'clientFk']
}); });
if (!ticket) if (!ticket) return 0;
return 0;
let mana = await Self.app.models.WorkerMana.findOne({where: {workerFk: ticket.client().salesPersonFk}, fields: 'amount'}); const mana = await models.WorkerMana.findOne({
where: {
workerFk: ticket.client().salesPersonFk
}, fields: 'amount'});
return mana ? mana.amount : 0; return mana ? mana.amount : 0;
}; };

View File

@ -1,7 +1,7 @@
module.exports = Self => { module.exports = Self => {
require('../methods/sale/getClaimableFromTicket')(Self); require('../methods/sale/getClaimableFromTicket')(Self);
require('../methods/sale/reserve')(Self); require('../methods/sale/reserve')(Self);
require('../methods/sale/removes')(Self); require('../methods/sale/deleteSales')(Self);
require('../methods/sale/updatePrice')(Self); require('../methods/sale/updatePrice')(Self);
require('../methods/sale/updateQuantity')(Self); require('../methods/sale/updateQuantity')(Self);
require('../methods/sale/updateConcept')(Self); require('../methods/sale/updateConcept')(Self);

View File

@ -145,8 +145,8 @@ class Controller extends Section {
removeSales() { removeSales() {
const sales = this.selectedValidSales(); const sales = this.selectedValidSales();
const params = {sales: sales, actualTicketFk: this.ticket.id}; const params = {sales: sales, ticketId: this.ticket.id};
this.$http.post(`Sales/removes`, params).then(() => { this.$http.post(`Sales/deleteSales`, params).then(() => {
this.removeSelectedSales(); this.removeSelectedSales();
this.vnApp.showSuccess(this.$t('Data saved!')); this.vnApp.showSuccess(this.$t('Data saved!'));
}).finally(() => this.resetChanges()); }).finally(() => this.resetChanges());
@ -164,15 +164,7 @@ class Controller extends Section {
createClaim() { createClaim() {
const sales = this.selectedValidSales(); const sales = this.selectedValidSales();
const params = { const params = {ticketId: this.ticket.id, sales: sales};
claim: {
ticketFk: this.ticket.id,
clientFk: this.ticket.clientFk,
ticketCreated: this.ticket.shipped
},
sales: sales
};
this.resetChanges(); this.resetChanges();
this.$http.post(`Claims/createFromSales`, params) this.$http.post(`Claims/createFromSales`, params)
.then(res => this.$state.go('claim.card.basicData', {id: res.data.id})); .then(res => this.$state.go('claim.card.basicData', {id: res.data.id}));
@ -339,21 +331,11 @@ class Controller extends Section {
} }
setReserved(reserved) { setReserved(reserved) {
let selectedSales = this.selectedValidSales(); const selectedSales = this.selectedValidSales();
let params = {sales: selectedSales, ticketFk: this.ticket.id, reserved: reserved}; const params = {ticketId: this.ticket.id, sales: selectedSales, reserved: reserved};
this.$http.post(`Sales/reserve`, params).then(() => {
let reservedSales = new Map(); selectedSales.forEach(sale => {
this.$http.post(`Sales/reserve`, params).then(res => { sale.reserved = reserved;
let isReserved = res.config.data.reserved;
res.config.data.sales.forEach(sale => {
reservedSales.set(sale.id, {reserved: isReserved});
});
this.sales.forEach(sale => {
const reservedSale = reservedSales.get(sale.id);
if (reservedSale)
sale.reserved = reservedSale.reserved;
}); });
}).finally(() => this.resetChanges()); }).finally(() => this.resetChanges());
} }

View File

@ -261,8 +261,8 @@ describe('Ticket', () => {
const firstSale = controller.sales[0]; const firstSale = controller.sales[0];
firstSale.checked = true; firstSale.checked = true;
const expectedParams = {sales: [firstSale], actualTicketFk: 1}; const expectedParams = {sales: [firstSale], ticketId: 1};
$httpBackend.expect('POST', `Sales/removes`, expectedParams).respond(200); $httpBackend.expect('POST', `Sales/deleteSales`, expectedParams).respond(200);
controller.removeSales(); controller.removeSales();
$httpBackend.flush(); $httpBackend.flush();
@ -300,11 +300,7 @@ describe('Ticket', () => {
const firstSale = controller.sales[0]; const firstSale = controller.sales[0];
firstSale.checked = true; firstSale.checked = true;
const expectedParams = { const expectedParams = {ticketId: 1, sales: [firstSale]};
claim: {ticketFk: 1, clientFk: 101, ticketCreated: 1},
sales: [firstSale]
};
$httpBackend.expect('POST', `Claims/createFromSales`, expectedParams).respond(200, {id: 1}); $httpBackend.expect('POST', `Claims/createFromSales`, expectedParams).respond(200, {id: 1});
controller.createClaim(); controller.createClaim();
$httpBackend.flush(); $httpBackend.flush();
@ -544,7 +540,7 @@ describe('Ticket', () => {
selectedSale.checked = true; selectedSale.checked = true;
const expectedParams = { const expectedParams = {
sales: [selectedSale], sales: [selectedSale],
ticketFk: 1, ticketId: 1,
reserved: false reserved: false
}; };

View File

@ -32,7 +32,7 @@ module.exports = Self => {
zoneFk: id zoneFk: id
}, },
include: { include: {
relation: 'state', relation: 'ticketState',
scope: { scope: {
fields: ['id', 'alertLevel', 'code'] fields: ['id', 'alertLevel', 'code']
} }
@ -49,7 +49,7 @@ module.exports = Self => {
ticketList.forEach(ticket => { ticketList.forEach(ticket => {
promises.push(ticket.updateAttributes({zoneFk: null}, options)); promises.push(ticket.updateAttributes({zoneFk: null}, options));
if (ticket.state().alertLevel == 0 && ticket.shipped >= today) { if (ticket.ticketState().alertLevel == 0 && ticket.shipped >= today) {
promises.push(models.TicketTracking.create({ promises.push(models.TicketTracking.create({
ticketFk: ticket.id, ticketFk: ticket.id,
stateFk: fixingState.id, stateFk: fixingState.id,