Merge branch 'dev' of http://git.verdnatura.es/salix into dev
This commit is contained in:
commit
f9bb1128a2
|
@ -332,6 +332,15 @@
|
||||||
"params": {
|
"params": {
|
||||||
"client": "$ctrl.client"
|
"client": "$ctrl.client"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/web-payment",
|
||||||
|
"state": "client.card.webPayment",
|
||||||
|
"component": "vn-client-web-payment",
|
||||||
|
"description": "Web Payment",
|
||||||
|
"menu": {
|
||||||
|
"icon": "web"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,3 +31,4 @@ import './credit-insurance/insurance/create';
|
||||||
import './contact';
|
import './contact';
|
||||||
import './sample/index';
|
import './sample/index';
|
||||||
import './sample/create';
|
import './sample/create';
|
||||||
|
import './web-payment';
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/client/api/clients/getTransactions"
|
||||||
|
filter="{}"
|
||||||
|
link="{clientFk: $ctrl.$stateParams.id}"
|
||||||
|
limit="20"
|
||||||
|
data="transactions">
|
||||||
|
</vn-crud-model>
|
||||||
|
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-card pad-large>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-title>Web Payment</vn-title>
|
||||||
|
<vn-table model="model">
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th></vn-th>
|
||||||
|
<vn-th field="id">Id</vn-th>
|
||||||
|
<vn-th field="amount" number>Amount</vn-th>
|
||||||
|
<vn-th field="created" default-order="DESC">Payed</vn-th>
|
||||||
|
<vn-th></vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="transaction in transactions">
|
||||||
|
<vn-td style="width: 3em; text-align: center">
|
||||||
|
<vn-icon orange pointer
|
||||||
|
vn-tooltip="Confirm transaction"
|
||||||
|
ng-click="$ctrl.confirm(transaction)"
|
||||||
|
ng-show="::!transaction.isConfirmed"
|
||||||
|
icon="check">
|
||||||
|
</vn-icon>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td>{{::transaction.id}}</vn-td>
|
||||||
|
<vn-td number>{{::transaction.amount | currency: '€ '}}</vn-td>
|
||||||
|
<vn-td>{{::transaction.created | date:'dd/MM/yyyy'}}</vn-td>
|
||||||
|
<vn-td>
|
||||||
|
<vn-icon orange
|
||||||
|
vn-tooltip="{{$ctrl.getFormattedMessage(transaction)}}"
|
||||||
|
ng-show="::(transaction.errorMessage || transaction.responseMessage)"
|
||||||
|
icon="warning">
|
||||||
|
</vn-icon>
|
||||||
|
</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
<vn-empty-rows ng-if="model.data.length === 0" translate>
|
||||||
|
No results
|
||||||
|
</vn-empty-rows>
|
||||||
|
</vn-table>
|
||||||
|
</vn-vertical>
|
||||||
|
<vn-pagination
|
||||||
|
model="model"
|
||||||
|
scroll-selector="ui-view">
|
||||||
|
</vn-pagination>
|
||||||
|
</vn-card>
|
||||||
|
</vn-vertical>
|
|
@ -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 ? '<br/>' : '';
|
||||||
|
const responseMessage = transaction.responseMessage ? transaction.responseMessage : '';
|
||||||
|
return `<strong style="font-size:13px">${errorMessage}</strong>`
|
||||||
|
+ separator
|
||||||
|
+ `<span style="font-size:13px">${responseMessage}</span>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$scope', '$http', '$stateParams'];
|
||||||
|
|
||||||
|
ngModule.component('vnClientWebPayment', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,4 @@
|
||||||
|
Web Payment: Pago Web
|
||||||
|
Confirmed: Confirmado
|
||||||
|
Payed: Pagado
|
||||||
|
Confirm transaction: Confirmar transacción
|
|
@ -4,8 +4,7 @@
|
||||||
filter="{}"
|
filter="{}"
|
||||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||||
limit="20"
|
limit="20"
|
||||||
data="sales"
|
data="sales">
|
||||||
on-data-change="$ctrl.getTags()">
|
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
|
|
|
@ -50,5 +50,6 @@
|
||||||
"A claim with that sale already exists": "Ya existe una reclamación para esta línea",
|
"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",
|
"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",
|
"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"
|
||||||
}
|
}
|
|
@ -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]);
|
||||||
|
};
|
||||||
|
};
|
|
@ -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);
|
||||||
|
};
|
||||||
|
};
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
|
@ -19,6 +19,8 @@ module.exports = Self => {
|
||||||
require('../methods/client/updateFiscalData')(Self);
|
require('../methods/client/updateFiscalData')(Self);
|
||||||
require('../methods/client/updateBillingData')(Self);
|
require('../methods/client/updateBillingData')(Self);
|
||||||
require('../methods/client/updateBasicData')(Self);
|
require('../methods/client/updateBasicData')(Self);
|
||||||
|
require('../methods/client/getTransactions')(Self);
|
||||||
|
require('../methods/client/confirmTransaction')(Self);
|
||||||
|
|
||||||
// Validations
|
// Validations
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
|
||||||
|
const ParameterizedSQL = require('vn-loopback/node_modules/loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('listSaleTracking', {
|
Self.remoteMethod('listSaleTracking', {
|
||||||
description: 'Returns all ticket sale trackings',
|
description: 'Returns all ticket sale trackings',
|
||||||
|
@ -20,40 +23,27 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.listSaleTracking = async filter => {
|
Self.listSaleTracking = async filter => {
|
||||||
let where = '';
|
let stmt = new ParameterizedSQL(`
|
||||||
let limit = '';
|
SELECT
|
||||||
let order = '';
|
st.id,
|
||||||
let params;
|
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) {
|
stmt.merge(Self.buildSuffix(filter));
|
||||||
let connector = Self.dataSource.connector;
|
|
||||||
if (filter.where) {
|
|
||||||
where = 'WHERE s.ticketFk = ?';
|
|
||||||
params = [filter.where.ticketFk];
|
|
||||||
}
|
|
||||||
|
|
||||||
limit = connector._buildLimit(null, filter.limit, filter.skip);
|
let trackings = await Self.rawStmt(stmt);
|
||||||
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 salesFilter = {
|
let salesFilter = {
|
||||||
include: [
|
include: [
|
||||||
|
|
Loading…
Reference in New Issue