Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2167-entry_buy
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2021-04-28 10:32:35 +02:00
commit 65457d6dac
19 changed files with 204 additions and 116 deletions

View File

@ -8,7 +8,9 @@ Salix is also the scientific name of a beautifull tree! :)
Required applications.
* Node.js = 14.15.1 LTS
* Node.js = 14.x LTS
* Docker
* Git
* Docker
You will need to install globally the following items.

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.`supplierAccount` ADD `beneficiary` VARCHAR(50) NULL DEFAULT NULL AFTER `bankFk`;
UPDATE vn.supplierAccount SET beneficiary = `description`;

View File

@ -1,24 +1,28 @@
drop procedure weekWaste;
DROP PROCEDURE IF EXISTS `bs`.`weekWaste`;
create definer = root@`%` procedure weekWaste__()
DELIMITER $$
$$
CREATE DEFINER = `root`@`%` PROCEDURE `bs`.`weekWaste__`()
BEGIN
DECLARE vWeek INT;
DECLARE vWeek INT;
DECLARE vYear INT;
SELECT week, year
INTO vWeek, vYear
FROM vn.time
WHERE dated = DATE_ADD(CURDATE(), INTERVAL -1 WEEK);
INTO vWeek, vYear
FROM vn.time
WHERE dated = DATE_ADD(CURDATE(), INTERVAL -1 WEEK);
SELECT *, 100 * dwindle / total AS percentage
FROM (
SELECT buyer,
sum(saleTotal) as total,
sum(saleWaste) as dwindle
FROM bs.waste
WHERE year = vYear and week = vWeek
GROUP BY buyer
) sub
ORDER BY percentage DESC;
END;
SELECT *, 100 * dwindle / total AS percentage
FROM (
SELECT buyer,
SUM(saleTotal) AS total,
SUM(saleWaste) AS dwindle
FROM bs.waste
WHERE year = vYear
AND week = vWeek
GROUP BY buyer
) sub
ORDER BY percentage DESC;
END;$$
DELIMITER ;

View File

@ -1,28 +1,32 @@
drop procedure weekWaste_byWorker;
DROP PROCEDURE IF EXISTS `bs`.`weekWaste_byWorker`;
create definer = root@`%` procedure weekWaste_byWorker__(IN vWorkerFk int)
DELIMITER $$
$$
CREATE
DEFINER = root@`%` PROCEDURE `bs`.`weekWaste_byWorker__`(IN vWorkerFk INT)
BEGIN
DECLARE vWeek INT;
DECLARE vWeek INT;
DECLARE vYear INT;
SELECT week, year
INTO vWeek, vYear
FROM vn.time
WHERE dated = TIMESTAMPADD(WEEK,-1,CURDATE());
INTO vWeek, vYear
FROM vn.time
WHERE dated = TIMESTAMPADD(WEEK, -1, CURDATE());
SELECT *, 100 * mermas / total as porcentaje
FROM (
SELECT ws.family,
sum(ws.saleTotal) as total,
sum(ws.saleWaste) as mermas
FROM bs.waste ws
SELECT *, 100 * mermas / total AS porcentaje
FROM (
SELECT ws.family,
SUM(ws.saleTotal) AS total,
SUM(ws.saleWaste) AS mermas
FROM bs.waste ws
JOIN vn.worker w ON w.user = ws.buyer
WHERE year = vYear AND week = vWeek
AND w.id = vWorkerFk
GROUP BY family
) sub
ORDER BY porcentaje DESC;
END;
WHERE year = vYear
AND week = vWeek
AND w.id = vWorkerFk
GROUP BY family
) sub
ORDER BY porcentaje DESC;
END;;$$
DELIMITER ;

View File

@ -1,25 +1,30 @@
drop procedure weekWaste_getDetail;
DROP PROCEDURE IF EXISTS `bs`.`weekWaste_getDetail`;
create definer = root@`%` procedure weekWaste_getDetail__()
DELIMITER $$
$$
CREATE
DEFINER = root@`%` PROCEDURE `bs`.`weekWaste_getDetail__`()
BEGIN
DECLARE vLastWeek DATE;
DECLARE vWeek INT;
DECLARE vLastWeek DATE;
DECLARE vWeek INT;
DECLARE vYear INT;
SET vLastWeek = TIMESTAMPADD(WEEK,-1,CURDATE());
SET vLastWeek = TIMESTAMPADD(WEEK, -1, CURDATE());
SET vYear = YEAR(vLastWeek);
SET vWeek = WEEK(vLastWeek, 1);
SELECT *, 100 * dwindle / total AS percentage
FROM (
SELECT buyer,
ws.family,
sum(ws.saleTotal) AS total,
sum(ws.saleWaste) AS dwindle
FROM bs.waste ws
WHERE year = vYear AND week = vWeek
GROUP BY buyer, family
) sub
ORDER BY percentage DESC;
END;
SELECT *, 100 * dwindle / total AS percentage
FROM (
SELECT buyer,
ws.family,
SUM(ws.saleTotal) AS total,
SUM(ws.saleWaste) AS dwindle
FROM bs.waste ws
WHERE year = vYear
AND week = vWeek
GROUP BY buyer, family
) sub
ORDER BY percentage DESC;
END;$$
DELIMITER ;

View File

@ -17,6 +17,5 @@ ALTER TABLE `bs`.`waste`
ALTER TABLE `bs`.`waste` DROP PRIMARY KEY;
ALTER TABLE `bs`.`waste`
AD PRIMARY KEY (buyer, year, week, family, itemFk);
ADD PRIMARY KEY (buyer, `year`, week, family, itemFk);

View File

@ -2,27 +2,28 @@ UPDATE `bs`.nightTask t SET t.`procedure` = 'waste_addSales' WHERE t.id = 54;
DROP PROCEDURE IF EXISTS `bs`.`waste_Add`;
DELIMITER $$
$$
CREATE
DEFINER = root@`%` PROCEDURE `bs`.`waste_addSales`()
DEFINER = root@`%` PROCEDURE `bs`.`waste_addSales`()
BEGIN
DECLARE vWeek INT;
DECLARE vYear INT;
SELECT week, year
DECLARE vYear INT;
SELECT week, year
INTO vWeek, vYear
FROM vn.time
WHERE dated = CURDATE();
FROM vn.time
WHERE dated = CURDATE();
REPLACE bs.waste
REPLACE bs.waste
SELECT *, 100 * mermas / total as porcentaje
FROM (
SELECT buyer,
year,
week,
week,
family,
itemFk,
itemTypeFk,
itemFk,
itemTypeFk,
floor(sum(value)) as total,
floor(sum(IF(clientTypeFk = 'loses', value, 0))) as mermas
FROM vn.saleValue
@ -32,7 +33,5 @@ BEGIN
) sub
ORDER BY mermas DESC;
END;
END;$$
DELIMITER ;

View File

@ -0,0 +1,3 @@
UPDATE salix.ACL
SET principalId = "salesAssistant"
WHERE model = 'Client' AND property = 'createReceipt';

View File

@ -128,7 +128,7 @@
</vn-data-viewer>
</div>
<vn-float-button
vn-acl="administrative"
vn-acl="salesAssistant"
vn-acl-action="remove"
icon="add"
vn-tooltip="New payment"

View File

@ -0,0 +1,64 @@
const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('loopback model Supplier-account', () => {
describe('create', () => {
const supplierId = 1;
const bankEntityId = 2100;
it('should throw an error when attempting to set an invalid iban account', async() => {
let error;
const expectedError = 'The IBAN does not have the correct format';
const iban = 'incorrect format';
try {
await app.models.SupplierAccount.create(
{
supplierFk: supplierId,
bankEntityFk: bankEntityId,
iban: iban
});
} catch (e) {
error = e;
expect(error.message).toContain(expectedError);
}
expect(error).toBeDefined();
});
it('should create a valid supplier account', async() => {
const tx = await app.models.Claim.beginTransaction({});
try {
const options = {transaction: tx};
const iban = 'ES91 2100 0418 4502 0005 1332';
const activeCtx = {
accessToken: {userId: 5},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
activeCtx.http.req.__ = value => {
return value;
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
const createdSupplierAccount = await app.models.SupplierAccount.create({
supplierFk: supplierId,
bankEntityFk: bankEntityId,
iban: iban
},
options);
expect(createdSupplierAccount.iban).toBe(iban);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});
});

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server');
describe('loopback model address', () => {
describe('loopback model Supplier', () => {
let supplierOne;
let supplierTwo;

View File

@ -0,0 +1,22 @@
const validateIban = require('vn-loopback/util/validateIban');
module.exports = Self => {
Self.validateAsync('iban', ibanValidation, {
message: 'The IBAN does not have the correct format'
});
async function ibanValidation(err, done) {
let filter = {
fields: ['code'],
where: {id: this.countryFk}
};
let country = await Self.app.models.Country.findOne(filter);
let code = country ? country.code.toLowerCase() : null;
if (code != 'es')
return done();
if (!validateIban(this.iban))
err();
done();
}
};

View File

@ -7,7 +7,7 @@
},
"options": {
"mysql": {
"table": "supplierAccount"
"table": "supplierAccount"
}
},
"properties": {
@ -16,39 +16,18 @@
"id": true,
"description": "Identifier"
},
"supplierFk": {
"type": "Number"
},
"iban": {
"type": "String"
},
"office": {
"beneficiary": {
"type": "String"
},
"DC": {
"type": "String"
},
"number": {
"type": "String"
},
"description": {
"type": "String"
},
"bicSufix": {
"type": "String"
},
"bankEntityFk": {
"type": "Number"
},
"bankFk": {
"type": "Number"
}
},
"relations": {
"supplier": {
"type": "belongsTo",
"model": "Supplier",
"foreignKey": "supplierFk"
"foreignKey": "supplierFk"
},
"bankEntity": {
"type": "belongsTo",

View File

@ -1,7 +1,7 @@
<vn-crud-model
vn-id="model"
url="SupplierAccounts"
fields="['id', 'supplierFk', 'iban', 'bankEntityFk']"
fields="['id', 'supplierFk', 'iban', 'bankEntityFk', 'beneficiary']"
link="{supplierFk: $ctrl.$params.id}"
include="$ctrl.include"
data="$ctrl.supplierAccounts"
@ -12,7 +12,7 @@
data="$ctrl.supplierAccounts"
form="form">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-lg">
<vn-card class="vn-pa-lg">
<vn-horizontal ng-repeat="supplierAccount in $ctrl.supplierAccounts">
<vn-textfield vn-three
@ -21,7 +21,7 @@
ng-model="supplierAccount.iban"
rule>
</vn-textfield>
<vn-autocomplete vn-two
<vn-autocomplete vn-three
label="Bank entity"
ng-model="supplierAccount.bankEntityFk"
url="BankEntities"
@ -35,6 +35,11 @@
ng-click="$ctrl.showBankEntity($event, $index)">
</vn-icon-button>
</append>
<vn-textfield vn-three
label="Beneficiary"
ng-model="supplierAccount.beneficiary"
info="Beneficiary information">
</vn-textfield>
<vn-none>
<vn-icon-button
vn-tooltip="Remove account"

View File

@ -0,0 +1 @@
Beneficiary information: Name of the bank account holder if different from the provider

View File

@ -1,3 +1,5 @@
Bank entity: Entidad bancaria
swift: Swift BIC
Add account: Añadir cuenta
Add account: Añadir cuenta
Beneficiary: Beneficiario
Beneficiary information: Nombre del titular de la cuenta bancaria en caso de ser diferente del proveedor

View File

@ -1,16 +1,13 @@
const UserError = require('vn-loopback/util/user-error');
const LoopBackContext = require('loopback-context');
module.exports = Self => {
Self.observe('before save', async ctx => {
const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const models = Self.app.models;
let changes = ctx.currentInstance || ctx.instance;
if (changes) {
let ticketId = changes.ticketFk;
let isEditable = await models.Ticket.isEditable(httpCtx, ticketId);
if (!isEditable)
let isLocked = await models.Ticket.isLocked(ticketId);
if (isLocked)
throw new UserError(`The current ticket can't be modified`);
if (changes.ticketServiceTypeFk) {
@ -21,13 +18,11 @@ module.exports = Self => {
});
Self.observe('before delete', async ctx => {
const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const models = Self.app.models;
const service = await models.TicketService.findById(ctx.where.id);
const isEditable = await models.Ticket.isEditable(httpCtx, service.ticketFk);
const isLocked = await models.Ticket.isLocked(service.ticketFk);
if (!isEditable)
if (isLocked)
throw new UserError(`The current ticket can't be modified`);
});
};

View File

@ -18,6 +18,7 @@
<vn-th field="name">Name</vn-th>
<vn-th field="isBox">Package type</vn-th>
<vn-th field="counter" number>Counter</vn-th>
<vn-th field="externalId" number>externalId</vn-th>
<vn-th field="worker">Worker</vn-th>
<vn-th field="created" expand>Created</vn-th>
</vn-tr>
@ -41,6 +42,7 @@
<vn-td>{{::expedition.packageItemName}}</vn-td>
<vn-td>{{::expedition.freightItemName}}</vn-td>
<vn-td number>{{::expedition.counter}}</vn-td>
<vn-td number>{{::expedition.externalId}}</vn-td>
<vn-td expand>
<span
class="link"

6
package-lock.json generated
View File

@ -17073,9 +17073,9 @@
}
},
"ssri": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
"integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
"integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
"dev": true,
"requires": {
"figgy-pudding": "^3.5.1"