Merge pull request '2855-claim_module_backend_transactions' (#587) from 2855-claim_module_backend_transactions into dev
gitea/salix/pipeline/head This commit looks good Details

Reviewed-on: #587
Reviewed-by: Joan Sanchez <joan@verdnatura.es>
This commit is contained in:
Carlos Jimenez Ruiz 2021-03-30 13:17:26 +00:00
commit 9589f2efa7
15 changed files with 528 additions and 331 deletions

View File

@ -20,17 +20,37 @@ module.exports = Self => {
}
});
Self.removeFile = async(ctx, id) => {
const models = Self.app.models;
const dms = await models.Dms.findById(id);
const trashDmsType = await models.DmsType.findOne({
where: {code: 'trash'}
});
Self.removeFile = async(ctx, id, options) => {
let tx;
let myOptions = {};
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dms.dmsTypeFk);
if (!hasWriteRole)
throw new UserError(`You don't have enough privileges`);
if (typeof options == 'object')
Object.assign(myOptions, options);
return dms.updateAttribute('dmsTypeFk', trashDmsType.id);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const models = Self.app.models;
const dms = await models.Dms.findById(id, null, myOptions);
const trashDmsType = await models.DmsType.findOne({
where: {code: 'trash'}
}, myOptions);
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dms.dmsTypeFk, myOptions);
if (!hasWriteRole)
throw new UserError(`You don't have enough privileges`);
await dms.updateAttribute('dmsTypeFk', trashDmsType.id, myOptions);
if (tx) await tx.commit();
return dms;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -3,7 +3,7 @@ module.exports = Self => {
description: 'Returns a list of allowed contentTypes',
accessType: 'READ',
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {

View File

@ -4,12 +4,12 @@ module.exports = Self => {
accessType: 'WRITE',
accepts: {
arg: 'id',
type: 'Number',
type: 'number',
description: 'The document id',
http: {source: 'path'}
},
returns: {
type: 'Object',
type: 'object',
root: true
},
http: {
@ -18,16 +18,36 @@ module.exports = Self => {
}
});
Self.removeFile = async(ctx, id) => {
const models = Self.app.models;
const targetClaimDms = await models.ClaimDms.findById(id);
const targetDms = await models.Dms.findById(targetClaimDms.dmsFk);
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}});
Self.removeFile = async(ctx, id, options) => {
let tx;
let myOptions = {};
await models.Dms.removeFile(ctx, targetClaimDms.dmsFk);
await targetClaimDms.destroy();
if (typeof options == 'object')
Object.assign(myOptions, options);
return targetDms.updateAttribute('dmsTypeFk', trashDmsType.id);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const models = Self.app.models;
const targetClaimDms = await models.ClaimDms.findById(id, null, myOptions);
const targetDms = await models.Dms.findById(targetClaimDms.dmsFk, null, myOptions);
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}}, myOptions);
await models.Dms.removeFile(ctx, targetClaimDms.dmsFk, myOptions);
await targetClaimDms.destroy(myOptions);
await targetDms.updateAttribute('dmsTypeFk', trashDmsType.id, myOptions);
if (tx) await tx.commit();
return targetDms;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -17,24 +17,45 @@ module.exports = Self => {
}
});
Self.importTicketSales = async(ctx, params) => {
Self.importTicketSales = async(ctx, params, options) => {
let models = Self.app.models;
let userId = ctx.req.accessToken.userId;
let worker = await models.Worker.findOne({where: {userFk: userId}});
let ticketSales = await models.Sale.find({
where: {ticketFk: params.ticketFk}
});
let tx;
let myOptions = {};
let claimEnds = [];
ticketSales.forEach(sale => {
claimEnds.push({
saleFk: sale.id,
claimFk: params.claimFk,
workerFk: worker.id
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const worker = await models.Worker.findOne({where: {userFk: userId}}, myOptions);
let ticketSales = await models.Sale.find({
where: {ticketFk: params.ticketFk}
}, myOptions);
let claimEnds = [];
ticketSales.forEach(sale => {
claimEnds.push({
saleFk: sale.id,
claimFk: params.claimFk,
workerFk: worker.id
});
});
});
return await Self.create(claimEnds);
const createdClaimEnds = await Self.create(claimEnds, myOptions);
if (tx) await tx.commit();
return createdClaimEnds;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,25 +1,26 @@
const app = require('vn-loopback/server/server');
describe('Claim importTicketSales()', () => {
let claimEnds;
afterAll(async done => {
claimEnds.forEach(async line => {
await line.destroy();
});
done();
});
it('should import sales to a claim actions from an specific ticket', async() => {
let ctx = {req: {accessToken: {userId: 5}}};
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: 1,
ticketFk: 1
});
const ctx = {req: {accessToken: {userId: 5}}};
expect(claimEnds.length).toEqual(4);
expect(claimEnds[0].saleFk).toEqual(1);
expect(claimEnds[2].saleFk).toEqual(3);
const tx = await app.models.Entry.beginTransaction({});
try {
const options = {transaction: tx};
const claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: 1,
ticketFk: 1
}, options);
expect(claimEnds.length).toEqual(4);
expect(claimEnds[0].saleFk).toEqual(1);
expect(claimEnds[2].saleFk).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -24,15 +24,22 @@ module.exports = Self => {
}
});
Self.createFromSales = async(ctx, ticketId, sales) => {
Self.createFromSales = async(ctx, ticketId, sales, options) => {
let tx;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const tx = await Self.beginTransaction({});
try {
let options = {transaction: tx};
const ticket = await models.Ticket.findById(ticketId, null, options);
const ticket = await models.Ticket.findById(ticketId, null, myOptions);
if (ticket.isDeleted)
throw new UserError(`You can't create a claim for a removed ticket`);
@ -41,7 +48,7 @@ module.exports = Self => {
clientFk: ticket.clientFk,
ticketCreated: ticket.shipped,
workerFk: userId
}, options);
}, myOptions);
const promises = [];
for (const sale of sales) {
@ -49,17 +56,18 @@ module.exports = Self => {
saleFk: sale.id,
claimFk: newClaim.id,
quantity: sale.quantity
}, options);
}, myOptions);
promises.push(newClaimBeginning);
}
await Promise.all(promises);
await tx.commit();
if (tx) await tx.commit();
return newClaim;
} catch (e) {
await tx.rollback();
if (tx) await tx.rollback();
throw e;
}
};

View File

@ -10,58 +10,67 @@ module.exports = Self => {
accepts: [
{
arg: 'filter',
type: 'Object',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
}, {
},
{
arg: 'tags',
type: ['Object'],
type: ['object'],
description: 'List of tags to filter with',
http: {source: 'query'}
}, {
},
{
arg: 'search',
type: 'String',
type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by client name`,
http: {source: 'query'}
}, {
},
{
arg: 'client',
type: 'String',
type: 'string',
description: 'The worker name',
http: {source: 'query'}
}, {
},
{
arg: 'id',
type: 'Integer',
type: 'integer',
description: 'The claim id',
http: {source: 'query'}
}, {
},
{
arg: 'clientFk',
type: 'Integer',
type: 'integer',
description: 'The client id',
http: {source: 'query'}
}, {
},
{
arg: 'claimStateFk',
type: 'Integer',
type: 'integer',
description: 'The claim state id',
http: {source: 'query'}
}, {
},
{
arg: 'salesPersonFk',
type: 'Integer',
type: 'integer',
description: 'The salesPerson id',
http: {source: 'query'}
}, {
},
{
arg: 'attenderFk',
type: 'Integer',
type: 'integer',
description: 'The attender worker id',
http: {source: 'query'}
}, {
},
{
arg: 'created',
type: 'Date',
type: 'date',
description: 'The to date filter',
http: {source: 'query'}
}
],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {

View File

@ -18,32 +18,39 @@ module.exports = Self => {
}
});
Self.regularizeClaim = async(ctx, claimFk) => {
Self.regularizeClaim = async(ctx, claimFk, options) => {
const models = Self.app.models;
const $t = ctx.req.__; // $translate
const resolvedState = 3;
let tx = await Self.beginTransaction({});
try {
let options = {transaction: tx};
let tx;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const claimEnds = await models.ClaimEnd.find({
include: {
relation: 'claimDestination',
fields: ['addressFk']
},
where: {claimFk: claimFk}
}, options);
}, myOptions);
for (let i = 0; i < claimEnds.length; i++) {
const claimEnd = claimEnds[i];
for (let claimEnd of claimEnds) {
const destination = claimEnd.claimDestination();
const sale = await getSale(claimEnd.saleFk, options);
const sale = await getSale(claimEnd.saleFk, myOptions);
const addressId = destination && destination.addressFk;
let address;
if (addressId)
address = await models.Address.findById(addressId, null, options);
address = await models.Address.findById(addressId, null, myOptions);
const salesPerson = sale.ticket().client().salesPersonUser();
if (salesPerson) {
@ -67,7 +74,7 @@ module.exports = Self => {
addressFk: addressId,
companyFk: sale.ticket().companyFk,
warehouseFk: sale.ticket().warehouseFk
}, options);
}, myOptions);
if (!ticketFk) {
ticketFk = await createTicket(ctx, {
@ -75,7 +82,7 @@ module.exports = Self => {
warehouseId: sale.ticket().warehouseFk,
companyId: sale.ticket().companyFk,
addressId: addressId
}, options);
}, myOptions);
}
await models.Sale.create({
@ -85,19 +92,19 @@ module.exports = Self => {
quantity: -sale.quantity,
price: sale.price,
discount: 100
}, options);
}, myOptions);
}
let claim = await Self.findById(claimFk, null, options);
let claim = await Self.findById(claimFk, null, myOptions);
claim = await claim.updateAttributes({
claimStateFk: resolvedState
}, options);
}, myOptions);
await tx.commit();
if (tx) await tx.commit();
return claim;
} catch (e) {
await tx.rollback();
if (tx) await tx.rollback();
throw e;
}
};

View File

@ -10,36 +10,45 @@ describe('Claim createFromSales()', () => {
const ctx = {req: {accessToken: {userId: 1}}};
it('should create a new claim', async() => {
let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
const tx = await app.models.Claim.beginTransaction({});
expect(claim.ticketFk).toEqual(ticketId);
try {
const options = {transaction: tx};
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}});
const claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
expect(claim.ticketFk).toEqual(ticketId);
const createdClaimId = claim.id;
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}}, options);
// restores
await app.models.Claim.destroyById(createdClaimId);
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should not be able to create a claim if exists that sale', async() => {
let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
const createdClaimId = claim.id;
const tx = await app.models.Claim.beginTransaction({});
let error;
await app.models.Claim.createFromSales(ctx, ticketId, newSale)
try {
const options = {transaction: tx};
.catch(e => {
error = e;
});
await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error.toString()).toContain(`A claim with that sale already exists`);
// restores
await app.models.Claim.destroyById(createdClaimId);
});
});

View File

@ -21,81 +21,94 @@ describe('regularizeClaim()', () => {
let claimEnds = [];
let trashTicket;
afterEach(async done => {
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
const tx = await app.models.Claim.beginTransaction({});
try {
let claim = await app.models.Claim.findById(claimFk);
await claim.updateAttributes({
claimStateFk: pendentState,
hasToPickUp: false
});
const options = {transaction: tx};
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
}, options);
for (claimEnd of claimEnds)
await claimEnd.destroy();
await claimEnd.updateAttributes({claimDestinationFk: trashDestination}, options);
if (trashTicket)
await app.models.Ticket.destroyById(trashTicket.id);
} catch (error) {
console.error(error);
let claimBefore = await app.models.Claim.findById(claimFk, null, options);
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
let claimAfter = await app.models.Claim.findById(claimFk, null, options);
trashTicket = await app.models.Ticket.findOne({where: {addressFk: 12}}, options);
expect(trashTicket.addressFk).toEqual(trashAddress);
expect(claimBefore.claimStateFk).toEqual(pendentState);
expect(claimAfter.claimStateFk).toEqual(resolvedState);
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Trash');
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
done();
});
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
});
for (claimEnd of claimEnds)
await claimEnd.updateAttributes({claimDestinationFk: trashDestination});
let claimBefore = await app.models.Claim.findById(claimFk);
await app.models.Claim.regularizeClaim(ctx, claimFk);
let claimAfter = await app.models.Claim.findById(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);
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Trash');
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
});
it('should send a chat message with value "Bueno" and then change claim state to resolved', async() => {
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
const tx = await app.models.Claim.beginTransaction({});
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
});
try {
const options = {transaction: tx};
for (claimEnd of claimEnds)
await claimEnd.updateAttributes({claimDestinationFk: okDestination});
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
await app.models.Claim.regularizeClaim(ctx, claimFk);
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
}, options);
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
for (claimEnd of claimEnds)
await claimEnd.updateAttributes({claimDestinationFk: okDestination}, options);
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should send a chat message to the salesPerson when claim isPickUp is enabled', async() => {
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
const tx = await app.models.Claim.beginTransaction({});
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
});
try {
const options = {transaction: tx};
for (claimEnd of claimEnds)
await claimEnd.updateAttributes({claimDestinationFk: okDestination});
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
await app.models.Claim.regularizeClaim(ctx, claimFk);
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: claimFk,
ticketFk: 1
}, options);
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
for (claimEnd of claimEnds)
await claimEnd.updateAttributes({claimDestinationFk: okDestination}, options);
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,7 +1,7 @@
const app = require('vn-loopback/server/server');
describe('Update Claim', () => {
let newDate = new Date();
const newDate = new Date();
const originalData = {
ticketFk: 3,
clientFk: 101,
@ -14,89 +14,114 @@ describe('Update Claim', () => {
};
it(`should throw an error as the user doesn't have rights`, async() => {
let newClaim = await app.models.Claim.create(originalData);
const forbiddenState = 3;
const salesPersonId = 18;
const ctx = {
req: {
accessToken: {
userId: salesPersonId
const tx = await app.models.Claim.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const newClaim = await app.models.Claim.create(originalData, options);
const forbiddenState = 3;
const salesPersonId = 18;
const ctx = {
req: {
accessToken: {
userId: salesPersonId
}
},
args: {
claimStateFk: forbiddenState,
observation: 'valid observation'
}
},
args: {
claimStateFk: forbiddenState,
observation: 'valid observation'
}
};
await app.models.Claim.updateClaim(ctx, newClaim.id)
.catch(e => {
error = e;
});
};
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error.message).toEqual(`You don't have enough privileges to change that field`);
// restores
await app.models.Claim.destroyById(newClaim.id);
});
it(`should success to update the claim within privileges `, async() => {
let newClaim = await app.models.Claim.create(originalData);
const tx = await app.models.Claim.beginTransaction({});
const canceledState = 4;
const claimManagerId = 72;
const ctx = {
req: {
accessToken: {
userId: claimManagerId
try {
const options = {transaction: tx};
const newClaim = await app.models.Claim.create(originalData, options);
const canceledState = 4;
const claimManagerId = 72;
const ctx = {
req: {
accessToken: {
userId: claimManagerId
}
},
args: {
observation: 'valid observation',
claimStateFk: canceledState,
hasToPickUp: false
}
},
args: {
observation: 'valid observation',
claimStateFk: canceledState,
hasToPickUp: false
}
};
await app.models.Claim.updateClaim(ctx, newClaim.id);
};
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
let updatedClaim = await app.models.Claim.findById(newClaim.id);
let updatedClaim = await app.models.Claim.findById(newClaim.id, null, options);
expect(updatedClaim.observation).toEqual(ctx.args.observation);
expect(updatedClaim.observation).toEqual(ctx.args.observation);
// restores
await app.models.Claim.destroyById(newClaim.id);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should change some sensible fields as claimManager', async() => {
let newClaim = await app.models.Claim.create(originalData);
const chatModel = app.models.Chat;
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
const tx = await app.models.Claim.beginTransaction({});
const claimManagerId = 72;
const ctx = {
req: {
accessToken: {userId: claimManagerId},
headers: {origin: 'http://localhost'}
},
args: {
claimStateFk: 3,
workerFk: 5,
observation: 'another valid observation',
hasToPickUp: true
}
};
ctx.req.__ = (value, params) => {
return params.nickname;
};
await app.models.Claim.updateClaim(ctx, newClaim.id);
try {
const options = {transaction: tx};
let updatedClaim = await app.models.Claim.findById(newClaim.id);
const newClaim = await app.models.Claim.create(originalData, options);
expect(updatedClaim.observation).toEqual(ctx.args.observation);
expect(updatedClaim.claimStateFk).toEqual(ctx.args.claimStateFk);
expect(updatedClaim.workerFk).toEqual(ctx.args.workerFk);
expect(chatModel.sendCheckingPresence).toHaveBeenCalled();
const chatModel = app.models.Chat;
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
// restores
await app.models.Claim.destroyById(newClaim.id);
const claimManagerId = 72;
const ctx = {
req: {
accessToken: {userId: claimManagerId},
headers: {origin: 'http://localhost'}
},
args: {
claimStateFk: 3,
workerFk: 5,
observation: 'another valid observation',
hasToPickUp: true
}
};
ctx.req.__ = (value, params) => {
return params.nickname;
};
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
let updatedClaim = await app.models.Claim.findById(newClaim.id, null, options);
expect(updatedClaim.observation).toEqual(ctx.args.observation);
expect(updatedClaim.claimStateFk).toEqual(ctx.args.claimStateFk);
expect(updatedClaim.workerFk).toEqual(ctx.args.workerFk);
expect(chatModel.sendCheckingPresence).toHaveBeenCalled();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,9 +1,8 @@
const app = require('vn-loopback/server/server');
describe('Update Claim', () => {
let newDate = new Date();
let newInstance;
let original = {
const newDate = new Date();
const original = {
ticketFk: 3,
clientFk: 101,
ticketCreated: newDate,
@ -14,30 +13,43 @@ describe('Update Claim', () => {
observation: 'observation'
};
beforeAll(async done => {
newInstance = await app.models.Claim.create(original);
done();
});
afterAll(async done => {
await app.models.Claim.destroyById(newInstance.id);
done();
});
it('should update the claim isChargedToMana attribute', async() => {
const ctx = {args: {isChargedToMana: false}};
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id);
const tx = await app.models.Claim.beginTransaction({});
expect(result.id).toEqual(newInstance.id);
expect(result.isChargedToMana).toBeFalsy();
try {
const options = {transaction: tx};
const ctx = {args: {isChargedToMana: false}};
const newInstance = await app.models.Claim.create(original, options);
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id, options);
expect(result.id).toEqual(newInstance.id);
expect(result.isChargedToMana).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should update the claim responsibility attribute', async() => {
const ctx = {args: {responsibility: 2}};
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id);
const tx = await app.models.Claim.beginTransaction({});
expect(result.id).toEqual(newInstance.id);
expect(result.responsibility).toEqual(2);
try {
const options = {transaction: tx};
const ctx = {args: {responsibility: 2}};
const newInstance = await app.models.Claim.create(original, options);
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id, options);
expect(result.id).toEqual(newInstance.id);
expect(result.responsibility).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -4,25 +4,26 @@ module.exports = Self => {
description: 'Update a claim with privileges',
accepts: [{
arg: 'ctx',
type: 'Object',
type: 'object',
http: {source: 'context'}
}, {
},
{
arg: 'id',
type: 'Number',
type: 'number',
description: 'Claim id',
http: {source: 'path'}
},
{
arg: 'workerFk',
type: 'Number'
type: 'number'
},
{
arg: 'claimStateFk',
type: 'Number'
type: 'number'
},
{
arg: 'observation',
type: 'String'
type: 'string'
},
{
arg: 'hasToPickUp',
@ -38,51 +39,69 @@ module.exports = Self => {
}
});
Self.updateClaim = async(ctx, id) => {
Self.updateClaim = async(ctx, id, options) => {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const args = ctx.args;
const $t = ctx.req.__; // $translate
const claim = await models.Claim.findById(id, {
include: {
relation: 'client',
scope: {
include: {
relation: 'salesPersonUser'
let tx;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const claim = await models.Claim.findById(id, {
include: {
relation: 'client',
scope: {
include: {
relation: 'salesPersonUser'
}
}
}
}, myOptions);
let changedHasToPickUp = false;
if (args.hasToPickUp)
changedHasToPickUp = true;
if (args.claimStateFk) {
const canUpdate = await canChangeState(ctx, claim.claimStateFk, myOptions);
const hasRights = await canChangeState(ctx, args.claimStateFk, myOptions);
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
throw new UserError(`You don't have enough privileges to change that field`);
}
delete args.ctx;
const updatedClaim = await claim.updateAttributes(args, myOptions);
// Get sales person from claim client
const salesPerson = claim.client().salesPersonUser();
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) {
const origin = ctx.req.headers.origin;
const message = $t('Claim will be picked', {
claimId: claim.id,
clientName: claim.client().name,
claimUrl: `${origin}/#!/claim/${claim.id}/summary`
});
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
}
});
let changedHasToPickUp = false;
if (args.hasToPickUp)
changedHasToPickUp = true;
if (args.claimStateFk) {
const canUpdate = await canChangeState(ctx, claim.claimStateFk);
const hasRights = await canChangeState(ctx, args.claimStateFk);
const isClaimManager = await models.Account.hasRole(userId, 'claimManager');
if (tx) await tx.commit();
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
throw new UserError(`You don't have enough privileges to change that field`);
return updatedClaim;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
delete args.ctx;
const updatedClaim = await claim.updateAttributes(args);
// Get sales person from claim client
const salesPerson = claim.client().salesPersonUser();
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) {
const origin = ctx.req.headers.origin;
const message = $t('Claim will be picked', {
claimId: claim.id,
clientName: claim.client().name,
claimUrl: `${origin}/#!/claim/${claim.id}/summary`
});
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
}
return updatedClaim;
};
async function canChangeState(ctx, id) {
async function canChangeState(ctx, id, options) {
let models = Self.app.models;
let userId = ctx.req.accessToken.userId;
@ -90,9 +109,9 @@ module.exports = Self => {
include: {
relation: 'writeRole'
}
});
}, options);
let stateRole = state.writeRole().name;
let canUpdate = await models.Account.hasRole(userId, stateRole);
let canUpdate = await models.Account.hasRole(userId, stateRole, options);
return canUpdate;
}

View File

@ -28,12 +28,32 @@ module.exports = Self => {
}
});
Self.updateClaimAction = async(ctx, id) => {
const models = Self.app.models;
const claim = await models.Claim.findById(id);
const args = ctx.args;
delete args.ctx;
Self.updateClaimAction = async(ctx, id, options) => {
let tx;
let myOptions = {};
return await claim.updateAttributes(args);
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const models = Self.app.models;
const claim = await models.Claim.findById(id, null, myOptions);
const args = ctx.args;
delete args.ctx;
const updatedClaim = await claim.updateAttributes(args, myOptions);
if (tx) await tx.commit();
return updatedClaim;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -4,40 +4,46 @@ module.exports = Self => {
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Number',
type: 'number',
description: 'The claim id',
http: {source: 'path'}
}, {
},
{
arg: 'warehouseId',
type: 'Number',
type: 'number',
description: 'The warehouse id',
required: true
}, {
},
{
arg: 'companyId',
type: 'Number',
type: 'number',
description: 'The company id',
required: true
}, {
},
{
arg: 'dmsTypeId',
type: 'Number',
type: 'number',
description: 'The dms type id',
required: true
}, {
},
{
arg: 'reference',
type: 'String',
type: 'string',
required: true
}, {
},
{
arg: 'description',
type: 'String',
type: 'string',
required: true
}, {
},
{
arg: 'hasFile',
type: 'Boolean',
type: 'boolean',
description: 'True if has an attached file',
required: true
}],
returns: {
type: 'Object',
type: 'object',
root: true
},
http: {
@ -46,31 +52,38 @@ module.exports = Self => {
}
});
Self.uploadFile = async(ctx, id) => {
Self.uploadFile = async(ctx, id, options) => {
let tx;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const models = Self.app.models;
const promises = [];
const tx = await Self.beginTransaction({});
try {
const options = {transaction: tx};
const uploadedFiles = await models.Dms.uploadFile(ctx, options);
const uploadedFiles = await models.Dms.uploadFile(ctx, myOptions);
uploadedFiles.forEach(dms => {
const newClaimDms = models.ClaimDms.create({
claimFk: id,
dmsFk: dms.id
}, options);
}, myOptions);
promises.push(newClaimDms);
});
const resolvedPromises = await Promise.all(promises);
await tx.commit();
if (tx) await tx.commit();
return resolvedPromises;
} catch (err) {
await tx.rollback();
throw err;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};