Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 6942-improveInvoiceIn
gitea/salix/pipeline/pr-dev This commit looks good
Details
gitea/salix/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
b0814304aa
|
@ -0,0 +1,31 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('assign', {
|
||||||
|
description: 'Assign a collection',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
http: {
|
||||||
|
path: `/assign`,
|
||||||
|
verb: 'POST'
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.assign = async(ctx, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const [,, {collectionFk}] = await Self.rawSql('CALL vn.collection_assign(?, @vCollectionFk); SELECT @vCollectionFk collectionFk',
|
||||||
|
[userId], myOptions);
|
||||||
|
|
||||||
|
if (!collectionFk) throw new UserError('There are not picking tickets');
|
||||||
|
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
||||||
|
|
||||||
|
return collectionFk;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,157 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('getSales', {
|
||||||
|
description: 'Get sales from ticket or collection',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'collectionOrTicketFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'print',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'source',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getSales`,
|
||||||
|
verb: 'GET'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getSales = async(ctx, collectionOrTicketFk, print, source, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
const $t = ctx.req.__;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const [{id}] = await Self.rawSql('SELECT vn.ticket_get(?) as id',
|
||||||
|
[collectionOrTicketFk],
|
||||||
|
myOptions);
|
||||||
|
|
||||||
|
const [tickets] = await Self.rawSql('CALL vn.collection_getTickets(?)', [id], myOptions);
|
||||||
|
|
||||||
|
if (source) {
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL vn.ticketStateToday_setState(?,?)', [id, source], myOptions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [sales] = await Self.rawSql('CALL vn.sale_getFromTicketOrCollection(?)',
|
||||||
|
[id], myOptions);
|
||||||
|
|
||||||
|
const isPicker = source != 'CHECKER';
|
||||||
|
const [placements] = await Self.rawSql('CALL vn.collectionPlacement_get(?, ?)',
|
||||||
|
[id, isPicker], myOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
if (print) await Self.rawSql('CALL vn.collection_printSticker(?,NULL)', [id], myOptions);
|
||||||
|
|
||||||
|
for (let ticket of tickets) {
|
||||||
|
let observations = ticket.observaciones.split(' ');
|
||||||
|
|
||||||
|
for (let observation of observations) {
|
||||||
|
const salesPerson = ticket.salesPersonFk;
|
||||||
|
if (observation.startsWith('#') || observation.startsWith('@')) {
|
||||||
|
await models.Chat.send(ctx,
|
||||||
|
observation,
|
||||||
|
$t('ticketCommercial', {ticket: ticket.ticketFk, salesPerson})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCollection(id, tickets, sales, placements, myOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getCollection(id, tickets, sales, placements, options) {
|
||||||
|
const collection = {
|
||||||
|
collectionFk: id,
|
||||||
|
tickets: [],
|
||||||
|
};
|
||||||
|
for (let ticket of tickets) {
|
||||||
|
const {ticketFk} = ticket;
|
||||||
|
ticket.sales = [];
|
||||||
|
|
||||||
|
const barcodes = await getBarcodes(ticketFk, options);
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL util.log_add(?, ?, ?, ?, ?, ?, ?, ?)',
|
||||||
|
['vn', 'ticket', 'Ticket', ticketFk, ticketFk, 'select', null, null],
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let sale of sales) {
|
||||||
|
if (sale.ticketFk == ticketFk) {
|
||||||
|
sale.placements = [];
|
||||||
|
for (const salePlacement of placements) {
|
||||||
|
if (salePlacement.saleFk == sale.saleFk && salePlacement.order) {
|
||||||
|
const placement = {
|
||||||
|
saleFk: salePlacement.saleFk,
|
||||||
|
itemFk: salePlacement.itemFk,
|
||||||
|
placement: salePlacement.placement,
|
||||||
|
shelving: salePlacement.shelving,
|
||||||
|
created: salePlacement.created,
|
||||||
|
visible: salePlacement.visible,
|
||||||
|
order: salePlacement.order,
|
||||||
|
grouping: salePlacement.grouping,
|
||||||
|
priority: salePlacement.priority,
|
||||||
|
saleOrder: salePlacement.saleOrder,
|
||||||
|
isPreviousPrepared: salePlacement.isPreviousPrepared,
|
||||||
|
itemShelvingSaleFk: salePlacement.itemShelvingSaleFk,
|
||||||
|
ticketFk: salePlacement.ticketFk,
|
||||||
|
id: salePlacement.id
|
||||||
|
};
|
||||||
|
sale.placements.push(placement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sale.barcodes = [];
|
||||||
|
for (const barcode of barcodes) {
|
||||||
|
if (barcode.movementId == sale.saleFk) {
|
||||||
|
if (barcode.code) {
|
||||||
|
sale.barcodes.push(barcode.code);
|
||||||
|
sale.barcodes.push(`0 ${barcode.code}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (barcode.id) {
|
||||||
|
sale.barcodes.push(barcode.id);
|
||||||
|
sale.barcodes.push(`0 ${barcode.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ticket.sales.push(sale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collection.tickets.push(ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getBarcodes(ticketId, options) {
|
||||||
|
const query =
|
||||||
|
`SELECT s.id movementId,
|
||||||
|
b.code,
|
||||||
|
c.id
|
||||||
|
FROM vn.sale s
|
||||||
|
LEFT JOIN vn.itemBarcode b ON b.itemFk = s.itemFk
|
||||||
|
LEFT JOIN vn.buy c ON c.itemFk = s.itemFk
|
||||||
|
LEFT JOIN vn.entry e ON e.id = c.entryFk
|
||||||
|
LEFT JOIN vn.travel tr ON tr.id = e.travelFk
|
||||||
|
WHERE s.ticketFk = ?
|
||||||
|
AND tr.landed >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)`;
|
||||||
|
return Self.rawSql(query, [ticketId], options);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('ticket assign()', () => {
|
||||||
|
let ctx;
|
||||||
|
let options;
|
||||||
|
let tx;
|
||||||
|
beforeEach(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: 1106},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
__: value => value
|
||||||
|
},
|
||||||
|
args: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: ctx.req
|
||||||
|
});
|
||||||
|
|
||||||
|
options = {transaction: tx};
|
||||||
|
tx = await models.Sale.beginTransaction({});
|
||||||
|
options.transaction = tx;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
await tx.rollback();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when there is not picking tickets', async() => {
|
||||||
|
try {
|
||||||
|
await models.Collection.assign(ctx, options);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toEqual('There are not picking tickets');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,62 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('collection getSales()', () => {
|
||||||
|
const collectionOrTicketFk = 999999;
|
||||||
|
const print = true;
|
||||||
|
const source = 'CHECKER';
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a collection with tickets, placements and barcodes settled correctly', async() => {
|
||||||
|
const tx = await models.Collection.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
const collection = await models.Collection.getSales(ctx,
|
||||||
|
collectionOrTicketFk, print, source, options);
|
||||||
|
|
||||||
|
const [firstTicket] = collection.tickets;
|
||||||
|
const [firstSale] = firstTicket.sales;
|
||||||
|
const [firstPlacement] = firstSale.placements;
|
||||||
|
|
||||||
|
expect(collection.tickets.length).toBeTruthy();
|
||||||
|
expect(collection.collectionFk).toEqual(firstTicket.ticketFk);
|
||||||
|
|
||||||
|
expect(firstSale.ticketFk).toEqual(firstTicket.ticketFk);
|
||||||
|
expect(firstSale.placements.length).toBeTruthy();
|
||||||
|
expect(firstSale.barcodes.length).toBeTruthy();
|
||||||
|
|
||||||
|
expect(firstSale.saleFk).toEqual(firstPlacement.saleFk);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should print a sticker', async() => {
|
||||||
|
const tx = await models.Collection.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const query = 'SELECT * FROM printQueue pq JOIN printQueueArgs pqa ON pqa.printQueueFk = pq.id';
|
||||||
|
try {
|
||||||
|
const printQueueBefore = await models.Collection.rawSql(
|
||||||
|
query, [], options);
|
||||||
|
await models.Collection.getSales(ctx,
|
||||||
|
collectionOrTicketFk, true, source, options);
|
||||||
|
const printQueueAfter = await models.Collection.rawSql(
|
||||||
|
query, [], options);
|
||||||
|
|
||||||
|
expect(printQueueAfter.length).toEqual(printQueueBefore.length + 1);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,132 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('machineWorker updateInTime()', () => {
|
||||||
|
const itBoss = 104;
|
||||||
|
const davidCharles = 1106;
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
__: value => value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the plate does not exist', async() => {
|
||||||
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const plate = 'RE-123';
|
||||||
|
ctx.req.accessToken.userId = 1106;
|
||||||
|
try {
|
||||||
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
const error = e;
|
||||||
|
|
||||||
|
expect(error.message).toContain('the plate does not exist');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should grab a machine where is not in use', async() => {
|
||||||
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const plate = 'RE-003';
|
||||||
|
ctx.req.accessToken.userId = 1107;
|
||||||
|
try {
|
||||||
|
const totalBefore = await models.MachineWorker.find(null, options);
|
||||||
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
|
const totalAfter = await models.MachineWorker.find(null, options);
|
||||||
|
|
||||||
|
expect(totalAfter.length).toEqual(totalBefore.length + 1);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('less than 12h', () => {
|
||||||
|
const plate = 'RE-001';
|
||||||
|
it('should trow an error if it is not himself', async() => {
|
||||||
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
ctx.req.accessToken.userId = davidCharles;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
const error = e;
|
||||||
|
|
||||||
|
expect(error.message).toContain('This machine is already in use');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if it is himself with a different machine', async() => {
|
||||||
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
ctx.req.accessToken.userId = itBoss;
|
||||||
|
const plate = 'RE-003';
|
||||||
|
try {
|
||||||
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
const error = e;
|
||||||
|
|
||||||
|
expect(error.message).toEqual('You are already using a machine');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the out time if it is himself', async() => {
|
||||||
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
ctx.req.accessToken.userId = itBoss;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const isNotParked = await models.MachineWorker.findOne({
|
||||||
|
where: {workerFk: itBoss}
|
||||||
|
}, options);
|
||||||
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
|
const isParked = await models.MachineWorker.findOne({
|
||||||
|
where: {workerFk: itBoss}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
expect(isNotParked.outTime).toBeNull();
|
||||||
|
expect(isParked.outTime).toBeDefined();
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('equal or more than 12h', () => {
|
||||||
|
const plate = 'RE-002';
|
||||||
|
it('should set the out time and grab the machine', async() => {
|
||||||
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
ctx.req.accessToken.userId = davidCharles;
|
||||||
|
const filter = {
|
||||||
|
where: {workerFk: davidCharles, machineFk: 2}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const isNotParked = await models.MachineWorker.findOne(filter, options);
|
||||||
|
const totalBefore = await models.MachineWorker.find(null, options);
|
||||||
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
|
const isParked = await models.MachineWorker.findOne(filter, options);
|
||||||
|
const totalAfter = await models.MachineWorker.find(null, options);
|
||||||
|
|
||||||
|
expect(isNotParked.outTime).toBeNull();
|
||||||
|
expect(isParked.outTime).toBeDefined();
|
||||||
|
expect(totalAfter.length).toEqual(totalBefore.length + 1);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,77 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('updateInTime', {
|
||||||
|
description: 'Updates the corresponding registry if the worker has been registered in the last few hours',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'plate',
|
||||||
|
type: 'string',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/updateInTime`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.updateInTime = async(ctx, plate, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const $t = ctx.req.__;
|
||||||
|
|
||||||
|
let tx;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const machine = await models.Machine.findOne({
|
||||||
|
fields: ['id', 'plate'],
|
||||||
|
where: {plate}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!machine)
|
||||||
|
throw new Error($t('the plate does not exist', {plate}));
|
||||||
|
|
||||||
|
const machineWorker = await Self.findOne({
|
||||||
|
where: {
|
||||||
|
or: [{machineFk: machine.id}, {workerFk: userId}],
|
||||||
|
outTime: null,
|
||||||
|
}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const {maxHours} = await models.MachineWorkerConfig.findOne({fields: ['maxHours']}, myOptions);
|
||||||
|
const hoursDifference = (Date.vnNow() - machineWorker.inTime.getTime()) / (60 * 60 * 1000);
|
||||||
|
|
||||||
|
if (machineWorker) {
|
||||||
|
const isHimself = userId == machineWorker.workerFk;
|
||||||
|
const isSameMachine = machine.id == machineWorker.machineFk;
|
||||||
|
|
||||||
|
if (hoursDifference < maxHours && !isHimself)
|
||||||
|
throw new UserError($t('This machine is already in use.'));
|
||||||
|
|
||||||
|
if (hoursDifference < maxHours && isHimself && !isSameMachine)
|
||||||
|
throw new UserError($t('You are already using a machine'));
|
||||||
|
|
||||||
|
await machineWorker.updateAttributes({
|
||||||
|
outTime: Date.vnNew()
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!machineWorker || hoursDifference >= maxHours)
|
||||||
|
await models.MachineWorker.create({machineFk: machine.id, workerFk: userId}, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,45 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('getVersion', {
|
||||||
|
description: 'gets app version data',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'app',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getVersion`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getVersion = async(ctx, app) => {
|
||||||
|
const {models} = Self.app;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
|
const workerFk = await models.WorkerAppTester.findOne({
|
||||||
|
where: {
|
||||||
|
workerFk: userId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let fields = ['id', 'appName'];
|
||||||
|
|
||||||
|
if (workerFk)
|
||||||
|
fields = fields.concat(['isVersionBetaCritical', 'versionBeta', 'urlBeta']);
|
||||||
|
else
|
||||||
|
fields = fields.concat(['isVersionCritical', 'version', 'urlProduction']);
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
appName: app
|
||||||
|
},
|
||||||
|
fields,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Self.findOne(filter);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('mobileAppVersionControl getVersion()', () => {
|
||||||
|
const appName = 'delivery';
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get the version app', async() => {
|
||||||
|
ctx.req.accessToken.userId = 9;
|
||||||
|
const {version, versionBeta} = await models.MobileAppVersionControl.getVersion(ctx, appName);
|
||||||
|
|
||||||
|
expect(version).toEqual('9.2');
|
||||||
|
expect(versionBeta).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get the beta version app', async() => {
|
||||||
|
ctx.req.accessToken.userId = 66;
|
||||||
|
const {version, versionBeta} = await models.MobileAppVersionControl.getVersion(ctx, appName);
|
||||||
|
|
||||||
|
expect(versionBeta).toBeDefined();
|
||||||
|
expect(version).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -79,9 +79,15 @@
|
||||||
"Language": {
|
"Language": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"Machine": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"MachineWorker": {
|
"MachineWorker": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"MachineWorkerConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"MobileAppVersionControl": {
|
"MobileAppVersionControl": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,4 +3,6 @@ module.exports = Self => {
|
||||||
require('../methods/collection/setSaleQuantity')(Self);
|
require('../methods/collection/setSaleQuantity')(Self);
|
||||||
require('../methods/collection/previousLabel')(Self);
|
require('../methods/collection/previousLabel')(Self);
|
||||||
require('../methods/collection/getTickets')(Self);
|
require('../methods/collection/getTickets')(Self);
|
||||||
|
require('../methods/collection/assign')(Self);
|
||||||
|
require('../methods/collection/getSales')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "MachineWorkerConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "vn.machineWorkerConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"maxHours": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/machine-worker/updateInTime')(Self);
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "Machine",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "vn.machine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"plate": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/mobile-app-version-control/getVersion')(Self);
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "MobileAppVersionControl",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "vn.mobileAppVersionControl"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"appName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
|
||||||
|
"isVersionCritical": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
|
||||||
|
"urlProduction": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"urlBeta": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"versionBeta": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"isVersionBetaCritical": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1239,6 +1239,7 @@ INSERT INTO `vn`.`train`(`id`, `name`)
|
||||||
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
|
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
|
||||||
VALUES
|
VALUES
|
||||||
('1106', '1', '1', 'H', '1', '1', '1'),
|
('1106', '1', '1', 'H', '1', '1', '1'),
|
||||||
|
('9', '2', '1', 'H', '1', '1', '1'),
|
||||||
('1107', '1', '1', 'V', '1', '1', '1');
|
('1107', '1', '1', 'V', '1', '1', '1');
|
||||||
|
|
||||||
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
|
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
|
||||||
|
@ -2726,10 +2727,10 @@ INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `m
|
||||||
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 'pending');
|
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 'pending');
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`)
|
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`,`versionBeta`)
|
||||||
VALUES
|
VALUES
|
||||||
('delivery', '9.2', 0),
|
('delivery', '9.2', 0,'9.7'),
|
||||||
('warehouse', '8.1', 0);
|
('warehouse', '8.1', 0,'8.3');
|
||||||
|
|
||||||
INSERT INTO `vn`.`machine` (`plate`, `maker`, `model`, `warehouseFk`, `departmentFk`, `type`, `use`, `productionYear`, `workerFk`, `companyFk`)
|
INSERT INTO `vn`.`machine` (`plate`, `maker`, `model`, `warehouseFk`, `departmentFk`, `type`, `use`, `productionYear`, `workerFk`, `companyFk`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -3067,4 +3068,667 @@ INSERT INTO `vn`.`cmr` (id,truckPlate,observations,senderInstruccions,paymentIns
|
||||||
UPDATE `vn`.`department`
|
UPDATE `vn`.`department`
|
||||||
SET workerFk = null;
|
SET workerFk = null;
|
||||||
|
|
||||||
|
-- NEW WAREHOUSE
|
||||||
|
|
||||||
|
INSERT INTO vn.packaging
|
||||||
|
VALUES('--', 2745600.00, 100.00, 120.00, 220.00, 0.00, 1, '2001-01-01 00:00:00.000', NULL, NULL, NULL, 0.00, 16, 0.00, 0, NULL, 0.00, NULL, NULL, 0, NULL, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.intrastat
|
||||||
|
SET id = 44219999,
|
||||||
|
description = 'Manufacturas de madera',
|
||||||
|
taxClassFk = 1,
|
||||||
|
taxCodeFk = 1;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.warehouse
|
||||||
|
SET id = 999,
|
||||||
|
name = 'TestingWarehouse',
|
||||||
|
hasAvailable = TRUE,
|
||||||
|
isForTicket = TRUE,
|
||||||
|
isInventory = TRUE,
|
||||||
|
hasUbications = TRUE,
|
||||||
|
hasProduction = TRUE;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.sector
|
||||||
|
SET id = 9991,
|
||||||
|
description = 'NormalSector',
|
||||||
|
warehouseFk = 999,
|
||||||
|
code = 'NS',
|
||||||
|
isPackagingArea = FALSE,
|
||||||
|
sonFk = NULL,
|
||||||
|
isMain = TRUE,
|
||||||
|
itemPackingTypeFk = NULL;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.sector
|
||||||
|
SET id = 9992,
|
||||||
|
description = 'PreviousSector',
|
||||||
|
warehouseFk = 999,
|
||||||
|
code = 'PS',
|
||||||
|
isPackagingArea = FALSE,
|
||||||
|
sonFk = NULL,
|
||||||
|
isMain = TRUE,
|
||||||
|
itemPackingTypeFk = NULL;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.sector
|
||||||
|
SET id = 9993,
|
||||||
|
description = 'MezaninneSector',
|
||||||
|
warehouseFk = 999,
|
||||||
|
code = 'MS',
|
||||||
|
isPackagingArea = FALSE,
|
||||||
|
sonFk = 9991,
|
||||||
|
isMain = TRUE,
|
||||||
|
itemPackingTypeFk = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO vn.parking (id,sectorFk, code, pickingOrder)
|
||||||
|
VALUES (4,9991, 'A-01-1', 1),
|
||||||
|
(5,9991, 'A-02-2', 2),
|
||||||
|
(6,9991, 'A-03-3', 3),
|
||||||
|
(7,9991, 'A-04-4', 4),
|
||||||
|
(8,9991, 'A-05-5', 5),
|
||||||
|
(9,9992, 'P-01-1', 6),
|
||||||
|
(10,9992, 'P-02-2', 7),
|
||||||
|
(11,9992, 'P-03-3', 8),
|
||||||
|
(12,9993, 'M-01-1', 9),
|
||||||
|
(13,9993, 'M-02-2', 10),
|
||||||
|
(14,9993, 'M-03-3', 11);
|
||||||
|
|
||||||
|
INSERT INTO vn.shelving (code, parkingFk, priority)
|
||||||
|
VALUES ('NAA', 4, 1),
|
||||||
|
('NBB', 5, 1),
|
||||||
|
('NCC', 6, 1),
|
||||||
|
('NDD', 7, 1),
|
||||||
|
('NEE', 8, 1),
|
||||||
|
('PAA', 9, 1),
|
||||||
|
('PBB', 10, 1),
|
||||||
|
('PCC', 11, 1),
|
||||||
|
('MAA', 12, 1),
|
||||||
|
('MBB', 13, 1),
|
||||||
|
('MCC', 14, 1);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.itemType
|
||||||
|
SET id = 999,
|
||||||
|
code = 'WOO',
|
||||||
|
name = 'Wood Objects',
|
||||||
|
categoryFk = 3,
|
||||||
|
workerFk = 103,
|
||||||
|
isInventory = TRUE,
|
||||||
|
life = 10,
|
||||||
|
density = 250,
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
temperatureFk = 'warm';
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.travel
|
||||||
|
SET id = 99,
|
||||||
|
shipped = CURDATE(),
|
||||||
|
landed = CURDATE(),
|
||||||
|
warehouseInFk = 999,
|
||||||
|
warehouseOutFk = 1,
|
||||||
|
isReceived = TRUE;
|
||||||
|
|
||||||
|
INSERT INTO vn.entry
|
||||||
|
SET id = 999,
|
||||||
|
supplierFk = 791,
|
||||||
|
isConfirmed = TRUE,
|
||||||
|
dated = CURDATE(),
|
||||||
|
travelFk = 99,
|
||||||
|
companyFk = 442;
|
||||||
|
|
||||||
|
INSERT INTO vn.ticket
|
||||||
|
SET id = 999999,
|
||||||
|
clientFk = 2,
|
||||||
|
warehouseFk = 999,
|
||||||
|
shipped = CURDATE(),
|
||||||
|
nickname = 'Cliente',
|
||||||
|
addressFk = 1,
|
||||||
|
companyFk = 442,
|
||||||
|
agencyModeFk = 10,
|
||||||
|
landed = CURDATE();
|
||||||
|
|
||||||
|
INSERT INTO vn.collection
|
||||||
|
SET id = 10101010,
|
||||||
|
workerFk = 9;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.ticketCollection
|
||||||
|
SET id = 10101010,
|
||||||
|
ticketFk = 999999,
|
||||||
|
collectionFk = 10101010;
|
||||||
|
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999991,
|
||||||
|
name = 'Palito para pinchos',
|
||||||
|
`size` = 25,
|
||||||
|
stems = NULL,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Palito para pinchos',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 6,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999991,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999991,
|
||||||
|
quantity = 8,
|
||||||
|
buyingValue = 0.61,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 20,
|
||||||
|
`grouping` = 1,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 50;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99991,
|
||||||
|
itemFk = 999991,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Palito para pinchos',
|
||||||
|
quantity = 3,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999992,
|
||||||
|
name = 'Madera verde',
|
||||||
|
`size` = 10,
|
||||||
|
stems = NULL,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Madera verde',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 50,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999992,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999992,
|
||||||
|
quantity = 40,
|
||||||
|
buyingValue = 0.62,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 40,
|
||||||
|
`grouping` = 5,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 25;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99992,
|
||||||
|
itemFk = 999992,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Madera Verde',
|
||||||
|
quantity = 10,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999993,
|
||||||
|
name = 'Madera Roja/Morada',
|
||||||
|
`size` = 12,
|
||||||
|
stems = 2,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Madera Roja/Morada',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 35,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999993,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999993,
|
||||||
|
quantity = 20,
|
||||||
|
buyingValue = 0.63,
|
||||||
|
stickers = 2,
|
||||||
|
packing = 10,
|
||||||
|
`grouping` = 5,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 25;
|
||||||
|
|
||||||
|
INSERT INTO vn.itemShelving
|
||||||
|
SET id = 9931,
|
||||||
|
itemFk = 999993,
|
||||||
|
shelvingFk = 'NCC',
|
||||||
|
visible = 10,
|
||||||
|
`grouping` = 5,
|
||||||
|
packing = 10;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99993,
|
||||||
|
itemFk = 999993,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Madera Roja/Morada',
|
||||||
|
quantity = 15,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999994,
|
||||||
|
name = 'Madera Naranja',
|
||||||
|
`size` = 18,
|
||||||
|
stems = 1,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Madera Naranja',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 160,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999994,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999994,
|
||||||
|
quantity = 20,
|
||||||
|
buyingValue = 0.64,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 20,
|
||||||
|
`grouping` = 4,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 25;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99994,
|
||||||
|
itemFk = 999994,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Madera Naranja',
|
||||||
|
quantity = 4,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999995,
|
||||||
|
name = 'Madera Amarilla',
|
||||||
|
`size` = 11,
|
||||||
|
stems = 5,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Madera Amarilla',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 78,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999995,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999995,
|
||||||
|
quantity = 4,
|
||||||
|
buyingValue = 0.65,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 20,
|
||||||
|
`grouping` = 1,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 35;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99995,
|
||||||
|
itemFk = 999995,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Madera Amarilla',
|
||||||
|
quantity = 5,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
-- Palito naranja
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999998,
|
||||||
|
name = 'Palito naranja',
|
||||||
|
`size` = 11,
|
||||||
|
stems = 1,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Palito naranja',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 78,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999998,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999998,
|
||||||
|
quantity = 80,
|
||||||
|
buyingValue = 0.65,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 200,
|
||||||
|
`grouping` = 30,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 35;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99998,
|
||||||
|
itemFk = 999998,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Palito naranja',
|
||||||
|
quantity = 60,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
-- Palito amarillo
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 999999,
|
||||||
|
name = 'Palito amarillo',
|
||||||
|
`size` = 11,
|
||||||
|
stems = 1,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Palito amarillo',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 78,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 9999999,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999999,
|
||||||
|
quantity = 70,
|
||||||
|
buyingValue = 0.65,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 500,
|
||||||
|
`grouping` = 10,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 35;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 99999,
|
||||||
|
itemFk = 999999,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Palito amarillo',
|
||||||
|
quantity = 50,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
-- Palito azul
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 1000000,
|
||||||
|
name = 'Palito azul',
|
||||||
|
`size` = 10,
|
||||||
|
stems = 1,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Palito azul',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 78,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 10000000,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 1000000,
|
||||||
|
quantity = 75,
|
||||||
|
buyingValue = 0.65,
|
||||||
|
stickers = 2,
|
||||||
|
packing = 300,
|
||||||
|
`grouping` = 50,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 35;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 100000,
|
||||||
|
itemFk = 1000000,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Palito azul',
|
||||||
|
quantity = 50,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
-- Palito rojo
|
||||||
|
INSERT INTO vn.item
|
||||||
|
SET id = 1000001,
|
||||||
|
name = 'Palito rojo',
|
||||||
|
`size` = 10,
|
||||||
|
stems = NULL,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Palito rojo',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 78,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT INTO vn.buy
|
||||||
|
SET id = 10000001,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 1000001,
|
||||||
|
quantity = 12,
|
||||||
|
buyingValue = 0.65,
|
||||||
|
stickers = 2,
|
||||||
|
packing = 50,
|
||||||
|
`grouping` = 5,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 1,
|
||||||
|
price2 = 1,
|
||||||
|
price3 = 1,
|
||||||
|
minPrice = 1,
|
||||||
|
weight = 35;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO vn.sale
|
||||||
|
SET id = 100001,
|
||||||
|
itemFk = 1000001,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Palito rojo',
|
||||||
|
quantity = 10,
|
||||||
|
price = 1,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
-- Previa
|
||||||
|
INSERT IGNORE INTO vn.item
|
||||||
|
SET id = 999996,
|
||||||
|
name = 'Bolas de madera',
|
||||||
|
`size` = 2,
|
||||||
|
stems = 4,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Bolas de madera',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 20,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT vn.buy
|
||||||
|
SET id = 9999996,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999996,
|
||||||
|
quantity = 5,
|
||||||
|
buyingValue = 3,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 5,
|
||||||
|
`grouping` = 2,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 7,
|
||||||
|
price2 = 7,
|
||||||
|
price3 = 7,
|
||||||
|
minPrice = 7,
|
||||||
|
weight = 80;
|
||||||
|
|
||||||
|
INSERT vn.sale
|
||||||
|
SET id = 99996,
|
||||||
|
itemFk = 999996,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Bolas de madera',
|
||||||
|
quantity = 4,
|
||||||
|
price = 7,
|
||||||
|
discount = 0,
|
||||||
|
isPicked = TRUE;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.item
|
||||||
|
SET id = 999997,
|
||||||
|
name = 'Palitos de polo MIX',
|
||||||
|
`size` = 14,
|
||||||
|
stems = NULL,
|
||||||
|
category = 'EXT',
|
||||||
|
typeFk = 999,
|
||||||
|
longName = 'Palitos de polo MIX',
|
||||||
|
itemPackingTypeFk = NULL,
|
||||||
|
originFk = 1,
|
||||||
|
weightByPiece = 20,
|
||||||
|
intrastatFk = 44219999;
|
||||||
|
|
||||||
|
INSERT vn.buy
|
||||||
|
SET id = 9999997,
|
||||||
|
entryFk = 999,
|
||||||
|
itemFk = 999997,
|
||||||
|
quantity = 100,
|
||||||
|
buyingValue = 3.2,
|
||||||
|
stickers = 1,
|
||||||
|
packing = 100,
|
||||||
|
`grouping` = 5,
|
||||||
|
groupingMode = 1,
|
||||||
|
packageFk = 94,
|
||||||
|
price1 = 7,
|
||||||
|
price2 = 7,
|
||||||
|
price3 = 7,
|
||||||
|
minPrice = 7,
|
||||||
|
weight = 80;
|
||||||
|
|
||||||
|
INSERT vn.sale
|
||||||
|
SET id = 99997,
|
||||||
|
itemFk = 999997,
|
||||||
|
ticketFk = 999999,
|
||||||
|
concept = 'Palitos de polo MIX',
|
||||||
|
quantity = 5,
|
||||||
|
price = 7,
|
||||||
|
discount = 0;
|
||||||
|
|
||||||
|
USE vn;
|
||||||
|
DELETE ish.* FROM vn.itemShelving ish
|
||||||
|
JOIN vn.shelving sh ON sh.code = ish.shelvingFk
|
||||||
|
JOIN vn.parking p ON p.id = sh.parkingFk
|
||||||
|
JOIN vn.sector s ON s.id = p.sectorFk
|
||||||
|
JOIN vn.warehouse w ON w.id = s.warehouseFk
|
||||||
|
WHERE w.name = 'TestingWarehouse';
|
||||||
|
|
||||||
|
INSERT INTO vn.itemShelving
|
||||||
|
(itemFk, shelvingFk, visible, created, `grouping`, packing, packagingFk, userFk, isChecked)
|
||||||
|
VALUES
|
||||||
|
(999991, 'NAA', 8, '2023-09-20', 1, 20, NULL, 103, NULL),
|
||||||
|
(999998, 'NAA', 80, '2023-09-20', 10, 30, NULL, 103, NULL),
|
||||||
|
(1000001, 'NAA', 6, '2023-09-20', 3, 50, NULL, 103, NULL),
|
||||||
|
(1000000, 'NBB', 50, '2023-09-18', 25, 500, NULL, 103, NULL),
|
||||||
|
(999993, 'NBB', 25, '2023-09-18', NULL, 10, NULL, 103, NULL),
|
||||||
|
(999999, 'NBB', 30, '2023-09-18', 10, 500, NULL, 103, NULL),
|
||||||
|
(999993, 'NCC', 25, '2023-09-20', 5, 10, NULL, 103, NULL),
|
||||||
|
(999997, 'NCC', 10, '2023-09-20', NULL, 100, NULL, 103, NULL),
|
||||||
|
(999999, 'NCC', 40, '2023-09-20', 10, 500, NULL, 103, NULL),
|
||||||
|
(999995, 'NDD', 10, '2023-09-19', NULL, 20, NULL, 103, NULL),
|
||||||
|
(999994, 'NDD', 48, '2023-09-19', 4, 20, NULL, 103, NULL),
|
||||||
|
(1000001, 'NEE', 6, '2023-09-21', 3, 50, NULL, 103, NULL),
|
||||||
|
(999992, 'NEE', 50, '2023-09-21', NULL, 1, NULL, 103, NULL),
|
||||||
|
(1000000, 'NEE', 25, '2023-09-21', 25, 500, NULL, 103, NULL),
|
||||||
|
(999996, 'PAA', 5, '2023-09-27', 1, 5, NULL, 103, NULL),
|
||||||
|
(999997, 'PCC', 10, '2023-09-27', 5, 100, NULL, 103, NULL);
|
||||||
|
|
||||||
|
-- Previous for Bolas de madera
|
||||||
|
INSERT IGNORE INTO vn.sectorCollection
|
||||||
|
SET id = 99,
|
||||||
|
userFk = 1,
|
||||||
|
sectorFk = 9992;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.saleGroup
|
||||||
|
SET id = 4,
|
||||||
|
userFk = 1,
|
||||||
|
parkingFk = 9,
|
||||||
|
sectorFk = 9992;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.sectorCollectionSaleGroup
|
||||||
|
SET id = 9999,
|
||||||
|
sectorCollectionFk = 99,
|
||||||
|
saleGroupFk = 999;
|
||||||
|
|
||||||
|
INSERT vn.saleGroupDetail
|
||||||
|
SET id = 99991,
|
||||||
|
saleFk = 99996,
|
||||||
|
saleGroupFk = 999;
|
||||||
|
|
||||||
|
INSERT INTO vn.saleTracking
|
||||||
|
SET id = 7,
|
||||||
|
saleFk = 99996,
|
||||||
|
isChecked = TRUE,
|
||||||
|
workerFk = 103,
|
||||||
|
stateFk = 28;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.itemShelvingSale
|
||||||
|
SET id = 991,
|
||||||
|
itemShelvingFk = 9962,
|
||||||
|
saleFk = 99996,
|
||||||
|
quantity = 5,
|
||||||
|
userFk = 1;
|
||||||
|
|
||||||
|
UPDATE vn.ticket
|
||||||
|
SET zoneFk=1
|
||||||
|
WHERE id=999999;
|
||||||
|
|
||||||
|
UPDATE vn.collection
|
||||||
|
SET workerFk=9
|
||||||
|
WHERE id=10101010;
|
||||||
|
|
||||||
|
UPDATE vn.sale
|
||||||
|
SET isPicked =FALSE;
|
||||||
|
|
||||||
|
INSERT INTO vn.machineWorkerConfig(maxHours)
|
||||||
|
VALUES(12);
|
||||||
|
|
||||||
|
INSERT INTO vn.workerAppTester(workerFk) VALUES(66);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`machine` (`plate`, `maker`, `model`, `warehouseFk`, `departmentFk`, `type`, `use`, `productionYear`, `workerFk`, `companyFk`)
|
||||||
|
VALUES
|
||||||
|
('RE-003', 'IRON', 'JPH-24', 60, 23, 'ELECTRIC TOW', 'Drag cars', 2020, 103, 442);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO vn.machineWorker(workerFk,machineFk,inTimed) VALUES (104,1,'2001-01-01 10:00:00.00.000');
|
||||||
|
|
||||||
|
UPDATE vn.buy SET itemOriginalFk = 1 WHERE id = 1;
|
||||||
|
|
||||||
|
UPDATE vn.saleTracking SET stateFk = 26 WHERE id = 5;
|
||||||
|
|
||||||
|
INSERT INTO vn.report (name) VALUES ('LabelCollection');
|
||||||
|
|
||||||
INSERT INTO `vn`.`ledgerConfig` (lastBookEntry, maxTolerance) VALUES (2,0.01);
|
INSERT INTO `vn`.`ledgerConfig` (lastBookEntry, maxTolerance) VALUES (2,0.01);
|
|
@ -1,7 +1,8 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getSimilar`(
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getSimilar`(
|
||||||
vSelf INT,
|
vSelf INT,
|
||||||
vTicketFk INT,
|
vWarehouseFk INT,
|
||||||
|
vDated DATE,
|
||||||
vShowType BOOL
|
vShowType BOOL
|
||||||
)
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
|
@ -10,11 +11,10 @@ BEGIN
|
||||||
* de veces usado y segun sus caracteristicas.
|
* de veces usado y segun sus caracteristicas.
|
||||||
*
|
*
|
||||||
* @param vSelf Id de artículo
|
* @param vSelf Id de artículo
|
||||||
* @param vTicketFk Id de ticket
|
* @param vWarehouseFk Id de almacen
|
||||||
|
* @param vDated Fecha
|
||||||
* @param vShowType Mostrar tipos
|
* @param vShowType Mostrar tipos
|
||||||
*/
|
*/
|
||||||
DECLARE vWarehouseFk INT;
|
|
||||||
DECLARE vShipped DATE;
|
|
||||||
DECLARE vCalcFk INT;
|
DECLARE vCalcFk INT;
|
||||||
DECLARE vTypeFk INT;
|
DECLARE vTypeFk INT;
|
||||||
DECLARE vPriority INT DEFAULT 1;
|
DECLARE vPriority INT DEFAULT 1;
|
||||||
|
@ -31,11 +31,6 @@ BEGIN
|
||||||
DECLARE vValue7 VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';
|
DECLARE vValue7 VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';
|
||||||
DECLARE vValue8 VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';
|
DECLARE vValue8 VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';
|
||||||
|
|
||||||
SELECT warehouseFk, shipped
|
|
||||||
INTO vWarehouseFk, vShipped
|
|
||||||
FROM ticket
|
|
||||||
WHERE id = vTicketFk;
|
|
||||||
|
|
||||||
SELECT typeFk,
|
SELECT typeFk,
|
||||||
tag5,
|
tag5,
|
||||||
value5,
|
value5,
|
||||||
|
@ -64,7 +59,7 @@ BEGIN
|
||||||
LEFT JOIN tag t ON t.id = it.tagFk
|
LEFT JOIN tag t ON t.id = it.tagFk
|
||||||
WHERE i.id = vSelf;
|
WHERE i.id = vSelf;
|
||||||
|
|
||||||
CALL cache.available_refresh(vCalcFk, FALSE, vWarehouseFk, vShipped);
|
CALL cache.available_refresh(vCalcFk, FALSE, vWarehouseFk, vDated);
|
||||||
|
|
||||||
SELECT i.id itemFk,
|
SELECT i.id itemFk,
|
||||||
i.longName,
|
i.longName,
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('Collection', 'assign', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('ExpeditionPallet', 'getPallet', 'READ', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('MachineWorker','updateInTime','WRITE','ALLOW','ROLE','production'),
|
||||||
|
('MobileAppVersionControl','getVersion','READ','ALLOW','ROLE','production'),
|
||||||
|
('SaleTracking','delete','WRITE','ALLOW','ROLE','production'),
|
||||||
|
('SaleTracking','updateTracking','WRITE','ALLOW','ROLE','production'),
|
||||||
|
('SaleTracking','setPicked','WRITE','ALLOW','ROLE','production'),
|
||||||
|
('ExpeditionPallet', '*', 'READ', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('Sale', 'getFromSectorCollection', 'READ', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('ItemBarcode', 'delete', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
|
@ -1,6 +1,7 @@
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
async function handleObserve(ctx) {
|
async function handleObserve(ctx) {
|
||||||
ctx.options.httpCtx = LoopBackContext.getCurrentContext();
|
const httpCtx = LoopBackContext.getCurrentContext();
|
||||||
|
ctx.options.userId = httpCtx?.active?.accessToken?.userId;
|
||||||
}
|
}
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
let Mixin = {
|
let Mixin = {
|
||||||
|
|
|
@ -209,5 +209,16 @@
|
||||||
"You cannot update these fields": "You cannot update these fields",
|
"You cannot update these fields": "You cannot update these fields",
|
||||||
"CountryFK cannot be empty": "Country cannot be empty",
|
"CountryFK cannot be empty": "Country cannot be empty",
|
||||||
"You are not allowed to modify the alias": "You are not allowed to modify the alias",
|
"You are not allowed to modify the alias": "You are not allowed to modify the alias",
|
||||||
"You already have the mailAlias": "You already have the mailAlias"
|
"You already have the mailAlias": "You already have the mailAlias",
|
||||||
|
"This machine is already in use.": "This machine is already in use.",
|
||||||
|
"the plate does not exist": "The plate {{plate}} does not exist",
|
||||||
|
"We do not have availability for the selected item": "We do not have availability for the selected item",
|
||||||
|
"You are already using a machine": "You are already using a machine",
|
||||||
|
"this state does not exist": "This state does not exist",
|
||||||
|
"The line could not be marked": "The line could not be marked",
|
||||||
|
"The sale cannot be tracked": "The sale cannot be tracked",
|
||||||
|
"Shelving not valid": "Shelving not valid",
|
||||||
|
"printerNotExists": "The printer does not exist",
|
||||||
|
"There are not picking tickets": "There are not picking tickets",
|
||||||
|
"ticketCommercial": "The ticket {{ ticket }} for the salesperson {{ salesMan }} is in preparation. (automatically generated message)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,7 +275,7 @@ class VnMySQL extends MySQL {
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeMethod(method, args, model, ctx, opts, cb) {
|
invokeMethod(method, args, model, ctx, opts, cb) {
|
||||||
if (!this.isLoggable(model))
|
if (!this.isLoggable(model) && !opts?.userId)
|
||||||
return super[method].apply(this, args);
|
return super[method].apply(this, args);
|
||||||
|
|
||||||
this.invokeMethodP(method, [...args], model, ctx, opts)
|
this.invokeMethodP(method, [...args], model, ctx, opts)
|
||||||
|
@ -287,11 +287,11 @@ class VnMySQL extends MySQL {
|
||||||
let tx;
|
let tx;
|
||||||
if (!opts.transaction) {
|
if (!opts.transaction) {
|
||||||
tx = await Transaction.begin(this, {});
|
tx = await Transaction.begin(this, {});
|
||||||
opts = Object.assign({transaction: tx, httpCtx: opts.httpCtx}, opts);
|
opts = Object.assign({transaction: tx}, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userId = opts.httpCtx && opts.httpCtx.active?.accessToken?.userId;
|
const {userId} = opts;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
const user = await Model.app.models.VnUser.findById(userId, {fields: ['name']}, opts);
|
const user = await Model.app.models.VnUser.findById(userId, {fields: ['name']}, opts);
|
||||||
await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts);
|
await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts);
|
||||||
|
|
|
@ -3,7 +3,6 @@ module.exports = function(iban, countryCode) {
|
||||||
if (typeof iban != 'string') return false;
|
if (typeof iban != 'string') return false;
|
||||||
if (countryCode?.toLowerCase() != 'es') return true;
|
if (countryCode?.toLowerCase() != 'es') return true;
|
||||||
|
|
||||||
iban = iban.toUpperCase();
|
|
||||||
iban = trim(iban);
|
iban = trim(iban);
|
||||||
iban = iban.replace(/\s/g, '');
|
iban = iban.replace(/\s/g, '');
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
label="IBAN"
|
label="IBAN"
|
||||||
|
ng-keyup="$ctrl.client.iban = $ctrl.client.iban.toUpperCase()"
|
||||||
ng-model="$ctrl.client.iban"
|
ng-model="$ctrl.client.iban"
|
||||||
rule
|
rule
|
||||||
on-change="$ctrl.autofillBic()"
|
on-change="$ctrl.autofillBic()"
|
||||||
|
|
|
@ -37,7 +37,7 @@ describe('Entry filter()', () => {
|
||||||
|
|
||||||
const result = await models.Entry.filter(ctx, options);
|
const result = await models.Entry.filter(ctx, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(8);
|
expect(result.length).toEqual(9);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -81,7 +81,7 @@ describe('Entry filter()', () => {
|
||||||
|
|
||||||
const result = await models.Entry.filter(ctx, options);
|
const result = await models.Entry.filter(ctx, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(7);
|
expect(result.length).toEqual(8);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('delete', {
|
||||||
|
description: 'Delete an ItemBarcode by itemFk and code',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'barcode',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'itemFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/delete`,
|
||||||
|
verb: 'DELETE'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.delete = async(barcode, itemFk, options) => {
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
await Self.destroyAll({
|
||||||
|
code: barcode,
|
||||||
|
itemFk
|
||||||
|
}, myOptions);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('itemBarcode delete()', () => {
|
||||||
|
it('should delete a record by itemFk and code', async() => {
|
||||||
|
const tx = await models.ItemBarcode.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const itemFk = 1;
|
||||||
|
const code = 1111111111;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const itemsBarcodeBefore = await models.ItemBarcode.find({}, options);
|
||||||
|
await models.ItemBarcode.delete(code, itemFk, options);
|
||||||
|
const itemsBarcodeAfter = await models.ItemBarcode.find({}, options);
|
||||||
|
|
||||||
|
expect(itemsBarcodeBefore.length).toBeGreaterThan(itemsBarcodeAfter.length);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,64 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getAlternative', {
|
||||||
|
description: 'Returns a list of items and possible alternative locations',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'shelvingFk',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getAlternative`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getAlternative = async(shelvingFk, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const filterItemShelvings = {
|
||||||
|
fields: ['id', 'visible', 'itemFk', 'shelvingFk'],
|
||||||
|
where: {shelvingFk},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'item',
|
||||||
|
scope: {
|
||||||
|
fields: ['longName', 'name', 'size']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let itemShelvings = await models.ItemShelving.find(filterItemShelvings, myOptions);
|
||||||
|
|
||||||
|
if (itemShelvings) {
|
||||||
|
const [alternatives] = await models.ItemShelving.rawSql('CALL vn.itemShelving_getAlternatives(?)',
|
||||||
|
[shelvingFk], myOptions
|
||||||
|
);
|
||||||
|
return itemShelvings.map(itemShelving => {
|
||||||
|
const item = itemShelving.item();
|
||||||
|
|
||||||
|
const shelvings = alternatives.filter(alternative => alternative.itemFk == itemShelving.itemFk);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: itemShelving.id,
|
||||||
|
itemFk: itemShelving.itemFk,
|
||||||
|
name: item.name,
|
||||||
|
size: item.size,
|
||||||
|
longName: item.longName,
|
||||||
|
quantity: itemShelving.visible,
|
||||||
|
shelvings
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('itemShelving getAlternative()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a list of items without alternatives', async() => {
|
||||||
|
const shelvingFk = 'HEJ';
|
||||||
|
const itemShelvings = await models.ItemShelving.getAlternative(shelvingFk);
|
||||||
|
|
||||||
|
expect(itemShelvings[0].shelvings.length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty list', async() => {
|
||||||
|
const shelvingFk = 'ZZP';
|
||||||
|
const itemShelvings = await models.ItemShelving.getAlternative(shelvingFk);
|
||||||
|
|
||||||
|
expect(itemShelvings.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,22 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('itemShelving updateFromSale()', () => {
|
||||||
|
it('should update the quantity', async() => {
|
||||||
|
const tx = await models.ItemBarcode.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const saleFk = 2;
|
||||||
|
const filter = {where: {itemFk: 4, shelvingFk: 'HEJ'}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const {visible: visibleBefore} = await models.ItemShelving.findOne(filter, options);
|
||||||
|
await models.ItemShelving.updateFromSale(saleFk, options);
|
||||||
|
const {visible: visibleAfter} = await models.ItemShelving.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(visibleAfter).toEqual(visibleBefore + 5);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,48 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('updateFromSale', {
|
||||||
|
description: 'Update the visible items',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'saleFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
}],
|
||||||
|
http: {
|
||||||
|
path: `/updateFromSale`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.updateFromSale = async(saleFk, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const itemShelvingSale = await models.ItemShelvingSale.findOne({
|
||||||
|
where: {saleFk},
|
||||||
|
include: {relation: 'itemShelving'}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const itemShelving = itemShelvingSale.itemShelving();
|
||||||
|
const quantity = itemShelving.visible + itemShelvingSale.quantity;
|
||||||
|
|
||||||
|
await itemShelving.updateAttributes(
|
||||||
|
{visible: quantity},
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,48 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('get', {
|
||||||
|
description: 'Get the data from an item',
|
||||||
|
accessType: 'READ',
|
||||||
|
http: {
|
||||||
|
path: `/get`,
|
||||||
|
verb: 'GET'
|
||||||
|
},
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'barcode',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'warehouseFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.get = async(barcode, warehouseFk, options) => {
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const models = Self.app.models;
|
||||||
|
|
||||||
|
const [[itemInfo]] = await Self.rawSql('CALL vn.item_getInfo(?, ?)', [barcode, warehouseFk], myOptions);
|
||||||
|
|
||||||
|
if (itemInfo) {
|
||||||
|
itemInfo.barcodes = await models.ItemBarcode.find({
|
||||||
|
fields: ['code'],
|
||||||
|
where: {
|
||||||
|
itemFk: itemInfo.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemInfo;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('item get()', () => {
|
||||||
|
const barcode = 1;
|
||||||
|
const warehouseFk = 1;
|
||||||
|
it('should get an item with several barcodes', async() => {
|
||||||
|
const card = await models.Item.get(barcode, warehouseFk);
|
||||||
|
|
||||||
|
expect(card).toBeDefined();
|
||||||
|
expect(card.barcodes.length).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,5 +1,6 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/item-barcode/toItem')(Self);
|
require('../methods/item-barcode/toItem')(Self);
|
||||||
|
require('../methods/item-barcode/delete')(Self);
|
||||||
|
|
||||||
Self.validatesUniquenessOf('code', {
|
Self.validatesUniquenessOf('code', {
|
||||||
message: `Barcode must be unique`
|
message: `Barcode must be unique`
|
||||||
|
|
|
@ -2,4 +2,6 @@ module.exports = Self => {
|
||||||
require('../methods/item-shelving/deleteItemShelvings')(Self);
|
require('../methods/item-shelving/deleteItemShelvings')(Self);
|
||||||
require('../methods/item-shelving/upsertItem')(Self);
|
require('../methods/item-shelving/upsertItem')(Self);
|
||||||
require('../methods/item-shelving/getInventory')(Self);
|
require('../methods/item-shelving/getInventory')(Self);
|
||||||
|
require('../methods/item-shelving/getAlternative')(Self);
|
||||||
|
require('../methods/item-shelving/updateFromSale')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,7 +54,8 @@
|
||||||
"shelving": {
|
"shelving": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Shelving",
|
"model": "Shelving",
|
||||||
"foreignKey": "shelvingFk"
|
"foreignKey": "shelvingFk",
|
||||||
}
|
"primaryKey": "code"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ module.exports = Self => {
|
||||||
require('../methods/item/buyerWasteEmail')(Self);
|
require('../methods/item/buyerWasteEmail')(Self);
|
||||||
require('../methods/item/labelPdf')(Self);
|
require('../methods/item/labelPdf')(Self);
|
||||||
require('../methods/item/setVisibleDiscard')(Self);
|
require('../methods/item/setVisibleDiscard')(Self);
|
||||||
|
require('../methods/item/get')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('addLog', {
|
||||||
|
description: 'Add a new log',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: {
|
||||||
|
arg: 'code',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: '/addLog',
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self.addLog = async(ctx, code, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const $t = ctx.req.__;
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const shelving = await Self.findOne({
|
||||||
|
where: {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!shelving) throw new UserError($t('Shelving not valid'));
|
||||||
|
|
||||||
|
await models.ShelvingLog.create({
|
||||||
|
changedModel: 'Shelving',
|
||||||
|
originFk: shelving.id,
|
||||||
|
changedModelId: shelving.id,
|
||||||
|
action: 'select',
|
||||||
|
userFk: userId
|
||||||
|
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('shelving addLog()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
accessToken: {userId: 66},
|
||||||
|
__: value => value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a log', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const code = 'AA6';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const shelvingLogsBefore = await models.ShelvingLog.find(null, options);
|
||||||
|
await models.Shelving.addLog(ctx, code, options);
|
||||||
|
const shelvingLogsAfter = await models.ShelvingLog.find(null, options);
|
||||||
|
|
||||||
|
expect(shelvingLogsAfter.length).toEqual(shelvingLogsBefore.length + 1);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when the code does not exist', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const code = 'DXI345';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.Shelving.addLog(ctx, code, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toEqual('Shelving not valid');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,3 +1,4 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/shelving/getSummary')(Self);
|
require('../methods/shelving/getSummary')(Self);
|
||||||
|
require('../methods/shelving/addLog')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('delete', {
|
Self.remoteMethod('delete', {
|
||||||
description: 'Delete sale trackings and item shelving sales',
|
description: 'Delete sale trackings and item shelving sales',
|
||||||
accessType: 'READ',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'saleFk',
|
arg: 'saleFk',
|
||||||
|
@ -10,21 +10,17 @@ module.exports = Self => {
|
||||||
description: 'The sale id'
|
description: 'The sale id'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'stateCode',
|
arg: 'stateCodes',
|
||||||
type: 'string'
|
type: ['string']
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
returns: {
|
|
||||||
type: ['object'],
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
http: {
|
||||||
path: `/delete`,
|
path: `/delete`,
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.delete = async(saleFk, stateCode, options) => {
|
Self.delete = async(saleFk, stateCodes, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
let tx;
|
let tx;
|
||||||
|
@ -38,20 +34,24 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (stateCode === 'PREPARED') {
|
const itemShelvingSales = await models.ItemShelvingSale.find({where: {saleFk: saleFk}}, myOptions);
|
||||||
const itemShelvingSales = await models.ItemShelvingSale.find({where: {saleFk: saleFk}}, myOptions);
|
|
||||||
for (let itemShelvingSale of itemShelvingSales)
|
|
||||||
await itemShelvingSale.destroy(myOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = await models.State.findOne({
|
for (let itemShelvingSale of itemShelvingSales)
|
||||||
where: {code: stateCode}
|
await itemShelvingSale.destroy(myOptions);
|
||||||
|
|
||||||
|
const states = await models.State.find({
|
||||||
|
fields: ['id'],
|
||||||
|
where: {
|
||||||
|
code: {inq: stateCodes}
|
||||||
|
}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
|
const stateIds = states.map(state => state.id);
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
saleFk: saleFk,
|
saleFk: saleFk,
|
||||||
stateFk: state.id
|
stateFk: {inq: stateIds}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const saleTrackings = await models.SaleTracking.find(filter, myOptions);
|
const saleTrackings = await models.SaleTracking.find(filter, myOptions);
|
||||||
|
@ -59,8 +59,6 @@ module.exports = Self => {
|
||||||
await saleTracking.destroy(myOptions);
|
await saleTracking.destroy(myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (tx) await tx.rollback();
|
if (tx) await tx.rollback();
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('setPicked', {
|
||||||
|
description: 'Add the sales line of the item and set the tracking.',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'saleFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'originalQuantity',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'code',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'isChecked',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'buyFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'isScanned',
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'quantity',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'itemShelvingFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/setPicked`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.setPicked = async(ctx, saleFk, originalQuantity, code, isChecked, buyFk, isScanned, quantity, itemShelvingFk, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.ItemShelvingSale.create({
|
||||||
|
itemShelvingFk,
|
||||||
|
saleFk,
|
||||||
|
quantity,
|
||||||
|
userFk: userId
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const itemShelving = await models.ItemShelving.findById(itemShelvingFk, null, myOptions);
|
||||||
|
|
||||||
|
await itemShelving.updateAttributes({visible: itemShelving.visible - quantity}, myOptions);
|
||||||
|
|
||||||
|
await Self.updateAll(
|
||||||
|
{saleFk},
|
||||||
|
{isChecked: true},
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
await Self.updateTracking(ctx, saleFk, originalQuantity, code, isChecked, null, isScanned, myOptions);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {itemOriginalFk} = await models.Buy.findById(buyFk, {fields: ['itemOriginalFk']}, myOptions);
|
||||||
|
if (itemOriginalFk) await models.SaleBuy.create({saleFk, buyFk}, myOptions);
|
||||||
|
} catch (e) {
|
||||||
|
throw new UserError('The sale cannot be tracked');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (e.message == 'The sale cannot be tracked') {
|
||||||
|
if (tx) tx.commit();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw new UserError('The line could not be marked');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -11,13 +11,12 @@ describe('sale-tracking delete()', () => {
|
||||||
const saleTrackingsBefore = await models.SaleTracking.find(null, options);
|
const saleTrackingsBefore = await models.SaleTracking.find(null, options);
|
||||||
|
|
||||||
const saleFk = 1;
|
const saleFk = 1;
|
||||||
const stateCode = 'PREPARED';
|
const stateCode = ['PREPARED'];
|
||||||
const result = await models.SaleTracking.delete(saleFk, stateCode, options);
|
await models.SaleTracking.delete(saleFk, stateCode, options);
|
||||||
|
|
||||||
const itemShelvingsAfter = await models.ItemShelvingSale.find(null, options);
|
const itemShelvingsAfter = await models.ItemShelvingSale.find(null, options);
|
||||||
const saleTrackingsAfter = await models.SaleTracking.find(null, options);
|
const saleTrackingsAfter = await models.SaleTracking.find(null, options);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
|
||||||
expect(saleTrackingsAfter.length).toBeLessThan(saleTrackingsBefore.length);
|
expect(saleTrackingsAfter.length).toBeLessThan(saleTrackingsBefore.length);
|
||||||
expect(itemShelvingsAfter.length).toBeLessThan(itemShelvingsBefore.length);
|
expect(itemShelvingsAfter.length).toBeLessThan(itemShelvingsBefore.length);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
describe('saleTracking setPicked()', () => {
|
||||||
|
const saleFk = 1;
|
||||||
|
const originalQuantity = 10;
|
||||||
|
const code = 'PREPARED';
|
||||||
|
const isChecked = true;
|
||||||
|
const buyFk = 1;
|
||||||
|
const isScanned = false;
|
||||||
|
const quantity = 1;
|
||||||
|
const itemShelvingFk = 1;
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: 104},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
__: value => value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the line was not able to be marked', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const code = 'FAKESTATE';
|
||||||
|
try {
|
||||||
|
await models.SaleTracking.setPicked(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
quantity,
|
||||||
|
itemShelvingFk,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
const error = e;
|
||||||
|
|
||||||
|
expect(error.message).toEqual('The line could not be marked');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if there are duplicate salebuys', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
await models.SaleTracking.setPicked(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
quantity,
|
||||||
|
itemShelvingFk,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
await models.SaleTracking.setPicked(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
quantity,
|
||||||
|
itemShelvingFk,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
const error = e;
|
||||||
|
|
||||||
|
expect(error.message).toEqual('The sale cannot be tracked');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add an itemShelvingSale and Modify a saleTracking', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
const itemShelvingSaleBefore = await models.ItemShelvingSale.find({}, options);
|
||||||
|
await models.SaleTracking.setPicked(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
quantity,
|
||||||
|
itemShelvingFk,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
const itemShelvingSaleAfter = await models.ItemShelvingSale.find({}, options);
|
||||||
|
const saleTracking = await models.SaleTracking.findOne({where: {saleFk, isChecked: false}}, options);
|
||||||
|
|
||||||
|
expect(itemShelvingSaleAfter.length).toEqual(itemShelvingSaleBefore.length + 1);
|
||||||
|
expect(saleTracking.isChecked).toBeFalse();
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,104 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('saleTracking updateTracking()', () => {
|
||||||
|
const saleFk = 1;
|
||||||
|
const originalQuantity = 10;
|
||||||
|
const code = 'PREPARED';
|
||||||
|
const isChecked = true;
|
||||||
|
const buyFk = 1;
|
||||||
|
const isScanned = false;
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: 104},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
__: value => value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the state does not exist', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const code = 'FAKESTATE';
|
||||||
|
try {
|
||||||
|
await models.SaleTracking.updateTracking(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
const error = e;
|
||||||
|
|
||||||
|
expect(error.message).toEqual('this state does not exist');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a new saleTracking and saleBuy', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const saleTrackingBefore = await models.SaleTracking.find(null, options);
|
||||||
|
const saleBuyBefore = await models.SaleBuy.find(null, options);
|
||||||
|
await models.SaleTracking.updateTracking(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
const saleTrackingAfter = await models.SaleTracking.find(null, options);
|
||||||
|
const saleBuyAfter = await models.SaleBuy.find(null, options);
|
||||||
|
|
||||||
|
expect(saleTrackingAfter.length).toEqual(saleTrackingBefore.length + 1);
|
||||||
|
expect(saleBuyAfter.length).toEqual(saleBuyBefore.length + 1);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only update a saleTracking', async() => {
|
||||||
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const saleFk = 2;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const saleTrackingBefore = await models.SaleTracking.find(null, options);
|
||||||
|
await models.SaleTracking.updateTracking(
|
||||||
|
ctx,
|
||||||
|
saleFk,
|
||||||
|
originalQuantity,
|
||||||
|
code,
|
||||||
|
isChecked,
|
||||||
|
buyFk,
|
||||||
|
isScanned,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
const saleTrackingAfter = await models.SaleTracking.find(null, options);
|
||||||
|
|
||||||
|
expect(saleTrackingAfter.length).toEqual(saleTrackingBefore.length + 1);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,110 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('updateTracking', {
|
||||||
|
description: 'Modify a saleTracking record and, if applicable, add a corresponding record in saleBuy.',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'saleFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'originalQuantity',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'code',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'isChecked',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'buyFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'isScanned',
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/updateTracking`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.updateTracking = async(ctx, saleFk, originalQuantity, code, isChecked, buyFk, isScanned = null, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {userId};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const state = await models.State.findOne({
|
||||||
|
where: {code},
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!state) throw new UserError('this state does not exist');
|
||||||
|
const uniqueAttributes = {
|
||||||
|
saleFk,
|
||||||
|
workerFk: userId,
|
||||||
|
stateFk: state?.id,
|
||||||
|
};
|
||||||
|
const attributes = {
|
||||||
|
isChecked,
|
||||||
|
originalQuantity,
|
||||||
|
isScanned
|
||||||
|
};
|
||||||
|
|
||||||
|
const saleTracking = await models.SaleTracking.findOne({
|
||||||
|
where: uniqueAttributes,
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!saleTracking) {
|
||||||
|
await models.SaleTracking.create({
|
||||||
|
...uniqueAttributes,
|
||||||
|
...attributes
|
||||||
|
}, myOptions);
|
||||||
|
} else {
|
||||||
|
await saleTracking.updateAttributes({
|
||||||
|
...attributes
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let isBuy;
|
||||||
|
if (buyFk) {
|
||||||
|
isBuy = await models.Buy.findOne({
|
||||||
|
where: {
|
||||||
|
id: buyFk,
|
||||||
|
itemOriginalFk: {
|
||||||
|
neq: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBuy)
|
||||||
|
await models.SaleBuy.create({saleFk, buyFk}, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,61 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('getFromSectorCollection', {
|
||||||
|
description: 'Get sales from sector collection',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'sectorCollectionFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'sectorFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getFromSectorCollection`,
|
||||||
|
verb: 'GET'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getFromSectorCollection = async(ctx, sectorCollectionFk, sectorFk, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
|
||||||
|
if (typeof options == 'object') Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const [sales] = await Self.rawSql('CALL sectorCollection_getSale(?)', [sectorCollectionFk], myOptions);
|
||||||
|
|
||||||
|
const itemShelvings = [];
|
||||||
|
for (let sale of sales) {
|
||||||
|
const [carros] = await Self.rawSql(
|
||||||
|
'CALL vn.itemPlacementSupplyStockGetTargetList(?, ?)',
|
||||||
|
[sale.itemFk, sectorFk],
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
itemShelvings.push({
|
||||||
|
id: sale.ticketFk,
|
||||||
|
itemFk: sale.itemFk,
|
||||||
|
longName: sale.longName,
|
||||||
|
packingType: sale.itemPackingTypeFk,
|
||||||
|
subName: sale.subName,
|
||||||
|
quantity: sale.quantity,
|
||||||
|
saldo: sale.quantity,
|
||||||
|
trabajador: sale.workerCode,
|
||||||
|
idMovimiento: sale.saleFk,
|
||||||
|
salesPersonFk: sale.salesPersonFk,
|
||||||
|
picked: sale.pickedQuantity,
|
||||||
|
carros
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemShelvings;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('sale getFromSectorCollection()', () => {
|
||||||
|
const sectorCollectionFk = 1;
|
||||||
|
const sectorFk = 1;
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
accessToken: {userId: 40}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find an item and a shelving', async() => {
|
||||||
|
const options = {};
|
||||||
|
const itemShelvings = await models.Sale.getFromSectorCollection(ctx, sectorCollectionFk, sectorFk, options);
|
||||||
|
|
||||||
|
expect(itemShelvings.length).toEqual(1);
|
||||||
|
expect(itemShelvings[0].carros.length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,56 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('addSaleByCode', {
|
||||||
|
description: 'Add a collection',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'barcode',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'quantity',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'ticketFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'warehouseFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/addSaleByCode`,
|
||||||
|
verb: 'POST'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.addSaleByCode = async(ctx, barcode, quantity, ticketFk, warehouseFk, options) => {
|
||||||
|
const myOptions = {};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [[item]] = await Self.rawSql('CALL vn.item_getInfo(?,?)', [barcode, warehouseFk], myOptions);
|
||||||
|
if (!item?.available) throw new UserError('We do not have availability for the selected item');
|
||||||
|
|
||||||
|
await Self.rawSql('CALL vn.collection_addItem(?, ?, ?)', [item.id, quantity, ticketFk], myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('Ticket addSaleByCode()', () => {
|
||||||
|
const quantity = 3;
|
||||||
|
const ticketFk = 13;
|
||||||
|
const warehouseFk = 1;
|
||||||
|
beforeAll(async() => {
|
||||||
|
activeCtx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
__: value => value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a new sale', async() => {
|
||||||
|
const tx = await models.Ticket.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const code = '1111111111';
|
||||||
|
|
||||||
|
const salesBefore = await models.Sale.find(null, options);
|
||||||
|
await models.Ticket.addSaleByCode(activeCtx, code, quantity, ticketFk, warehouseFk, options);
|
||||||
|
const salesAfter = await models.Sale.find(null, options);
|
||||||
|
|
||||||
|
expect(salesAfter.length).toEqual(salesBefore.length + 1);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -50,14 +50,17 @@ describe('ticket setDeleted()', () => {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
const ticketId = 23;
|
const ticketId = 23;
|
||||||
|
const [sectorCollectionBefore] = await models.Ticket.rawSql(
|
||||||
await models.Ticket.setDeleted(ctx, ticketId, options);
|
|
||||||
|
|
||||||
const [sectorCollection] = await models.Ticket.rawSql(
|
|
||||||
`SELECT COUNT(*) numberRows
|
`SELECT COUNT(*) numberRows
|
||||||
FROM vn.sectorCollection`, [], options);
|
FROM vn.sectorCollection`, [], options);
|
||||||
|
|
||||||
expect(sectorCollection.numberRows).toEqual(0);
|
await models.Ticket.setDeleted(ctx, ticketId, options);
|
||||||
|
|
||||||
|
const [sectorCollectionAfter] = await models.Ticket.rawSql(
|
||||||
|
`SELECT COUNT(*) numberRows
|
||||||
|
FROM vn.sectorCollection`, [], options);
|
||||||
|
|
||||||
|
expect(sectorCollectionAfter.numberRows).toEqual(sectorCollectionBefore.numberRows - 1);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -65,6 +65,9 @@
|
||||||
"SaleTracking": {
|
"SaleTracking": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"SaleBuy": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"State": {
|
"State": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ExpeditionPallet",
|
"name": "ExpeditionPallet",
|
||||||
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "expeditionPallet"
|
"table": "expeditionPallet"
|
||||||
|
@ -10,13 +11,24 @@
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"id": true,
|
"id": true,
|
||||||
"description": "Identifier"
|
"description": "Identifier"
|
||||||
}
|
},
|
||||||
|
"built": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"isPrint": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"acls": [{
|
"relations": {
|
||||||
"accessType": "WRITE",
|
"expeditionTruck": {
|
||||||
"principalType": "ROLE",
|
"type": "belongsTo",
|
||||||
"principalId": "production",
|
"model": "ExpeditionTruck",
|
||||||
"permission": "ALLOW"
|
"foreignKey": "truckFk"
|
||||||
}]
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "SaleBuy",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "saleBuy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"saleFk": {
|
||||||
|
"id": true,
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"buyFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"type": "date"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"sale": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Sale",
|
||||||
|
"foreignKey": "saleFk"
|
||||||
|
},
|
||||||
|
"worker": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "workerFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,4 +3,6 @@ module.exports = Self => {
|
||||||
require('../methods/sale-tracking/listSaleTracking')(Self);
|
require('../methods/sale-tracking/listSaleTracking')(Self);
|
||||||
require('../methods/sale-tracking/new')(Self);
|
require('../methods/sale-tracking/new')(Self);
|
||||||
require('../methods/sale-tracking/delete')(Self);
|
require('../methods/sale-tracking/delete')(Self);
|
||||||
|
require('../methods/sale-tracking/updateTracking')(Self);
|
||||||
|
require('../methods/sale-tracking/setPicked')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
},
|
},
|
||||||
"originalQuantity": {
|
"originalQuantity": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
|
},
|
||||||
|
"isScanned": {
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -12,6 +12,7 @@ module.exports = Self => {
|
||||||
require('../methods/sale/canEdit')(Self);
|
require('../methods/sale/canEdit')(Self);
|
||||||
require('../methods/sale/usesMana')(Self);
|
require('../methods/sale/usesMana')(Self);
|
||||||
require('../methods/sale/clone')(Self);
|
require('../methods/sale/clone')(Self);
|
||||||
|
require('../methods/sale/getFromSectorCollection')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('concept', {
|
Self.validatesPresenceOf('concept', {
|
||||||
message: `Concept cannot be blank`
|
message: `Concept cannot be blank`
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('./ticket-methods')(Self);
|
require('./ticket-methods')(Self);
|
||||||
require('../methods/ticket/state')(Self);
|
require('../methods/ticket/state')(Self);
|
||||||
|
require('../methods/ticket/addSaleByCode')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -100,7 +100,7 @@ class Controller extends Section {
|
||||||
saleTrackingDel(sale, stateCode) {
|
saleTrackingDel(sale, stateCode) {
|
||||||
const params = {
|
const params = {
|
||||||
saleFk: sale.saleFk,
|
saleFk: sale.saleFk,
|
||||||
stateCode: stateCode
|
stateCodes: [stateCode]
|
||||||
};
|
};
|
||||||
this.$http.post(`SaleTrackings/delete`, params).then(() => {
|
this.$http.post(`SaleTrackings/delete`, params).then(() => {
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
|
|
@ -53,6 +53,9 @@
|
||||||
"Time": {
|
"Time": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"WorkerAppTester": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"WorkCenter": {
|
"WorkCenter": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = function(Self) {
|
module.exports = Self => {
|
||||||
Self.observe('after save', async function(ctx) {
|
Self.observe('after save', async function(ctx) {
|
||||||
const instance = ctx.data || ctx.instance;
|
const instance = ctx.data || ctx.instance;
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
|
|
@ -43,6 +43,12 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Printer",
|
"model": "Printer",
|
||||||
"foreignKey": "labelerFk"
|
"foreignKey": "labelerFk"
|
||||||
|
},
|
||||||
|
"itemPackingType": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "ItemPackingType",
|
||||||
|
"foreignKey": "itemPackingTypeFk",
|
||||||
|
"primaryKey": "code"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "WorkerAppTester",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "vn.workerAppTester"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"workerFk": {
|
||||||
|
"id": true,
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"worker": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "workerFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue