Added new section client contacts #365 - CR: Javi
This commit is contained in:
parent
38914a060f
commit
dfa1d1edb2
|
@ -280,6 +280,24 @@
|
|||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/contact",
|
||||
"abstract": true,
|
||||
"state": "client.card.contact",
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/index",
|
||||
"state": "client.card.contact.index",
|
||||
"component": "vn-client-contact-index",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Contacts",
|
||||
"icon": "contact_phone"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -27,3 +27,4 @@ import './credit-insurance/index';
|
|||
import './credit-insurance/create';
|
||||
import './credit-insurance/insurance/index';
|
||||
import './credit-insurance/insurance/create';
|
||||
import './contact';
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientContactIndex', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
$scope = $rootScope.$new();
|
||||
$scope.form = {$invalid: false};
|
||||
$scope.index = {accept: () => {}};
|
||||
controller = $componentController('vnClientContactIndex', {$scope: $scope}, {$state: $state});
|
||||
controller.client = {
|
||||
id: 101
|
||||
};
|
||||
}));
|
||||
|
||||
describe('add / remove tags', () => {
|
||||
it('should add one empty contact into controller contacts collection', () => {
|
||||
controller.contacts = [];
|
||||
controller.add();
|
||||
|
||||
expect(controller.contacts.length).toEqual(1);
|
||||
expect(controller.contacts[0].id).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should remove a contact that occupies the position in the index', () => {
|
||||
let index = 2;
|
||||
controller.contacts = [
|
||||
{id: 1, name: 'My contact 1', phone: '123456789'},
|
||||
{id: 2, name: 'My contact 2', phone: '123456789'},
|
||||
{id: 3, name: 'My contact 3', phone: '123456789'}
|
||||
];
|
||||
|
||||
controller.remove(index);
|
||||
|
||||
expect(controller.contacts.length).toEqual(2);
|
||||
expect(controller.contacts[index]).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isEqual()', () => {
|
||||
it('should return true if two contacts are equals', () => {
|
||||
let contact1 = {id: 1, name: 'My contact 1', phone: '123456789'};
|
||||
let contact2 = {id: 1, name: 'My contact 1', phone: '123456789'};
|
||||
let equals = controller.isEqual(contact1, contact2);
|
||||
|
||||
expect(equals).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if two contacts aint equal', () => {
|
||||
let contact1 = {id: 1, name: 'My contact 1', phone: '123456789'};
|
||||
let contact2 = {id: 2, name: 'My contact 2', phone: '123456789'};
|
||||
let equals = controller.isEqual(contact1, contact2);
|
||||
|
||||
expect(equals).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('submit()', () => {
|
||||
it("should perfom a query to delete contacts", () => {
|
||||
controller._oldContacts = [];
|
||||
controller._oldContacts[1] = {id: 1, clientFk: 101, name: 'My contact 1', phone: '123456789'};
|
||||
controller._oldContacts[2] = {id: 2, clientFk: 101, name: 'My contact 2', phone: '123456789'};
|
||||
|
||||
controller._contacts = [
|
||||
{id: 2, name: 'My contact 2', phone: '123456789'}
|
||||
];
|
||||
controller.removedContacts = [1];
|
||||
|
||||
let newData = {
|
||||
clientFk: 101,
|
||||
delete: [1],
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
$httpBackend.whenPOST(`/client/api/ClientContacts/crud`, newData).respond(200, true);
|
||||
$httpBackend.expectPOST(`/client/api/ClientContacts/crud`, newData);
|
||||
controller.submit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it("should perfom a query to update contacts", () => {
|
||||
controller._oldContacts = [];
|
||||
controller._oldContacts[1] = {id: 1, clientFk: 101, name: 'My contact 1', phone: '123456789'};
|
||||
controller._oldContacts[2] = {id: 2, clientFk: 101, name: 'My contact 2', phone: '123456789'};
|
||||
|
||||
controller._contacts = [
|
||||
{id: 1, clientFk: 101, name: 'My contact 1', phone: '123456789'},
|
||||
{id: 2, clientFk: 101, name: 'My contact 2', phone: '111111111'}
|
||||
];
|
||||
controller.removedContacts = [];
|
||||
|
||||
let newData = {
|
||||
clientFk: 101,
|
||||
delete: [],
|
||||
create: [],
|
||||
update: [
|
||||
{id: 2, clientFk: 101, name: 'My contact 2', phone: '111111111'}
|
||||
]
|
||||
};
|
||||
|
||||
$httpBackend.whenPOST(`/client/api/ClientContacts/crud`, newData).respond(200, true);
|
||||
$httpBackend.expectPOST(`/client/api/ClientContacts/crud`, newData);
|
||||
controller.submit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it("should perfom a query to create new contact", () => {
|
||||
controller._oldContacts = [];
|
||||
controller._oldContacts[1] = {id: 1, name: 'My contact 1', phone: '123456789'};
|
||||
controller._oldContacts[2] = {id: 2, name: 'My contact 2', phone: '123456789'};
|
||||
|
||||
controller._contacts = [
|
||||
{id: 1, name: 'My contact 1', phone: '123456789'},
|
||||
{id: 2, name: 'My contact 2', phone: '123456789'},
|
||||
{name: 'My contact 3', phone: '123456789'}
|
||||
];
|
||||
controller.removedContacts = [];
|
||||
|
||||
let newData = {
|
||||
clientFk: 101,
|
||||
delete: [],
|
||||
create: [{name: 'My contact 3', phone: '123456789'}],
|
||||
update: []
|
||||
};
|
||||
|
||||
$httpBackend.whenPOST(`/client/api/ClientContacts/crud`, newData).respond(200, true);
|
||||
$httpBackend.expectPOST(`/client/api/ClientContacts/crud`, newData);
|
||||
controller.submit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it("should throw 'No changes to save' error when there are no changes to apply", () => {
|
||||
let newData = {
|
||||
delete: [],
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
let hasChanges = controller.hasChanges(newData);
|
||||
|
||||
expect(hasChanges).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
<mg-ajax
|
||||
path="/client/api/Clients/{{index.params.id}}/contacts"
|
||||
options="mgIndex"
|
||||
actions="$ctrl.contacts = index.model">
|
||||
</mg-ajax>
|
||||
<form name="form" ng-submit="$ctrl.submit()">
|
||||
<vn-card pad-large>
|
||||
<vn-title>Contacts</vn-title>
|
||||
<vn-horizontal ng-repeat="contact in index.model track by $index">
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
model="contact.name"
|
||||
rule="clientContact.name">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Phone"
|
||||
model="contact.phone"
|
||||
rule="clientContact.phone" vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-auto pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
medium-grey
|
||||
vn-tooltip="Remove contact"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.remove($index)">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-icon-button
|
||||
vn-bind="+"
|
||||
vn-tooltip="Add contact"
|
||||
icon="add_circle"
|
||||
ng-click="$ctrl.add()">
|
||||
</vn-icon-button>
|
||||
</vn-one>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,126 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($http, $scope, $translate, vnApp) {
|
||||
this.$http = $http;
|
||||
this.$scope = $scope;
|
||||
this.$translate = $translate;
|
||||
this.vnApp = vnApp;
|
||||
this.removedContacts = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for contacts and original contacts
|
||||
* @param {Object} value - Contacts object
|
||||
*/
|
||||
set contacts(value) {
|
||||
this._contacts = value;
|
||||
this.oldContacts = value;
|
||||
}
|
||||
|
||||
get contacts() {
|
||||
return this._contacts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the original contacts
|
||||
* @param {Object} value - Default values
|
||||
*/
|
||||
set oldContacts(value) {
|
||||
this._oldContacts = [];
|
||||
this.removedContacts = [];
|
||||
|
||||
value.forEach(item => {
|
||||
this._oldContacts[item.id] = Object.assign({}, item);
|
||||
});
|
||||
}
|
||||
|
||||
get oldContacts() {
|
||||
return this._oldContacts;
|
||||
}
|
||||
|
||||
submit() {
|
||||
let query = `/client/api/ClientContacts/crud`;
|
||||
let data = {
|
||||
clientFk: this.client.id,
|
||||
delete: this.removedContacts,
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
this.contacts.forEach(item => {
|
||||
if (typeof item.id === 'undefined')
|
||||
data.create.push(item);
|
||||
|
||||
if (typeof item.id !== 'undefined' && !this.isEqual(item, this.oldContacts[item.id]))
|
||||
data.update.push(item);
|
||||
});
|
||||
|
||||
if (!this.hasChanges(data))
|
||||
return this.vnApp.showError(this.$translate.instant('No changes to save'));
|
||||
|
||||
if (this.$scope.form.$invalid)
|
||||
return this.vnApp.showError(this.$translate.instant('Some fields are invalid'));
|
||||
|
||||
this.$http.post(query, data).then(() => {
|
||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||
this.$scope.index.accept();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove contact from list
|
||||
* @param {Int} index - Contact array position
|
||||
*/
|
||||
remove(index) {
|
||||
if (this.contacts[index] && this.contacts[index].id)
|
||||
this.removedContacts.push(this.contacts[index].id);
|
||||
|
||||
this.contacts.splice(index, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add contact to list
|
||||
*/
|
||||
add() {
|
||||
let data = {
|
||||
clientFk: this.client.id,
|
||||
name: 'Teléfono',
|
||||
phone: null
|
||||
};
|
||||
this.contacts.push(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true/false if the new
|
||||
* contact equals the old one
|
||||
* @param {Object} newContact - New contact
|
||||
* @param {Object} oldContact - Old contact
|
||||
* @return {Boolean} - True if are equals
|
||||
*/
|
||||
isEqual(newContact, oldContact) {
|
||||
return newContact.name === oldContact.name && newContact.phone == oldContact.phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there's any changes to do
|
||||
* @param {Object} data - Crud data
|
||||
* @return {Boolean} - Returns true if there's any changes to do
|
||||
*/
|
||||
hasChanges(data) {
|
||||
if (data.create.length || data.update.length || data.delete.length)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$scope', '$translate', 'vnApp'];
|
||||
|
||||
ngModule.component('vnClientContactIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -22,4 +22,5 @@ Credit contracts: Contratos de crédito
|
|||
Verified data: Datos comprobados
|
||||
Mandate: Mandato
|
||||
Amount: Importe
|
||||
Back: Volver
|
||||
Back: Volver
|
||||
Contacts: Contactos
|
|
@ -0,0 +1,32 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('crud', {
|
||||
description: 'Client contact crud',
|
||||
accepts: [{
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: {
|
||||
root: true,
|
||||
type: 'boolean'
|
||||
},
|
||||
http: {
|
||||
verb: 'post',
|
||||
path: '/crud'
|
||||
}
|
||||
});
|
||||
|
||||
Self.crud = async data => {
|
||||
let models = Self.app.models;
|
||||
|
||||
await Promise.all(data.delete.map(contactId => {
|
||||
return models.ClientContact.destroyById(contactId);
|
||||
}));
|
||||
|
||||
let upsert = data.update.concat(data.create);
|
||||
|
||||
await Promise.all(upsert.map(contact => {
|
||||
return models.ClientContact.upsert(contact);
|
||||
}));
|
||||
};
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
const app = require(`${servicesDir}/client/server/server`);
|
||||
|
||||
describe('Client crud', () => {
|
||||
afterAll(async() => {
|
||||
await app.models.ClientContact.destroyById(4113);
|
||||
});
|
||||
|
||||
it('should perfom a query to create new contacts', async() => {
|
||||
let data = {
|
||||
delete: [],
|
||||
create: [
|
||||
{id: 4113, clientFk: 101, name: 'My contact', phone: '111111111'}
|
||||
],
|
||||
update: []
|
||||
};
|
||||
|
||||
await app.models.ClientContact.crud(data);
|
||||
let contacts = await app.models.ClientContact.find();
|
||||
|
||||
expect(contacts.length).toEqual(25);
|
||||
});
|
||||
|
||||
it('should perfom a query to update contacts', async() => {
|
||||
let data = {
|
||||
delete: [],
|
||||
create: [],
|
||||
update: [
|
||||
{id: 4113, name: 'My contact 2 updated', phone: '222222222'}
|
||||
]
|
||||
};
|
||||
|
||||
await app.models.ClientContact.crud(data);
|
||||
let contacts = await app.models.ClientContact.findById(4113);
|
||||
|
||||
expect(contacts.name).toEqual('My contact 2 updated');
|
||||
expect(contacts.phone).toEqual('222222222');
|
||||
});
|
||||
|
||||
it('should perfom a query to delete contacts', async() => {
|
||||
let data = {
|
||||
delete: [4113],
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
await app.models.ClientContact.crud(data);
|
||||
|
||||
let contacts = await app.models.ClientContact.find();
|
||||
|
||||
expect(contacts.length).toEqual(24);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/client-contact/crud')(Self);
|
||||
|
||||
Self.validatesPresenceOf('name', {
|
||||
message: 'Name cannot be blank'
|
||||
});
|
||||
|
||||
Self.validatesPresenceOf('phone', {
|
||||
message: 'Phone cannot be blank'
|
||||
});
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "ClientContact",
|
||||
"description": "Client phone contacts",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "clientContact",
|
||||
"database": "vn"
|
||||
}
|
||||
},
|
||||
"validateUpsert": true,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"client": {
|
||||
"type": "belongsTo",
|
||||
"model": "Client",
|
||||
"foreignKey": "clientFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,9 @@
|
|||
"ClientObservation": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ClientContact": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Greuge": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -18,5 +18,9 @@
|
|||
"That payment method requires an IBAN": "That payment method requires an IBAN",
|
||||
"State cannot be blank": "State cannot be blank",
|
||||
"Cannot change the payment method if no salesperson": "Cannot change the payment method if no salesperson",
|
||||
"Only manager can change the credit": "Only manager can change the credit"
|
||||
"Only manager can change the credit": "Only manager can change the credit",
|
||||
"Name cannot be blank": "Name cannot be blank",
|
||||
"Phone cannot be blank": "Phone cannot be blank",
|
||||
"ValidationError: La instancia `ClientContact` no es válida. Detalles: `name` Name cannot be blank (value: null).": "ValidationError: La instancia `ClientContact` no es válida. Detalles: `name` Name cannot be blank (value: null).",
|
||||
"La instancia `ClientContact` no es válida. Detalles: `name` Name cannot be blank (value: null).": "La instancia `ClientContact` no es válida. Detalles: `name` Name cannot be blank (value: null)."
|
||||
}
|
|
@ -24,5 +24,7 @@
|
|||
"The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero",
|
||||
"The grade must be similar to the last one": "El grade debe ser similar al último",
|
||||
"NO_AGENCY_AVAILABLE": "NO_AGENCY_AVAILABLE",
|
||||
"Only manager can change the credit": "Solo el gerente puede cambiar el credito de este cliente"
|
||||
"Only manager can change the credit": "Solo el gerente puede cambiar el credito de este cliente",
|
||||
"Name cannot be blank": "El nombre no puede estar en blanco",
|
||||
"Phone cannot be blank": "El teléfono no puede estar en blanco"
|
||||
}
|
|
@ -4,7 +4,7 @@ describe('sale priceDifference()', () => {
|
|||
it('should call the priceDifference method and return a NO_AGENCY_AVAILABLE signal error', done => {
|
||||
let data = {
|
||||
landed: Date.now(),
|
||||
addressFk: 121,
|
||||
addressFk: 121,
|
||||
agencyModeFk: 1,
|
||||
warehouseFk: 1
|
||||
};
|
||||
|
|
|
@ -161,6 +161,11 @@
|
|||
"type": "hasMany",
|
||||
"model": "CreditClassification",
|
||||
"foreignKey": "client"
|
||||
},
|
||||
"contacts": {
|
||||
"type": "hasMany",
|
||||
"model": "ClientContact",
|
||||
"foreignKey": "clientFk"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue