8032-devToTest_2440 #3009

Merged
alexm merged 262 commits from 8032-devToTest_2440 into test 2024-09-24 09:34:49 +00:00
40 changed files with 749 additions and 343 deletions
Showing only changes of commit 168e2e3e25 - Show all commits

View File

@ -1,3 +1,89 @@
# Version 24.38 - 2024-09-17
### Added 🆕
- chore: refs #7323 filter data by:jorgep
- chore: refs #7323 fix test by:jorgep
- chore: refs #7323 worker changes by:jorgep
- chore: refs #7323 worker changes wip by:jorgep
- chore: refs #7524 add select limit by:jorgep
- feat(AccessToken&ACL): refs #7547 upgrade security by:alexm
- feat: deleted code and redirect to Lilium by:Jon
- feat: refs #4515 New throw buy_checkItem by:guillermo
- feat: refs #6650 Added saleGroupLog by:guillermo
- feat: refs #6650 new itemShelvingLog by:guillermo
- feat: refs #6760 refs #actualiza campo nickname by:jgallego
- feat: refs #7277 fdescribe by:jgallego
- feat: refs #7277 fit by:jgallego
- feat: refs #7277 refundInvoices by:jgallego
- feat: refs #7277 test with warehouse by:jgallego
- feat: refs #7277 traducciones by:jgallego
- feat: refs #7277 transfer addressFk by:jgallego
- feat: refs #7532 Requested changes by:guillermo
- feat: refs #7564 Added proc by:guillermo
- feat: refs #7564 Added ticket_setVolumeItemCost by:guillermo
- feat: refs #7564 Added volume column by:guillermo
- feat: refs #7564 Fix version by:guillermo
- feat: refs #7564 Requested changes by:guillermo
- feat: refs #7615 setDeleted by:robert
- feat: refs #7650 Added no transfer lines to inventory entry and fixtures by:guillermo
- feat: refs #7650 Fix tests by:guillermo
- feat: refs #7747 Delete buyUltimate and buyUltimateFromInterval by:ivanm
- feat: refs #7759 Changed defined only of vn objects by:guillermo
- feat: refs #7759 Changed definer root to vn-admin by:guillermo
- feat: refs #7759 Changed name by:guillermo
- feat: refs #7759 Deleted version 11163-maroonEucalyptus by:guillermo
- feat: refs #7759 Revoke routine grants vn by:guillermo
- feat: refs #7811 Added comment by:guillermo
- feat: refs #7811 Added new params in datasources.json by:guillermo
- feat: refs #7898 Add column "floor" in vn.parking by:ivanm
- feat: refs #7898 Modify default by:ivanm
- feat: refs #7905 Added new method getBuysCsv by:guillermo
- feat: refs #7905 Added param toCsv by:guillermo
- feat: refs #7938 remove unnecessary insert in clientLog by:alexm
- feat: refs #7953 pullinfo (7953-devToTest_2438) by:alexm
- feat(salix): #7671 define isDestiny field in model by:Javier Segarra
- feat(salix): refs #7896 update version and changelog (origin/7896_down_devToTest_2436) by:Javier Segarra
- feat(salix): refs #7905 #7905 use getBuys toCSV flattened by:Javier Segarra
- feat(ssalix): refs #7671 #7671 checkDates by:Javier Segarra
- feat(ssalix): refs #7671 #7671 checkDates to present by:Javier Segarra
- feat: ticket 215005 Changed acl show transferClient by:guillermo
### Changed 📦
- perf: refs #7671 improve showBadDates by:Javier Segarra
- perf(salix): refs #7671 #7671 imrpove and revert where changes by:Javier Segarra
- refactor: deleted e2e & added back descriptor and summary by:Jon
### Fixed 🛠️
- chore: refs #7323 fix test by:jorgep
- feat: refs #7650 Added no transfer lines to inventory entry and fixtures by:guillermo
- fix by:guillermo
- fixes: refs #7760 collection problems by:Carlos Andrés
- fix merge dev (7407-workerMedical) by:alexm
- fix: refs #6727 No delete log tables data in clean procedures by:guillermo
- fix: refs #6897 back and tests by:carlossa
- fix: refs #6897 back by:carlossa
- fix: refs #6897 fix filter by:carlossa
- fix: refs #6897 fix json by:carlossa
- fix: refs #6897 travel filter by:carlossa
- fix: refs #6897 error test by:jgallego
- fix: refs #7323 fetch from right source by:jorgep
- fix: refs #7564 Deleted query by:guillermo
- fix: refs #7759 Added user 'vn'@'localhost' & grants by:guillermo
- fix: refs #7760 collection problems by:Carlos Andrés
- fix: refs #7760 tmp.ticketIPT by:Carlos Andrés
- fix: refs #7905 added comments to flatten.js by:guillermo
- fix: refs ##7905 Handle error by:guillermo
- fix(salix): refs #7905 #7905 use right fn to flatten data by:Javier Segarra
- perf(salix): refs #7671 #7671 imrpove and revert where changes by:Javier Segarra
- refs #6898 fix supplier remove by:carlossa
- refs #7407 fix acls fixtures by:carlossa
- test: fix connections e2e (7547-accessToken-security) by:alexm
- test: refs #7277 fix test proposal by:Javier Segarra
- test(salix): refs #7671 #7671 improve and revert where changes by:Javier Segarra
# Version 24.36 - 2024-09-03 # Version 24.36 - 2024-09-03
### Added 🆕 ### Added 🆕

View File

@ -12,9 +12,8 @@ const ticket1 = {
'addressFk': 1, 'addressFk': 1,
'agencyModeFk': 999 'agencyModeFk': 999
}; };
let expedition;
const expedition1 = { const expedition1 = {
'id': 17,
'agencyModeFk': 999, 'agencyModeFk': 999,
'ticketFk': 44, 'ticketFk': 44,
'freightItemFk': 71, 'freightItemFk': 71,
@ -47,7 +46,7 @@ describe('MRWConfig createShipment()', () => {
await createMrwConfig(); await createMrwConfig();
await models.Ticket.create(ticket1); await models.Ticket.create(ticket1);
await models.Expedition.create(expedition1); expedition = await models.Expedition.create(expedition1);
}); });
afterAll(async() => { afterAll(async() => {
@ -93,7 +92,7 @@ describe('MRWConfig createShipment()', () => {
} }
it('should create a shipment and return a base64Binary label', async() => { it('should create a shipment and return a base64Binary label', async() => {
const {file} = await models.MrwConfig.createShipment(expedition1.id); const {file} = await models.MrwConfig.createShipment(expedition.id);
expect(file).toEqual(mockBase64Binary); expect(file).toEqual(mockBase64Binary);
}); });
@ -101,7 +100,7 @@ describe('MRWConfig createShipment()', () => {
it('should fail if mrwConfig has no data', async() => { it('should fail if mrwConfig has no data', async() => {
let error; let error;
await models.MrwConfig.destroyAll(); await models.MrwConfig.destroyAll();
await models.MrwConfig.createShipment(expedition1.id).catch(e => { await models.MrwConfig.createShipment(expedition.id).catch(e => {
error = e; error = e;
}).finally(async() => { }).finally(async() => {
expect(error.message).toEqual(`MRW service is not configured`); expect(error.message).toEqual(`MRW service is not configured`);
@ -126,7 +125,7 @@ describe('MRWConfig createShipment()', () => {
yesterday.setDate(yesterday.getDate() - 1); yesterday.setDate(yesterday.getDate() - 1);
await models.Ticket.updateAll({id: ticket1.id}, {shipped: yesterday}); await models.Ticket.updateAll({id: ticket1.id}, {shipped: yesterday});
await models.MrwConfig.createShipment(expedition1.id).catch(e => { await models.MrwConfig.createShipment(expedition.id).catch(e => {
error = e; error = e;
}).finally(async() => { }).finally(async() => {
expect(error.message).toEqual(`This ticket has a shipped date earlier than today`); expect(error.message).toEqual(`This ticket has a shipped date earlier than today`);
@ -136,7 +135,7 @@ describe('MRWConfig createShipment()', () => {
it('should send mail if you are past the dead line and is not notified today', async() => { it('should send mail if you are past the dead line and is not notified today', async() => {
await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: null}); await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: null});
await models.MrwConfig.createShipment(expedition1.id); await models.MrwConfig.createShipment(expedition.id);
const notification = await getLastNotification(); const notification = await getLastNotification();
expect(notification.notificationFk).toEqual(filter.notificationFk); expect(notification.notificationFk).toEqual(filter.notificationFk);
@ -144,7 +143,7 @@ describe('MRWConfig createShipment()', () => {
it('should send mail if you are past the dead line and it is notified from another day', async() => { it('should send mail if you are past the dead line and it is notified from another day', async() => {
await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: new Date()}); await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: new Date()});
await models.MrwConfig.createShipment(expedition1.id); await models.MrwConfig.createShipment(expedition.id);
const notification = await getLastNotification(); const notification = await getLastNotification();
expect(notification.notificationFk).toEqual(filter.notificationFk); expect(notification.notificationFk).toEqual(filter.notificationFk);
@ -152,7 +151,7 @@ describe('MRWConfig createShipment()', () => {
it('should not send mail if you are past the dead line and it is notified', async() => { it('should not send mail if you are past the dead line and it is notified', async() => {
await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: Date.vnNew()}); await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: Date.vnNew()});
await models.MrwConfig.createShipment(expedition1.id); await models.MrwConfig.createShipment(expedition.id);
const notification = await getLastNotification(); const notification = await getLastNotification();
expect(notification).toEqual(null); expect(notification).toEqual(null);

View File

@ -15,6 +15,9 @@
"nickname": { "nickname": {
"type": "string", "type": "string",
"required": true "required": true
},
"display": {
"type": "boolean"
} }
}, },
"acls": [ "acls": [

View File

@ -4,7 +4,9 @@ GRANT SELECT,
INSERT, INSERT,
UPDATE, UPDATE,
DELETE, DELETE,
DROP,
CREATE TEMPORARY TABLES, CREATE TEMPORARY TABLES,
EXECUTE, EXECUTE,
EVENT,
TRIGGER TRIGGER
ON *.* TO 'vn'@'localhost'; ON *.* TO 'vn'@'localhost';

View File

@ -179,12 +179,12 @@ INSERT INTO `vn`.`country`(`id`, `name`, `isUeeMember`, `code`, `currencyFk`, `i
(30,'Canarias', 1, 'IC', 1, 24, 4, 1, 2); (30,'Canarias', 1, 'IC', 1, 24, 4, 1, 2);
INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasDms`, `hasComission`, `countryFk`, `hasProduction`, `isOrigin`, `isDestiny`) INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasDms`, `hasComission`, `countryFk`, `hasProduction`, `isOrigin`, `isDestiny`)
VALUES VALUES (1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
(1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
(2, 'Warehouse Two', NULL, 1, 1, 1, 1, 0, 1, 13, 1, 1, 0), (2, 'Warehouse Two', NULL, 1, 1, 1, 1, 0, 1, 13, 1, 1, 0),
(3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0), (3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0),
(4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1), (4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1),
(5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0), (5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0),
(6, 'Warehouse six', 'VNH', 1, 1, 1, 1, 0, 0, 1, 1, 0, 0),
(13, 'Inventory', 'inv', 1, 1, 1, 0, 0, 0, 1, 0, 0, 0), (13, 'Inventory', 'inv', 1, 1, 1, 0, 0, 0, 1, 0, 0, 0),
(60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0); (60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0);
@ -335,12 +335,12 @@ INSERT INTO `vn`.`payDem`(`id`, `payDem`)
(2, 20), (2, 20),
(7, 0); (7, 0);
INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`) INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`, `hasDailyInvoice`)
VALUES VALUES
(1, 'Autonomy one', 1), (1, 'Autonomy one', 1, 1),
(2, 'Autonomy two', 1), (2, 'Autonomy two', 1, 0),
(3, 'Autonomy three', 2), (3, 'Autonomy three', 2, 0),
(4, 'Autonomy four', 13); (4, 'Autonomy four', 13, 0);
INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `autonomyFk`, `warehouseFk`) INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `autonomyFk`, `warehouseFk`)
@ -397,7 +397,7 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
(1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 19, 0, 'florist','normal'), (1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 19, 0, 'florist','normal'),
(1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 19, 0, 'florist','normal'), (1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 19, 0, 'florist','normal'),
(1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 9, 0, 'florist','normal'), (1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 9, 0, 'florist','normal'),
(1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, NULL, 0, 'florist','normal'), (1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, NULL, 1, 'florist','normal'),
(1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'), (1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'),
(1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'); (1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses');
@ -821,10 +821,10 @@ INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `userFk`, `created`)
(12, 3, 19, util.VN_NOW()), (12, 3, 19, util.VN_NOW()),
(13, 3, 19, util.VN_NOW()), (13, 3, 19, util.VN_NOW()),
(14, 3, 19, util.VN_NOW()), (14, 3, 19, util.VN_NOW()),
(15, 2, 19, util.VN_NOW()), (15, 10, 19, util.VN_NOW()),
(16, 3, 19, util.VN_NOW()), (16, 3, 19, util.VN_NOW()),
(17, 2, 19, util.VN_NOW()), (17, 2, 19, util.VN_NOW()),
(18, 2, 19, util.VN_NOW()), (37, 10, 19, util.VN_NOW()),
(19, 2, 19, util.VN_NOW()), (19, 2, 19, util.VN_NOW()),
(20, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)), (20, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)),
(21, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)), (21, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)),
@ -1043,7 +1043,8 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`,
(10, 7, 7, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), (10, 7, 7, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL),
(11, 7, 8, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), (11, 7, 8, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL),
(12, 7, 9, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), (12, 7, 9, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL),
(13, 1, 10,71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL); (13, 1, 10, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL),
(14, 1, 37, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL);
INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`) INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`)
@ -1478,7 +1479,8 @@ INSERT INTO `vn`.`ticketWeekly`(`ticketFk`, `weekDay`)
(2, 1), (2, 1),
(3, 2), (3, 2),
(5, 6), (5, 6),
(15, 6); (15, 6),
(17, 6);
INSERT INTO `vn`.`awb` (id, code, package, weight, created, amount, transitoryFk, taxFk) INSERT INTO `vn`.`awb` (id, code, package, weight, created, amount, transitoryFk, taxFk)
VALUES VALUES
@ -1494,16 +1496,16 @@ INSERT INTO `vn`.`awb` (id, code, package, weight, created, amount, transitoryFk
(10, '07546500856', 185, 2364, util.VN_CURDATE(), 5321, 442, 1); (10, '07546500856', 185, 2364, util.VN_CURDATE(), 5321, 442, 1);
INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyModeFk`, `m3`, `kg`,`ref`, `totalEntries`, `cargoSupplierFk`, `awbFK`) INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyModeFk`, `m3`, `kg`,`ref`, `totalEntries`, `cargoSupplierFk`, `awbFK`)
VALUES VALUES (1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000, 'first travel', 1, 1, 1),
(1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000, 'first travel', 1, 1, 1), (2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150.00, 2000, 'second travel', 2, 2, 2),
(2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000, 'second travel', 2, 2, 2),
(3, util.VN_CURDATE(), util.VN_CURDATE(), 1, 2, 1, 0.00, 0.00, 'third travel', 1, 1, 3), (3, util.VN_CURDATE(), util.VN_CURDATE(), 1, 2, 1, 0.00, 0.00, 'third travel', 1, 1, 3),
(4, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 3, 1, 50.00, 500, 'fourth travel', 0, 2, 4), (4, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 3, 1, 50.00, 500, 'fourth travel', 0, 2, 4),
(5, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 3, 1, 50.00, 500, 'fifth travel', 1, 1, 5), (5, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 3, 1, 50.00, 500, 'fifth travel', 1, 1, 5),
(6, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 50.00, 500, 'sixth travel', 1, 2, 6), (6, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 50.00, 500, 'sixth travel', 1, 2, 6),
(7, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1, 7), (7, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1, 7),
(8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2, 10), (8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2, 10),
(10, DATE_ADD(util.VN_CURDATE(), INTERVAL + 5 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 5 DAY), 5, 1, 1, 50.00, 500, 'nineth travel', 1, 2, 10); (10, DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY), 5, 1, 1, 50.00, 500, 'nineth travel', 1, 2, 10),
(11, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `isRaid`, `evaNotes`) INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `isRaid`, `evaNotes`)
VALUES VALUES
@ -1516,7 +1518,8 @@ INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 0, 'observation seven'), (7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 0, 'observation seven'),
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, 1, ''), (8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, 1, ''),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, 1, ''), (9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, 1, ''),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, 1, ''); (10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, 1, ''),
(99, 69, '2000-12-01 00:00:00.000', 11, 0, 442, 'IN2009', 'Movement 99', 1, 1, '');
INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`) INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`)
VALUES (2, 4, 1); VALUES (2, 4, 1);
@ -1539,7 +1542,7 @@ INSERT INTO `bs`.`waste`(`buyerFk`, `year`, `week`, `itemFk`, `itemTypeFk`, `sal
('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 6, 1, '186', '0', '51', '53.12', '56.20', '56.20', '56.20'), ('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 6, 1, '186', '0', '51', '53.12', '56.20', '56.20', '56.20'),
('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 7, 1, '277', '0', '53.12', '56.20', '56.20', '56.20', '56.20'); ('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 7, 1, '277', '0', '53.12', '56.20', '56.20', '56.20', '56.20');
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packagingFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`, `printedStickers`,`isChecked`,`isIgnored`,`weight`, `created`) INSERT INTO vn.buy(id,entryFk,itemFk,buyingValue,quantity,packagingFk,stickers,freightValue,packageValue,comissionValue,packing,grouping,groupingMode,location,price1,price2,price3,printedStickers,isChecked,isIgnored,weight,created)
VALUES VALUES
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH), (1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH),
(2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 1 MONTH), (2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 1 MONTH),
@ -1555,7 +1558,8 @@ INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packagi
(12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()), (12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 4, util.VN_CURDATE()), (13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 4, util.VN_CURDATE()),
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()), (14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()),
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()); (15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
(16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000');
INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`) INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`)
VALUES VALUES
@ -3932,38 +3936,32 @@ INSERT INTO vn.medicalReview
(id, workerFk, centerFk, `date`, `time`, isFit, amount, invoice, remark) (id, workerFk, centerFk, `date`, `time`, isFit, amount, invoice, remark)
VALUES(3, 9, 2, '2000-01-01', '8:00', 1, 150.0, NULL, NULL); VALUES(3, 9, 2, '2000-01-01', '8:00', 1, 150.0, NULL, NULL);
INSERT INTO vn.payrollComponent INSERT INTO vn.stockBought (workerFk, bought, reserve, dated)
(id, name, isSalaryAgreed, isVariable, isException) VALUES(35, 1.00, 1.00, '2001-01-01');
VALUES
(1, 'Salario1', 1, 0, 0), INSERT INTO vn.auctionConfig (id,conversionCoefficient,warehouseFk)
VALUES (1,0.6,6);
INSERT INTO vn.payrollComponent (id, name, isSalaryAgreed, isVariable, isException)
VALUES (1, 'Salario1', 1, 0, 0),
(2, 'Salario2', 1, 1, 0), (2, 'Salario2', 1, 1, 0),
(3, 'Salario3', 1, 0, 1); (3, 'Salario3', 1, 0, 1);
INSERT INTO vn.workerIncome (debit, credit, incomeTypeFk, paymentDate, workerFk, concept)
INSERT INTO vn.workerIncome VALUES (1000.00, 900.00, 2, '2000-01-01', 1106, NULL),
(debit, credit, incomeTypeFk, paymentDate, workerFk, concept)
VALUES
(1000.00, 900.00, 2, '2000-01-01', 1106, NULL),
(1001.00, 800.00, 2, '2000-01-01', 1106, NULL); (1001.00, 800.00, 2, '2000-01-01', 1106, NULL);
INSERT INTO dipole.printer (id, description) VALUES(1, '');
INSERT INTO dipole.printer (id, description) INSERT INTO dipole.expedition_PrintOut (expeditionFk, ticketFk, addressFk, street, postalCode, city, shopName, isPrinted, created, printerFk, routeFk, parkingCode, truckName, clientFk, phone, province, agency, m3, workerCode, itemFk, quantity, longName, shelvingFk, comments)
VALUES(1, '');
INSERT INTO dipole.expedition_PrintOut (expeditionFk, ticketFk, addressFk, street, postalCode, city, shopName, isPrinted, created, printerFk, routeFk, parkingCode,
truckName, clientFk, phone, province, agency, m3, workerCode, itemFk, quantity, longName, shelvingFk, comments)
VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, NULL, 'NCC', NULL); VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, NULL, 'NCC', NULL);
INSERT INTO vn.accountDetail INSERT INTO vn.accountDetail (id, value, accountDetailTypeFk, supplierAccountFk)
(id, value, accountDetailTypeFk, supplierAccountFk) VALUES (21, 'ES12345B12345678', 3, 241),
VALUES
(21, 'ES12345B12345678', 3, 241),
(35, 'ES12346B12345679', 3, 241); (35, 'ES12346B12345679', 3, 241);
INSERT INTO vn.accountDetailType INSERT INTO vn.accountDetailType (id, description, code)
(id, description, code) VALUES (1, 'IBAN', 'iban'),
VALUES
(1, 'IBAN', 'iban'),
(2, 'SWIFT', 'swift'), (2, 'SWIFT', 'swift'),
(3, 'Referencia Remesas', 'remRef'), (3, 'Referencia Remesas', 'remRef'),
(4, 'Referencia Transferencias', 'trnRef'), (4, 'Referencia Transferencias', 'trnRef'),

View File

@ -75,6 +75,9 @@ proc: BEGIN
WHERE saleFk = vSaleFk; WHERE saleFk = vSaleFk;
IF vTotalReservedQuantity <> vSaleQuantity THEN IF vTotalReservedQuantity <> vSaleQuantity THEN
CALL util.debugAdd('itemShelvingSale_addBySale',
CONCAT(vSaleFk, ' - ', vSaleQuantity,' - ', vTotalReservedQuantity,'-', vOutStanding,'-', account.myUser_getId()));
UPDATE sale UPDATE sale
SET quantity = vTotalReservedQuantity SET quantity = vTotalReservedQuantity
WHERE id = vSaleFk; WHERE id = vSaleFk;
@ -93,7 +96,8 @@ proc: BEGIN
SET vOutStanding = vOutStanding - vReservedQuantity; SET vOutStanding = vOutStanding - vReservedQuantity;
IF vReservedQuantity > 0 THEN IF vReservedQuantity > 0 THEN
CALL util.debugAdd('itemShelvingSale_addBySale_reservedQuantity',
CONCAT(vSaleFk, ' - ', vReservedQuantity, ' - ', vOutStanding, account.myUser_getId()));
INSERT INTO itemShelvingSale( INSERT INTO itemShelvingSale(
itemShelvingFk, itemShelvingFk,
saleFk, saleFk,

View File

@ -3,25 +3,24 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getSimilar`(
vSelf INT, vSelf INT,
vWarehouseFk INT, vWarehouseFk INT,
vDated DATE, vDated DATE,
vShowType BOOL vShowType BOOL,
vDaysInForward INT
) )
BEGIN BEGIN
/** /**
* Propone articulos disponibles ordenados, con la cantidad * Propone articulos ordenados, con la cantidad
* 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 vWarehouseFk Id de almacen * @param vWarehouseFk Id de almacen
* @param vDated Fecha * @param vDated Fecha
* @param vShowType Mostrar tipos * @param vShowType Mostrar tipos
* @param vDaysInForward Días de alcance para las ventas
*/ */
DECLARE vAvailableCalcFk INT; DECLARE vAvailableCalcFk INT;
DECLARE vVisibleCalcFk INT;
DECLARE vTypeFk INT;
DECLARE vPriority INT DEFAULT 1; DECLARE vPriority INT DEFAULT 1;
CALL cache.available_refresh(vAvailableCalcFk, FALSE, vWarehouseFk, vDated); CALL cache.available_refresh(vAvailableCalcFk, FALSE, vWarehouseFk, vDated);
CALL cache.visible_refresh(vVisibleCalcFk, FALSE, vWarehouseFk);
WITH itemTags AS ( WITH itemTags AS (
SELECT i.id, SELECT i.id,
@ -41,8 +40,25 @@ BEGIN
AND it.priority = vPriority AND it.priority = vPriority
LEFT JOIN vn.tag t ON t.id = it.tagFk LEFT JOIN vn.tag t ON t.id = it.tagFk
WHERE i.id = vSelf WHERE i.id = vSelf
),
stock AS (
SELECT itemFk, SUM(visible) stock
FROM vn.itemShelvingStock
WHERE warehouseFk = vWarehouseFk
GROUP BY itemFk
),
sold AS (
SELECT SUM(s.quantity) quantity, s.itemFk
FROM vn.sale s
JOIN vn.ticket t ON t.id = s.ticketFk
LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id
WHERE t.shipped BETWEEN CURDATE() AND CURDATE() + INTERVAL vDaysInForward DAY
AND iss.saleFk IS NULL
AND t.warehouseFk = vWarehouseFk
GROUP BY s.itemFk
) )
SELECT i.id itemFk, SELECT i.id itemFk,
CAST(sd.quantity AS INT) advanceable,
i.longName, i.longName,
i.subName, i.subName,
i.tag5, i.tag5,
@ -64,13 +80,13 @@ BEGIN
WHEN b.groupingMode = 'packing' THEN b.packing WHEN b.groupingMode = 'packing' THEN b.packing
ELSE 1 ELSE 1
END minQuantity, END minQuantity,
v.visible located, sk.stock located,
b.price2 b.price2
FROM vn.item i FROM vn.item i
LEFT JOIN sold sd ON sd.itemFk = i.id
JOIN cache.available a ON a.item_id = i.id JOIN cache.available a ON a.item_id = i.id
AND a.calc_id = vAvailableCalcFk AND a.calc_id = vAvailableCalcFk
LEFT JOIN cache.visible v ON v.item_id = i.id LEFT JOIN stock sk ON sk.itemFk = i.id
AND v.calc_id = vVisibleCalcFk
LEFT JOIN cache.last_buy lb ON lb.item_id = i.id LEFT JOIN cache.last_buy lb ON lb.item_id = i.id
AND lb.warehouse_id = vWarehouseFk AND lb.warehouse_id = vWarehouseFk
LEFT JOIN vn.itemProposal ip ON ip.mateFk = i.id LEFT JOIN vn.itemProposal ip ON ip.mateFk = i.id
@ -80,10 +96,11 @@ BEGIN
LEFT JOIN vn.tag t ON t.id = it.tagFk LEFT JOIN vn.tag t ON t.id = it.tagFk
LEFT JOIN vn.buy b ON b.id = lb.buy_id LEFT JOIN vn.buy b ON b.id = lb.buy_id
JOIN itemTags its JOIN itemTags its
WHERE a.available > 0 WHERE (a.available > 0 OR sd.quantity < sk.stock)
AND (i.typeFk = its.typeFk OR NOT vShowType) AND (i.typeFk = its.typeFk OR NOT vShowType)
AND i.id <> vSelf AND i.id <> vSelf
ORDER BY `counter` DESC, ORDER BY (a.available > 0) DESC,
`counter` DESC,
(t.name = its.name) DESC, (t.name = its.name) DESC,
(it.value = its.value) DESC, (it.value = its.value) DESC,
(i.tag5 = its.tag5) DESC, (i.tag5 = its.tag5) DESC,

View File

@ -276,7 +276,8 @@ proc: BEGIN
JOIN productionConfig pc JOIN productionConfig pc
SET hasPlantTray = TRUE SET hasPlantTray = TRUE
WHERE ic.code = 'plant' WHERE ic.code = 'plant'
AND p.`depth` >= pc.minPlantTrayLength; AND p.`depth` >= pc.minPlantTrayLength
AND pb.isOwn;
DROP TEMPORARY TABLE DROP TEMPORARY TABLE
tmp.productionTicket, tmp.productionTicket,

View File

@ -0,0 +1,52 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`stockBought_calculate`()
BEGIN
/**
* Inserts the purchase volume per buyer
* into stockBought according to the current date.
*/
DECLARE vDated DATE;
SET vDated = util.VN_CURDATE();
CREATE OR REPLACE TEMPORARY TABLE tStockBought
SELECT workerFk, reserve
FROM stockBought
WHERE dated = vDated
AND reserve;
DELETE FROM stockBought WHERE dated = vDated;
INSERT INTO stockBought (workerFk, bought, dated)
SELECT it.workerFk,
ROUND(SUM(
(ac.conversionCoefficient *
(b.quantity / b.packing) *
buy_getVolume(b.id)
) / (vc.trolleyM3 * 1000000)
), 1),
vDated
FROM entry e
JOIN travel t ON t.id = e.travelFk
JOIN warehouse w ON w.id = t.warehouseInFk
JOIN buy b ON b.entryFk = e.id
JOIN item i ON i.id = b.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN auctionConfig ac
JOIN volumeConfig vc
WHERE t.shipped = vDated
AND t.warehouseInFk = ac.warehouseFk
GROUP BY it.workerFk;
UPDATE stockBought s
JOIN tStockBought ts ON ts.workerFk = s.workerFk
SET s.reserve = ts.reserve
WHERE s.dated = vDated;
INSERT INTO stockBought (workerFk, reserve, dated)
SELECT ts.workerFk, ts.reserve, vDated
FROM tStockBought ts
WHERE ts.workerFk NOT IN (SELECT workerFk FROM stockBought WHERE dated = vDated);
DROP TEMPORARY TABLE tStockBought;
END$$
DELIMITER ;

View File

@ -10,6 +10,7 @@ BEGIN
* *
* @param vSelf Id ticket * @param vSelf Id ticket
* @param vOriginalItemPackingTypeFk Tipo empaquetado al que se mantiene el ticket original * @param vOriginalItemPackingTypeFk Tipo empaquetado al que se mantiene el ticket original
* @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk)
*/ */
DECLARE vDone INT DEFAULT FALSE; DECLARE vDone INT DEFAULT FALSE;
DECLARE vHasItemPackingType BOOL; DECLARE vHasItemPackingType BOOL;
@ -72,6 +73,16 @@ BEGIN
SET s.ticketFk = stm.ticketFk SET s.ticketFk = stm.ticketFk
WHERE stm.ticketFk; WHERE stm.ticketFk;
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT(
ticketFk INT,
itemPackingTypeFk VARCHAR(1)
) ENGINE=MEMORY
SELECT ticketFk, itemPackingTypeFk
FROM tSalesToMove
GROUP BY ticketFk
UNION
SELECT vSelf, vOriginalItemPackingTypeFk;
DROP TEMPORARY TABLE tSalesToMove; DROP TEMPORARY TABLE tSalesToMove;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -2,10 +2,12 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost`
SQL SECURITY DEFINER SQL SECURITY DEFINER
VIEW `vn`.`buyer` VIEW `vn`.`buyer`
AS SELECT DISTINCT `u`.`id` AS `userFk`, AS SELECT DISTINCT `u`.`id` AS `userFk`,
`u`.`nickname` AS `nickname` `u`.`nickname` AS `nickname`,
`ic`.`display` AS `display`
FROM ( FROM (
`account`.`user` `u` `account`.`user` `u`
JOIN `vn`.`itemType` `it` ON(`it`.`workerFk` = `u`.`id`) JOIN `vn`.`itemType` `it` ON(`it`.`workerFk` = `u`.`id`)
JOIN `vn`.`itemCategory` `ic` ON(`ic`.`id` = `it`.`categoryFk`)
) )
WHERE `u`.`active` <> 0 WHERE `u`.`active` <> 0
ORDER BY `u`.`nickname` ORDER BY `u`.`nickname`

View File

@ -1,10 +1,10 @@
ALTER TABLE vn.collectionWagonTicket DROP FOREIGN KEY IF EXISTS collectionWagonTicket_tray; ALTER TABLE vn.collectionWagonTicket DROP FOREIGN KEY IF EXISTS collectionWagonTicket_tray;
ALTER TABLE vn.wagonConfig DROP FOREIGN KEY IF EXISTS wagonConfig_wagonTypeColor_FK; ALTER TABLE vn.wagonConfig DROP FOREIGN KEY IF EXISTS wagonConfig_wagonTypeColor_FK;
CREATE OR REPLACE TABLE vn.wagonTypeTray ( CREATE OR REPLACE TABLE vn.wagonTypeTray (
id INT(11) UNSIGNED, id INT(11) UNSIGNED auto_increment,
wagonTypeFk INT(11) unsigned NULL, wagonTypeFk INT(11) UNSIGNED NULL,
height INT(11) UNSIGNED NULL, height INT(11) UNSIGNED NULL,
wagonTypeColorFk int(11) unsigned NULL, wagonTypeColorFk int(11) UNSIGNED NULL,
CONSTRAINT wagonTypeTray_pk PRIMARY KEY (id), CONSTRAINT wagonTypeTray_pk PRIMARY KEY (id),
CONSTRAINT wagonTypeTray_wagonType_FK FOREIGN KEY (wagonTypeFk) REFERENCES vn.wagonType(id) ON DELETE CASCADE ON UPDATE RESTRICT, CONSTRAINT wagonTypeTray_wagonType_FK FOREIGN KEY (wagonTypeFk) REFERENCES vn.wagonType(id) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT wagonTypeTray_wagonTypeColor_FK FOREIGN KEY (wagonTypeColorFk) REFERENCES vn.wagonTypeColor(id) CONSTRAINT wagonTypeTray_wagonTypeColor_FK FOREIGN KEY (wagonTypeColorFk) REFERENCES vn.wagonTypeColor(id)
@ -14,6 +14,6 @@ DEFAULT CHARSET=utf8mb3
COLLATE=utf8mb3_unicode_ci; COLLATE=utf8mb3_unicode_ci;
ALTER TABLE vn.wagonConfig ADD IF NOT EXISTS defaultHeight INT UNSIGNED DEFAULT 0 NULL COMMENT 'Default height in cm for a base tray'; ALTER TABLE vn.wagonConfig ADD IF NOT EXISTS defaultHeight INT UNSIGNED DEFAULT 0 NULL COMMENT 'Default height in cm for a base tray';
ALTER TABLE vn.wagonConfig ADD IF NOT EXISTS defaultTrayColorFk int(11) unsigned NULL COMMENT 'Default color for a base tray'; ALTER TABLE vn.wagonConfig ADD IF NOT EXISTS defaultTrayColorFk int(11) UNSIGNED NULL COMMENT 'Default color for a base tray';
ALTER TABLE vn.wagonConfig ADD CONSTRAINT wagonConfig_wagonTypeColor_FK FOREIGN KEY (defaultTrayColorFk) REFERENCES vn.wagonTypeColor(id); ALTER TABLE vn.wagonConfig ADD CONSTRAINT wagonConfig_wagonTypeColor_FK FOREIGN KEY (defaultTrayColorFk) REFERENCES vn.wagonTypeColor(id);
ALTER TABLE vn.collectionWagonTicket ADD CONSTRAINT collectionWagonTicket_tray FOREIGN KEY (trayFk) REFERENCES vn.wagonTypeTray(id); ALTER TABLE vn.collectionWagonTicket ADD CONSTRAINT collectionWagonTicket_tray FOREIGN KEY (trayFk) REFERENCES vn.wagonTypeTray(id);

View File

@ -0,0 +1,30 @@
-- Place your SQL code here
-- vn.stockBought definition
CREATE TABLE IF NOT EXISTS vn.stockBought (
id INT UNSIGNED auto_increment NOT NULL,
workerFk int(10) unsigned NOT NULL,
bought decimal(10,2) NOT NULL COMMENT 'purchase volume in m3 for the day',
reserve decimal(10,2) NULL COMMENT 'reserved volume in m3 for the day',
dated DATE NOT NULL DEFAULT current_timestamp(),
CONSTRAINT stockBought_pk PRIMARY KEY (id),
CONSTRAINT stockBought_unique UNIQUE KEY (workerFk,dated),
CONSTRAINT stockBought_worker_FK FOREIGN KEY (workerFk) REFERENCES vn.worker(id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb3
COLLATE=utf8mb3_unicode_ci;
INSERT IGNORE vn.stockBought (workerFk, bought, reserve, dated)
SELECT userFk, SUM(buyed), SUM(IFNULL(reserved,0)), dated
FROM vn.stockBuyed
WHERE userFk IS NOT NULL
AND buyed IS NOT NULL
GROUP BY userFk, dated;
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('StockBought','*','READ','ALLOW','ROLE','buyer'),
('StockBought','*','WRITE','ALLOW','ROLE','buyer'),
('Buyer','*','READ','ALLOW','ROLE','buyer');

View File

@ -1,3 +1,2 @@
-- Place your SQL code here ALTER TABLE vn.productionConfig ADD IF NOT EXISTS minPlantTrayLength INT DEFAULT 53 NOT NULL
ALTER TABLE vn.productionConfig ADD minPlantTrayLength INT DEFAULT 53 NOT NULL
COMMENT 'minimum length for plant tray restriction. Avoid to make collection of the ticket with this kind of item'; COMMENT 'minimum length for plant tray restriction. Avoid to make collection of the ticket with this kind of item';

View File

@ -0,0 +1,12 @@
ALTER TABLE vn.collectionWagon DROP FOREIGN KEY IF EXISTS collectionWagon_FK_1;
ALTER TABLE vn.collectionWagonTicket DROP FOREIGN KEY IF EXISTS collectionWagonTicket_FK_1;
ALTER TABLE vn.wagonVolumetry DROP FOREIGN KEY IF EXISTS wagonVolumetry_FK_1;
ALTER TABLE vn.wagon MODIFY COLUMN id int(11) unsigned auto_increment NOT NULL COMMENT '26 letras de alfabeto inglés';
ALTER TABLE vn.collectionWagon MODIFY COLUMN wagonFk int(11) unsigned NOT NULL;
ALTER TABLE vn.collectionWagonTicket MODIFY COLUMN wagonFk int(11) unsigned NOT NULL;
ALTER TABLE vn.wagonVolumetry MODIFY COLUMN wagonFk int(11) unsigned NOT NULL;
ALTER TABLE vn.collectionWagon ADD CONSTRAINT collectionWagon_FK_1 FOREIGN KEY (wagonFk) REFERENCES vn.wagon(id) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE vn.collectionWagonTicket ADD CONSTRAINT collectionWagonTicket_FK_1 FOREIGN KEY (wagonFk) REFERENCES vn.wagon(id) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE vn.wagonVolumetry ADD CONSTRAINT wagonVolumetry_FK_1 FOREIGN KEY (wagonFk) REFERENCES vn.wagon(id) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -19,7 +19,7 @@ describe('Ticket descriptor path', () => {
it('should count the amount of tickets in the turns section', async() => { it('should count the amount of tickets in the turns section', async() => {
const result = await page.countElement(selectors.ticketsIndex.weeklyTicket); const result = await page.countElement(selectors.ticketsIndex.weeklyTicket);
expect(result).toEqual(5); expect(result).toEqual(6);
}); });
it('should go back to the ticket index then search and access a ticket summary', async() => { it('should go back to the ticket index then search and access a ticket summary', async() => {
@ -106,7 +106,7 @@ describe('Ticket descriptor path', () => {
await page.doSearch(); await page.doSearch();
const nResults = await page.countElement(selectors.ticketsIndex.searchWeeklyResult); const nResults = await page.countElement(selectors.ticketsIndex.searchWeeklyResult);
expect(nResults).toEqual(5); expect(nResults).toEqual(6);
}); });
it('should update the agency then remove it afterwards', async() => { it('should update the agency then remove it afterwards', async() => {

View File

@ -235,9 +235,10 @@
"Cannot add holidays on this day": "Cannot add holidays on this day", "Cannot add holidays on this day": "Cannot add holidays on this day",
"Cannot send mail": "Cannot send mail", "Cannot send mail": "Cannot send mail",
"CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`": "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`", "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`": "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`",
"This postcode already exists": "This postcode already exists",
"Original invoice not found": "Original invoice not found", "Original invoice not found": "Original invoice not found",
"There is already a tray with the same height": "There is already a tray with the same height", "There is already a tray with the same height": "There is already a tray with the same height",
"The height must be greater than 50cm": "The height must be greater than 50cm", "The height must be greater than 50cm": "The height must be greater than 50cm",
"The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm" "The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm",
"This postcode already exists": "This postcode already exists",
"This buyer has already made a reservation for this date": "This buyer has already made a reservation for this date"
} }

View File

@ -366,16 +366,17 @@
"The invoices have been created but the PDFs could not be generated": "Se ha facturado pero no se ha podido generar el PDF", "The invoices have been created but the PDFs could not be generated": "Se ha facturado pero no se ha podido generar el PDF",
"It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono", "It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
"Payment method is required": "El método de pago es obligatorio", "Payment method is required": "El método de pago es obligatorio",
"Cannot send mail": "Não é possível enviar o email", "Cannot send mail": "No se ha podido enviar el correo",
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos", "CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
"The sale not exists in the item shelving": "La venta no existe en la estantería del artículo", "The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
"The entry not have stickers": "La entrada no tiene etiquetas",
"Too many records": "Demasiados registros",
"Original invoice not found": "Factura original no encontrada", "Original invoice not found": "Factura original no encontrada",
"The entry has no lines or does not exist": "La entrada no tiene lineas o no existe", "The entry has no lines or does not exist": "La entrada no tiene lineas o no existe",
"Weight already set": "El peso ya está establecido", "Weight already set": "El peso ya está establecido",
"This ticket is not allocated to your department": "Este ticket no está asignado a tu departamento", "This ticket is not allocated to your department": "Este ticket no está asignado a tu departamento",
"There is already a tray with the same height": "Ya existe una bandeja con la misma altura", "There is already a tray with the same height": "Ya existe una bandeja con la misma altura",
"The height must be greater than 50cm": "La altura debe ser superior a 50cm", "The height must be greater than 50cm": "La altura debe ser superior a 50cm",
"The maximum height of the wagon is 200cm": "La altura máxima es 200cm" "The maximum height of the wagon is 200cm": "La altura máxima es 200cm",
"The entry does not have stickers": "La entrada no tiene etiquetas",
"Too many records": "Demasiados registros",
"This buyer has already made a reservation for this date": "Este comprador ya ha hecho una reserva para esta fecha"
} }

View File

@ -1,5 +1,6 @@
const ForbiddenError = require('vn-loopback/util/forbiddenError'); const ForbiddenError = require('vn-loopback/util/forbiddenError');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.rewriteDbError(function(err) { Self.rewriteDbError(function(err) {

View File

@ -52,7 +52,7 @@ module.exports = Self => {
await merger.add(new Uint8Array(pdfBuffer[0])); await merger.add(new Uint8Array(pdfBuffer[0]));
} }
if (!merger._doc) throw new UserError('The entry not have stickers'); if (!merger._doc) throw new UserError('The entry does not have stickers');
await Self.rawSql(` await Self.rawSql(`
UPDATE buy UPDATE buy

View File

@ -39,7 +39,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(11); expect(result.length).toEqual(12);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -131,7 +131,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(10); expect(result.length).toEqual(11);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -0,0 +1,60 @@
module.exports = Self => {
Self.remoteMethod('getStockBought', {
description: 'Returns the stock bought for a given date',
accessType: 'READ',
accepts: [{
arg: 'workerFk',
type: 'number',
description: 'The id for a buyer',
},
{
arg: 'dated',
type: 'date',
description: 'The date to filter',
}
],
returns: {
type: ['object'],
root: true
},
http: {
path: `/getStockBought`,
verb: 'GET'
}
});
Self.getStockBought = async(workerFk, dated = Date.vnNew()) => {
const models = Self.app.models;
const today = Date.vnNew();
dated.setHours(0, 0, 0, 0);
today.setHours(0, 0, 0, 0);
if (dated.getTime() === today.getTime())
await models.StockBought.rawSql(`CALL vn.stockBought_calculate()`);
const filter = {
where: {
dated: dated
},
include: [
{
relation: 'worker',
scope: {
include: [
{
relation: 'user',
scope: {
fields: ['id', 'name']
}
}
]
}
}
]
};
if (workerFk) filter.where.workerFk = workerFk;
return models.StockBought.find(filter);
};
};

View File

@ -0,0 +1,58 @@
module.exports = Self => {
Self.remoteMethod('getStockBoughtDetail', {
description: 'Returns the detail of stock bought for a given date and a worker',
accessType: 'READ',
accepts: [{
arg: 'workerFk',
type: 'number',
description: 'The worker to filter',
required: true,
}, {
arg: 'dated',
type: 'string',
description: 'The date to filter',
}
],
returns: {
type: ['object'],
root: true
},
http: {
path: `/getStockBoughtDetail`,
verb: 'GET'
}
});
Self.getStockBoughtDetail = async(workerFk, dated) => {
if (!dated) {
dated = Date.vnNew();
dated.setHours(0, 0, 0, 0);
}
return Self.rawSql(
`SELECT e.id entryFk,
i.id itemFk,
i.longName itemName,
b.quantity,
ROUND((ac.conversionCoefficient *
(b.quantity / b.packing) *
buy_getVolume(b.id)
) / (vc.trolleyM3 * 1000000),
2
) volume,
b.packagingFk,
b.packing
FROM entry e
JOIN travel t ON t.id = e.travelFk
JOIN buy b ON b.entryFk = e.id
JOIN item i ON i.id = b.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN worker w ON w.id = it.workerFk
JOIN auctionConfig ac
JOIN volumeConfig vc
WHERE t.warehouseInFk = ac.warehouseFk
AND it.workerFk = ?
AND t.shipped = util.VN_CURDATE()`,
[workerFk]
);
};
};

View File

@ -25,5 +25,8 @@
}, },
"EntryType": { "EntryType": {
"dataSource": "vn" "dataSource": "vn"
},
"StockBought": {
"dataSource": "vn"
} }
} }

View File

@ -0,0 +1,10 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
require('../methods/stock-bought/getStockBought')(Self);
require('../methods/stock-bought/getStockBoughtDetail')(Self);
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`This buyer has already made a reservation for this date`);
return err;
});
};

View File

@ -0,0 +1,34 @@
{
"name": "StockBought",
"base": "VnModel",
"options": {
"mysql": {
"table": "stockBought"
}
},
"properties": {
"id": {
"type": "number",
"id": true
},
"workerFk": {
"type": "number"
},
"bought": {
"type": "number"
},
"reserve": {
"type": "number"
},
"dated": {
"type": "date"
}
},
"relations": {
"worker": {
"type": "belongsTo",
"model": "Worker",
"foreignKey": "workerFk"
}
}
}

View File

@ -83,8 +83,10 @@ module.exports = Self => {
const invoiceOutSerial = await Self.app.models.InvoiceOutSerial.findById(serial); const invoiceOutSerial = await Self.app.models.InvoiceOutSerial.findById(serial);
if (invoiceOutSerial?.taxAreaFk == 'WORLD') { if (invoiceOutSerial?.taxAreaFk == 'WORLD') {
const address = await Self.app.models.Address.findById(addressId); const address = await Self.app.models.Address.findById(addressId);
if (!address || !address.customsAgentFk || !address.incotermsFk) if (!address?.customsAgentFk || !address.incotermsFk) {
throw new UserError('The address of the customer must have information about Incoterms and Customs Agent'); throw new UserError(
'The address of the customer must have information about Incoterms and Customs Agent');
}
} }
return serial; return serial;

View File

@ -39,7 +39,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {}; const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options); const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toBeGreaterThan(10); expect(result.length).toBeGreaterThan(9);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -146,13 +146,20 @@ describe('SalesMonitor salesFilter()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const alertLevel = await models.AlertLevel.findOne({
where: {code: 'FREE'},
options
});
const alertLevelFree = alertLevel.id;
const ctx = {req: {accessToken: {userId: 9}}, args: {pending: false}}; const ctx = {req: {accessToken: {userId: 9}}, args: {pending: false}};
const filter = {order: 'alertLevel ASC'}; const filter = {order: 'alertLevel ASC'};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options); const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
const firstRow = result[0];
expect(result.length).toEqual(15); result.forEach(row => {
expect(firstRow.alertLevel).not.toEqual(0); expect(row.alertLevel).toBeGreaterThan(alertLevelFree);
});
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -38,13 +38,14 @@ module.exports = Self => {
Object.assign(myOptions, options); Object.assign(myOptions, options);
const where = buildFilter(ctx.args, (param, value) => { const where = buildFilter(ctx.args, (param, value) => {
switch (param) { if (param === 'search') {
case 'search': return {
return {or: [ or: [
{'t.id': value}, {'t.id': value},
{'c.id': value}, {'c.id': value},
{'c.name': {like: `%${value}%`}} {'c.name': {like: `%${value}%`}}
]}; ]
};
} }
}); });

View File

@ -13,11 +13,11 @@ describe('ticket-weekly filter()', () => {
const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}}; const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}};
const result = await models.TicketWeekly.filter(ctx, null, options); const result = await models.TicketWeekly.filter(ctx, null, options);
const totalRecords = await models.TicketWeekly.count();
const firstRow = result[0]; const firstRow = result[0];
expect(firstRow.ticketFk).toEqual(2); expect(firstRow.ticketFk).toEqual(2);
expect(result.length).toEqual(4); expect(result.length).toEqual(totalRecords);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -1,79 +0,0 @@
const closure = require('./closure');
module.exports = Self => {
Self.remoteMethodCtx('closeByAgency', {
description: 'Makes the closure process by agency mode',
accessType: 'WRITE',
accepts: [
{
arg: 'agencyModeFk',
type: ['number'],
required: true,
description: 'The agencies mode ids',
},
{
arg: 'warehouseFk',
type: 'number',
description: 'The ticket warehouse id',
required: true
},
{
arg: 'to',
type: 'date',
description: 'Max closure date',
required: true
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/close-by-agency`,
verb: 'POST'
}
});
Self.closeByAgency = async ctx => {
const args = ctx.args;
const tickets = await Self.rawSql(`
SELECT
t.id,
t.clientFk,
t.companyFk,
c.name clientName,
c.email recipient,
c.salesPersonFk,
c.isToBeMailed,
c.hasToInvoice,
co.hasDailyInvoice,
eu.email salesPersonEmail
FROM expedition e
JOIN ticket t ON t.id = e.ticketFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN alertLevel al ON al.id = ts.alertLevel
JOIN client c ON c.id = t.clientFk
JOIN province p ON p.id = c.provinceFk
JOIN country co ON co.id = p.countryFk
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
WHERE al.code = 'PACKED'
AND t.agencyModeFk IN(?)
AND t.warehouseFk = ?
AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY)
AND util.dayEnd(?)
AND t.refFk IS NULL
GROUP BY e.ticketFk`, [
args.agencyModeFk,
args.warehouseFk,
args.to,
args.to
]);
await closure(Self, tickets);
return {
message: 'Success'
};
};
};

View File

@ -1,75 +0,0 @@
const closure = require('./closure');
const {Email} = require('vn-print');
module.exports = Self => {
Self.remoteMethodCtx('closeByRoute', {
description: 'Makes the closure process by route',
accessType: 'WRITE',
accepts: [
{
arg: 'routeFk',
type: 'number',
required: true,
description: 'The routes ids',
},
],
returns: {
type: 'object',
root: true
},
http: {
path: `/close-by-route`,
verb: 'POST'
}
});
Self.closeByRoute = async ctx => {
const args = ctx.args;
const tickets = await Self.rawSql(`
SELECT
t.id,
t.clientFk,
t.companyFk,
c.name clientName,
c.email recipient,
c.salesPersonFk,
c.isToBeMailed,
c.hasToInvoice,
co.hasDailyInvoice,
eu.email salesPersonEmail
FROM expedition e
JOIN ticket t ON t.id = e.ticketFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN alertLevel al ON al.id = ts.alertLevel
JOIN client c ON c.id = t.clientFk
JOIN province p ON p.id = c.provinceFk
JOIN country co ON co.id = p.countryFk
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
WHERE al.code = 'PACKED'
AND t.routeFk = ?
AND t.refFk IS NULL
GROUP BY e.ticketFk`, [args.routeFk]);
await closure(Self, tickets);
// Send route report to the agency
const [agencyMail] = await Self.rawSql(`
SELECT am.reportMail
FROM route r
JOIN agencyMode am ON am.id = r.agencyModeFk
WHERE r.id = ?`, [args.routeFk]);
if (agencyMail) {
const email = new Email('driver-route', {
id: args.routeFk,
recipient: agencyMail
});
await email.send();
}
return {
message: 'Success'
};
};
};

View File

@ -23,7 +23,21 @@ module.exports = Self => {
} }
}); });
Self.closeByTicket = async ctx => { Self.closeByTicket = async(ctx, options) => {
let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const userId = ctx.req.accessToken.userId;
myOptions.userId = userId;
const args = ctx.args; const args = ctx.args;
const tickets = await Self.rawSql(` const tickets = await Self.rawSql(`
@ -37,7 +51,8 @@ module.exports = Self => {
c.isToBeMailed, c.isToBeMailed,
c.hasToInvoice, c.hasToInvoice,
co.hasDailyInvoice, co.hasDailyInvoice,
eu.email salesPersonEmail eu.email salesPersonEmail,
t.addressFk
FROM expedition e FROM expedition e
JOIN ticket t ON t.id = e.ticketFk JOIN ticket t ON t.id = e.ticketFk
JOIN ticketState ts ON ts.ticketFk = t.id JOIN ticketState ts ON ts.ticketFk = t.id
@ -49,9 +64,14 @@ module.exports = Self => {
WHERE al.code = 'PACKED' WHERE al.code = 'PACKED'
AND t.id = ? AND t.id = ?
AND t.refFk IS NULL AND t.refFk IS NULL
GROUP BY e.ticketFk`, [args.id]); GROUP BY e.ticketFk`,
[args.id],
myOptions);
await closure(Self, tickets); await closure(ctx, Self, tickets, myOptions);
if (tx)
await tx.commit();
return { return {
message: 'Success' message: 'Success'

View File

@ -1,13 +1,22 @@
/* eslint max-len: ["error", { "code": 150 }]*/
const Report = require('vn-print/core/report'); const Report = require('vn-print/core/report');
const Email = require('vn-print/core/email'); const Email = require('vn-print/core/email');
const smtp = require('vn-print/core/smtp'); const smtp = require('vn-print/core/smtp');
const config = require('vn-print/core/config'); const config = require('vn-print/core/config');
const storage = require('vn-print/core/storage'); const storage = require('vn-print/core/storage');
module.exports = async function(ctx, Self, tickets, reqArgs = {}) { module.exports = async function(ctx, Self, tickets, options) {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const myOptions = {userId};
if (typeof options == 'object')
Object.assign(myOptions, options);
let tx;
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
if (tickets.length == 0) return; if (tickets.length == 0) return;
const failedtickets = []; const failedtickets = [];
@ -17,7 +26,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
await Self.rawSql( await Self.rawSql(
`CALL vn.ticket_closeByTicket(?)`, `CALL vn.ticket_closeByTicket(?)`,
[ticket.id], [ticket.id],
{userId} myOptions
); );
const [invoiceOut] = await Self.rawSql(` const [invoiceOut] = await Self.rawSql(`
@ -26,7 +35,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
JOIN invoiceOut io ON io.ref = t.refFk JOIN invoiceOut io ON io.ref = t.refFk
JOIN company cny ON cny.id = io.companyFk JOIN company cny ON cny.id = io.companyFk
WHERE t.id = ? WHERE t.id = ?
`, [ticket.id]); `, [ticket.id], myOptions);
const mailOptions = { const mailOptions = {
overrideAttachments: true, overrideAttachments: true,
@ -63,7 +72,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
await Self.rawSql( await Self.rawSql(
'UPDATE invoiceOut SET hasPdf = true WHERE id = ?', 'UPDATE invoiceOut SET hasPdf = true WHERE id = ?',
[invoiceOut.id], [invoiceOut.id],
{userId}, myOptions
); );
if (isToBeMailed) { if (isToBeMailed) {
@ -108,7 +117,9 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
WHERE t.clientFk = ? WHERE t.clientFk = ?
AND NOT t.isDeleted AND NOT t.isDeleted
AND c.isVies AND c.isVies
`, [ticket.clientFk]); `,
[ticket.clientFk],
myOptions);
if (firstOrder == 1) { if (firstOrder == 1) {
const args = { const args = {
@ -127,20 +138,22 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
SELECT id SELECT id
FROM sample FROM sample
WHERE code = 'incoterms-authorization' WHERE code = 'incoterms-authorization'
`); `,
null,
myOptions);
await Self.rawSql(` await Self.rawSql(`
INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?)
`, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); `,
[ticket.clientFk, sample.id, ticket.companyFk],
myOptions);
} }
} catch (error) { } catch (error) {
// Domain not found
if (error.responseCode == 450) { if (error.responseCode == 450) {
await invalidEmail(ticket); await invalidEmail(ticket);
continue; continue;
} }
// Save tickets on a list of failed ids
failedtickets.push({ failedtickets.push({
id: ticket.id, id: ticket.id,
stacktrace: error, stacktrace: error,
@ -148,7 +161,6 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
} }
} }
// Send email with failed tickets
if (failedtickets.length > 0) { if (failedtickets.length > 0) {
let body = 'This following tickets have failed:<br/><br/>'; let body = 'This following tickets have failed:<br/><br/>';
@ -164,11 +176,14 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
}).catch(err => console.error(err)); }).catch(err => console.error(err));
} }
if (tx)
await tx.commit();
async function invalidEmail(ticket) { async function invalidEmail(ticket) {
await Self.rawSql( await Self.rawSql(
`UPDATE client SET email = NULL WHERE id = ?`, `UPDATE client SET email = NULL WHERE id = ?`,
[ticket.clientFk], [ticket.clientFk],
{userId}, myOptions
); );
const body = `No se ha podido enviar el albarán <strong>${ticket.id}</strong> const body = `No se ha podido enviar el albarán <strong>${ticket.id}</strong>

View File

@ -39,7 +39,7 @@ module.exports = Self => {
}, myOptions); }, myOptions);
for (const ticketId of tickets) { for (const ticketId of tickets) {
const ticket = await models.Ticket.findById(ticketId, myOptions); const ticket = await models.Ticket.findById(ticketId, null, myOptions);
if (ticket.cmrFk) { if (ticket.cmrFk) {
const hasDmsCmr = await Self.rawSql(` const hasDmsCmr = await Self.rawSql(`

View File

@ -0,0 +1,119 @@
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
const smtp = require('vn-print/core/smtp');
const Email = require('vn-print/core/email');
const config = require('vn-print/core/config');
const closure = require('../closure');
describe('Ticket closure functionality', () => {
const userId = 19;
const companyFk = 442;
const activeCtx = {
getLocale: () => 'es',
accessToken: {userId: userId},
headers: {origin: 'http://localhost:5000'},
};
let ctx = {req: activeCtx};
let tx;
let options;
beforeEach(async() => {
LoopBackContext.getCurrentContext = () => ({
active: activeCtx,
});
tx = await models.Sale.beginTransaction({});
options = {transaction: tx};
});
afterEach(async() => {
await tx.rollback();
});
it('should successfully close a ticket and not invoiced', async() => {
const ticketId = 15;
const tickets = [{
id: ticketId,
clientFk: 1101,
companyFk,
addressFk: 1,
isToBeMailed: true,
recipient: 'some@email.com',
salesPersonFk: userId
}];
const ticketStateBefore = await models.TicketState.findById(ticketId, null, options);
await closure(ctx, models.Ticket, tickets, options);
const ticketStateAfter = await models.TicketState.findById(ticketId, null, options);
expect(ticketStateBefore.code).not.toBe(ticketStateAfter.code);
const ticketAfter = await models.TicketState.findById(ticketId, null, options);
expect(ticketAfter.refFk).toBeUndefined();
});
it('should send Incoterms authorization email on first order', async() => {
const ticketId = 37;
ctx.args = {
id: ticketId,
};
const ticket = await models.Ticket.findById(ticketId, null, options);
spyOn(Email.prototype, 'send').and.returnValue(Promise.resolve());
await models.Ticket.closeByTicket(ctx, options);
const sample = await models.Sample.findOne({
where: {code: 'incoterms-authorization'},
fields: ['id']
},
options);
const insertedSample = await models.ClientSample.findOne({
where: {
clientFk: ticket.clientFk,
typeFk: sample.id,
companyFk: companyFk
}
}, options);
expect(insertedSample.clientFk).toEqual(ticket.clientFk);
});
it('should report failed tickets and set client email to null', async() => {
const ticketId = 37;
const clientId = 1110;
const tickets = [{
id: ticketId,
clientFk: clientId,
companyFk,
addressFk: 1,
isToBeMailed: true,
recipient: 'invalid@example.com',
salesPersonFk: userId
}];
spyOn(Email.prototype, 'send').and.callFake(() => {
const error = new Error('Invalid email');
error.responseCode = 450;
return Promise.reject(error);
});
await closure(ctx, models.Ticket, tickets, options);
const client = await models.Client.findById(clientId, null, options);
expect(client.email).toBeNull();
const reportEmail = await smtp.send({
to: config.app.reportEmail,
subject: '[API] Nightly ticket closure report',
html: `This following tickets have failed:`
});
expect(reportEmail).not.toBeNull();
});
});

View File

@ -21,7 +21,7 @@ describe('ticket filter()', () => {
} }
}); });
it('should return the tickets matching the problems on true', async() => { it('should return at least one ticket matching the problems on true', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
try { try {
@ -41,7 +41,15 @@ describe('ticket filter()', () => {
const filter = {}; const filter = {};
const result = await models.Ticket.filter(ctx, filter, options); const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toBeGreaterThan(3); const hasProblemTicket = result.some(ticket =>
ticket.isFreezed === true ||
ticket.hasRisk === true ||
ticket.hasTicketRequest === true ||
(typeof ticket.hasRounding === 'string' && ticket.hasRounding.trim().length > 0) ||
(typeof ticket.itemShortage === 'string' && ticket.itemShortage.trim().length > 0)
);
expect(hasProblemTicket).toBe(true);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -71,7 +79,13 @@ describe('ticket filter()', () => {
const filter = {}; const filter = {};
const result = await models.Ticket.filter(ctx, filter, options); const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(11); result.forEach(ticket => {
expect(ticket.isFreezed).toEqual(null);
expect(ticket.hasRisk).toEqual(null);
expect(ticket.hasTicketRequest).toEqual(null);
expect(ticket.itemShortage).toEqual(null);
expect(ticket.hasRounding).toEqual(null);
});
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -65,7 +65,7 @@ describe('ticket isEditableOrThrow()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 1}}}; const ctx = {req: {accessToken: {userId: 1}}};
await models.Ticket.isEditableOrThrow(ctx, 15, options); await models.Ticket.isEditableOrThrow(ctx, 17, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
error = e; error = e;

View File

@ -33,8 +33,6 @@ module.exports = function(Self) {
require('../methods/ticket/deliveryNoteCsvEmail')(Self); require('../methods/ticket/deliveryNoteCsvEmail')(Self);
require('../methods/ticket/closeAll')(Self); require('../methods/ticket/closeAll')(Self);
require('../methods/ticket/closeByTicket')(Self); require('../methods/ticket/closeByTicket')(Self);
require('../methods/ticket/closeByAgency')(Self);
require('../methods/ticket/closeByRoute')(Self);
require('../methods/ticket/getTicketsFuture')(Self); require('../methods/ticket/getTicketsFuture')(Self);
require('../methods/ticket/merge')(Self); require('../methods/ticket/merge')(Self);
require('../methods/ticket/getTicketsAdvance')(Self); require('../methods/ticket/getTicketsAdvance')(Self);

View File

@ -33,7 +33,7 @@ class Email extends Component {
const attachments = []; const attachments = [];
const getAttachments = async(componentPath, files) => { const getAttachments = async(componentPath, files) => {
for (const file of files) { for (const file of files) {
const fileCopy = Object.assign({}, file); const fileCopy = {...file};
const fileName = fileCopy.filename; const fileName = fileCopy.filename;
if (options.overrideAttachments && !fileName.includes('.png')) continue; if (options.overrideAttachments && !fileName.includes('.png')) continue;