3384-item_basic-data add field genericFk #807

Merged
joan merged 10 commits from 3384-item_basic-data into dev 2021-11-29 09:21:26 +00:00
24 changed files with 1381 additions and 986 deletions
Showing only changes of commit 9fce06dfe0 - Show all commits

View File

@ -1,6 +1,7 @@
const app = require('vn-loopback/server/server');
describe('newCollection()', () => {
// #3400 analizar que hacer con rutas de back colletion
xdescribe('newCollection()', () => {
it('return a new collection', async() => {
let ctx = {req: {accessToken: {userId: 1106}}};
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);

View File

@ -0,0 +1,27 @@
INSERT INTO `salix`.`ACL`
(model, property, accessType, permission, principalType, principalId)
VALUES
('EntryObservation', '*', '*', 'ALLOW', 'ROLE', 'buyer'),
('LdapConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin'),
('SambaConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin'),
('ACL', '*', '*', 'ALLOW', 'ROLE', 'developer'),
('AccessToken', '*', '*', 'ALLOW', 'ROLE', 'developer'),
('MailAliasAccount', '*', '*', 'ALLOW', 'ROLE', 'marketing'),
('MailAliasAccount', '*', '*', 'ALLOW', 'ROLE', 'hr'),
('MailAlias', '*', '*', 'ALLOW', 'ROLE', 'hr'),
('MailForward', '*', '*', 'ALLOW', 'ROLE', 'marketing'),
('MailForward', '*', '*', 'ALLOW', 'ROLE', 'hr'),
('RoleInherit', '*', '*', 'ALLOW', 'ROLE', 'it'),
('RoleRole', '*', '*', 'ALLOW', 'ROLE', 'it'),
('AccountConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin');
UPDATE `salix`.`ACL`
SET accessType='*', principalId='it'
WHERE model = 'Role';
DELETE FROM `salix`.`ACL`
WHERE id IN (280, 281);
UPDATE `salix`.`ACL`
SET accessType='*', principalId='marketing'
WHERE id=279;

View File

@ -0,0 +1,5 @@
UPDATE `salix`.`defaultViewConfig`
SET `columns` = '{"intrastat":false,"description":false,"density":false,"isActive":false,
"freightValue":false,"packageValue":false,"isIgnored":false,"price2":false,"ektFk":false,"weight":false,
"size":false,"comissionValue":false,"landing":false}'
WHERE tableCode = 'latestBuys'

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@ TABLES=(
ACL
fieldAcl
module
defaultViewConfig
)
dump_tables ${TABLES[@]}

View File

@ -8,7 +8,7 @@ describe('Entry observations path', () => {
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('developer', 'entry');
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('2');
await page.accessToSection('entry.card.observation');
});

View File

@ -59,13 +59,12 @@ describe('Account create and basic data path', () => {
await page.accessToSection('account.card.roles');
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
expect(rolesCount).toEqual(4);
expect(rolesCount).toEqual(3);
});
describe('Descriptor option', () => {
describe('Edit role', () => {
it('should edit the role using the descriptor menu', async() => {
await page.waitForTimeout(1000); // sometimes descriptor fails to load it's functionalities without this timeout
await page.waitToClick(selectors.accountDescriptor.menuButton);
await page.waitToClick(selectors.accountDescriptor.changeRole);
await page.autocompleteSearch(selectors.accountDescriptor.newRole, 'adminBoss');
@ -76,7 +75,7 @@ describe('Account create and basic data path', () => {
});
it('should reload the roles section to see now there are more roles', async() => {
// when role updated the db takes a while to return the changes, without this timeout the result would have been 4
// when role updates db takes time to return changes, without this timeout the result would have been 3
await page.waitForTimeout(1000);
await page.reloadSection('account.card.roles');
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);

View File

@ -8,7 +8,7 @@ describe('Account Role create and basic data path', () => {
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('developer', 'account');
await page.loginAndModule('it', 'account');
await page.accessToSection('account.role');
});
@ -76,11 +76,11 @@ describe('Account Role create and basic data path', () => {
expect(subrolesCount).toEqual(1);
});
it('should search for the employee role group then access to the roles inheritance section then check the roles listed are the expected ones', async() => {
it('should access the employee roles inheritance then check the roles listed are the expected ones', async() => {
await page.accessToSearchResult('employee');
await page.accessToSection('account.role.card.inherited');
const rolesCount = await page.countElement(selectors.accountRoleInheritance.anyResult);
expect(rolesCount).toEqual(7);
expect(rolesCount).toEqual(6);
});
});

View File

@ -29,5 +29,11 @@
"foreignKey": "mailAlias",
"property": "id"
}
}
},
"acls": [{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}]
}

View File

@ -5,14 +5,16 @@
<vn-item
ng-click="deleteUser.show()"
name="deleteUser"
vn-acl="developer"
vn-acl="it"
vn-acl-action="remove"
translate>
Delete
</vn-item>
<vn-item
ng-click="$ctrl.onChangeRole()"
name="changeRole"
vn-acl="developer"
vn-acl="hr"
vn-acl-action="remove"
translate>
Change role
</vn-item>
@ -20,13 +22,16 @@
ng-if="::$root.user.id == $ctrl.id"
ng-click="$ctrl.onChangePassClick(true)"
name="changePassword"
vn-acl="hr"
vn-acl-action="remove"
translate>
Change password
</vn-item>
<vn-item
ng-click="$ctrl.onChangePassClick(false)"
name="setPassword"
vn-acl="developer"
vn-acl="hr"
vn-acl-action="remove"
translate>
Set password
</vn-item>
@ -34,7 +39,8 @@
ng-if="!$ctrl.hasAccount"
ng-click="enableAccount.show()"
name="enableAccount"
vn-acl="developer"
vn-acl="it"
vn-acl-action="remove"
translate>
Enable account
</vn-item>
@ -42,7 +48,8 @@
ng-if="$ctrl.hasAccount"
ng-click="disableAccount.show()"
name="disableAccount"
vn-acl="developer"
vn-acl="it"
vn-acl-action="remove"
translate>
Disable account
</vn-item>
@ -50,7 +57,8 @@
ng-if="!$ctrl.user.active"
ng-click="activateUser.show()"
name="activateUser"
vn-acl="developer"
vn-acl="hr"
vn-acl-action="remove"
translate>
Activate user
</vn-item>
@ -58,7 +66,8 @@
ng-if="$ctrl.user.active"
ng-click="deactivateUser.show()"
name="deactivateUser"
vn-acl="developer"
vn-acl="hr"
vn-acl-action="remove"
translate>
Deactivate user
</vn-item>

View File

@ -5,40 +5,43 @@
model="model"
class="vn-w-sm">
<vn-card>
<div class="vn-list separated">
<a
ng-repeat="user in model.data track by user.id"
ui-sref="account.card.summary(::{id: user.id})"
translate-attr="{title: 'View user'}"
class="vn-item search-result">
<vn-item-section>
<h6>{{::user.nickname}}</h6>
<vn-label-value
label="Id"
value="{{::user.id}}">
</vn-label-value>
<vn-label-value
label="User"
value="{{::user.name}}">
</vn-label-value>
</vn-item-section>
<vn-item-section side>
<vn-icon-button
vn-click-stop="$ctrl.preview(user)"
vn-tooltip="Preview"
icon="preview">
</vn-icon-button>
</vn-item-section>
</a>
</div>
<div class="vn-list separated">
<a
ng-repeat="user in model.data track by user.id"
ui-sref="account.card.summary(::{id: user.id})"
translate-attr="{title: 'View user'}"
class="vn-item search-result">
<vn-item-section>
<h6>{{::user.nickname}}</h6>
<vn-label-value
label="Id"
value="{{::user.id}}">
</vn-label-value>
<vn-label-value
label="User"
value="{{::user.name}}">
</vn-label-value>
</vn-item-section>
<vn-item-section side>
<vn-icon-button
vn-click-stop="$ctrl.preview(user)"
vn-tooltip="Preview"
icon="preview">
</vn-icon-button>
</vn-item-section>
</a>
</div>
</vn-card>
</vn-data-viewer>
<vn-popup vn-id="summary">
<vn-user-summary user="$ctrl.selectedUser"></vn-user-summary>
</vn-popup>
<a ui-sref="account.create"
<a
fixed-bottom-right
ui-sref="account.create"
vn-tooltip="New user"
vn-bind="+"
fixed-bottom-right>
vn-acl="it"
vn-acl-action="remove">
<vn-float-button icon="add"></vn-float-button>
</a>

View File

@ -6,26 +6,26 @@
model="model"
class="vn-w-sm">
<vn-card>
<div class="vn-list separated">
<a
ng-repeat="role in model.data track by role.id"
ui-sref="account.role.card.summary(::{id: role.id})"
ui-sref-opts="{inherit: false}"
translate-attr="{title: 'View role'}"
class="vn-item search-result">
<vn-item-section>
<h6>{{::role.name}}</h6>
<div>{{::role.description}}</div>
</vn-item-section>
<vn-item-section side>
<vn-icon-button
vn-click-stop="$ctrl.preview(role)"
vn-tooltip="Preview"
icon="preview">
</vn-icon-button>
</vn-item-section>
</a>
</div>
<div class="vn-list separated">
<a
ng-repeat="role in model.data track by role.id"
ui-sref="account.role.card.summary(::{id: role.id})"
ui-sref-opts="{inherit: false}"
translate-attr="{title: 'View role'}"
class="vn-item search-result">
<vn-item-section>
<h6>{{::role.name}}</h6>
<div>{{::role.description}}</div>
</vn-item-section>
<vn-item-section side>
<vn-icon-button
vn-click-stop="$ctrl.preview(role)"
vn-tooltip="Preview"
icon="preview">
</vn-icon-button>
</vn-item-section>
</a>
</div>
</vn-card>
</vn-data-viewer>
<vn-popup vn-id="summary">
@ -35,7 +35,7 @@
ui-sref-opts="{inherit: false}"
vn-tooltip="New role"
vn-bind="+"
vn-acl="developer"
vn-acl="it"
vn-acl-action="remove"
fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>

View File

@ -41,24 +41,29 @@
"component": "vn-user",
"description": "Users",
"abstract": true
}, {
},
{
"url": "/index?q",
"state": "account.index",
"component": "vn-user-index",
"description": "Users",
"acl": ["hr"]
}, {
"acl": ["marketing", "hr"]
},
{
"url": "/create",
"state": "account.create",
"component": "vn-user-create",
"description": "New user"
}, {
"description": "New user",
"acl": ["it"]
},
{
"url": "/:id",
"state": "account.card",
"component": "vn-user-card",
"abstract": true,
"description": "Detail"
}, {
},
{
"url": "/summary",
"state": "account.card.summary",
"component": "vn-user-summary",
@ -66,88 +71,110 @@
"params": {
"user": "$ctrl.user"
}
}, {
},
{
"url": "/basic-data",
"state": "account.card.basicData",
"component": "vn-user-basic-data",
"description": "Basic data"
}, {
"description": "Basic data",
"acl": ["hr"]
},
{
"url": "/roles",
"state": "account.card.roles",
"component": "vn-user-roles",
"description": "Inherited roles"
}, {
"description": "Inherited roles",
"acl": ["it"]
},
{
"url": "/mail-forwarding",
"state": "account.card.mailForwarding",
"component": "vn-user-mail-forwarding",
"description": "Mail forwarding"
}, {
},
{
"url": "/aliases",
"state": "account.card.aliases",
"component": "vn-user-aliases",
"description": "Mail aliases"
}, {
"description": "Mail aliases",
"acl": ["marketing", "hr"]
},
{
"url": "/role?q",
"state": "account.role",
"component": "vn-role",
"description": "Roles"
}, {
"description": "Roles",
"acl": ["it"]
},
{
"url": "/create",
"state": "account.role.create",
"component": "vn-role-create",
"description": "New role"
}, {
"description": "New role",
"acl": ["it"]
},
{
"url": "/:id",
"state": "account.role.card",
"component": "vn-role-card",
"abstract": true,
"description": "Detail"
}, {
},
{
"url": "/summary",
"state": "account.role.card.summary",
"component": "vn-role-summary",
"description": "Summary",
"params": {
"role": "$ctrl.role"
}
}, {
},
"acl": ["it"]
},
{
"url": "/basic-data",
"state": "account.role.card.basicData",
"component": "vn-role-basic-data",
"description": "Basic data",
"acl": ["developer"],
"params": {
"role": "$ctrl.role"
}
}, {
},
"acl": ["it"]
},
{
"url": "/subroles",
"state": "account.role.card.subroles",
"component": "vn-role-subroles",
"acl": ["developer"],
"description": "Subroles"
}, {
"description": "Subroles",
"acl": ["it"]
},
{
"url": "/inherited",
"state": "account.role.card.inherited",
"component": "vn-role-inherited",
"description": "Inherited roles"
}, {
"description": "Inherited roles",
"acl": ["it"]
},
{
"url": "/alias?q",
"state": "account.alias",
"component": "vn-alias",
"description": "Mail aliases",
"acl": ["developer"]
}, {
"acl": ["marketing"]
},
{
"url": "/create",
"state": "account.alias.create",
"component": "vn-alias-create",
"description": "New alias"
}, {
},
{
"url": "/:id",
"state": "account.alias.card",
"component": "vn-alias-card",
"abstract": true,
"description": "Detail"
}, {
},
{
"url": "/summary",
"state": "account.alias.card.summary",
"component": "vn-alias-summary",
@ -155,7 +182,8 @@
"params": {
"alias": "$ctrl.alias"
}
}, {
},
{
"url": "/basic-data",
"state": "account.alias.card.basicData",
"component": "vn-alias-basic-data",
@ -163,50 +191,62 @@
"params": {
"alias": "$ctrl.alias"
}
}, {
},
{
"url": "/users",
"state": "account.alias.card.users",
"component": "vn-alias-users",
"description": "Users"
}, {
"description": "Users",
"acl": ["it"]
},
{
"url": "/accounts",
"state": "account.accounts",
"component": "vn-account-accounts",
"description": "Accounts",
"acl": ["developer"]
}, {
"acl": ["sysadmin"]
},
{
"url": "/ldap",
"state": "account.ldap",
"component": "vn-account-ldap",
"description": "LDAP",
"acl": ["developer"]
}, {
"acl": ["sysadmin"]
},
{
"url": "/samba",
"state": "account.samba",
"component": "vn-account-samba",
"description": "Samba",
"acl": ["developer"]
}, {
"acl": ["sysadmin"]
},
{
"url": "/acl?q",
"state": "account.acl",
"component": "vn-acl-component",
"description": "ACLs",
"acl": ["developer"]
}, {
},
{
"url": "/create",
"state": "account.acl.create",
"component": "vn-acl-create",
"description": "New ACL"
}, {
"description": "New ACL",
"acl": ["developer"]
},
{
"url": "/:id/edit",
"state": "account.acl.edit",
"component": "vn-acl-create",
"description": "Edit ACL"
}, {
"description": "Edit ACL",
"acl": ["developer"]
},
{
"url": "/connections",
"state": "account.connections",
"component": "vn-connections",
"description": "Connections"
"description": "Connections",
"acl": ["developer"]
}
]
}

View File

@ -73,6 +73,16 @@ module.exports = Self => {
arg: 'packingOut',
type: 'integer',
description: 'the packingOut',
},
{
arg: 'from',
type: 'date',
description: `The from date filter`
},
{
arg: 'to',
type: 'date',
description: `The to date filter`
}
],
returns: {
@ -117,6 +127,10 @@ module.exports = Self => {
return {'i.isActive': value};
case 'floramondo':
return {'i.isFloramondo': value};
case 'from':
return {'lb.landing': {gte: value}};
case 'to':
return {'lb.landing': {lte: value}};
case 'visible':
if (value)
return {'v.visible': {gt: 0}};
@ -176,7 +190,8 @@ module.exports = Self => {
b.price3,
b.ektFk,
b.weight,
b.packageFk
b.packageFk,
lb.landing
FROM cache.last_buy lb
LEFT JOIN cache.visible v ON v.item_id = lb.item_id
AND v.calc_id = @calc_id

View File

@ -172,5 +172,24 @@ describe('Buy latests buys filter()', () => {
expect(results.length).toBe(2);
});
it('should return results matching "from" and "to"', async() => {
const from = new Date();
from.setHours(0, 0, 0, 0);
const to = new Date();
to.setHours(23, 59, 59, 999);
let ctx = {
args: {
from: from,
to: to
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
expect(results.length).toBe(2);
});
});

View File

@ -58,6 +58,18 @@
<tpl-item>{{name}}: {{nickname}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-date-picker
vn-one
label="From"
ng-model="filter.from">
</vn-date-picker>
<vn-date-picker
vn-one
label="To"
ng-model="filter.to">
</vn-date-picker>
</vn-horizontal>
<vn-horizontal>
<vn-check
label="Is active"

View File

@ -112,6 +112,9 @@
<th field="packingOut">
<span translate>Package out</span>
</th>
<th field="landing">
<span translate>Landing</span>
</th>
</tr>
</thead>
<tbody>
@ -207,6 +210,7 @@
<td>{{::buy.weight}}</td>
<td>{{::buy.packageFk}}</td>
<td>{{::buy.packingOut}}</td>
<td>{{::buy.landing | date: 'dd/MM/yyyy'}}</td>
</tr>
</tbody>
</table>

View File

@ -61,6 +61,10 @@ export default class Controller extends Section {
field: 'isIgnored',
searchable: false
},
{
field: 'landing',
searchable: false
}
]
};
}
@ -76,7 +80,8 @@ export default class Controller extends Section {
{field: 'description', displayName: this.$t('Description')},
{field: 'size', displayName: this.$t('Size')},
{field: 'density', displayName: this.$t('Density')},
{field: 'packingOut', displayName: this.$t('PackingOut')}
{field: 'packingOut', displayName: this.$t('PackingOut')},
{field: 'landing', displayName: this.$t('Landing')}
];
return this._columns;
@ -112,6 +117,8 @@ export default class Controller extends Section {
return {'intr.description': value};
case 'origin':
return {'ori.code': value};
case 'landing':
return {[`lb.${param}`]: value};
case 'packing':
case 'grouping':
case 'quantity':

View File

@ -102,8 +102,8 @@ module.exports = Self => {
}
await sale.updateAttributes({price: newPrice}, myOptions);
query = `CALL vn.manaSpellersRequery(?)`;
await Self.rawSql(query, [userId], myOptions);
await Self.rawSql('CALL vn.manaSpellersRequery(?)', [userId], myOptions);
await Self.rawSql('CALL vn.ticket_recalc(?)', [sale.ticketFk], myOptions);
const salesPerson = sale.ticket().client().salesPersonUser();
if (salesPerson) {

View File

@ -66,7 +66,12 @@ module.exports = Self => {
}
}, myOptions);
const itemInfo = await models.Item.getVisibleAvailable(itemId, ticket.warehouseFk, ticket.shipped, myOptions);
const itemInfo = await models.Item.getVisibleAvailable(
itemId,
ticket.warehouseFk,
ticket.shipped,
myOptions
);
const isPackaging = item.family == 'EMB';
if (!isPackaging && itemInfo.available < quantity)
@ -80,6 +85,7 @@ module.exports = Self => {
}, myOptions);
await Self.rawSql('CALL vn.sale_calculateComponent(?, NULL)', [newSale.id], myOptions);
await Self.rawSql('CALL vn.ticket_recalc(?)', [id], myOptions);
const sale = await models.Sale.findById(newSale.id, {
include: {

View File

@ -85,9 +85,10 @@ module.exports = Self => {
};
if (sale.quantity == originalSale.quantity) {
await models.Sale.updateAll({
id: sale.id
}, {ticketFk: ticketId}, myOptions);
query = `UPDATE sale
SET ticketFk = ?
WHERE id = ?`;
await Self.rawSql(query, [ticketId, sale.id], myOptions);
} else if (sale.quantity != originalSale.quantity) {
await transferPartialSale(
ticketId, originalSale, sale, myOptions);
@ -170,29 +171,31 @@ module.exports = Self => {
// Update original sale
const rest = originalSale.quantity - sale.quantity;
const originalInstance = await models.Sale.findById(sale.id, null, options);
await originalInstance.updateAttribute('quantity', rest, options);
query = `UPDATE sale
SET quantity = ?
WHERE id = ?`;
await Self.rawSql(query, [rest, sale.id], options);
// Clone sale with new quantity
const newSale = originalSale;
newSale.id = undefined;
newSale.ticketFk = ticketId;
newSale.quantity = sale.quantity;
const createdSale = await models.Sale.create(newSale, options);
query = `INSERT INTO sale (itemFk, ticketFk, concept, quantity, originalQuantity, price, discount, priceFixed,
reserved, isPicked, isPriceFixed, isAdded)
SELECT itemFk, ?, concept, ?, originalQuantity, price, discount, priceFixed,
reserved, isPicked, isPriceFixed, isAdded
FROM sale
WHERE id = ?`;
await Self.rawSql(query, [ticketId, sale.quantity, sale.id], options);
const [lastInsertedSale] = await Self.rawSql('SELECT LAST_INSERT_ID() AS id', null, options);
// Clone sale components
const saleComponents = await models.SaleComponent.find({
where: {saleFk: sale.id}
}, options);
const newComponents = saleComponents.map(component => {
component.saleFk = createdSale.id;
component.saleFk = lastInsertedSale.id;
return component;
});
await models.SaleComponent.create(newComponents, options);
return originalInstance;
}
};

View File

@ -117,13 +117,15 @@ module.exports = Self => {
const updatedSale = sale.updateAttribute('discount', newDiscount, myOptions);
promises.push(newComponent, updatedSale);
changesMade += `\r\n-${sale.itemFk}: ${sale.concept} (${sale.quantity}) ${oldDiscount}% ➔ *${newDiscount}%*`;
const change = `${oldDiscount}% ➔ *${newDiscount}%*`;
changesMade += `\r\n-${sale.itemFk}: ${sale.concept} (${sale.quantity}) ${change}`;
}
await Promise.all(promises);
const query = `call vn.manaSpellersRequery(?)`;
await Self.rawSql(query, [userId], myOptions);
await Self.rawSql('CALL vn.manaSpellersRequery(?)', [userId], myOptions);
await Self.rawSql('CALL vn.ticket_recalc(?)', [id], myOptions);
const ticket = await models.Ticket.findById(id, {
include: {

View File

@ -127,6 +127,8 @@ class Controller extends Section {
resetChanges() {
if (this.newInstances().length === 0)
this.$.watcher.updateOriginalData();
this.card.reload();
}
changeState(value) {