diff --git a/back/methods/mrw-config/specs/createShipment.spec.js b/back/methods/mrw-config/specs/createShipment.spec.js
index 1ab77f608..c8a5295f7 100644
--- a/back/methods/mrw-config/specs/createShipment.spec.js
+++ b/back/methods/mrw-config/specs/createShipment.spec.js
@@ -12,9 +12,8 @@ const ticket1 = {
'addressFk': 1,
'agencyModeFk': 999
};
-
+let expedition;
const expedition1 = {
- 'id': 17,
'agencyModeFk': 999,
'ticketFk': 44,
'freightItemFk': 71,
@@ -47,7 +46,7 @@ describe('MRWConfig createShipment()', () => {
await createMrwConfig();
await models.Ticket.create(ticket1);
- await models.Expedition.create(expedition1);
+ expedition = await models.Expedition.create(expedition1);
});
afterAll(async() => {
@@ -93,7 +92,7 @@ describe('MRWConfig createShipment()', () => {
}
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);
});
@@ -101,7 +100,7 @@ describe('MRWConfig createShipment()', () => {
it('should fail if mrwConfig has no data', async() => {
let error;
await models.MrwConfig.destroyAll();
- await models.MrwConfig.createShipment(expedition1.id).catch(e => {
+ await models.MrwConfig.createShipment(expedition.id).catch(e => {
error = e;
}).finally(async() => {
expect(error.message).toEqual(`MRW service is not configured`);
@@ -126,7 +125,7 @@ describe('MRWConfig createShipment()', () => {
yesterday.setDate(yesterday.getDate() - 1);
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;
}).finally(async() => {
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() => {
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();
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() => {
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();
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() => {
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();
expect(notification).toEqual(null);
diff --git a/back/models/buyer.json b/back/models/buyer.json
index a17d3b538..a1297eda3 100644
--- a/back/models/buyer.json
+++ b/back/models/buyer.json
@@ -15,6 +15,9 @@
"nickname": {
"type": "string",
"required": true
+ },
+ "display": {
+ "type": "boolean"
}
},
"acls": [
diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql
index 6fbd34274..91de1dc05 100644
--- a/db/dump/fixtures.before.sql
+++ b/db/dump/fixtures.before.sql
@@ -179,12 +179,12 @@ INSERT INTO `vn`.`country`(`id`, `name`, `isUeeMember`, `code`, `currencyFk`, `i
(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`)
- VALUES
- (1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ VALUES (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),
(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),
(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),
(60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0);
@@ -335,21 +335,21 @@ INSERT INTO `vn`.`payDem`(`id`, `payDem`)
(2, 20),
(7, 0);
-INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`)
+INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`, `hasDailyInvoice`)
VALUES
- (1, 'Autonomy one', 1),
- (2, 'Autonomy two', 1),
- (3, 'Autonomy three', 2),
- (4, 'Autonomy four', 13);
+ (1, 'Autonomy one', 1, 1),
+ (2, 'Autonomy two', 1, 0),
+ (3, 'Autonomy three', 2, 0),
+ (4, 'Autonomy four', 13, 0);
INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `autonomyFk`, `warehouseFk`)
VALUES
- (1, 'Province one', 1, 1, NULL),
- (2, 'Province two', 1, 1, NULL),
- (3, 'Province three', 30, 2, NULL),
- (4, 'Province four', 2, 3, NULL),
- (5, 'Province five', 13, 4, NULL);
+ (1, 'Province one', 1, 1, NULL),
+ (2, 'Province two', 1, 1, NULL),
+ (3, 'Province three', 30, 2, NULL),
+ (4, 'Province four', 2, 3, NULL),
+ (5, 'Province five', 13, 4, NULL);
INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`)
VALUES
@@ -361,11 +361,11 @@ INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`)
INSERT INTO `vn`.`postCode`(`code`, `townFk`, `geoFk`)
VALUES
- ('46000', 1, 6),
- ('46460', 2, 6),
- ('46680', 3, 6),
- ('46600', 4, 7),
- ('EC170150', 5, 8);
+ ('46000', 1, 6),
+ ('46460', 2, 6),
+ ('46680', 3, 6),
+ ('46600', 4, 7),
+ ('EC170150', 5, 8);
INSERT INTO `vn`.`clientType`(`code`, `type`)
VALUES
@@ -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'),
(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'),
- (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'),
(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()),
(13, 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()),
(17, 2, 19, util.VN_NOW()),
- (18, 2, 19, util.VN_NOW()),
+ (37, 10, 19, util.VN_NOW()),
(19, 2, 19, util.VN_NOW()),
(20, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)),
(21, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)),
@@ -1031,19 +1031,20 @@ INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`)
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, `created`, `counter`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`, `hostFk`)
VALUES
- (1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, 'UR9000006041', 94, 1, 'pc1'),
- (2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 18, 'UR9000006041', 94, 1, NULL),
- (3, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 18, 'UR9000006041', 94, 2, NULL),
- (4, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 18, 'UR9000006041', 94, 2, NULL),
- (5, 1, 2, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 3, NULL),
- (6, 7, 3, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 18, NULL, 94, 3, NULL),
- (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), 1, 18, NULL, 94, NULL,NULL),
- (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), 1, 18, NULL, 94, 1, NULL),
- (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 2, 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),
- (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);
+ (1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, 'UR9000006041', 94, 1, 'pc1'),
+ (2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 18, 'UR9000006041', 94, 1, NULL),
+ (3, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 18, 'UR9000006041', 94, 2, NULL),
+ (4, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 18, 'UR9000006041', 94, 2, NULL),
+ (5, 1, 2, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 3, NULL),
+ (6, 7, 3, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 18, NULL, 94, 3, NULL),
+ (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), 1, 18, NULL, 94, NULL,NULL),
+ (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), 1, 18, NULL, 94, 1, NULL),
+ (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 2, 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),
+ (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),
+ (14, 1, 37, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL);
INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`)
@@ -1478,7 +1479,8 @@ INSERT INTO `vn`.`ticketWeekly`(`ticketFk`, `weekDay`)
(2, 1),
(3, 2),
(5, 6),
- (15, 6);
+ (15, 6),
+ (17, 6);
INSERT INTO `vn`.`awb` (id, code, package, weight, created, amount, transitoryFk, taxFk)
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);
INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyModeFk`, `m3`, `kg`,`ref`, `totalEntries`, `cargoSupplierFk`, `awbFK`)
- 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),
- (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),
- (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),
- (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),
- (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);
+ 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),
+ (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),
+ (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),
+ (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),
+ (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),
+ (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`)
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'),
(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, ''),
- (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`)
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), 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
(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),
@@ -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()),
(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()),
- (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`)
VALUES
@@ -3932,44 +3936,38 @@ INSERT INTO vn.medicalReview
(id, workerFk, centerFk, `date`, `time`, isFit, amount, invoice, remark)
VALUES(3, 9, 2, '2000-01-01', '8:00', 1, 150.0, NULL, NULL);
-INSERT INTO vn.payrollComponent
-(id, name, isSalaryAgreed, isVariable, isException)
- VALUES
- (1, 'Salario1', 1, 0, 0),
+INSERT INTO vn.stockBought (workerFk, bought, reserve, dated)
+ VALUES(35, 1.00, 1.00, '2001-01-01');
+
+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),
(3, 'Salario3', 1, 0, 1);
-
-INSERT INTO vn.workerIncome
-(debit, credit, incomeTypeFk, paymentDate, workerFk, concept)
- VALUES
- (1000.00, 900.00, 2, '2000-01-01', 1106, NULL),
+INSERT INTO vn.workerIncome (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);
+INSERT INTO dipole.printer (id, description) VALUES(1, '');
-INSERT INTO dipole.printer (id, description)
-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);
-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);
+INSERT INTO vn.accountDetail (id, value, accountDetailTypeFk, supplierAccountFk)
+ VALUES (21, 'ES12345B12345678', 3, 241),
+ (35, 'ES12346B12345679', 3, 241);
-INSERT INTO vn.accountDetail
-(id, value, accountDetailTypeFk, supplierAccountFk)
-VALUES
- (21, 'ES12345B12345678', 3, 241),
- (35, 'ES12346B12345679', 3, 241);
+INSERT INTO vn.accountDetailType (id, description, code)
+ VALUES (1, 'IBAN', 'iban'),
+ (2, 'SWIFT', 'swift'),
+ (3, 'Referencia Remesas', 'remRef'),
+ (4, 'Referencia Transferencias', 'trnRef'),
+ (5, 'Referencia Nominas', 'payRef'),
+ (6, 'ABA', 'aba');
-INSERT INTO vn.accountDetailType
-(id, description, code)
-VALUES
- (1, 'IBAN', 'iban'),
- (2, 'SWIFT', 'swift'),
- (3, 'Referencia Remesas', 'remRef'),
- (4, 'Referencia Transferencias', 'trnRef'),
- (5, 'Referencia Nominas', 'payRef'),
- (6, 'ABA', 'aba');
-
-INSERT IGNORE INTO ormConfig
+INSERT IGNORE INTO ormConfig
SET id =1,
selectLimit = 1000;
diff --git a/db/routines/vn/procedures/stockBought_calculate.sql b/db/routines/vn/procedures/stockBought_calculate.sql
new file mode 100644
index 000000000..6eabe015c
--- /dev/null
+++ b/db/routines/vn/procedures/stockBought_calculate.sql
@@ -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 ;
diff --git a/db/routines/vn/views/buyer.sql b/db/routines/vn/views/buyer.sql
index 4f668d35d..e690dc16f 100644
--- a/db/routines/vn/views/buyer.sql
+++ b/db/routines/vn/views/buyer.sql
@@ -2,10 +2,12 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`buyer`
AS SELECT DISTINCT `u`.`id` AS `userFk`,
- `u`.`nickname` AS `nickname`
+ `u`.`nickname` AS `nickname`,
+ `ic`.`display` AS `display`
FROM (
`account`.`user` `u`
JOIN `vn`.`itemType` `it` ON(`it`.`workerFk` = `u`.`id`)
+ JOIN `vn`.`itemCategory` `ic` ON(`ic`.`id` = `it`.`categoryFk`)
)
WHERE `u`.`active` <> 0
ORDER BY `u`.`nickname`
diff --git a/db/versions/11115-turquoiseRose/00-firstScript.sql b/db/versions/11115-turquoiseRose/00-firstScript.sql
new file mode 100644
index 000000000..3982936fc
--- /dev/null
+++ b/db/versions/11115-turquoiseRose/00-firstScript.sql
@@ -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');
+
diff --git a/db/versions/11235-purpleCordyline/00-firstScript.sql b/db/versions/11235-purpleCordyline/00-firstScript.sql
new file mode 100644
index 000000000..f3bb6ddab
--- /dev/null
+++ b/db/versions/11235-purpleCordyline/00-firstScript.sql
@@ -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;
diff --git a/e2e/paths/05-ticket/09_weekly.spec.js b/e2e/paths/05-ticket/09_weekly.spec.js
index 1caf91f9c..370d422e6 100644
--- a/e2e/paths/05-ticket/09_weekly.spec.js
+++ b/e2e/paths/05-ticket/09_weekly.spec.js
@@ -19,7 +19,7 @@ describe('Ticket descriptor path', () => {
it('should count the amount of tickets in the turns section', async() => {
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() => {
@@ -106,7 +106,7 @@ describe('Ticket descriptor path', () => {
await page.doSearch();
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() => {
diff --git a/loopback/locale/en.json b/loopback/locale/en.json
index 1753d1d07..352e08826 100644
--- a/loopback/locale/en.json
+++ b/loopback/locale/en.json
@@ -235,9 +235,10 @@
"Cannot add holidays on this day": "Cannot add holidays on this day",
"Cannot send mail": "Cannot send mail",
"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",
"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 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"
+}
\ No newline at end of file
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 1093fe326..49c44a4d8 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -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",
"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",
- "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",
"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",
"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",
"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",
"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"
}
\ No newline at end of file
diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js
index 61ca344e9..0eee6a123 100644
--- a/modules/account/back/models/mail-alias-account.js
+++ b/modules/account/back/models/mail-alias-account.js
@@ -1,5 +1,6 @@
const ForbiddenError = require('vn-loopback/util/forbiddenError');
+const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.rewriteDbError(function(err) {
diff --git a/modules/entry/back/methods/entry/print.js b/modules/entry/back/methods/entry/print.js
index 5b9de9a69..11abf0788 100644
--- a/modules/entry/back/methods/entry/print.js
+++ b/modules/entry/back/methods/entry/print.js
@@ -52,7 +52,7 @@ module.exports = Self => {
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(`
UPDATE buy
diff --git a/modules/entry/back/methods/entry/specs/filter.spec.js b/modules/entry/back/methods/entry/specs/filter.spec.js
index c7156062a..145da170a 100644
--- a/modules/entry/back/methods/entry/specs/filter.spec.js
+++ b/modules/entry/back/methods/entry/specs/filter.spec.js
@@ -39,7 +39,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options);
- expect(result.length).toEqual(11);
+ expect(result.length).toEqual(12);
await tx.rollback();
} catch (e) {
@@ -131,7 +131,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options);
- expect(result.length).toEqual(10);
+ expect(result.length).toEqual(11);
await tx.rollback();
} catch (e) {
diff --git a/modules/entry/back/methods/stock-bought/getStockBought.js b/modules/entry/back/methods/stock-bought/getStockBought.js
new file mode 100644
index 000000000..94e206ece
--- /dev/null
+++ b/modules/entry/back/methods/stock-bought/getStockBought.js
@@ -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);
+ };
+};
diff --git a/modules/entry/back/methods/stock-bought/getStockBoughtDetail.js b/modules/entry/back/methods/stock-bought/getStockBoughtDetail.js
new file mode 100644
index 000000000..6f09f1f67
--- /dev/null
+++ b/modules/entry/back/methods/stock-bought/getStockBoughtDetail.js
@@ -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]
+ );
+ };
+};
diff --git a/modules/entry/back/model-config.json b/modules/entry/back/model-config.json
index dc7fd86be..85f5e8285 100644
--- a/modules/entry/back/model-config.json
+++ b/modules/entry/back/model-config.json
@@ -25,5 +25,8 @@
},
"EntryType": {
"dataSource": "vn"
+ },
+ "StockBought": {
+ "dataSource": "vn"
}
}
\ No newline at end of file
diff --git a/modules/entry/back/models/stock-bought.js b/modules/entry/back/models/stock-bought.js
new file mode 100644
index 000000000..ae52e7654
--- /dev/null
+++ b/modules/entry/back/models/stock-bought.js
@@ -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;
+ });
+};
diff --git a/modules/entry/back/models/stock-bought.json b/modules/entry/back/models/stock-bought.json
new file mode 100644
index 000000000..18c9f0347
--- /dev/null
+++ b/modules/entry/back/models/stock-bought.json
@@ -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"
+ }
+ }
+}
diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js
index 47dbcbea4..bab1fa375 100644
--- a/modules/invoiceOut/back/models/invoice-out.js
+++ b/modules/invoiceOut/back/models/invoice-out.js
@@ -83,8 +83,10 @@ module.exports = Self => {
const invoiceOutSerial = await Self.app.models.InvoiceOutSerial.findById(serial);
if (invoiceOutSerial?.taxAreaFk == 'WORLD') {
const address = await Self.app.models.Address.findById(addressId);
- if (!address || !address.customsAgentFk || !address.incotermsFk)
- throw new UserError('The address of the customer must have information about Incoterms and Customs Agent');
+ if (!address?.customsAgentFk || !address.incotermsFk) {
+ throw new UserError(
+ 'The address of the customer must have information about Incoterms and Customs Agent');
+ }
}
return serial;
diff --git a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js
index 9460addfa..738af5219 100644
--- a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js
+++ b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js
@@ -39,7 +39,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
- expect(result.length).toBeGreaterThan(10);
+ expect(result.length).toBeGreaterThan(9);
await tx.rollback();
} catch (e) {
@@ -146,13 +146,20 @@ describe('SalesMonitor salesFilter()', () => {
try {
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 filter = {order: 'alertLevel ASC'};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
- const firstRow = result[0];
- expect(result.length).toEqual(15);
- expect(firstRow.alertLevel).not.toEqual(0);
+ result.forEach(row => {
+ expect(row.alertLevel).toBeGreaterThan(alertLevelFree);
+ });
await tx.rollback();
} catch (e) {
diff --git a/modules/ticket/back/methods/ticket-weekly/filter.js b/modules/ticket/back/methods/ticket-weekly/filter.js
index a43b5e270..6c9ed4f8b 100644
--- a/modules/ticket/back/methods/ticket-weekly/filter.js
+++ b/modules/ticket/back/methods/ticket-weekly/filter.js
@@ -38,13 +38,14 @@ module.exports = Self => {
Object.assign(myOptions, options);
const where = buildFilter(ctx.args, (param, value) => {
- switch (param) {
- case 'search':
- return {or: [
- {'t.id': value},
- {'c.id': value},
- {'c.name': {like: `%${value}%`}}
- ]};
+ if (param === 'search') {
+ return {
+ or: [
+ {'t.id': value},
+ {'c.id': value},
+ {'c.name': {like: `%${value}%`}}
+ ]
+ };
}
});
diff --git a/modules/ticket/back/methods/ticket-weekly/specs/filter.spec.js b/modules/ticket/back/methods/ticket-weekly/specs/filter.spec.js
index 453b7924f..9b1ad5209 100644
--- a/modules/ticket/back/methods/ticket-weekly/specs/filter.spec.js
+++ b/modules/ticket/back/methods/ticket-weekly/specs/filter.spec.js
@@ -13,11 +13,11 @@ describe('ticket-weekly filter()', () => {
const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}};
const result = await models.TicketWeekly.filter(ctx, null, options);
-
+ const totalRecords = await models.TicketWeekly.count();
const firstRow = result[0];
expect(firstRow.ticketFk).toEqual(2);
- expect(result.length).toEqual(4);
+ expect(result.length).toEqual(totalRecords);
await tx.rollback();
} catch (e) {
diff --git a/modules/ticket/back/methods/ticket/closeByAgency.js b/modules/ticket/back/methods/ticket/closeByAgency.js
deleted file mode 100644
index eb1aee349..000000000
--- a/modules/ticket/back/methods/ticket/closeByAgency.js
+++ /dev/null
@@ -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'
- };
- };
-};
diff --git a/modules/ticket/back/methods/ticket/closeByRoute.js b/modules/ticket/back/methods/ticket/closeByRoute.js
deleted file mode 100644
index 58e130b8e..000000000
--- a/modules/ticket/back/methods/ticket/closeByRoute.js
+++ /dev/null
@@ -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'
- };
- };
-};
diff --git a/modules/ticket/back/methods/ticket/closeByTicket.js b/modules/ticket/back/methods/ticket/closeByTicket.js
index 8884897c2..40fe048a5 100644
--- a/modules/ticket/back/methods/ticket/closeByTicket.js
+++ b/modules/ticket/back/methods/ticket/closeByTicket.js
@@ -23,11 +23,25 @@ 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 tickets = await Self.rawSql(`
- SELECT
+ SELECT
t.id,
t.clientFk,
t.companyFk,
@@ -37,7 +51,8 @@ module.exports = Self => {
c.isToBeMailed,
c.hasToInvoice,
co.hasDailyInvoice,
- eu.email salesPersonEmail
+ eu.email salesPersonEmail,
+ t.addressFk
FROM expedition e
JOIN ticket t ON t.id = e.ticketFk
JOIN ticketState ts ON ts.ticketFk = t.id
@@ -49,9 +64,14 @@ module.exports = Self => {
WHERE al.code = 'PACKED'
AND t.id = ?
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 {
message: 'Success'
diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js
index 4622ba271..a75596bac 100644
--- a/modules/ticket/back/methods/ticket/closure.js
+++ b/modules/ticket/back/methods/ticket/closure.js
@@ -1,13 +1,22 @@
-/* eslint max-len: ["error", { "code": 150 }]*/
-
const Report = require('vn-print/core/report');
const Email = require('vn-print/core/email');
const smtp = require('vn-print/core/smtp');
const config = require('vn-print/core/config');
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 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;
const failedtickets = [];
@@ -17,7 +26,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
await Self.rawSql(
`CALL vn.ticket_closeByTicket(?)`,
[ticket.id],
- {userId}
+ myOptions
);
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 company cny ON cny.id = io.companyFk
WHERE t.id = ?
- `, [ticket.id]);
+ `, [ticket.id], myOptions);
const mailOptions = {
overrideAttachments: true,
@@ -63,7 +72,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
await Self.rawSql(
'UPDATE invoiceOut SET hasPdf = true WHERE id = ?',
[invoiceOut.id],
- {userId},
+ myOptions
);
if (isToBeMailed) {
@@ -108,7 +117,9 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
WHERE t.clientFk = ?
AND NOT t.isDeleted
AND c.isVies
- `, [ticket.clientFk]);
+ `,
+ [ticket.clientFk],
+ myOptions);
if (firstOrder == 1) {
const args = {
@@ -127,20 +138,22 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
SELECT id
FROM sample
WHERE code = 'incoterms-authorization'
- `);
+ `,
+ null,
+ myOptions);
await Self.rawSql(`
INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?)
- `, [ticket.clientFk, sample.id, ticket.companyFk], {userId});
+ `,
+ [ticket.clientFk, sample.id, ticket.companyFk],
+ myOptions);
}
} catch (error) {
- // Domain not found
if (error.responseCode == 450) {
await invalidEmail(ticket);
continue;
}
- // Save tickets on a list of failed ids
failedtickets.push({
id: ticket.id,
stacktrace: error,
@@ -148,7 +161,6 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
}
}
- // Send email with failed tickets
if (failedtickets.length > 0) {
let body = 'This following tickets have failed:
';
@@ -164,11 +176,14 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
}).catch(err => console.error(err));
}
+ if (tx)
+ await tx.commit();
+
async function invalidEmail(ticket) {
await Self.rawSql(
`UPDATE client SET email = NULL WHERE id = ?`,
[ticket.clientFk],
- {userId},
+ myOptions
);
const body = `No se ha podido enviar el albarán ${ticket.id}
diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js
index f8d0af8ef..339ac1e38 100644
--- a/modules/ticket/back/methods/ticket/saveCmr.js
+++ b/modules/ticket/back/methods/ticket/saveCmr.js
@@ -39,7 +39,7 @@ module.exports = Self => {
}, myOptions);
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) {
const hasDmsCmr = await Self.rawSql(`
diff --git a/modules/ticket/back/methods/ticket/specs/closure.spec.js b/modules/ticket/back/methods/ticket/specs/closure.spec.js
new file mode 100644
index 000000000..303c38233
--- /dev/null
+++ b/modules/ticket/back/methods/ticket/specs/closure.spec.js
@@ -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();
+ });
+});
diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js
index 72249fe5d..d0edb24e3 100644
--- a/modules/ticket/back/methods/ticket/specs/filter.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js
@@ -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({});
try {
@@ -41,7 +41,15 @@ describe('ticket filter()', () => {
const filter = {};
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();
} catch (e) {
@@ -71,7 +79,13 @@ describe('ticket filter()', () => {
const filter = {};
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();
} catch (e) {
diff --git a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js
index 883b0de2e..1a8025f09 100644
--- a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js
@@ -65,7 +65,7 @@ describe('ticket isEditableOrThrow()', () => {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 1}}};
- await models.Ticket.isEditableOrThrow(ctx, 15, options);
+ await models.Ticket.isEditableOrThrow(ctx, 17, options);
await tx.rollback();
} catch (e) {
error = e;
diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js
index 12161d5f5..7fe968b26 100644
--- a/modules/ticket/back/models/ticket-methods.js
+++ b/modules/ticket/back/models/ticket-methods.js
@@ -33,8 +33,6 @@ module.exports = function(Self) {
require('../methods/ticket/deliveryNoteCsvEmail')(Self);
require('../methods/ticket/closeAll')(Self);
require('../methods/ticket/closeByTicket')(Self);
- require('../methods/ticket/closeByAgency')(Self);
- require('../methods/ticket/closeByRoute')(Self);
require('../methods/ticket/getTicketsFuture')(Self);
require('../methods/ticket/merge')(Self);
require('../methods/ticket/getTicketsAdvance')(Self);
diff --git a/print/core/email.js b/print/core/email.js
index a0bcf9122..a673685bb 100644
--- a/print/core/email.js
+++ b/print/core/email.js
@@ -33,7 +33,7 @@ class Email extends Component {
const attachments = [];
const getAttachments = async(componentPath, files) => {
for (const file of files) {
- const fileCopy = Object.assign({}, file);
+ const fileCopy = {...file};
const fileName = fileCopy.filename;
if (options.overrideAttachments && !fileName.includes('.png')) continue;