diff --git a/db/changes/10400-christmas/00-payMethod_hasVerified.sql b/db/changes/10400-christmas/00-payMethod_hasVerified.sql
new file mode 100644
index 000000000..280a9e097
--- /dev/null
+++ b/db/changes/10400-christmas/00-payMethod_hasVerified.sql
@@ -0,0 +1 @@
+ALTER TABLE `vn`.`payMethod` ADD hasVerified TINYINT(1) DEFAULT 0 NULL;
\ No newline at end of file
diff --git a/db/changes/10400-christmas/00-updateDepartment.sql b/db/changes/10400-christmas/00-updateDepartment.sql
new file mode 100644
index 000000000..ce46220ca
--- /dev/null
+++ b/db/changes/10400-christmas/00-updateDepartment.sql
@@ -0,0 +1,3 @@
+UPDATE `vn`.`department`
+ SET `notificationEmail` = 'finanzas@verdnatura.es'
+ WHERE `name` = 'FINANZAS';
\ No newline at end of file
diff --git a/db/changes/10400-christmas/00-updateSupplier.sql b/db/changes/10400-christmas/00-updateSupplier.sql
new file mode 100644
index 000000000..49fa2eb15
--- /dev/null
+++ b/db/changes/10400-christmas/00-updateSupplier.sql
@@ -0,0 +1,2 @@
+UPDATE `vn`.`supplier`
+ SET isPayMethodChecked = TRUE;
\ No newline at end of file
diff --git a/db/changes/10400-christmas/01-payment_afterInsert.sql b/db/changes/10400-christmas/01-payment_afterInsert.sql
new file mode 100644
index 000000000..f422ebce2
--- /dev/null
+++ b/db/changes/10400-christmas/01-payment_afterInsert.sql
@@ -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 ;
diff --git a/db/changes/10400-christmas/01-supplier_beforeUpdate.sql b/db/changes/10400-christmas/01-supplier_beforeUpdate.sql
new file mode 100644
index 000000000..b3ffccf9c
--- /dev/null
+++ b/db/changes/10400-christmas/01-supplier_beforeUpdate.sql
@@ -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 ;
diff --git a/db/changes/10400-christmas/delete.keep b/db/changes/10400-christmas/delete.keep
deleted file mode 100644
index 603d82d74..000000000
--- a/db/changes/10400-christmas/delete.keep
+++ /dev/null
@@ -1 +0,0 @@
-Delete me!
\ No newline at end of file
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index 3e99bd39e..1bc5a4fad 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -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
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index 24b87b398..8675797e7 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -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"]'
},
diff --git a/e2e/paths/13-supplier/02_basic_data.spec.js b/e2e/paths/13-supplier/02_basic_data.spec.js
index f98fa779e..4f3c49512 100644
--- a/e2e/paths/13-supplier/02_basic_data.spec.js
+++ b/e2e/paths/13-supplier/02_basic_data.spec.js
@@ -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');
});
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 00c642192..dc662e8d3 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -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"
}
\ No newline at end of file
diff --git a/modules/supplier/back/models/specs/supplier.spec.js b/modules/supplier/back/models/specs/supplier.spec.js
index 27bd873ad..3140981c3 100644
--- a/modules/supplier/back/models/specs/supplier.spec.js
+++ b/modules/supplier/back/models/specs/supplier.spec.js
@@ -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);
+ });
});
});
diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js
index 1ac6e3bd2..2912a3577 100644
--- a/modules/supplier/back/models/supplier.js
+++ b/modules/supplier/back/models/supplier.js
@@ -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;
diff --git a/modules/supplier/front/basic-data/index.html b/modules/supplier/front/basic-data/index.html
index 0ec80641d..9991908d4 100644
--- a/modules/supplier/front/basic-data/index.html
+++ b/modules/supplier/front/basic-data/index.html
@@ -38,7 +38,8 @@
+ ng-model="$ctrl.supplier.isPayMethodChecked"
+ vn-acl="financial">
diff --git a/modules/supplier/front/billing-data/index.js b/modules/supplier/front/billing-data/index.js
index 0c9cbb0dc..9d2863f64 100644
--- a/modules/supplier/front/billing-data/index.js
+++ b/modules/supplier/front/billing-data/index.js
@@ -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'
}
});
diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js
index 44ef7c486..58c440e95 100644
--- a/modules/ticket/back/methods/ticket/filter.js
+++ b/modules/ticket/back/methods/ticket/filter.js
@@ -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({
diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js
index 14ada5c6e..b251d5335 100644
--- a/modules/ticket/back/methods/ticket/specs/filter.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js
@@ -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;
+ }
+ });
});
diff --git a/modules/ticket/front/search-panel/index.html b/modules/ticket/front/search-panel/index.html
index 445729952..b0d4963bd 100644
--- a/modules/ticket/front/search-panel/index.html
+++ b/modules/ticket/front/search-panel/index.html
@@ -135,6 +135,12 @@
ng-model="filter.pending"
triple-state="true">
+
+
diff --git a/modules/ticket/front/search-panel/locale/es.yml b/modules/ticket/front/search-panel/locale/es.yml
index d6d01d0aa..52cc04d6e 100644
--- a/modules/ticket/front/search-panel/locale/es.yml
+++ b/modules/ticket/front/search-panel/locale/es.yml
@@ -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