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

This commit is contained in:
Carlos Jimenez Ruiz 2021-12-21 11:44:16 +00:00
commit 31da353f07
18 changed files with 225 additions and 29 deletions

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`payMethod` ADD hasVerified TINYINT(1) DEFAULT 0 NULL;

View File

@ -0,0 +1,3 @@
UPDATE `vn`.`department`
SET `notificationEmail` = 'finanzas@verdnatura.es'
WHERE `name` = 'FINANZAS';

View File

@ -0,0 +1,2 @@
UPDATE `vn`.`supplier`
SET isPayMethodChecked = TRUE;

View File

@ -0,0 +1,33 @@
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`payment_afterInsert` AFTER INSERT ON `payment` FOR EACH ROW
BEGIN
DECLARE vIsPayMethodChecked BOOLEAN;
DECLARE vEmail VARCHAR(150);
SELECT isPayMethodChecked INTO vIsPayMethodChecked
FROM supplier
WHERE id = NEW.supplierFk;
IF vIsPayMethodChecked = FALSE THEN
SELECT notificationEmail INTO vEmail
FROM department
WHERE name = 'FINANZAS';
CALL mail_insert(
vEmail,
NULL,
'Pago con método sin verificar',
CONCAT(
'Se ha realizado el pago ',
NEW.id,
' al proveedor ',
NEW.supplierFk,
' con el método de pago sin verificar.'
)
);
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,26 @@
DROP TRIGGER IF EXISTS `vn`.`supplier_beforeUpdate`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`supplier_beforeUpdate`
BEFORE UPDATE ON `vn`.`supplier` FOR EACH ROW
BEGIN
DECLARE vHasChange BOOL DEFAULT FALSE;
DECLARE vPayMethodHasVerified BOOL;
SELECT hasVerified INTO vPayMethodHasVerified
FROM payMethod
WHERE id = NEW.payMethodFk;
SET vHasChange = (NEW.payDemFk <> OLD.payDemFk) OR (NEW.payDay <> OLD.payDay);
IF vPayMethodHasVerified AND !vHasChange THEN
SET vHasChange = (NEW.payMethodFk <> OLD.payMethodFk);
END IF;
IF vHasChange THEN
SET NEW.isPayMethodChecked = FALSE;
END IF;
END$$
DELIMITER ;

View File

@ -1 +0,0 @@
Delete me!

View File

@ -217,14 +217,14 @@ 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`, `isIbanRequiredForClients`, `isIbanRequiredForSuppliers`)
INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt`, `isIbanRequiredForClients`, `isIbanRequiredForSuppliers`, `hasVerified`)
VALUES
(1, NULL, 'PayMethod one', 0, 001, 0, 0),
(2, NULL, 'PayMethod two', 10, 001, 0, 0),
(3, 'compensation', 'PayMethod three', 0, 001, 0, 0),
(4, NULL, 'PayMethod with IBAN', 0, 001, 1, 0),
(5, NULL, 'PayMethod five', 10, 001, 0, 0),
(8,'wireTransfer', 'WireTransfer', 5, 001, 1, 1);
(1, NULL, 'PayMethod one', 0, 001, 0, 0, 0),
(2, NULL, 'PayMethod two', 10, 001, 0, 0, 1),
(3, 'compensation', 'PayMethod three', 0, 001, 0, 0, 0),
(4, NULL, 'PayMethod with IBAN', 0, 001, 1, 0, 0),
(5, NULL, 'PayMethod five', 10, 001, 0, 0, 0),
(8,'wireTransfer', 'WireTransfer', 5, 001, 1, 1, 0);
INSERT INTO `vn`.`payDem`(`id`, `payDem`)
VALUES

View File

@ -524,7 +524,7 @@ export default {
saturdayButton: '.vn-popup.shown vn-tool-bar > vn-button:nth-child(6)',
acceptDialog: '.vn-dialog.shown button[response="accept"]',
acceptChangeHourButton: '.vn-dialog.shown button[response="accept"]',
descriptorDeliveryDate: 'vn-ticket-descriptor slot-body > .attributes > vn-label-value:nth-child(3) > section > span',
descriptorDeliveryDate: 'vn-ticket-descriptor slot-body > .attributes > vn-label-value:nth-child(4) > section > span',
acceptInvoiceOutButton: '.vn-confirm.shown button[response="accept"]',
acceptDeleteStowawayButton: '.vn-dialog.shown button[response="accept"]'
},

View File

@ -8,7 +8,7 @@ describe('Supplier basic data path', () => {
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('administrative', 'supplier');
await page.loginAndModule('financial', 'supplier');
await page.accessToSearchResult('1');
await page.accessToSection('supplier.card.basicData');
});

View File

@ -214,5 +214,6 @@
"The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
"The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
"The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día"
"The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día",
"You can not modify is pay method checked": "No se puede modificar el campo método de pago validado"
}

View File

@ -8,6 +8,19 @@ describe('loopback model Supplier', () => {
beforeAll(async() => {
supplierOne = await models.Supplier.findById(1);
supplierTwo = await models.Supplier.findById(442);
const activeCtx = {
accessToken: {userId: 9},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
});
afterAll(async() => {
@ -32,19 +45,6 @@ describe('loopback model Supplier', () => {
});
it('should not throw if the payMethod id is valid', async() => {
const activeCtx = {
accessToken: {userId: 9},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
let error;
const supplier = await models.Supplier.findById(442);
await supplier.updateAttribute('payMethodFk', 4)
@ -54,5 +54,40 @@ describe('loopback model Supplier', () => {
expect(error).not.toBeDefined();
});
it('should have checked isPayMethodChecked for payMethod hasVerfified is false', async() => {
const supplier = await models.Supplier.findById(442);
await supplier.updateAttribute('isPayMethodChecked', true);
await supplier.updateAttribute('payMethodFk', 5);
const result = await models.Supplier.findById(442);
expect(result.isPayMethodChecked).toEqual(true);
});
it('should have unchecked isPayMethodChecked for payMethod hasVerfified is true', async() => {
const supplier = await models.Supplier.findById(442);
await supplier.updateAttribute('isPayMethodChecked', true);
await supplier.updateAttribute('payMethodFk', 2);
const result = await models.Supplier.findById(442);
expect(result.isPayMethodChecked).toEqual(false);
});
it('should have unchecked isPayMethodChecked for payDay and peyDemFk', async() => {
const supplier = await models.Supplier.findById(442);
await supplier.updateAttribute('isPayMethodChecked', true);
await supplier.updateAttribute('payDay', 5);
const firstResult = await models.Supplier.findById(442);
await supplier.updateAttribute('isPayMethodChecked', true);
await supplier.updateAttribute('payDemFk', 1);
const secondResult = await models.Supplier.findById(442);
expect(firstResult.isPayMethodChecked).toEqual(false);
expect(secondResult.isPayMethodChecked).toEqual(false);
});
});
});

View File

@ -1,5 +1,6 @@
const UserError = require('vn-loopback/util/user-error');
const validateTin = require('vn-loopback/util/validateTin');
const LoopBackContext = require('loopback-context');
module.exports = Self => {
require('../methods/supplier/filter')(Self);
@ -88,8 +89,24 @@ module.exports = Self => {
}
Self.observe('before save', async function(ctx) {
let changes = ctx.data || ctx.instance;
let orgData = ctx.currentInstance;
const loopbackContext = LoopBackContext.getCurrentContext();
const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance;
const userId = loopbackContext.active.accessToken.userId;
const isNotFinancial = !await Self.app.models.Account.hasRole(userId, 'financial');
const isPayMethodChecked = changes.isPayMethodChecked || orgData.isPayMethodChecked;
const hasChanges = orgData && changes;
const isPayMethodCheckedChanged = hasChanges
&& orgData.isPayMethodChecked != isPayMethodChecked;
if (isNotFinancial && isPayMethodCheckedChanged)
throw new UserError('You can not modify is pay method checked');
});
Self.observe('before save', async function(ctx) {
const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance;
const socialName = changes.name || orgData.name;
const hasChanges = orgData && changes;

View File

@ -38,7 +38,8 @@
</vn-check>
<vn-check
label="PayMethodChecked"
ng-model="$ctrl.supplier.isPayMethodChecked">
ng-model="$ctrl.supplier.isPayMethodChecked"
vn-acl="financial">
</vn-check>
</vn-horizontal>
<vn-horizontal>

View File

@ -11,7 +11,8 @@ export default class Controller extends Section {
}
onSubmit() {
return this.$.watcher.submit();
this.$.watcher.submit()
.then(() => this.card.reload());
}
}
@ -20,5 +21,8 @@ ngModule.vnComponent('vnSupplierBillingData', {
controller: Controller,
bindings: {
supplier: '<'
},
require: {
card: '^vnSupplierCard'
}
});

View File

@ -83,6 +83,11 @@ module.exports = Self => {
type: 'boolean',
description: `Whether to show only tickets with problems`
},
{
arg: 'hasRoute',
type: 'boolean',
description: `Whether to show only tickets with route`
},
{
arg: 'pending',
type: 'boolean',
@ -188,6 +193,10 @@ module.exports = Self => {
case 'alertLevel':
return {'ts.alertLevel': value};
case 'hasRoute':
if (value == true)
return {'t.routeFk': {neq: null}};
return {'t.routeFk': null};
case 'pending':
if (value) {
return {and: [
@ -266,7 +275,8 @@ module.exports = Self => {
LEFT JOIN state st ON st.id = ts.stateFk
LEFT JOIN client c ON c.id = t.clientFk
LEFT JOIN worker wk ON wk.id = c.salesPersonFk
LEFT JOIN account.user u ON u.id = wk.userFk`);
LEFT JOIN account.user u ON u.id = wk.userFk
LEFT JOIN route r ON r.id = t.routeFk`);
if (args.orderFk) {
stmt.merge({

View File

@ -221,4 +221,61 @@ describe('ticket filter()', () => {
throw e;
}
});
it('should return the tickets matching the route on true', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 9}}, args: {hasRoute: true}};
const filter = {};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(22);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the tickets matching the route on false', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 9}}, args: {hasRoute: false}};
const filter = {};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the tickets matching the route on null', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 9}}, args: {hasRoute: null}};
const filter = {};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(27);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -135,6 +135,12 @@
ng-model="filter.pending"
triple-state="true">
</vn-check>
<vn-check
vn-one
label="Has route"
ng-model="filter.hasRoute"
triple-state="true">
</vn-check>
</vn-horizontal>
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
<vn-submit label="Search"></vn-submit>

View File

@ -12,6 +12,7 @@ Order id: Id cesta
Grouped States: Estado agrupado
Days onward: Días adelante
With problems: Con problemas
Has route: Con ruta
Pending: Pendiente
FREE: Libre
DELIVERED: Servido