more module transactions
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2021-08-13 16:46:44 +02:00
parent cd334bf967
commit 7a7bbe2ba8
8 changed files with 257 additions and 228 deletions

View File

@ -77,12 +77,13 @@ module.exports = Self => {
}, myOptions); }, myOptions);
if (!ticketFk) { if (!ticketFk) {
ticketFk = await createTicket(ctx, { ctx.args = {
clientId: address.clientFk, clientId: address.clientFk,
warehouseId: sale.ticket().warehouseFk, warehouseId: sale.ticket().warehouseFk,
companyId: sale.ticket().companyFk, companyId: sale.ticket().companyFk,
addressId: addressId addressId: addressId
}, myOptions); };
ticketFk = await createTicket(ctx, myOptions);
} }
await models.Sale.create({ await models.Sale.create({
@ -153,22 +154,13 @@ module.exports = Self => {
return ticket && ticket.id; return ticket && ticket.id;
} }
async function createTicket(ctx, params, options) { async function createTicket(ctx, options) {
params.shipped = new Date(); ctx.args.shipped = new Date();
params.landed = new Date(); ctx.args.landed = new Date();
params.agencyModeId = null; ctx.args.agencyModeId = null;
params.routeId = null; ctx.args.routeId = null;
const ticket = await Self.app.models.Ticket.new(ctx, const ticket = await Self.app.models.Ticket.new(ctx, options);
params.clientId,
params.shipped,
params.landed,
params.warehouseId,
params.companyId,
params.addressId,
params.agencyModeId,
params.routeId,
options);
return ticket.id; return ticket.id;
} }

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('regularizeClaim()', () => { describe('claim regularizeClaim()', () => {
const ctx = { const ctx = {
req: { req: {
accessToken: {userId: 18}, accessToken: {userId: 18},

View File

@ -65,16 +65,17 @@ module.exports = Self => {
}, myOptions); }, myOptions);
if (!ticketId) { if (!ticketId) {
ticketId = await createTicket(ctx, { ctx.args = {
clientId: itemDestination.address().clientFk, clientId: itemDestination.address().clientFk,
warehouseId: warehouseFk, warehouseId: warehouseFk,
addressId: itemDestination.addressFk addressId: itemDestination.addressFk
}, myOptions); };
ticketId = await createTicket(ctx, myOptions);
} }
res = await models.Item.getVisibleAvailable(itemFk, warehouseFk); const res = await models.Item.getVisibleAvailable(itemFk, warehouseFk, null, myOptions);
let newQuantity = res.visible - quantity; const newQuantity = res.visible - quantity;
await models.Sale.create({ await models.Sale.create({
ticketFk: ticketId, ticketFk: ticketId,
@ -92,23 +93,14 @@ module.exports = Self => {
throw e; throw e;
} }
async function createTicket(ctx, params, options) { async function createTicket(ctx, options) {
params.shipped = new Date(); ctx.args.shipped = new Date();
params.landed = new Date(); ctx.args.landed = new Date();
params.companyId = null; ctx.args.companyId = null;
params.agencyModeId = null; ctx.args.agencyModeId = null;
params.routeId = null; ctx.args.routeId = null;
const ticket = await Self.app.models.Ticket.new(ctx, const ticket = await Self.app.models.Ticket.new(ctx, options);
params.clientId,
params.shipped,
params.landed,
params.warehouseId,
params.companyId,
params.addressId,
params.agencyModeId,
params.routeId,
options);
return ticket.id; return ticket.id;
} }

View File

@ -57,77 +57,78 @@ module.exports = Self => {
} }
}); });
Self.new = async(ctx, clientId, shipped, landed, warehouseId, Self.new = async(ctx, options) => {
companyId, addressId, agencyModeId, routeId, options) => { const args = ctx.args;
const myUserId = ctx.req.accessToken.userId; const myUserId = ctx.req.accessToken.userId;
const models = Self.app.models; const models = Self.app.models;
const address = await models.Address.findOne({ const myOptions = {};
where: {id: addressId},
fields: ['id', 'clientFk'],
include: {
relation: 'client',
scope: {
include: {
relation: 'type'
}
}
}
});
if (!address)
throw new UserError(`This address doesn't exist`);
let agencyMode;
if (agencyModeId)
agencyMode = await models.AgencyMode.findById(agencyModeId);
if (address.client().type().code === 'normal' && (!agencyMode || agencyMode.code != 'refund')) {
const canCreateTicket = await models.Client.canCreateTicket(clientId);
if (!canCreateTicket)
throw new UserError(`You can't create a ticket for a inactive client`);
}
let tx; let tx;
if ((typeof options) != 'object') if (typeof options == 'object')
options = {}; Object.assign(myOptions, options);
if (!options.transaction) { if (!myOptions.transaction) {
tx = await Self.beginTransaction({}); tx = await Self.beginTransaction({});
options.transaction = tx; myOptions.transaction = tx;
} }
try { try {
if (!shipped && landed) { const address = await models.Address.findOne({
const shippedResult = await models.Agency.getShipped(landed, where: {id: args.addressId},
address.id, agencyModeId, warehouseId); fields: ['id', 'clientFk'],
shipped = (shippedResult && shippedResult.shipped) || landed; include: {
relation: 'client',
scope: {
include: {
relation: 'type'
}
}
}
}, myOptions);
if (!address)
throw new UserError(`This address doesn't exist`);
let agencyMode;
if (args.agencyModeId)
agencyMode = await models.AgencyMode.findById(args.agencyModeId, null, myOptions);
if (address.client().type().code === 'normal' && (!agencyMode || agencyMode.code != 'refund')) {
const canCreateTicket = await models.Client.canCreateTicket(args.clientId, myOptions);
if (!canCreateTicket)
throw new UserError(`You can't create a ticket for a inactive client`);
} }
if (shipped && !landed) { if (!args.shipped && args.landed) {
const landedResult = await models.Agency.getLanded(shipped, const shippedResult = await models.Agency.getShipped(args.landed,
address.id, agencyModeId, warehouseId, false); address.id, args.agencyModeId, args.warehouseId, myOptions);
landed = landedResult && landedResult.landed; args.shipped = (shippedResult && shippedResult.shipped) || args.landed;
}
if (args.shipped && !args.landed) {
const landedResult = await models.Agency.getLanded(args.shipped,
address.id, args.agencyModeId, args.warehouseId, false, myOptions);
args.landed = landedResult && landedResult.landed;
} }
query = `CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result); query = `CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result);
SELECT @result newTicketId;`; SELECT @result newTicketId;`;
let result = await Self.rawSql(query, [ const result = await Self.rawSql(query, [
clientId, args.clientId,
shipped, args.shipped,
warehouseId, args.warehouseId,
companyId || 442, args.companyId || 442,
addressId, args.addressId,
agencyModeId || null, args.agencyModeId || null,
routeId || null, args.routeId || null,
landed, args.landed,
myUserId myUserId
], options); ], myOptions);
let ticket = await models.Ticket.findById(result[1][0].newTicketId, null, options); const ticket = await models.Ticket.findById(result[1][0].newTicketId, null, myOptions);
let cleanInstance = JSON.parse(JSON.stringify(ticket)); const cleanInstance = JSON.parse(JSON.stringify(ticket));
let logRecord = { const logRecord = {
originFk: cleanInstance.id, originFk: cleanInstance.id,
userFk: myUserId, userFk: myUserId,
action: 'insert', action: 'insert',
@ -137,9 +138,10 @@ module.exports = Self => {
newInstance: cleanInstance newInstance: cleanInstance
}; };
await models.TicketLog.create(logRecord, options); await models.TicketLog.create(logRecord, myOptions);
if (tx) await tx.commit(); if (tx) await tx.commit();
return await ticket; return await ticket;
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();

View File

@ -6,43 +6,43 @@ module.exports = Self => {
accessType: 'READ', accessType: 'READ',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
required: true, required: true,
description: 'The ticket id', description: 'The ticket id',
http: {source: 'path'} http: {source: 'path'}
}, },
{ {
arg: 'landed', arg: 'landed',
type: 'Date', type: 'date',
description: 'The landing date', description: 'The landing date',
required: true required: true
}, },
{ {
arg: 'addressId', arg: 'addressId',
type: 'Number', type: 'number',
description: 'The address id', description: 'The address id',
required: true required: true
}, },
{ {
arg: 'agencyModeId', arg: 'agencyModeId',
type: 'Number', type: 'number',
description: 'The agencyMode id', description: 'The agencyMode id',
required: true required: true
}, },
{ {
arg: 'zoneId', arg: 'zoneId',
type: 'Number', type: 'number',
description: 'The zone id', description: 'The zone id',
required: true required: true
}, },
{ {
arg: 'warehouseId', arg: 'warehouseId',
type: 'Number', type: 'number',
description: 'The warehouse id', description: 'The warehouse id',
required: true required: true
}], }],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -51,38 +51,57 @@ module.exports = Self => {
} }
}); });
Self.priceDifference = async(ctx, id, landed, addressId, agencyModeId, zoneId, warehouseId) => { Self.priceDifference = async(ctx, options) => {
const args = ctx.args;
const models = Self.app.models; const models = Self.app.models;
const isEditable = await Self.isEditable(ctx, id);
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const isEditable = await Self.isEditable(ctx, args.id, myOptions);
if (!isEditable) if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss'); const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss', myOptions);
if (!isProductionBoss) { if (!isProductionBoss) {
const zoneShipped = await models.Agency.getShipped(landed, addressId, agencyModeId, warehouseId); const zoneShipped = await models.Agency.getShipped(
args.landed,
args.addressId,
args.agencyModeId,
args.warehouseId,
myOptions);
if (!zoneShipped || zoneShipped.zoneFk != zoneId) if (!zoneShipped || zoneShipped.zoneFk != args.zoneId)
throw new UserError(`You don't have privileges to change the zone`); throw new UserError(`You don't have privileges to change the zone`);
} }
let salesObj = { const items = await models.Sale.find({
items: await models.Sale.find({ where: {
where: { ticketFk: args.id
ticketFk: id },
}, order: 'concept ASC',
order: 'concept ASC', include: 'item'
include: 'item' }, myOptions);
}),
const salesObj = {
items: items,
totalUnitPrice: 0.00, totalUnitPrice: 0.00,
totalNewPrice: 0.00, totalNewPrice: 0.00,
totalDifference: 0.00, totalDifference: 0.00,
}; };
const query = `CALL vn.ticket_priceDifference(?, ?, ?, ?, ?)`; const query = `CALL vn.ticket_priceDifference(?, ?, ?, ?, ?)`;
const args = [id, landed, addressId, zoneId, warehouseId]; const params = [args.id, args.landed, args.addressId, args.zoneId, args.warehouseId];
const [difComponents] = await Self.rawSql(query, args); const [difComponents] = await Self.rawSql(query, params, myOptions);
const map = new Map(); const map = new Map();

View File

@ -1,118 +1,119 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
let UserError = require('vn-loopback/util/user-error'); let UserError = require('vn-loopback/util/user-error');
describe('ticket new()', () => { describe('ticket new()', () => {
let ticketIdsToDelete = []; const today = new Date();
let today = new Date(); const ctx = {req: {accessToken: {userId: 1}}};
let ctx = {req: {accessToken: {userId: 1}}};
afterAll(async done => {
for (id of ticketIdsToDelete)
await app.models.Ticket.destroyById(id);
done();
});
it('should throw an error if the client isnt frozen and isnt active', async() => { it('should throw an error if the client isnt frozen and isnt active', async() => {
let error; const tx = await models.Ticket.beginTransaction({});
let params = {
clientId: 1106,
shipped: today,
landed: null,
warehouseId: 1,
companyId: 442,
addressId: 6
};
await app.models.Ticket.new(ctx, let error;
params.clientId,
params.shipped, try {
params.landed, const options = {transaction: tx};
params.warehouseId,
params.companyId, ctx.args = {
params.addressId clientId: 1106,
).catch(e => { shipped: today,
landed: null,
warehouseId: 1,
companyId: 442,
addressId: 6
};
await models.Ticket.new(ctx, options);
await tx.rollback();
} catch (e) {
error = e; error = e;
}); await tx.rollback();
}
expect(error).toEqual(new UserError(`You can't create a ticket for a inactive client`)); expect(error).toEqual(new UserError(`You can't create a ticket for a inactive client`));
}); });
it('should throw an error if the address doesnt exist', async() => { it('should throw an error if the address doesnt exist', async() => {
const tx = await models.Ticket.beginTransaction({});
let error; let error;
let params = {
clientId: 1104,
shipped: today,
landed: null,
warehouseId: 1,
companyId: 442,
addressId: 'invalid address'
};
await app.models.Ticket.new(ctx, try {
params.clientId, const options = {transaction: tx};
params.shipped,
params.landed,
params.warehouseId,
params.companyId,
params.addressId
).catch(response => {
expect(response.message).toEqual(`This address doesn't exist`);
error = response;
});
expect(error).toBeDefined(); ctx.args = {
clientId: 1104,
shipped: today,
landed: null,
warehouseId: 1,
companyId: 442,
addressId: 'invalid address'
};
await models.Ticket.new(ctx, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error.message).toEqual(`This address doesn't exist`);
}); });
it('should return the id of the created ticket', async() => { it('should return the id of the created ticket', async() => {
let params = { const tx = await models.Ticket.beginTransaction({});
clientId: 1104,
shipped: today,
landed: today,
warehouseId: 2,
companyId: 442,
addressId: 4,
agencyModeId: 1
};
const ticket = await app.models.Ticket.new(ctx, try {
params.clientId, const options = {transaction: tx};
params.shipped,
params.landed,
params.warehouseId,
params.companyId,
params.addressId,
params.agencyModeId);
let newestTicketIdInFixtures = 21; ctx.args = {
clientId: 1104,
shipped: today,
landed: today,
warehouseId: 2,
companyId: 442,
addressId: 4,
agencyModeId: 1
};
ticketIdsToDelete.push(ticket.id); const ticket = await models.Ticket.new(ctx, options);
expect(ticket.id).toBeGreaterThan(newestTicketIdInFixtures); const newestTicketIdInFixtures = 21;
expect(ticket.id).toBeGreaterThan(newestTicketIdInFixtures);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return the set a shipped when the agency is not especified', async() => { it('should return the set a shipped when the agency is not especified', async() => {
let params = { const tx = await models.Ticket.beginTransaction({});
clientId: 1104,
landed: today,
shipped: null,
warehouseId: 2,
companyId: 442,
addressId: 4,
agencyModeId: null
};
const ticket = await app.models.Ticket.new(ctx, try {
params.clientId, const options = {transaction: tx};
params.shipped,
params.landed,
params.warehouseId,
params.companyId,
params.addressId,
params.agencyModeId);
ticketIdsToDelete.push(ticket.id); ctx.args = {
clientId: 1104,
landed: today,
shipped: null,
warehouseId: 2,
companyId: 442,
addressId: 4,
agencyModeId: null
};
expect(ticket.shipped).toEqual(jasmine.any(Date)); const ticket = await models.Ticket.new(ctx, options);
expect(ticket.shipped).toEqual(jasmine.any(Date));
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,38 +1,61 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
let UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
describe('sale priceDifference()', () => { describe('sale priceDifference()', () => {
it('should return ticket price differences', async() => { it('should return ticket price differences', async() => {
let tomorrow = new Date(); const tx = await models.Ticket.beginTransaction({});
tomorrow.setDate(tomorrow.getDate() + 1);
const ticketId = 16; try {
const landed = tomorrow; const options = {transaction: tx};
const addressId = 126;
const agencyModeId = 7;
const zoneId = 3;
const warehouseId = 1;
const httpCtx = {req: {accessToken: {userId: 1106}}}; const tomorrow = new Date();
let result = await app.models.Ticket.priceDifference(httpCtx, ticketId, landed, tomorrow.setDate(tomorrow.getDate() + 1);
addressId, agencyModeId, zoneId, warehouseId);
expect(result.totalUnitPrice).toEqual(result.totalNewPrice); const ctx = {req: {accessToken: {userId: 1106}}};
expect(result.totalDifference).toEqual(0); ctx.args = {
id: 16,
landed: tomorrow,
addressId: 126,
agencyModeId: 7,
zoneId: 3,
warehouseId: 1
};
const result = await models.Ticket.priceDifference(ctx, options);
expect(result.totalUnitPrice).toEqual(result.totalNewPrice);
expect(result.totalDifference).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return an error if the ticket is not editable', async() => { it('should return an error if the ticket is not editable', async() => {
const ticketId = 1; const tx = await models.Ticket.beginTransaction({});
const landed = new Date();
const addressId = 121;
const zoneId = 3;
const warehouseId = 1;
let error; let error;
const httpCtx = {req: {accessToken: {userId: 1106}}};
await app.models.Ticket.priceDifference(httpCtx, ticketId, landed, addressId, zoneId, warehouseId) try {
.catch(e => { const options = {transaction: tx};
error = e;
}); const ctx = {req: {accessToken: {userId: 1106}}};
ctx.args = {
id: 1,
landed: new Date(),
addressId: 121,
zoneId: 3,
warehouseId: 1
};
await models.Ticket.priceDifference(ctx, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error).toEqual(new UserError(`The sales of this ticket can't be modified`)); expect(error).toEqual(new UserError(`The sales of this ticket can't be modified`));
}); });

View File

@ -35,7 +35,7 @@ module.exports = Self => {
}); });
Self.getShipped = async(landed, addressFk, agencyModeFk, warehouseFk, options) => { Self.getShipped = async(landed, addressFk, agencyModeFk, warehouseFk, options) => {
let myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);