refs #6276 feat:newWarehouse
This commit is contained in:
parent
aa27eb1922
commit
99689917f5
|
@ -1,31 +1,32 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('assign', {
|
Self.remoteMethodCtx('assign', {
|
||||||
description: 'Assign a collection',
|
description: 'Assign a collection',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
http: {
|
http: {
|
||||||
path: `/assign`,
|
path: `/assign`,
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
},
|
},
|
||||||
returns: {
|
returns: {
|
||||||
type: ['object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.assign = async(ctx, options) => {
|
Self.assign = async(ctx, options) => {
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const myOptions = {userId};
|
const myOptions = {userId};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const [,, {collectionFk}] = await Self.rawSql('CALL vn.collection_assign(?, @vCollectionFk); SELECT @vCollectionFk collectionFk',
|
const [, , [{collectionFk}]] =
|
||||||
[userId], myOptions);
|
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);
|
if (!collectionFk) throw new UserError('There are not picking tickets');
|
||||||
|
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
||||||
return collectionFk;
|
|
||||||
};
|
return collectionFk;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -1,132 +1,132 @@
|
||||||
const {models} = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('machineWorker updateInTime()', () => {
|
describe('machineWorker updateInTime()', () => {
|
||||||
const itBoss = 104;
|
const itBoss = 104;
|
||||||
const davidCharles = 1106;
|
const davidCharles = 1106;
|
||||||
|
|
||||||
beforeAll(async() => {
|
beforeAll(async() => {
|
||||||
ctx = {
|
ctx = {
|
||||||
req: {
|
req: {
|
||||||
accessToken: {},
|
accessToken: {},
|
||||||
headers: {origin: 'http://localhost'},
|
headers: {origin: 'http://localhost'},
|
||||||
__: value => value
|
__: value => value
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if the plate does not exist', async() => {
|
it('should throw an error if the plate does not exist', async() => {
|
||||||
const tx = await models.MachineWorker.beginTransaction({});
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
const plate = 'RE-123';
|
const plate = 'RE-123';
|
||||||
ctx.req.accessToken.userId = 1106;
|
ctx.req.accessToken.userId = 1106;
|
||||||
try {
|
try {
|
||||||
await models.MachineWorker.updateInTime(ctx, plate, options);
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const error = e;
|
const error = e;
|
||||||
|
|
||||||
expect(error.message).toContain('the plate does not exist');
|
expect(error.message).toContain('the plate does not exist');
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should grab a machine where is not in use', async() => {
|
it('should grab a machine where is not in use', async() => {
|
||||||
const tx = await models.MachineWorker.beginTransaction({});
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
const plate = 'RE-003';
|
const plate = 'RE-003';
|
||||||
ctx.req.accessToken.userId = 1107;
|
ctx.req.accessToken.userId = 1107;
|
||||||
try {
|
try {
|
||||||
const totalBefore = await models.MachineWorker.find(null, options);
|
const totalBefore = await models.MachineWorker.find(null, options);
|
||||||
await models.MachineWorker.updateInTime(ctx, plate, options);
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
const totalAfter = await models.MachineWorker.find(null, options);
|
const totalAfter = await models.MachineWorker.find(null, options);
|
||||||
|
|
||||||
expect(totalAfter.length).toEqual(totalBefore.length + 1);
|
expect(totalAfter.length).toEqual(totalBefore.length + 1);
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('less than 12h', () => {
|
describe('less than 12h', () => {
|
||||||
const plate = 'RE-001';
|
const plate = 'RE-001';
|
||||||
it('should trow an error if it is not himself', async() => {
|
it('should trow an error if it is not himself', async() => {
|
||||||
const tx = await models.MachineWorker.beginTransaction({});
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
ctx.req.accessToken.userId = davidCharles;
|
ctx.req.accessToken.userId = davidCharles;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await models.MachineWorker.updateInTime(ctx, plate, options);
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const error = e;
|
const error = e;
|
||||||
|
|
||||||
expect(error.message).toContain('This machine is already in use');
|
expect(error.message).toContain('This machine is already in use');
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if it is himself with a different machine', async() => {
|
it('should throw an error if it is himself with a different machine', async() => {
|
||||||
const tx = await models.MachineWorker.beginTransaction({});
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
ctx.req.accessToken.userId = itBoss;
|
ctx.req.accessToken.userId = itBoss;
|
||||||
const plate = 'RE-003';
|
const plate = 'RE-003';
|
||||||
try {
|
try {
|
||||||
await models.MachineWorker.updateInTime(ctx, plate, options);
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const error = e;
|
const error = e;
|
||||||
|
|
||||||
expect(error.message).toEqual('You are already using a machine');
|
expect(error.message).toEqual('You are already using a machine');
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the out time if it is himself', async() => {
|
it('should set the out time if it is himself', async() => {
|
||||||
const tx = await models.MachineWorker.beginTransaction({});
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
ctx.req.accessToken.userId = itBoss;
|
ctx.req.accessToken.userId = itBoss;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const isNotParked = await models.MachineWorker.findOne({
|
const isNotParked = await models.MachineWorker.findOne({
|
||||||
where: {workerFk: itBoss}
|
where: {workerFk: itBoss}
|
||||||
}, options);
|
}, options);
|
||||||
await models.MachineWorker.updateInTime(ctx, plate, options);
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
const isParked = await models.MachineWorker.findOne({
|
const isParked = await models.MachineWorker.findOne({
|
||||||
where: {workerFk: itBoss}
|
where: {workerFk: itBoss}
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
expect(isNotParked.outTime).toBeNull();
|
expect(isNotParked.outTime).toBeNull();
|
||||||
expect(isParked.outTime).toBeDefined();
|
expect(isParked.outTime).toBeDefined();
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('equal or more than 12h', () => {
|
describe('equal or more than 12h', () => {
|
||||||
const plate = 'RE-002';
|
const plate = 'RE-002';
|
||||||
it('should set the out time and grab the machine', async() => {
|
it('should set the out time and grab the machine', async() => {
|
||||||
const tx = await models.MachineWorker.beginTransaction({});
|
const tx = await models.MachineWorker.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
ctx.req.accessToken.userId = davidCharles;
|
ctx.req.accessToken.userId = davidCharles;
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {workerFk: davidCharles, machineFk: 2}
|
where: {workerFk: davidCharles, machineFk: 2}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const isNotParked = await models.MachineWorker.findOne(filter, options);
|
const isNotParked = await models.MachineWorker.findOne(filter, options);
|
||||||
const totalBefore = await models.MachineWorker.find(null, options);
|
const totalBefore = await models.MachineWorker.find(null, options);
|
||||||
await models.MachineWorker.updateInTime(ctx, plate, options);
|
await models.MachineWorker.updateInTime(ctx, plate, options);
|
||||||
const isParked = await models.MachineWorker.findOne(filter, options);
|
const isParked = await models.MachineWorker.findOne(filter, options);
|
||||||
const totalAfter = await models.MachineWorker.find(null, options);
|
const totalAfter = await models.MachineWorker.find(null, options);
|
||||||
|
|
||||||
expect(isNotParked.outTime).toBeNull();
|
expect(isNotParked.outTime).toBeNull();
|
||||||
expect(isParked.outTime).toBeDefined();
|
expect(isParked.outTime).toBeDefined();
|
||||||
expect(totalAfter.length).toEqual(totalBefore.length + 1);
|
expect(totalAfter.length).toEqual(totalBefore.length);
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,77 +1,77 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('updateInTime', {
|
Self.remoteMethodCtx('updateInTime', {
|
||||||
description: 'Updates the corresponding registry if the worker has been registered in the last few hours',
|
description: 'Updates the corresponding registry if the worker has been registered in the last few hours',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'plate',
|
arg: 'plate',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
http: {
|
http: {
|
||||||
path: `/updateInTime`,
|
path: `/updateInTime`,
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.updateInTime = async(ctx, plate, options) => {
|
Self.updateInTime = async(ctx, plate, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const $t = ctx.req.__;
|
const $t = ctx.req.__;
|
||||||
|
|
||||||
let tx;
|
let tx;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
if (!myOptions.transaction) {
|
if (!myOptions.transaction) {
|
||||||
tx = await Self.beginTransaction({});
|
tx = await Self.beginTransaction({});
|
||||||
myOptions.transaction = tx;
|
myOptions.transaction = tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const machine = await models.Machine.findOne({
|
const machine = await models.Machine.findOne({
|
||||||
fields: ['id', 'plate'],
|
fields: ['id', 'plate'],
|
||||||
where: {plate}
|
where: {plate}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
if (!machine)
|
if (!machine)
|
||||||
throw new Error($t('the plate does not exist', {plate}));
|
throw new Error($t('the plate does not exist', {plate}));
|
||||||
|
|
||||||
const machineWorker = await Self.findOne({
|
const machineWorker = await Self.findOne({
|
||||||
where: {
|
where: {
|
||||||
or: [{machineFk: machine.id}, {workerFk: userId}],
|
or: [{machineFk: machine.id}, {workerFk: userId}],
|
||||||
outTime: null,
|
outTime: null,
|
||||||
}
|
}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
const {maxHours} = await models.MachineWorkerConfig.findOne({fields: ['maxHours']}, myOptions);
|
const {maxHours} = await models.MachineWorkerConfig.findOne({fields: ['maxHours']}, myOptions);
|
||||||
const hoursDifference = (Date.vnNow() - machineWorker.inTime.getTime()) / (60 * 60 * 1000);
|
const hoursDifference = (Date.vnNow() - machineWorker?.inTimed?.getTime() ?? 0) / (60 * 60 * 1000);
|
||||||
|
|
||||||
if (machineWorker) {
|
if (machineWorker) {
|
||||||
const isHimself = userId == machineWorker.workerFk;
|
const isHimself = userId == machineWorker.workerFk;
|
||||||
const isSameMachine = machine.id == machineWorker.machineFk;
|
const isSameMachine = machine.id == machineWorker.machineFk;
|
||||||
|
|
||||||
if (hoursDifference < maxHours && !isHimself)
|
if (hoursDifference < maxHours && !isHimself)
|
||||||
throw new UserError($t('This machine is already in use.'));
|
throw new UserError($t('This machine is already in use.'));
|
||||||
|
|
||||||
if (hoursDifference < maxHours && isHimself && !isSameMachine)
|
if (hoursDifference < maxHours && isHimself && !isSameMachine)
|
||||||
throw new UserError($t('You are already using a machine'));
|
throw new UserError($t('You are already using a machine'));
|
||||||
|
|
||||||
await machineWorker.updateAttributes({
|
await machineWorker.updateAttributes({
|
||||||
outTime: Date.vnNew()
|
outTime: Date.vnNew()
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!machineWorker || hoursDifference >= maxHours)
|
if (!machineWorker || hoursDifference >= maxHours)
|
||||||
await models.MachineWorker.create({machineFk: machine.id, workerFk: userId}, myOptions);
|
await models.MachineWorker.create({machineFk: machine.id, workerFk: userId}, myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (tx) await tx.rollback();
|
if (tx) await tx.rollback();
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,45 +1,50 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('getVersion', {
|
Self.remoteMethodCtx('getVersion', {
|
||||||
description: 'gets app version data',
|
description: 'gets app version data',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'app',
|
arg: 'app',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true
|
required: true
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
path: `/getVersion`,
|
path: `/getVersion`,
|
||||||
verb: 'GET'
|
verb: 'GET'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getVersion = async(ctx, app) => {
|
Self.getVersion = async(ctx, app) => {
|
||||||
const {models} = Self.app;
|
const {models} = Self.app;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
const workerFk = await models.WorkerAppTester.findOne({
|
const workerFk = await models.WorkerAppTester.findOne({
|
||||||
where: {
|
where: {
|
||||||
workerFk: userId
|
workerFk: userId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let fields = ['id', 'appName'];
|
let fields = ['id', 'appName'];
|
||||||
|
|
||||||
if (workerFk)
|
if (workerFk)
|
||||||
fields = fields.concat(['isVersionBetaCritical', 'versionBeta', 'urlBeta']);
|
fields = fields.concat(['isVersionBetaCritical', 'versionBeta', 'urlBeta']);
|
||||||
else
|
else
|
||||||
fields = fields.concat(['isVersionCritical', 'version', 'urlProduction']);
|
fields = fields.concat(['isVersionCritical', 'version', 'urlProduction']);
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
appName: app
|
appName: app
|
||||||
},
|
},
|
||||||
fields,
|
fields,
|
||||||
};
|
};
|
||||||
|
|
||||||
return Self.findOne(filter);
|
const result = await Self.findOne(filter);
|
||||||
};
|
return {
|
||||||
};
|
isVersionCritical: result?.isVersionBetaCritical ?? result?.isVersionCritical,
|
||||||
|
version: result?.versionBeta ?? result?.version,
|
||||||
|
url: result?.urlBeta ?? result?.urlProduction
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
const {models} = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('mobileAppVersionControl getVersion()', () => {
|
describe('mobileAppVersionControl getVersion()', () => {
|
||||||
const appName = 'delivery';
|
const appName = 'delivery';
|
||||||
beforeAll(async() => {
|
const appNameVersion = '9.2';
|
||||||
ctx = {
|
const appNameVersionBeta = '9.7';
|
||||||
req: {
|
beforeAll(async() => {
|
||||||
accessToken: {},
|
ctx = {
|
||||||
headers: {origin: 'http://localhost'},
|
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);
|
it('should get the version app', async() => {
|
||||||
|
ctx.req.accessToken.userId = 9;
|
||||||
expect(version).toEqual('9.2');
|
const {version} = await models.MobileAppVersionControl.getVersion(ctx, appName);
|
||||||
expect(versionBeta).toBeUndefined();
|
|
||||||
});
|
expect(version).toEqual(appNameVersion);
|
||||||
|
});
|
||||||
it('should get the beta version app', async() => {
|
|
||||||
ctx.req.accessToken.userId = 66;
|
it('should get the beta version app', async() => {
|
||||||
const {version, versionBeta} = await models.MobileAppVersionControl.getVersion(ctx, appName);
|
ctx.req.accessToken.userId = 66;
|
||||||
|
const {version} = await models.MobileAppVersionControl.getVersion(ctx, appName);
|
||||||
expect(versionBeta).toBeDefined();
|
|
||||||
expect(version).toBeUndefined();
|
expect(version).toEqual(appNameVersionBeta);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
VALUES
|
VALUES
|
||||||
('Collection', 'assign', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
('Collection', 'assign', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
('ExpeditionPallet', 'getPallet', 'READ', 'ALLOW', 'ROLE', 'production'),
|
('MachineWorker','updateInTime','WRITE','ALLOW','ROLE','production'),
|
||||||
('MachineWorker','updateInTime','WRITE','ALLOW','ROLE','production'),
|
('MobileAppVersionControl','getVersion','READ','ALLOW','ROLE','production'),
|
||||||
('MobileAppVersionControl','getVersion','READ','ALLOW','ROLE','production'),
|
('SaleTracking','delete','WRITE','ALLOW','ROLE','production'),
|
||||||
('SaleTracking','delete','WRITE','ALLOW','ROLE','production'),
|
('SaleTracking','updateTracking','WRITE','ALLOW','ROLE','production'),
|
||||||
('SaleTracking','updateTracking','WRITE','ALLOW','ROLE','production'),
|
('SaleTracking','setPicked','WRITE','ALLOW','ROLE','production'),
|
||||||
('SaleTracking','setPicked','WRITE','ALLOW','ROLE','production'),
|
('ExpeditionPallet', '*', 'READ', 'ALLOW', 'ROLE', 'production'),
|
||||||
('ExpeditionPallet', '*', 'READ', 'ALLOW', 'ROLE', 'production'),
|
('Sale', 'getFromSectorCollection', 'READ', 'ALLOW', 'ROLE', 'production'),
|
||||||
('Sale', 'getFromSectorCollection', 'READ', 'ALLOW', 'ROLE', 'production'),
|
('ItemBarcode', 'delete', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
('ItemBarcode', 'delete', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
('Ticket', 'addSaleByCode', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
Loading…
Reference in New Issue