diff --git a/client/client/src/credit-create/credit-create.html b/client/client/src/credit-create/credit-create.html
index 4d706aa02..5602e6432 100644
--- a/client/client/src/credit-create/credit-create.html
+++ b/client/client/src/credit-create/credit-create.html
@@ -5,7 +5,7 @@
form="form"
save="patch">
-
+
+
diff --git a/client/client/src/credit-create/credit-create.js b/client/client/src/credit-create/credit-create.js
index 2d0bccf56..54353ca9a 100644
--- a/client/client/src/credit-create/credit-create.js
+++ b/client/client/src/credit-create/credit-create.js
@@ -1,7 +1,44 @@
import ngModule from '../module';
+class Controller {
+ constructor($http, $scope, $state) {
+ this.$http = $http;
+ this.$scope = $scope;
+ this.$state = $state;
+ }
+
+ onSubmit() {
+ this.$http.get(`/client/api/Recoveries/${this.$state.params.id}/hasActiveRecovery`).then(res => {
+ let activeRecovery = res.data;
+ if (activeRecovery)
+ this.$scope.confirmation.show();
+ else
+ this.addCredit();
+ });
+ }
+
+ returnDialog(response) {
+ if (response === 'CANCEL')
+ return;
+
+ this.addCredit();
+ }
+
+ addCredit() {
+ this.$scope.watcher.submit().then(
+ () => {
+ this.$state.go('clientCard.credit.list');
+ }
+ );
+ }
+
+}
+
+Controller.$inject = ['$http', '$scope', '$state'];
+
ngModule.component('vnClientCreditCreate', {
template: require('./credit-create.html'),
+ controller: Controller,
bindings: {
client: '<'
}
diff --git a/client/client/src/credit-create/credit-create.spec.js b/client/client/src/credit-create/credit-create.spec.js
new file mode 100644
index 000000000..c7c1b6a3c
--- /dev/null
+++ b/client/client/src/credit-create/credit-create.spec.js
@@ -0,0 +1,85 @@
+import './credit-create.js';
+
+describe('Client', () => {
+ describe('Component vnClientCreditCreate', () => {
+ let $componentController;
+ let controller;
+ let $httpBackend;
+ let $state;
+ let $scope;
+ let client;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_, $rootScope, _$state_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $scope.confirmation = {show: () => {
+ return {
+ then: () => {}
+ };
+ }};
+ $scope.watcher = {
+ submit: () => {
+ return {
+ then: callback => {
+ callback();
+ }
+ };
+ }
+ };
+ client = {credit: 0};
+ $state = _$state_;
+ $state.params.id = 101;
+ $httpBackend = _$httpBackend_;
+ controller = $componentController('vnClientCreditCreate', {$scope: $scope}, {$state: $state});
+ }));
+ describe('onSubmit()', () => {
+ it('should perform a query to check (GET) if the client has an active recovery', () => {
+ $httpBackend.whenGET(`/client/api/Recoveries/101/hasActiveRecovery`).respond(true);
+ $httpBackend.expectGET(`/client/api/Recoveries/101/hasActiveRecovery`);
+ controller.onSubmit();
+ $httpBackend.flush();
+ });
+
+ it('should call show() method when the client have a recovery', () => {
+ spyOn(controller.$scope.confirmation, 'show');
+ $httpBackend.whenGET(`/client/api/Recoveries/101/hasActiveRecovery`).respond(true);
+ $httpBackend.expectGET(`/client/api/Recoveries/101/hasActiveRecovery`);
+ controller.onSubmit();
+ $httpBackend.flush();
+
+ expect(controller.$scope.confirmation.show).toHaveBeenCalledWith();
+ });
+
+ it('should call addCredit() method when the client doesnt have a recovery', () => {
+ spyOn(controller, 'addCredit');
+ $httpBackend.whenGET(`/client/api/Recoveries/101/hasActiveRecovery`).respond(false);
+ $httpBackend.expectGET(`/client/api/Recoveries/101/hasActiveRecovery`);
+ controller.onSubmit();
+ $httpBackend.flush();
+
+ expect(controller.addCredit).toHaveBeenCalledWith();
+ });
+ });
+ describe('returnDialog()', () => {
+ it('should call addCredit() when is called with a param disctint from CANCEL', () => {
+ spyOn(controller, 'addCredit');
+ controller.returnDialog('Manzano');
+
+ expect(controller.addCredit).toHaveBeenCalledWith();
+ });
+ });
+ describe('addCredit()', () => {
+ it('should call the function go() on $state to go to the credit list', () => {
+ spyOn($state, 'go');
+ client.credit = 1;
+ controller.addCredit();
+
+ expect(controller.$state.go).toHaveBeenCalledWith('clientCard.credit.list');
+ });
+ });
+ });
+});
diff --git a/client/core/src/components/watcher/watcher.js b/client/core/src/components/watcher/watcher.js
index 62224137f..9ba12bd8d 100644
--- a/client/core/src/components/watcher/watcher.js
+++ b/client/core/src/components/watcher/watcher.js
@@ -153,18 +153,18 @@ export default class Watcher extends Component {
resolve(json);
}
- noChanges(resolve) {
+ noChanges(reject) {
this.vnApp.showMessage(
this.$translate.instant('No changes to save')
);
- resolve();
+ reject(new Error('No changes to save'));
}
- invalidForm(resolve) {
+ invalidForm(reject) {
this.vnApp.showMessage(
this.$translate.instant('Some fields are invalid')
);
- resolve();
+ reject(new Error('Some fields are invalid'));
}
updateOriginalData() {
diff --git a/client/salix/src/module.js b/client/salix/src/module.js
index c0c539f3b..3431a62c3 100644
--- a/client/salix/src/module.js
+++ b/client/salix/src/module.js
@@ -16,6 +16,17 @@ export function config($translatePartialLoaderProvider, $httpProvider, $qProvide
}
ngModule.config(config);
+/*
+// FIXME: Handle unhandled exceptions
+exceptionHandler.$inject = ['vnApp'];
+function exceptionHandler(vnApp) {
+ return function(exception, cause) {
+ console.error(exception);
+ };
+}
+ngModule.factory('$exceptionHandler', exceptionHandler);
+*/
+
const HOOK_ABORTED_TRANSITION = 3;
run.$inject = ['$window', '$rootScope', 'vnApp', '$state'];
diff --git a/e2e/paths/client-module/09_add_credit.spec.js b/e2e/paths/client-module/09_add_credit.spec.js
index 8b5083d32..d066f7596 100644
--- a/e2e/paths/client-module/09_add_credit.spec.js
+++ b/e2e/paths/client-module/09_add_credit.spec.js
@@ -22,10 +22,10 @@ describe('Client', () => {
});
});
- it('should search for the user Petter Parker', () => {
+ it('should search for the user Ororo Munroe', () => {
return nightmare
.wait(selectors.clientsIndex.searchResult)
- .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .type(selectors.clientsIndex.searchClientInput, 'Ororo Munroe')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
@@ -36,7 +36,7 @@ describe('Client', () => {
it(`should click on the search result to access to the client's credit`, () => {
return nightmare
- .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Ororo Munroe')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.clientCredit.creditButton)
.waitForURL('credit/list')
diff --git a/services/client/common/methods/recovery/hasActiveRecovery.js b/services/client/common/methods/recovery/hasActiveRecovery.js
new file mode 100644
index 000000000..1fe1394d9
--- /dev/null
+++ b/services/client/common/methods/recovery/hasActiveRecovery.js
@@ -0,0 +1,34 @@
+module.exports = Self => {
+ Self.remoteMethod('hasActiveRecovery', {
+ description: 'Returns a boolean that is true when a client has an active recovery',
+ accessType: 'READ',
+ accepts: [
+ {
+ arg: 'clientFk',
+ type: 'number',
+ required: true,
+ description: 'The id of a client',
+ http: {source: 'path'}
+ }
+ ],
+ returns: {
+ type: 'boolean',
+ root: true
+ },
+ http: {
+ path: `/:clientFk/hasActiveRecovery`,
+ verb: 'GET'
+ }
+ });
+
+ Self.hasActiveRecovery = async id => {
+ let result = await Self.rawSql(
+ `SELECT count(*) AS hasActiveRecovery
+ FROM vn.recovery
+ WHERE clientFk = ?
+ AND IFNULL(finished,CURDATE()) >= CURDATE();`,
+ [id]
+ );
+ return result[0].hasActiveRecovery != 0;
+ };
+};
diff --git a/services/client/common/models/recovery.js b/services/client/common/models/recovery.js
index 337143fd1..1386b3754 100644
--- a/services/client/common/models/recovery.js
+++ b/services/client/common/models/recovery.js
@@ -1,3 +1,4 @@
module.exports = function(Self) {
require('../methods/recovery/filter')(Self);
+ require('../methods/recovery/hasActiveRecovery')(Self);
};
diff --git a/services/loopback/common/methods/item/filter.js b/services/loopback/common/methods/item/filter.js
index f6170d6f4..3f2273f97 100644
--- a/services/loopback/common/methods/item/filter.js
+++ b/services/loopback/common/methods/item/filter.js
@@ -7,16 +7,22 @@ module.exports = Self => {
skip: (params.page - 1) * params.size,
limit: params.size,
order: params.order || 'name ASC', // name, relevancy DESC
- include: {
- relation: 'itemType',
- scope: {
- fields: ['id', 'name', 'workerFk'],
- include: {
- relation: 'worker',
- fields: ['firstName', 'name']
+ include: [
+ {relation: 'itemType',
+ scope: {
+ fields: ['name', 'workerFk'],
+ include: {
+ relation: 'worker',
+ fields: ['firstName', 'name']
+ }
}
- }
- }
+ },
+ {relation: 'origin'},
+ {relation: 'ink'},
+ {relation: 'producer'},
+ {relation: 'intrastat'},
+ {relation: 'expence'}
+ ]
};
delete params.page;
diff --git a/services/loopback/common/methods/workerMana/getCurrentWorkerMana.js b/services/loopback/common/methods/workerMana/getCurrentWorkerMana.js
new file mode 100644
index 000000000..a8a6ae892
--- /dev/null
+++ b/services/loopback/common/methods/workerMana/getCurrentWorkerMana.js
@@ -0,0 +1,20 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('getCurrentWorkerMana', {
+ description: 'Returns the mana of the logged worker',
+ accessType: 'READ',
+ accepts: [],
+ returns: {
+ type: 'number',
+ root: true
+ },
+ http: {
+ path: `/getCurrentWorkerMana`,
+ verb: 'GET'
+ }
+ });
+
+ Self.getCurrentWorkerMana = async ctx => {
+ let loggedWorkerId = ctx.req.accessToken.userId;
+ return await Self.rawSql(`SELECT used AS mana FROM vn.manaSpellers WHERE worker = ?`, [loggedWorkerId]);
+ };
+};
diff --git a/services/loopback/common/models/workerMana.js b/services/loopback/common/models/workerMana.js
new file mode 100644
index 000000000..68a14d355
--- /dev/null
+++ b/services/loopback/common/models/workerMana.js
@@ -0,0 +1,3 @@
+module.exports = Self => {
+ require('../methods/workerMana/getCurrentWorkerMana')(Self);
+};