Merge branch 'dev' into 3369-filterValue_sqli
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2021-11-23 08:54:50 +00:00
commit 51a3673160
16 changed files with 150 additions and 15 deletions

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.payMethod CHANGE ibanRequiredForClients isIbanRequiredForClients tinyint(3) DEFAULT 0 NULL;
ALTER TABLE vn.payMethod CHANGE ibanRequiredForSuppliers isIbanRequiredForSuppliers tinyint(3) DEFAULT 0 NULL;

View File

@ -217,7 +217,7 @@ UPDATE `vn`.`agencyMode` SET `web` = 1, `reportMail` = 'no-reply@gothamcity.com'
UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23;
INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt`, `ibanRequiredForClients`, `ibanRequiredForSuppliers`)
INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt`, `isIbanRequiredForClients`, `isIbanRequiredForSuppliers`)
VALUES
(1, NULL, 'PayMethod one', 0, 001, 0, 0),
(2, NULL, 'PayMethod two', 10, 001, 0, 0),
@ -806,7 +806,7 @@ INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `d
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0),
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0),
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0),
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 0),
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1),
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0),
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0),
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0),

View File

@ -138,7 +138,8 @@ module.exports = Self => {
function hasIban(err, done) {
Self.app.models.PayMethod.findById(this.payMethodFk, (_, instance) => {
if (instance && instance.ibanRequiredForClients && !this.iban)
const isMissingIban = instance && instance.isIbanRequiredForClients && !this.iban;
if (isMissingIban)
err();
done();
});

View File

@ -25,10 +25,10 @@
"outstandingDebt": {
"type": "Number"
},
"ibanRequiredForClients": {
"isIbanRequiredForClients": {
"type": "boolean"
},
"ibanRequiredForSuppliers": {
"isIbanRequiredForSuppliers": {
"type": "boolean"
}
}

View File

@ -19,7 +19,7 @@
vn-acl="salesAssistant"
ng-model="$ctrl.client.payMethodFk"
data="paymethods"
fields="['ibanRequiredForClients']"
fields="['isIbanRequiredForClients']"
initial-data="$ctrl.client.payMethod">
</vn-autocomplete>
<vn-input-number

View File

@ -17,8 +17,8 @@
<slot-body>
<div class="attributes">
<vn-label-value
label="Phone"
value="{{$ctrl.client.phone | phone}}">
label="Pay method"
value="{{$ctrl.client.payMethod.name}}">
</vn-label-value>
<vn-label-value
label="Credit"

View File

@ -3,4 +3,5 @@ View consumer report: Ver informe de consumo
From date: Fecha desde
To date: Fecha hasta
Go to user: Ir al usuario
Client invoices list: Listado de facturas del cliente
Client invoices list: Listado de facturas del cliente
Pay method: Forma de pago

View File

@ -39,6 +39,11 @@ module.exports = Self => {
type: 'integer',
description: 'The buyer of the item',
},
{
arg: 'supplierFk',
type: 'integer',
description: 'The supplier of the item',
},
{
arg: 'active',
type: 'boolean',
@ -49,6 +54,11 @@ module.exports = Self => {
type: 'boolean',
description: 'Whether the item is or not visible',
},
{
arg: 'floramondo',
type: 'boolean',
description: 'Whether the item is or not floramondo',
},
{
arg: 'typeFk',
type: 'integer',
@ -99,10 +109,14 @@ module.exports = Self => {
return {'ic.id': value};
case 'salesPersonFk':
return {'it.workerFk': value};
case 'supplierFk':
return {'s.id': value};
case 'code':
return {'it.code': value};
case 'active':
return {'i.isActive': value};
case 'floramondo':
return {'i.isFloramondo': value};
case 'visible':
if (value)
return {'v.visible': {gt: 0}};
@ -172,7 +186,9 @@ module.exports = Self => {
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
LEFT JOIN itemType t ON t.id = i.typeFk
LEFT JOIN intrastat intr ON intr.id = i.intrastatFk
LEFT JOIN origin ori ON ori.id = i.originFk`
LEFT JOIN origin ori ON ori.id = i.originFk
LEFT JOIN entry e ON e.id = b.entryFk AND e.created >= DATE_SUB(CURDATE(),INTERVAL 1 YEAR)
LEFT JOIN supplier s ON s.id = e.supplierFk`
);
if (ctx.args.tags) {

View File

@ -113,6 +113,30 @@ describe('Buy latests buys filter()', () => {
expect(results.length).toBe(0);
});
it('should return results matching "floramondo"', async() => {
let ctx = {
args: {
floramondo: true
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
expect(results.length).toBe(1);
});
it('should return results matching "not floramondo"', async() => {
let ctx = {
args: {
floramondo: false
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
expect(results.length).toBe(5);
});
it('should return results matching "salesPersonFk"', async() => {
let ctx = {
args: {
@ -136,5 +160,17 @@ describe('Buy latests buys filter()', () => {
expect(results.length).toBe(1);
});
it('should return results matching "supplierFk"', async() => {
let ctx = {
args: {
supplierFk: 1
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
expect(results.length).toBe(2);
});
});

View File

@ -46,6 +46,17 @@
where="{role: {inq: ['logistic', 'buyer']}}"
label="Buyer">
</vn-autocomplete>
<vn-autocomplete
vn-one
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-horizontal>
<vn-horizontal>
<vn-check
@ -58,6 +69,11 @@
ng-model="filter.visible"
triple-state="true">
</vn-check>
<vn-check
label="Is floramondo"
ng-model="filter.floramondo"
triple-state="true">
</vn-check>
</vn-horizontal>
<vn-horizontal class="vn-pt-sm">
<vn-one class="text-subtitle1" translate>

View File

@ -4,6 +4,8 @@ Freight value: Porte
Commission value: Comisión
Package value: Embalaje
Is ignored: Ignorado
Is visible: Visible
Is floramondo: Floramondo
Grouping price: Precio grouping
Packing price: Precio packing
Min price: Precio min

View File

@ -48,6 +48,11 @@ module.exports = Self => {
type: 'integer',
description: 'The buyer of the item',
},
{
arg: 'supplierFk',
type: 'integer',
description: 'The supplier of the item',
},
{
arg: 'description',
type: 'string',
@ -119,6 +124,8 @@ module.exports = Self => {
return {'ic.id': value};
case 'buyerFk':
return {'it.workerFk': value};
case 'supplierFk':
return {'s.id': value};
case 'origin':
return {'ori.code': value};
case 'intrastat':
@ -169,7 +176,9 @@ module.exports = Self => {
LEFT JOIN producer pr ON pr.id = i.producerFk
LEFT JOIN origin ori ON ori.id = i.originFk
LEFT JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = it.warehouseFk
LEFT JOIN vn.buy b ON b.id = lb.buy_id`
LEFT JOIN buy b ON b.id = lb.buy_id
LEFT JOIN entry e ON e.id = b.entryFk
LEFT JOIN supplier s ON s.id = e.supplierFk`
);
if (ctx.args.tags) {

View File

@ -70,8 +70,48 @@ describe('item filter()', () => {
const ctx = {args: {filter: filter, isFloramondo: true}};
const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(3);
expect(result[0].id).toEqual(9);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return 2 result filtering by buyerFk', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {};
const ctx = {args: {filter: filter, buyerFk: 16}};
const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(2);
expect(result[0].id).toEqual(13);
expect(result[0].id).toEqual(16);
expect(result[1].id).toEqual(71);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return 2 result filtering by supplierFk', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {};
const ctx = {args: {filter: filter, supplierFk: 1}};
const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(2);
expect(result[0].id).toEqual(1);
expect(result[1].id).toEqual(3);
await tx.rollback();
} catch (e) {

View File

@ -43,10 +43,21 @@
ng-model="filter.buyerFk"
url="Items/activeBuyers"
show-field="nickname"
search-function="{firstName: $search}"
search-function="{nickname: {like: '%'+ $search +'%'}}"
value-field="workerFk"
label="Buyer">
</vn-autocomplete>
<vn-autocomplete
vn-one
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-horizontal>
<vn-horizontal class="vn-pt-sm">
<vn-one class="text-subtitle1" translate>

View File

@ -79,8 +79,9 @@ module.exports = Self => {
const payMethod = await Self.app.models.PayMethod.findById(this.payMethodFk);
const supplierAccount = await Self.app.models.SupplierAccount.findOne({where: {supplierFk: this.id}});
const hasIban = supplierAccount && supplierAccount.iban;
const isMissingIban = payMethod && payMethod.isIbanRequiredForSuppliers && !hasIban;
if (payMethod && payMethod.ibanRequiredForSuppliers && !hasIban)
if (isMissingIban)
err();
done();

View File

@ -24,7 +24,7 @@
vn-acl="salesAssistant"
ng-model="$ctrl.supplier.payMethodFk"
data="paymethods"
fields="['ibanRequiredForSuppliers']"
fields="['isIbanRequiredForSuppliers']"
initial-data="$ctrl.supplier.payMethod">
</vn-autocomplete>
<vn-autocomplete