diff --git a/Jenkinsfile b/Jenkinsfile
index 8f87ffe61..85914ad62 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -49,7 +49,7 @@ pipeline {
NODE_ENV = ""
}
steps {
- nodejs('node-lts') {
+ nodejs('node-v12') {
sh 'npm install --no-audit --prefer-offline'
sh 'gulp install --ci'
}
@@ -66,14 +66,14 @@ pipeline {
parallel {
stage('Frontend') {
steps {
- nodejs('node-lts') {
+ nodejs('node-v12') {
sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2'
}
}
}
// stage('Backend') {
// steps {
- // nodejs('node-lts') {
+ // nodejs('node-v12') {
// sh 'gulp launchBackTest --ci'
// }
// }
@@ -89,7 +89,7 @@ pipeline {
CREDS = credentials('docker-registry')
}
steps {
- nodejs('node-lts') {
+ nodejs('node-v12') {
sh 'gulp build'
}
diff --git a/back/methods/dms/updateFile.js b/back/methods/dms/updateFile.js
index 4182148f7..314761932 100644
--- a/back/methods/dms/updateFile.js
+++ b/back/methods/dms/updateFile.js
@@ -38,8 +38,7 @@ module.exports = Self => {
{
arg: 'hasFile',
type: 'Boolean',
- description: 'True if has an attached file',
- required: true
+ description: 'True if has an attached file'
},
{
arg: 'hasFileAttached',
diff --git a/db/changes/10281-valentineDay/00-item_getBalance.sql b/db/changes/10281-valentineDay/00-item_getBalance.sql
new file mode 100644
index 000000000..96c82cc01
--- /dev/null
+++ b/db/changes/10281-valentineDay/00-item_getBalance.sql
@@ -0,0 +1,137 @@
+DROP PROCEDURE `vn`.`item_getBalance`;
+
+DELIMITER $$
+$$
+CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`item_getBalance`(IN vItemId INT, IN vWarehouse INT)
+BEGIN
+ DECLARE vDateInventory DATETIME;
+ DECLARE vCurdate DATE DEFAULT CURDATE();
+ DECLARE vDayEnd DATETIME DEFAULT util.dayEnd(vCurdate);
+
+ SELECT inventoried INTO vDateInventory FROM config;
+ SET @a = 0;
+ SET @currentLineFk = 0;
+ SET @shipped = '';
+
+ SELECT DATE(@shipped:= shipped) shipped,
+ alertLevel,
+ stateName,
+ origin,
+ reference,
+ clientFk,
+ name,
+ `in`,
+ `out`,
+ @a := @a + IFNULL(`in`,0) - IFNULL(`out`,0) as balance,
+ @currentLineFk := IF (@shipped < CURDATE()
+ OR (@shipped = CURDATE() AND (isPicked OR alertLevel >= 2)),
+ lineFk,@currentLineFk) lastPreparedLineFk,
+ isTicket,
+ lineFk,
+ isPicked,
+ clientType
+ FROM
+ ( SELECT tr.landed AS shipped,
+ b.quantity AS `in`,
+ NULL AS `out`,
+ al.alertLevel AS alertLevel,
+ st.name AS stateName,
+ s.name AS name,
+ e.ref AS reference,
+ e.id AS origin,
+ s.id AS clientFk,
+ IF(al.alertLevel = 3, TRUE, FALSE) isPicked,
+ FALSE AS isTicket,
+ b.id lineFk,
+ NULL `order`,
+ NULL AS clientType
+ FROM buy b
+ JOIN entry e ON e.id = b.entryFk
+ JOIN travel tr ON tr.id = e.travelFk
+ JOIN supplier s ON s.id = e.supplierFk
+ JOIN alertLevel al ON al.alertLevel =
+ CASE
+ WHEN tr.shipped < CURDATE() THEN 3
+ WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
+ ELSE 0
+ END
+ JOIN state st ON st.code = al.code
+ WHERE tr.landed >= vDateInventory
+ AND vWarehouse = tr.warehouseInFk
+ AND b.itemFk = vItemId
+ AND e.isInventory = FALSE
+ AND e.isRaid = FALSE
+ UNION ALL
+
+ SELECT tr.shipped,
+ NULL as `in`,
+ b.quantity AS `out`,
+ al.alertLevel AS alertLevel,
+ st.name AS stateName,
+ s.name AS name,
+ e.ref AS reference,
+ e.id AS origin,
+ s.id AS clientFk,
+ IF(al.alertLevel = 3, TRUE, FALSE) isPicked,
+ FALSE AS isTicket,
+ b.id,
+ NULL `order`,
+ NULL AS clientType
+ FROM buy b
+ JOIN entry e ON e.id = b.entryFk
+ JOIN travel tr ON tr.id = e.travelFk
+ JOIN warehouse w ON w.id = tr.warehouseOutFk
+ JOIN supplier s ON s.id = e.supplierFk
+ JOIN alertLevel al ON al.alertLevel =
+ CASE
+ WHEN tr.shipped < CURDATE() THEN 3
+ WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
+ ELSE 0
+ END
+ JOIN state st ON st.code = al.code
+ WHERE tr.shipped >= vDateInventory
+ AND vWarehouse =tr.warehouseOutFk
+ AND s.id <> 4
+ AND b.itemFk = vItemId
+ AND e.isInventory = FALSE
+ AND w.isFeedStock = FALSE
+ AND e.isRaid = FALSE
+ UNION ALL
+
+ SELECT DATE(t.shipped),
+ NULL as `in`,
+ s.quantity AS `out`,
+ al.alertLevel AS alertLevel,
+ st.name AS stateName,
+ t.nickname AS name,
+ t.refFk AS reference,
+ t.id AS origin,
+ t.clientFk,
+ stk.id AS isPicked,
+ TRUE AS isTicket,
+ s.id,
+ st.`order`,
+ ct.code AS clientType
+ FROM sale s
+ JOIN ticket t ON t.id = s.ticketFk
+ LEFT JOIN ticketState ts ON ts.ticket = t.id
+ LEFT JOIN state st ON st.code = ts.code
+ JOIN client c ON c.id = t.clientFk
+ JOIN clientType ct ON ct.id = c.clientTypeFk
+ JOIN alertLevel al ON al.alertLevel =
+ CASE
+ WHEN t.shipped < curdate() THEN 3
+ WHEN t.shipped > util.dayEnd(curdate()) THEN 0
+ ELSE IFNULL(ts.alertLevel, 0)
+ END
+ LEFT JOIN state stPrep ON stPrep.`code` = 'PREPARED'
+ LEFT JOIN saleTracking stk ON stk.saleFk = s.id AND stk.stateFk = stPrep.id
+ WHERE t.shipped >= vDateInventory
+ AND s.itemFk = vItemId
+ AND vWarehouse =t.warehouseFk
+ ORDER BY shipped, alertLevel DESC, isTicket, `order` DESC, isPicked DESC, `in` DESC, `out` DESC
+ ) AS itemDiary;
+
+END$$
+DELIMITER ;
+
diff --git a/db/changes/10281-valentineDay/00-supplier.sql b/db/changes/10281-valentineDay/00-supplier.sql
new file mode 100644
index 000000000..c35a86a23
--- /dev/null
+++ b/db/changes/10281-valentineDay/00-supplier.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `vn`.`supplier` ADD COLUMN `workerFk` INT(11) NULL DEFAULT NULL COMMENT 'Responsible for approving invoices' AFTER `isTrucker`;
+ALTER TABLE `vn`.`supplier` ADD CONSTRAINT `supplier_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE;
\ No newline at end of file
diff --git a/db/changes/10281-valentineDay/delete.keep b/db/changes/10281-valentineDay/delete.keep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index 3200cf4ab..d821c7bfc 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -1233,11 +1233,11 @@ INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`)
(104, 500),
(105, 5000);
-INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`)
+INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`)
VALUES
- (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1),
- (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8),
- (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3);
+ (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18),
+ (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18),
+ (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18);
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index fe35dcfe3..ca521f445 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -316,7 +316,7 @@ export default {
fourthRelevancy: 'vn-item-tags vn-horizontal:nth-child(4) [ng-model="itemTag.priority"]',
fourthRemoveTagButton: 'vn-item-tags vn-horizontal:nth-child(4) vn-icon-button[icon="delete"]',
fifthTag: 'vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[ng-model="itemTag.tagFk"]',
- fifthValue: 'vn-item-tags vn-horizontal:nth-child(5) vn-textfield[ng-model="itemTag.value"]',
+ fifthValue: 'vn-item-tags vn-horizontal:nth-child(5) vn-autocomplete[ng-model="itemTag.value"]',
fifthRelevancy: 'vn-item-tags vn-horizontal:nth-child(5) vn-input-number[ng-model="itemTag.priority"]',
sixthTag: 'vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[ng-model="itemTag.tagFk"]',
sixthValue: 'vn-item-tags vn-horizontal:nth-child(6) vn-textfield[ng-model="itemTag.value"]',
diff --git a/e2e/paths/04-item/04_tags.spec.js b/e2e/paths/04-item/04_tags.spec.js
index 9f2a8e295..574ff7562 100644
--- a/e2e/paths/04-item/04_tags.spec.js
+++ b/e2e/paths/04-item/04_tags.spec.js
@@ -16,7 +16,7 @@ describe('Item create tags path', () => {
await browser.close();
});
- it(`should create a new tag and delete a former one`, async() => {
+ it('should create a new tag and delete a former one', async() => {
await page.waitToClick(selectors.itemTags.fourthRemoveTagButton);
await page.waitToClick(selectors.itemTags.addItemTagButton);
await page.autocompleteSearch(selectors.itemTags.seventhTag, 'Ancho de la base');
@@ -29,7 +29,7 @@ describe('Item create tags path', () => {
expect(message.text).toContain('Data saved!');
});
- it(`should confirm the fourth row data is the expected one`, async() => {
+ it('should confirm the fourth row data is the expected one', async() => {
await page.reloadSection('item.card.tags');
await page.waitForSelector('vn-item-tags');
let result = await page.waitToGetProperty(selectors.itemTags.fourthTag, 'value');
@@ -47,7 +47,7 @@ describe('Item create tags path', () => {
expect(result).toEqual('4');
});
- it(`should confirm the fifth row data is the expected one`, async() => {
+ it('should confirm the fifth row data is the expected one', async() => {
let tag = await page
.waitToGetProperty(selectors.itemTags.fifthTag, 'value');
@@ -62,7 +62,7 @@ describe('Item create tags path', () => {
expect(relevancy).toEqual('5');
});
- it(`should confirm the sixth row data is the expected one`, async() => {
+ it('should confirm the sixth row data is the expected one', async() => {
let tag = await page
.waitToGetProperty(selectors.itemTags.sixthTag, 'value');
diff --git a/modules/item/back/methods/item/getBalance.js b/modules/item/back/methods/item/getBalance.js
index 26fc2a7dc..916757c46 100644
--- a/modules/item/back/methods/item/getBalance.js
+++ b/modules/item/back/methods/item/getBalance.js
@@ -20,8 +20,12 @@ module.exports = Self => {
});
Self.getBalance = async filter => {
- let where = filter.where;
+ const where = filter.where;
let [diary] = await Self.rawSql(`CALL vn.item_getBalance(?, ?)`, [where.itemFk, where.warehouseFk]);
+
+ for (const entry of diary)
+ if (entry.clientType === 'loses') entry.highlighted = true;
+
return diary;
};
};
diff --git a/modules/item/back/methods/item/specs/getBalance.spec.js b/modules/item/back/methods/item/specs/getBalance.spec.js
new file mode 100644
index 000000000..671b8c103
--- /dev/null
+++ b/modules/item/back/methods/item/specs/getBalance.spec.js
@@ -0,0 +1,33 @@
+const app = require('vn-loopback/server/server');
+const LoopBackContext = require('loopback-context');
+
+describe('item getBalance()', () => {
+ it('should return the balance lines of a client type loses in which one has highlighted true', async() => {
+ const activeCtx = {
+ accessToken: {userId: 9},
+ };
+ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
+ active: activeCtx
+ });
+
+ const losesClientId = 111;
+ const ticket = await app.models.Ticket.findById(7);
+ const originalClientId = ticket.clientFk;
+ await ticket.updateAttribute('clientFk', losesClientId);
+
+ const filter = {
+ where: {
+ itemFk: 1,
+ warehouseFk: 1
+ }
+ };
+ const results = await app.models.Item.getBalance(filter);
+
+ const result = results.find(element => element.clientType == 'loses');
+
+ expect(result.highlighted).toBe(true);
+
+ // restores
+ await ticket.updateAttribute('clientFk', originalClientId);
+ });
+});
diff --git a/modules/item/front/diary/index.html b/modules/item/front/diary/index.html
index 3fdc9a9e4..7c210a26a 100644
--- a/modules/item/front/diary/index.html
+++ b/modules/item/front/diary/index.html
@@ -64,14 +64,16 @@
{{::sale.stateName | dashIfEmpty}}
{{::sale.reference | dashIfEmpty}}
-
- {{::sale.name | dashIfEmpty}}
-
-
- {{::sale.name | dashIfEmpty}}
+
+
+ {{::sale.name | dashIfEmpty}}
+
+
+ {{::sale.name | dashIfEmpty}}
+
{{::sale.in | dashIfEmpty}}
diff --git a/modules/item/front/tags/index.html b/modules/item/front/tags/index.html
index 3775526be..c040b9984 100644
--- a/modules/item/front/tags/index.html
+++ b/modules/item/front/tags/index.html
@@ -32,14 +32,14 @@
rule>
{
'sageTaxTypeFk',
'sageTransactionTypeFk',
'sageWithholdingFk',
+ 'workerFk'
],
include: [
{
@@ -85,7 +86,19 @@ module.exports = Self => {
scope: {
fields: ['id', 'withholding']
}
- }
+ },
+ {
+ relation: 'worker',
+ scope: {
+ fields: ['userFk'],
+ include: {
+ relation: 'user',
+ scope: {
+ fields: ['nickname']
+ }
+ }
+ }
+ },
]
};
let supplier = await Self.app.models.Supplier.findOne(filter);
diff --git a/modules/supplier/back/models/supplier.json b/modules/supplier/back/models/supplier.json
index eb3c5989e..4ec568c8b 100644
--- a/modules/supplier/back/models/supplier.json
+++ b/modules/supplier/back/models/supplier.json
@@ -11,75 +11,78 @@
},
"properties": {
"id": {
- "type": "Number",
+ "type": "number",
"id": true,
"description": "Identifier"
},
"name": {
- "type": "String"
+ "type": "string"
},
"account": {
- "type": "String"
+ "type": "string"
},
"countryFk": {
- "type": "Number"
+ "type": "number"
},
"nif": {
- "type": "String"
+ "type": "string"
},
"isFarmer": {
- "type": "Boolean"
+ "type": "boolean"
},
"phone": {
- "type": "Number"
+ "type": "number"
},
"retAccount": {
- "type": "Number"
+ "type": "number"
},
"commission": {
- "type": "Boolean"
+ "type": "boolean"
},
"created": {
- "type": "Date"
+ "type": "date"
},
"postcodeFk": {
- "type": "Number"
+ "type": "number"
},
"isActive": {
- "type": "Boolean"
+ "type": "boolean"
},
"isOfficial": {
- "type": "Boolean"
+ "type": "boolean"
},
"isSerious": {
- "type": "Boolean"
+ "type": "boolean"
},
"note": {
- "type": "String"
+ "type": "string"
},
"street": {
- "type": "String"
+ "type": "string"
},
"city": {
- "type": "String"
+ "type": "string"
},
"provinceFk": {
- "type": "Number"
+ "type": "number"
},
"postCode": {
- "type": "String"
+ "type": "string"
},
"payMethodFk": {
- "type": "Number"
+ "type": "number"
},
"payDemFk": {
- "type": "Number"
+ "type": "number"
},
"payDay": {
- "type": "Number"
+ "type": "number"
},
"nickname": {
- "type": "String"
+ "type": "string"
+ },
+ "workerFk": {
+ "type": "number"
},
"sageTaxTypeFk": {
"type": "number",
@@ -126,6 +129,11 @@
"model": "Client",
"foreignKey": "nif",
"primaryKey": "fi"
+ },
+ "worker": {
+ "type": "belongsTo",
+ "model": "Worker",
+ "foreignKey": "workerFk"
},
"sageTaxType": {
"type": "belongsTo",
diff --git a/modules/supplier/front/basic-data/index.html b/modules/supplier/front/basic-data/index.html
index 72accfb5f..7d2f801a4 100644
--- a/modules/supplier/front/basic-data/index.html
+++ b/modules/supplier/front/basic-data/index.html
@@ -15,6 +15,17 @@
rule
vn-focus>
+
+
+
+
+ {{$ctrl.summary.worker.user.nickname}}
+
+
diff --git a/modules/supplier/front/summary/locale/es.yml b/modules/supplier/front/summary/locale/es.yml
index 6afaf857d..512b75f9d 100644
--- a/modules/supplier/front/summary/locale/es.yml
+++ b/modules/supplier/front/summary/locale/es.yml
@@ -6,4 +6,5 @@ Is Farmer: Es agrÃcola
Sage tax type: Tipo de impuesto Sage
Sage transaction type: Tipo de transacción Sage
Sage withholding: Retencion Sage
-Go to the supplier: Ir al proveedor
\ No newline at end of file
+Go to the supplier: Ir al proveedor
+Responsible: Responsable
\ No newline at end of file