2564-item_priceFixed + e2e #513

Merged
carlosjr merged 19 commits from 2564-item_priceFixed into dev 2021-01-20 14:34:07 +00:00
19 changed files with 158 additions and 60 deletions
Showing only changes of commit 464366fdbe - Show all commits

2
Jenkinsfile vendored
View File

@ -25,9 +25,11 @@ pipeline {
switch (env.BRANCH_NAME) {
case 'master':
env.NODE_ENV = 'production'
env.BACK_REPLICAS = 4
break
case 'test':
env.NODE_ENV = 'test'
env.BACK_REPLICAS = 2
break
}
}

View File

@ -48,7 +48,7 @@ module.exports = Self => {
throw new UserError(`You don't have enough privileges`);
if (process.env.NODE_ENV == 'test')
throw new UserError(`You can't upload images on the test instance`);
throw new UserError(`You can't upload images on the test environment`);
// Upload file to temporary path
const tempContainer = await TempContainer.container(args.collection);

View File

@ -0,0 +1,19 @@
DROP TRIGGER IF EXISTS `vn`.`itemTag_afterUpdate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`itemTag_afterUpdate`
AFTER UPDATE ON `itemTag` FOR EACH ROW
trig: BEGIN
IF @isTriggerDisabled THEN
LEAVE trig;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
SELECT NEW.itemFk id;
CALL item_refreshTags();
DROP TEMPORARY TABLE tmp.item;
END$$
DELIMITER ;

View File

@ -8,7 +8,7 @@ services:
ports:
- 80
deploy:
replicas: 3
replicas: 2
back:
image: registry.verdnatura.es/salix-back:${BRANCH_NAME:?}
build: .
@ -30,7 +30,7 @@ services:
- /mnt/storage/dms:/var/lib/salix/dms
- /mnt/storage/image:/var/lib/salix/image
deploy:
replicas: 6
replicas: ${BACK_REPLICAS:?}
configs:
datasources:
external: true

View File

@ -721,9 +721,9 @@ export default {
},
workerSummary: {
header: 'vn-worker-summary h5',
id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) > section > span',
email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span',
department: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span',
id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span',
email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span',
department: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(5) > section > span',
userId: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(2) > section > span',
userName: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(3) > section > span',
role: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(4) > section > span',

View File

@ -35,14 +35,13 @@ module.exports = Self => {
accountConfig
} = this;
let newEntry;
let dn = `uid=${userName},${this.userDn}`;
if (info.hasAccount) {
let {user} = info;
let oldUser = await client.searchOne(this.userDn, {
scope: 'sub',
attributes: ['userPassword', 'sambaNTPassword'],
filter: `&(uid=${userName})`
});
@ -52,7 +51,7 @@ module.exports = Self => {
? nameArgs.splice(1).join(' ')
: '-';
newEntry = {
let newEntry = {
uid: userName,
objectClass: [
'inetOrgPerson',
@ -101,62 +100,115 @@ module.exports = Self => {
if (newEntry[prop] == null)
delete newEntry[prop];
}
if (oldUser) {
let changes = [];
let skipProps = new Set([
'dn',
'controls'
]);
for (let prop in oldUser) {
let deleteProp = !skipProps.has(prop)
&& !newEntry.hasOwnProperty(prop);
if (!deleteProp) continue;
changes.push(new ldap.Change({
operation: 'delete',
modification: {
[prop]: oldUser[prop]
}
}));
}
for (let prop in newEntry) {
if (this.isEqual(oldUser[prop], newEntry[prop]))
continue;
changes.push(new ldap.Change({
operation: 'replace',
modification: {
[prop]: newEntry[prop]
}
}));
}
if (changes.length)
await client.modify(dn, changes);
} else
await client.add(dn, newEntry);
} else {
try {
await client.del(dn);
console.log(` -> User '${userName}' removed from LDAP`);
} catch (e) {
if (e.name !== 'NoSuchObjectError') throw e;
}
}
},
// Remove and recreate (if applicable) user
let dn = `uid=${userName},${this.userDn}`;
let operation;
try {
await client.del(dn);
operation = 'delete';
} catch (e) {
if (e.name !== 'NoSuchObjectError') throw e;
}
if (info.hasAccount) {
await client.add(dn, newEntry);
operation = 'add';
}
if (operation === 'delete')
console.log(` -> User '${userName}' removed from LDAP`);
isEqual(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length)
return false;
for (let element of a) {
if (b.indexOf(element) === -1)
return false;
}
return true;
} else
return a == b;
},
async syncUserGroups(userName, info) {
let {client} = this;
let {user} = info;
let groupDn = this.groupDn;
let opts = {
scope: 'sub',
attributes: ['dn'],
attributes: ['dn', 'cn'],
filter: `&(memberUid=${userName})(objectClass=posixGroup)`
};
let oldGroups = await client.searchAll(this.groupDn, opts);
let oldGroups = await client.searchAll(groupDn, opts);
let reqs = [];
for (let oldGroup of oldGroups) {
let change = new ldap.Change({
operation: 'delete',
modification: {memberUid: userName}
});
reqs.push(client.modify(oldGroup.dn, change));
let deleteGroups = [];
let addGroups = [];
if (info.hasAccount) {
let oldSet = new Set();
oldGroups.forEach(e => oldSet.add(e.cn));
let newSet = new Set();
user.roles().forEach(e => newSet.add(e.inherits().name));
for (let group of oldGroups) {
if (!newSet.has(group.cn))
deleteGroups.push(group.cn);
}
for (let role of user.roles()) {
if (!oldSet.has(role.inherits().name))
addGroups.push(role.inherits().name);
}
} else {
for (let group of oldGroups)
deleteGroups.push(group.cn);
}
await Promise.all(reqs);
if (!info.hasAccount) return;
reqs = [];
for (let role of info.user.roles()) {
let change = new ldap.Change({
operation: 'add',
modification: {memberUid: userName}
});
let roleName = role.inherits().name;
let dn = `cn=${roleName},${this.groupDn}`;
reqs.push(client.modify(dn, change));
async function applyOperations(groups, operation) {
for (let group of groups) {
try {
let dn = `cn=${group},${groupDn}`;
await client.modify(dn, new ldap.Change({
operation,
modification: {memberUid: userName}
}));
} catch (err) {
if (err.name !== 'NoSuchObjectError')
throw err;
}
}
}
await Promise.all(reqs);
await applyOperations(deleteGroups, 'delete');
await applyOperations(addGroups, 'add');
},
async getUsers(usersToSync) {

View File

@ -33,7 +33,7 @@ class Controller extends Section {
get reportParams() {
const userParams = this.$.model.userParams;
return Object.assign({
authorization: this.vnToken.token,
recipient: this.client.email,
recipientId: this.client.id
}, userParams);
}

View File

@ -93,7 +93,12 @@ module.exports = Self => {
let where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return {'e.id': value};
return /^\d+$/.test(value)
? {'e.id': value}
: {or: [
{'s.name': {like: `%${value}%`}},
{'s.nickname': {like: `%${value}%`}}
]};
case 'ref':
param = `e.${param}`;
return {[param]: {like: `%${value}%`}};
@ -141,6 +146,7 @@ module.exports = Self => {
e.invoiceInFk,
t.landed,
s.name AS supplierName,
s.nickname AS supplierAlias,
co.code AS companyCode,
cu.code AS currencyCode
FROM vn.entry e

View File

@ -8,11 +8,14 @@
<vn-searchbar
vn-focus
panel="vn-entry-search-panel"
info="Search entrys by id"
info="Search entry by id or a suppliers by name or alias"
model="model">
</vn-searchbar>
</vn-portal>
<vn-portal slot="menu">
<vn-left-menu></vn-left-menu>
</vn-portal>
<ui-view></ui-view>
<ui-view></ui-view>

View File

@ -5,7 +5,7 @@
vn-one
label="General search"
ng-model="filter.search"
info="Search entries by id"
info="Search entry by id or a suppliers by name or alias"
vn-focus>
</vn-textfield>
</vn-horizontal>
@ -45,8 +45,11 @@
label="Supplier"
ng-model="filter.supplierFk"
url="Suppliers"
fields="['name','nickname']"
search-function="{or: [{nickname: {like: '%'+ $search +'%'}}, {name: {like: '%'+ $search +'%'}}]}"
show-field="name"
value-field="id">
<tpl-item>{{name}}: {{nickname}}</tpl-item>
</vn-autocomplete>
<vn-date-picker
vn-one

View File

@ -4,4 +4,5 @@ Nickname: Alias
From: Desde
To: Hasta
Agency: Agencia
Warehouse: Almacén
Warehouse: Almacén
Search entry by id or a suppliers by name or alias: Buscar entrada por id o proveedores por nombre y alias

View File

@ -119,6 +119,7 @@ module.exports = Self => {
ori.code AS origin,
ic.name AS category,
i.density,
i.stemMultiplier,
b.grouping,
b.packing,
itn.code AS niche, @visibleCalc

View File

@ -65,7 +65,10 @@
"type": "number",
"description": "Density"
},
"image": {
"stemMultiplier": {
"type": "number",
"description": "Multiplier"
},"image": {
"type": "string",
"description": "Image"
},

View File

@ -25,6 +25,7 @@
<vn-th field="origin" shrink>Origin</vn-th>
<vn-th field="salesperson" shrink>Buyer</vn-th>
<vn-th field="density" shrink>Density</vn-th>
<vn-th field="stemMultiplier" shrink>Multiplier</vn-th>
<vn-th field="active" shrink>Active</vn-th>
<vn-th></vn-th>
</vn-tr>
@ -78,6 +79,7 @@
</span>
</vn-td>
<vn-td shrink>{{::item.density}}</vn-td>
<vn-td shrink >{{::item.stemMultiplier}}</vn-td>
<vn-td shrink>
<vn-check
disabled="true"

View File

@ -6,6 +6,7 @@
auto-load="true">
</vn-crud-model>
<vn-crud-model
vn-id="typesModel"
auto-load="true"
url="TicketServiceTypes"
data="ticketServiceTypes"

View File

@ -35,6 +35,10 @@ class Controller extends Section {
throw new UserError(`Name can't be empty`);
return this.$http.post(`TicketServiceTypes`, this.$.newServiceType)
.then(res => {
this.$.typesModel.refresh();
return res;
})
.then(res => service.ticketServiceTypeFk = res.data.id);
}

View File

@ -1,4 +1,5 @@
import './index.js';
import crudModel from 'core/mocks/crud-model';
describe('Ticket component vnTicketService', () => {
let controller;
@ -11,7 +12,7 @@ describe('Ticket component vnTicketService', () => {
beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => {
$httpBackend = _$httpBackend_;
$scope = $rootScope.$new();
$scope.typesModel = crudModel;
$element = angular.element(`<div></div>`);
controller = $componentController('vnTicketService', {$scope, $element});
}));

View File

@ -1,6 +1,6 @@
{
"name": "Calendar",
"base": "Loggable",
"base": "VnModel",
"log": {
"model": "WorkerLog",
"relation": "labour"

View File

@ -7,4 +7,4 @@ FROM client c
JOIN company AS cny
JOIN supplierAccount AS sa ON sa.id = cny.supplierAccountFk
JOIN bankEntity be ON be.id = sa.bankEntityFk
WHERE c.id = ? AND cny.id = ?`
WHERE c.id = ? AND cny.id = ?