diff --git a/client/client/routes.json b/client/client/routes.json
index e26ae5356..153c1449b 100644
--- a/client/client/routes.json
+++ b/client/client/routes.json
@@ -332,6 +332,15 @@
"params": {
"client": "$ctrl.client"
}
+ },
+ {
+ "url": "/web-payment",
+ "state": "client.card.webPayment",
+ "component": "vn-client-web-payment",
+ "description": "Web Payment",
+ "menu": {
+ "icon": "web"
+ }
}
]
}
diff --git a/client/client/src/client.js b/client/client/src/client.js
index 4c67413dc..f6e2eff9f 100644
--- a/client/client/src/client.js
+++ b/client/client/src/client.js
@@ -31,3 +31,4 @@ import './credit-insurance/insurance/create';
import './contact';
import './sample/index';
import './sample/create';
+import './web-payment';
diff --git a/client/client/src/web-payment/index.html b/client/client/src/web-payment/index.html
new file mode 100644
index 000000000..1511a02f5
--- /dev/null
+++ b/client/client/src/web-payment/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+ Web Payment
+
+
+
+
+ Id
+ Amount
+ Payed
+
+
+
+
+
+
+
+
+
+ {{::transaction.id}}
+ {{::transaction.amount | currency: '€ '}}
+ {{::transaction.created | date:'dd/MM/yyyy'}}
+
+
+
+
+
+
+
+ No results
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/web-payment/index.js b/client/client/src/web-payment/index.js
new file mode 100644
index 000000000..54ba6534b
--- /dev/null
+++ b/client/client/src/web-payment/index.js
@@ -0,0 +1,33 @@
+import ngModule from '../module';
+
+class Controller {
+ constructor($scope, $http, $stateParams) {
+ this.$scope = $scope;
+ this.$http = $http;
+ this.$stateParams = $stateParams;
+ }
+
+ confirm(transaction) {
+ const path = '/client/api/Clients/confirmTransaction';
+ let data = {id: transaction.id};
+ this.$http.post(path, data).then(res => {
+ this.$scope.model.refresh();
+ });
+ }
+
+ getFormattedMessage(transaction) {
+ const errorMessage = transaction.errorMessage ? transaction.errorMessage : '';
+ const separator = transaction.errorMessage && transaction.responseMessage ? '
' : '';
+ const responseMessage = transaction.responseMessage ? transaction.responseMessage : '';
+ return `${errorMessage}`
+ + separator
+ + `${responseMessage}`;
+ }
+}
+
+Controller.$inject = ['$scope', '$http', '$stateParams'];
+
+ngModule.component('vnClientWebPayment', {
+ template: require('./index.html'),
+ controller: Controller
+});
diff --git a/client/client/src/web-payment/index.spec.js b/client/client/src/web-payment/index.spec.js
new file mode 100644
index 000000000..452dd4963
--- /dev/null
+++ b/client/client/src/web-payment/index.spec.js
@@ -0,0 +1,50 @@
+import './index';
+import {crudModel} from '../../../helpers/crudModelHelper';
+
+describe('Component vnClientWebPayment', () => {
+ let $componentController;
+ let $httpBackend;
+ let $scope;
+ let vnApp;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _vnApp_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $scope.model = crudModel;
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ vnApp = _vnApp_;
+ spyOn(vnApp, 'showError');
+ controller = $componentController('vnClientWebPayment', {$scope: $scope});
+ }));
+
+ describe('confirm()', () => {
+ it(`should confirm a transaction`, () => {
+ let transaction = {id: 1};
+ let query = '/client/api/Clients/confirmTransaction';
+
+ controller.confirm(transaction);
+ $httpBackend.when('POST', query, transaction).respond('ok');
+ $httpBackend.expect('POST', query, transaction);
+ $httpBackend.flush();
+ });
+ });
+
+ describe('getFormattedMessage()', () => {
+ it(`should return error message and response Message`, () => {
+ let transaction = {
+ errorMessage: 'My error message',
+ responseMessage: 'My response message'
+ };
+ let result = controller.getFormattedMessage(transaction);
+
+ expect(result).toContain('My error message');
+ expect(result).toContain('My response message');
+ });
+ });
+});
diff --git a/client/client/src/web-payment/locale/es.yml b/client/client/src/web-payment/locale/es.yml
new file mode 100644
index 000000000..656bfd32d
--- /dev/null
+++ b/client/client/src/web-payment/locale/es.yml
@@ -0,0 +1,4 @@
+Web Payment: Pago Web
+Confirmed: Confirmado
+Payed: Pagado
+Confirm transaction: Confirmar transacción
\ No newline at end of file
diff --git a/client/ticket/src/sale-tracking/index.html b/client/ticket/src/sale-tracking/index.html
index 13ecc543c..6f3ce16e6 100644
--- a/client/ticket/src/sale-tracking/index.html
+++ b/client/ticket/src/sale-tracking/index.html
@@ -4,8 +4,7 @@
filter="{}"
link="{ticketFk: $ctrl.$stateParams.id}"
limit="20"
- data="sales"
- on-data-change="$ctrl.getTags()">
+ data="sales">
diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json
index 3e3cca4cc..21e049ff2 100644
--- a/services/loopback/common/locale/es.json
+++ b/services/loopback/common/locale/es.json
@@ -50,5 +50,6 @@
"A claim with that sale already exists": "Ya existe una reclamación para esta línea",
"You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo",
"Warehouse cannot be blank": "El almacén no puede quedar en blanco",
- "Agency cannot be blank": "La agencia no puede quedar en blanco"
+ "Agency cannot be blank": "La agencia no puede quedar en blanco",
+ "You don't have enough privileges to do that": "No tienes permisos para para hacer esto"
}
\ No newline at end of file
diff --git a/services/loopback/common/methods/client/confirmTransaction.js b/services/loopback/common/methods/client/confirmTransaction.js
new file mode 100644
index 000000000..2c6e6c624
--- /dev/null
+++ b/services/loopback/common/methods/client/confirmTransaction.js
@@ -0,0 +1,32 @@
+const UserError = require('../../../common/helpers').UserError;
+
+module.exports = Self => {
+ Self.remoteMethodCtx('confirmTransaction', {
+ description: 'Returns last entries',
+ accessType: 'READ',
+ accepts: [{
+ arg: 'id',
+ type: 'number',
+ required: true,
+ description: 'Transaction id'
+ }],
+ returns: {
+ type: 'Object',
+ root: true
+ },
+ http: {
+ path: `/confirmTransaction`,
+ verb: 'POST'
+ }
+ });
+
+ Self.confirmTransaction = async(ctx, id) => {
+ let userId = ctx.req.accessToken.userId;
+ let isAdministrative = await Self.app.models.Account.hasRole(userId, 'administrative');
+
+ if (!isAdministrative)
+ throw new UserError(`You don't have enough privileges to do that`);
+
+ return await Self.rawSql('CALL hedera.tpvTransactionConfirmById(?)', [id]);
+ };
+};
diff --git a/services/loopback/common/methods/client/getTransactions.js b/services/loopback/common/methods/client/getTransactions.js
new file mode 100644
index 000000000..764e0df7d
--- /dev/null
+++ b/services/loopback/common/methods/client/getTransactions.js
@@ -0,0 +1,43 @@
+
+const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
+
+module.exports = Self => {
+ Self.remoteMethod('getTransactions', {
+ description: 'Returns last entries',
+ accessType: 'READ',
+ accepts: [{
+ arg: 'filter',
+ type: 'Object',
+ description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
+ http: {source: 'query'}
+ }],
+ returns: {
+ type: ['Object'],
+ root: true
+ },
+ http: {
+ path: `/getTransactions`,
+ verb: 'GET'
+ }
+ });
+
+ Self.getTransactions = async filter => {
+ let stmt = new ParameterizedSQL(`
+ SELECT
+ t.id,
+ t.clientFk,
+ t.created,
+ t.amount / 100 amount,
+ t.receiptFk IS NOT NULL AS isConfirmed,
+ tt.message responseMessage,
+ te.message errorMessage
+ FROM hedera.tpvTransaction t
+ JOIN hedera.tpvMerchant m ON m.id = t.merchantFk
+ LEFT JOIN hedera.tpvResponse tt ON tt.id = t.response
+ LEFT JOIN hedera.tpvError te ON te.code = errorCode`);
+
+ stmt.merge(Self.buildSuffix(filter, 't'));
+
+ return await Self.rawStmt(stmt);
+ };
+};
diff --git a/services/loopback/common/methods/client/specs/confirmTransaction.spec.js b/services/loopback/common/methods/client/specs/confirmTransaction.spec.js
new file mode 100644
index 000000000..7cd5bd292
--- /dev/null
+++ b/services/loopback/common/methods/client/specs/confirmTransaction.spec.js
@@ -0,0 +1,32 @@
+const app = require(`${servicesDir}/client/server/server`);
+
+describe('Client confirmTransaction', () => {
+ const transactionId = 2;
+
+ afterAll(async() => {
+ await app.models.Client.rawSql(`
+ CALL hedera.tpvTransactionUndo(?)`, [transactionId]);
+ });
+
+ it('should call confirmTransaction() method and throw error for a non administrative person', async() => {
+ let ctx = {req: {accessToken: {userId: 1}}};
+ let error;
+ await app.models.Client.confirmTransaction(ctx, transactionId).catch(e => {
+ error = e;
+ }).finally(() => {
+ expect(error.message).toEqual(`You don't have enough privileges to do that`);
+ });
+ });
+
+ it('should call confirmTransaction() method to mark transaction as confirmed', async() => {
+ let ctx = {req: {accessToken: {userId: 5}}};
+ await app.models.Client.confirmTransaction(ctx, transactionId);
+
+ let [receipt] = await app.models.Client.rawSql(
+ `SELECT receiptFk
+ FROM hedera.tpvTransaction
+ WHERE id = ?`, [transactionId]);
+
+ expect(receipt.receiptFk).toBeGreaterThan(0);
+ });
+});
diff --git a/services/loopback/common/methods/client/specs/getTransactions.spec.js b/services/loopback/common/methods/client/specs/getTransactions.spec.js
new file mode 100644
index 000000000..d7e553115
--- /dev/null
+++ b/services/loopback/common/methods/client/specs/getTransactions.spec.js
@@ -0,0 +1,10 @@
+const app = require(`${servicesDir}/client/server/server`);
+
+describe('Client getTransations', () => {
+ it('should call getTransations() method to receive a list of Web Payments from Bruce Wayne', async() => {
+ let filter = {where: {clientFk: 101}};
+ let result = await app.models.Client.getTransactions(filter);
+
+ expect(result[1].id).toBeTruthy();
+ });
+});
diff --git a/services/loopback/common/models/client.js b/services/loopback/common/models/client.js
index 41149b30a..c7fa10e81 100644
--- a/services/loopback/common/models/client.js
+++ b/services/loopback/common/models/client.js
@@ -19,6 +19,8 @@ module.exports = Self => {
require('../methods/client/updateFiscalData')(Self);
require('../methods/client/updateBillingData')(Self);
require('../methods/client/updateBasicData')(Self);
+ require('../methods/client/getTransactions')(Self);
+ require('../methods/client/confirmTransaction')(Self);
// Validations
diff --git a/services/ticket/common/methods/sale-tracking/listSaleTracking.js b/services/ticket/common/methods/sale-tracking/listSaleTracking.js
index e45249ec6..ff198f3ad 100644
--- a/services/ticket/common/methods/sale-tracking/listSaleTracking.js
+++ b/services/ticket/common/methods/sale-tracking/listSaleTracking.js
@@ -1,3 +1,6 @@
+
+const ParameterizedSQL = require('vn-loopback/node_modules/loopback-connector').ParameterizedSQL;
+
module.exports = Self => {
Self.remoteMethod('listSaleTracking', {
description: 'Returns all ticket sale trackings',
@@ -20,40 +23,27 @@ module.exports = Self => {
});
Self.listSaleTracking = async filter => {
- let where = '';
- let limit = '';
- let order = '';
- let params;
+ let stmt = new ParameterizedSQL(`
+ SELECT
+ st.id,
+ s.ticketFk,
+ s.quantity,
+ s.concept,
+ s.itemFk,
+ st.originalQuantity,
+ st.created,
+ st.workerFk,
+ w.firstName,
+ w.name,
+ ste.name AS state
+ FROM saleTracking st
+ JOIN sale s ON s.id = st.saleFk
+ JOIN worker w ON w.id = st.workerFk
+ JOIN state ste ON ste.id = st.stateFk`);
- if (filter) {
- let connector = Self.dataSource.connector;
- if (filter.where) {
- where = 'WHERE s.ticketFk = ?';
- params = [filter.where.ticketFk];
- }
+ stmt.merge(Self.buildSuffix(filter));
- limit = connector._buildLimit(null, filter.limit, filter.skip);
- order = connector.buildOrderBy('Item', filter.order);
- }
-
- let query = `SELECT
- st.id,
- s.quantity,
- s.concept,
- s.itemFk,
- st.originalQuantity,
- st.created,
- st.workerFk,
- w.firstName,
- w.name,
- ste.name AS state
- FROM saleTracking st
- JOIN sale s ON s.id = st.saleFK
- JOIN worker w ON w.id = st.workerFk
- JOIN ticketState ts ON ts.ticketFk = s.ticketFk
- JOIN state ste ON ste.id = ts.stateFK ${where} ${order} ${limit}`;
-
- let trackings = await Self.rawSql(query, params);
+ let trackings = await Self.rawStmt(stmt);
let salesFilter = {
include: [