Merge branch 'master' of https://git.verdnatura.es/salix
This commit is contained in:
commit
1fbfbd6f7c
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"salixHost": "localhost",
|
||||
"salixPort": "3306",
|
||||
"salixUser": "root",
|
||||
"salixPassword": "root"
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
extends: google
|
||||
installedESLint: true
|
||||
extends: [eslint:recommended, google, plugin:jasmine/recommended]
|
||||
parserOptions:
|
||||
ecmaVersion: 2017
|
||||
plugins:
|
||||
- jasmine
|
||||
env:
|
||||
jasmine: true
|
||||
rules:
|
||||
indent: [error, 4]
|
||||
require-jsdoc: 0
|
||||
|
@ -9,3 +14,9 @@ rules:
|
|||
operator-linebreak: 0
|
||||
radix: 0
|
||||
guard-for-in: 0
|
||||
camelcase: 0
|
||||
default-case: 0
|
||||
no-eq-null: 0
|
||||
no-console: 0
|
||||
no-warning-comments: 0
|
||||
no-empty: [error, allowEmptyCatch: true]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
node_modules
|
||||
spliting.js
|
||||
build
|
||||
npm-debug.log
|
||||
debug.log
|
||||
datasources.development.json
|
||||
docker-compose.yml
|
||||
|
|
|
@ -2,85 +2,10 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Iniciar",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/app.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": null,
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"console": "internalConsole",
|
||||
"sourceMaps": false,
|
||||
"outFiles": []
|
||||
},
|
||||
{
|
||||
"name": "Asociar",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 5858,
|
||||
"address": "localhost",
|
||||
"restart": false,
|
||||
"sourceMaps": false,
|
||||
"outFiles": [],
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": null
|
||||
},
|
||||
{
|
||||
"name": "Asociar al proceso",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"processId": "${command.PickProcess}",
|
||||
"port": 5858,
|
||||
"sourceMaps": false,
|
||||
"outFiles": []
|
||||
},
|
||||
{
|
||||
"name": "Loopback",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/services/client/server/server.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": null,
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"console": "internalConsole",
|
||||
"sourceMaps": false,
|
||||
"outFiles": []
|
||||
},
|
||||
{
|
||||
"name": "gulp debug",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}\\@salix\\node_modules\\gulp\\bin\\gulp.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}\\@salix",
|
||||
"preLaunchTask": null,
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"console": "internalConsole",
|
||||
"sourceMaps": false,
|
||||
"outFiles": []
|
||||
"name": "Attach by Process ID",
|
||||
"processId": "${command:PickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
FROM node:8.9.4
|
||||
|
||||
COPY . /app
|
||||
COPY ../loopback /loopback
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install
|
||||
RUN npm -g install pm2
|
||||
|
||||
CMD ["pm2-docker", "./server/server.js"]
|
||||
|
||||
EXPOSE 3000
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env groovy
|
||||
|
||||
def branchName = "${env.BRANCH_NAME}";
|
||||
def branchProduction = "master"
|
||||
def branchTest = "test";
|
||||
|
||||
env.BRANCH_NAME = branchName;
|
||||
env.TAG = "${env.BUILD_NUMBER}";
|
||||
env.salixUser="${env.salixUser}";
|
||||
env.salixPassword="${env.salixPassword}";
|
||||
env.salixHost = "${env.productionSalixHost}";
|
||||
env.salixPort = "${env.productionSalixPort}";
|
||||
|
||||
switch (branchName){
|
||||
case branchTest:
|
||||
env.NODE_ENV = "test";
|
||||
env.salixHost = "${env.testSalixHost}";
|
||||
env.salixPort = "${env.testSalixPort}";
|
||||
break;
|
||||
case branchProduction:
|
||||
env.DOCKER_HOST = "tcp://172.16.255.29:2375";
|
||||
env.NODE_ENV = "production"
|
||||
break;
|
||||
}
|
||||
|
||||
node
|
||||
{
|
||||
stage ('Print environment variables'){
|
||||
echo "Branch ${branchName}, Build ${env.TAG}, salixHost ${env.salixHost}, NODE_ENV ${env.NODE_ENV} en docker Host ${env.DOCKER_HOST}"
|
||||
}
|
||||
stage ('Checkout') {
|
||||
checkout scm
|
||||
}
|
||||
|
||||
stage ('install modules'){
|
||||
sh "npm install"
|
||||
}
|
||||
|
||||
stage ('build Project'){
|
||||
sh "gulp build"
|
||||
}
|
||||
|
||||
stage ("docker")
|
||||
{
|
||||
stage ("install modules loopback service")
|
||||
{
|
||||
sh "cd ./services/loopback && npm install"
|
||||
}
|
||||
|
||||
stage ("Stopping/Removing Docker")
|
||||
{
|
||||
sh "docker-compose down --rmi 'all'"
|
||||
}
|
||||
|
||||
stage ("Generar dockers")
|
||||
{
|
||||
sh "docker-compose up -d --build"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
Copyright (C) 2018 - Verdnatura Levante S.L.
|
||||
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
On Debian systems, the complete text of the GNU General Public
|
||||
License can be found in "/usr/share/common-licenses/GPL-3".
|
|
@ -0,0 +1,73 @@
|
|||
# Salix
|
||||
|
||||
This project is an Enterprise resource planning (ERP) integrated management of core business processes, in real-time and mediated by software and technology developed with the stack listed below.
|
||||
|
||||
Salix is also the scientific name of a beautifull tree! :)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Required applications.
|
||||
|
||||
* Node.js = 8.9.4
|
||||
* NGINX
|
||||
* Docker
|
||||
|
||||
You will need to install globally the following items.
|
||||
```
|
||||
$ npm install -g karma-cli gulp webpack nodemon
|
||||
```
|
||||
|
||||
## Getting Started // Installing
|
||||
|
||||
Pull from repository.
|
||||
|
||||
Run this commands on project root directory to install Node dependencies.
|
||||
```
|
||||
$ npm install
|
||||
$ gulp install
|
||||
```
|
||||
|
||||
Launch application in developer environment.
|
||||
```
|
||||
$ gulp
|
||||
```
|
||||
|
||||
Also you can run backend and frontend as separately gulp tasks (including NGINX).
|
||||
```
|
||||
$ gulp client
|
||||
$ gulp services
|
||||
```
|
||||
|
||||
Manually reset fixtures.
|
||||
```
|
||||
$ gulp docker
|
||||
```
|
||||
|
||||
## Running the unit tests
|
||||
|
||||
For client-side unit tests run from project's root.
|
||||
```
|
||||
$ karma start
|
||||
```
|
||||
|
||||
For server-side unit tests run from project's root.
|
||||
```
|
||||
$ npm run test
|
||||
```
|
||||
|
||||
For end-to-end tests run from project's root.
|
||||
```
|
||||
$ gulp e2e
|
||||
```
|
||||
|
||||
## Built With
|
||||
|
||||
* [angularjs](https://angularjs.org/)
|
||||
* [nodejs](https://nodejs.org/)
|
||||
* [webpack](https://webpack.js.org/)
|
||||
* [loopback](https://loopback.io/)
|
||||
* [docker](https://www.docker.com/)
|
||||
* [gulp.js](https://gulpjs.com/)
|
||||
* [Karma](https://karma-runner.github.io/)
|
||||
* [Jasmine](https://jasmine.github.io/)
|
||||
* [Nightmare](http://www.nightmarejs.org/)
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "@salix/auth",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://git.verdnatura.es:/salix"
|
||||
}
|
||||
}
|
|
@ -1,4 +1,2 @@
|
|||
export * from './module';
|
||||
import './config';
|
||||
|
||||
export {component as Login} from './login/login';
|
||||
import './module';
|
||||
import './login/login';
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import {module} from './module';
|
||||
|
||||
config.$inject = ['$translatePartialLoaderProvider', '$httpProvider'];
|
||||
export function config($translatePartialLoaderProvider, $httpProvider) {
|
||||
$translatePartialLoaderProvider.addPart('auth');
|
||||
|
||||
$httpProvider.defaults.useXDomain = true;
|
||||
delete $httpProvider.defaults.headers.common['X-Requested-With'];
|
||||
}
|
||||
module.config(config);
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"User": "User",
|
||||
"Password": "Password",
|
||||
"Do not close session": "Do not close session",
|
||||
"Enter": "Enter"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
User: User
|
||||
Password: Password
|
||||
Do not close session: Do not close session
|
||||
Enter: Enter
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"User": "Usuario",
|
||||
"Password": "Contraseña",
|
||||
"Do not close session": "No cerrar sesión",
|
||||
"Enter": "Entrar"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
User: Usuario
|
||||
Password: Contraseña
|
||||
Do not close session: No cerrar sesión
|
||||
Enter: Entrar
|
|
@ -3,8 +3,19 @@
|
|||
<div class="box">
|
||||
<img src="./logo.svg"/>
|
||||
<form name="form" ng-submit="$ctrl.submit()">
|
||||
<vn-textfield label="User" field="$ctrl.model.email"></vn-textfield>
|
||||
<vn-password label="Password" field="$ctrl.model.password"></vn-password>
|
||||
<vn-textfield
|
||||
label="User"
|
||||
model="$ctrl.user"
|
||||
name="user"
|
||||
vn-id="userField"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
label="Password"
|
||||
model="$ctrl.password"
|
||||
name="password"
|
||||
type="password">
|
||||
</vn-textfield>
|
||||
<div class="footer">
|
||||
<vn-submit label="Enter"></vn-submit>
|
||||
<div class="spinner-wrapper">
|
||||
|
@ -14,5 +25,5 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<vn-snackbar></vn-snackbar>
|
||||
<vn-snackbar vn-id="snackbar"></vn-snackbar>
|
||||
</div>
|
||||
|
|
|
@ -1,38 +1,56 @@
|
|||
import {module} from '../module';
|
||||
import './login.scss';
|
||||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
|
||||
export const component = {
|
||||
template: require('./login.html'),
|
||||
controller: controller
|
||||
};
|
||||
module.component('vnLogin', component);
|
||||
|
||||
controller.$inject = ['$http', '$element', '$window'];
|
||||
function controller($http, $element, $window) {
|
||||
Object.assign(this, {
|
||||
submit: function() {
|
||||
let model = this.model;
|
||||
|
||||
if (!(model && model.email && model.password)) {
|
||||
this.showMessage('Please insert your email and password');
|
||||
/**
|
||||
* A simple login form.
|
||||
*/
|
||||
export default class Controller {
|
||||
constructor($element, $scope, $window, $http) {
|
||||
this.$element = $element;
|
||||
this.$ = $scope;
|
||||
this.$window = $window;
|
||||
this.$http = $http;
|
||||
}
|
||||
submit() {
|
||||
if (!this.user) {
|
||||
this.focusUser();
|
||||
this.showError('Please insert your user and password');
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
model.appId = $window.location.href;
|
||||
$http.post('/auth', this.model).then(
|
||||
let params = {
|
||||
user: this.user,
|
||||
password: this.password,
|
||||
location: this.$window.location.href
|
||||
};
|
||||
this.$http.post('/auth/login', params).then(
|
||||
json => this.onLoginOk(json),
|
||||
json => this.onLoginErr(json)
|
||||
);
|
||||
},
|
||||
onLoginOk: function(json) {
|
||||
}
|
||||
onLoginOk(json) {
|
||||
this.loading = false;
|
||||
let data = json.data;
|
||||
$window.location = `${data.location}?access_token=${data.location}`;
|
||||
},
|
||||
onLoginErr: function(json) {
|
||||
let params = {
|
||||
token: data.token,
|
||||
continue: data.continue
|
||||
};
|
||||
this.$window.location = `${data.loginUrl}?${this.encodeUri(params)}`;
|
||||
}
|
||||
encodeUri(object) {
|
||||
let uri = '';
|
||||
for (var key in object)
|
||||
if (object[key]) {
|
||||
if (uri.length > 0)
|
||||
uri += '&';
|
||||
uri += encodeURIComponent(key) + '=' + encodeURIComponent(object[key]);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
onLoginErr(json) {
|
||||
this.loading = false;
|
||||
this.model.password = '';
|
||||
this.password = '';
|
||||
|
||||
let message;
|
||||
|
||||
|
@ -47,11 +65,20 @@ function controller($http, $element, $window) {
|
|||
message = 'Something went wrong';
|
||||
}
|
||||
|
||||
this.showMessage(message);
|
||||
},
|
||||
showMessage: function(message) {
|
||||
let snackbar = $element.find('vn-snackbar').controller('vnSnackbar');
|
||||
snackbar.show({message: message});
|
||||
this.showError(message);
|
||||
this.focusUser();
|
||||
}
|
||||
focusUser() {
|
||||
this.$.userField.select();
|
||||
this.$.userField.focus();
|
||||
}
|
||||
showError(message) {
|
||||
this.$.snackbar.showError({message: message});
|
||||
}
|
||||
});
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope', '$window', '$http'];
|
||||
|
||||
ngModule.component('vnLogin', {
|
||||
template: require('./login.html'),
|
||||
controller: Controller
|
||||
});
|
||||
|
|
|
@ -12,10 +12,11 @@ vn-login > div {
|
|||
|
||||
.box-wrapper {
|
||||
position: relative;
|
||||
max-width: 22em;
|
||||
max-width: 19em;
|
||||
margin: auto;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.box {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
|
@ -27,15 +28,18 @@ vn-login > div {
|
|||
box-shadow: 0 0 1em 0 rgba(1,1,1,.6);
|
||||
border-radius: .5em;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 1em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.spinner-wrapper {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
|
@ -44,4 +48,3 @@ vn-login > div {
|
|||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,14 @@
|
|||
import {ng} from 'vendor';
|
||||
import * as core from 'core';
|
||||
import 'core';
|
||||
|
||||
export const module = ng.module('vnAuth', [core.NAME]);
|
||||
let ngModule = ng.module('vnAuth', ['vnCore']);
|
||||
export default ngModule;
|
||||
|
||||
config.$inject = ['$translatePartialLoaderProvider', '$httpProvider'];
|
||||
export function config($translatePartialLoaderProvider, $httpProvider) {
|
||||
$translatePartialLoaderProvider.addPart('auth');
|
||||
|
||||
$httpProvider.defaults.useXDomain = true;
|
||||
delete $httpProvider.defaults.headers.common['X-Requested-With'];
|
||||
}
|
||||
ngModule.config(config);
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "@salix/client",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://git.verdnatura.es:/salix"
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
"module": "client",
|
||||
"routes": [
|
||||
{
|
||||
"url": "/clients",
|
||||
"state": "clients",
|
||||
"component": "vn-client-index"
|
||||
}, {
|
||||
"url": "/clients/:id",
|
||||
"state": "clientCard",
|
||||
"component": "vn-client-card"
|
||||
}, {
|
||||
"url": "/basic-data",
|
||||
"state": "clientCard.basicData",
|
||||
"component": "vn-client-basic-data",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
},
|
||||
"description": "Datos básicos",
|
||||
"icon": "person"
|
||||
}, {
|
||||
"url": "/fiscal-data",
|
||||
"state": "clientCard.fiscalData",
|
||||
"component": "vn-client-fiscal-data",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
},
|
||||
"description": "Datos facturación",
|
||||
"icon": "assignment"
|
||||
}, {
|
||||
"url": "/addresses",
|
||||
"state": "clientCard.addresses",
|
||||
"component": "vn-client-addresses",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
},
|
||||
"description": "Consignatarios",
|
||||
"icon": "local_shipping"
|
||||
}, {
|
||||
"url": "/web-access",
|
||||
"state": "clientCard.webAccess",
|
||||
"component": "vn-client-web-access",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
},
|
||||
"description": "Acceso web",
|
||||
"icon": "language"
|
||||
}, {
|
||||
"url": "/notes",
|
||||
"state": "clientCard.notes",
|
||||
"component": "vn-client-notes",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
},
|
||||
"description": "Notas",
|
||||
"icon": "insert_drive_file"
|
||||
}, {
|
||||
"url": "/new-note",
|
||||
"state": "clientCard.newNote",
|
||||
"component": "vn-new-note"
|
||||
},{
|
||||
"url": "/create",
|
||||
"state": "create",
|
||||
"component": "vn-client-create"
|
||||
}, {
|
||||
"url": "/address/create",
|
||||
"state": "clientCard.addressCreate",
|
||||
"component": "vn-address-create"
|
||||
}, {
|
||||
"url": "/address/:addressId",
|
||||
"state": "clientCard.addressEdit",
|
||||
"component": "vn-address-edit"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
{
|
||||
"module": "client",
|
||||
"name": "Clients",
|
||||
"icon": "person",
|
||||
"validations" : true,
|
||||
"routes": [
|
||||
{
|
||||
"url": "/clients?q",
|
||||
"state": "clients",
|
||||
"component": "vn-client-index",
|
||||
"acl": ["employee"]
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "create",
|
||||
"component": "vn-client-create"
|
||||
},
|
||||
{
|
||||
"url": "/clients/:id",
|
||||
"state": "clientCard",
|
||||
"abstract": true,
|
||||
"component": "vn-client-card"
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "clientCard.basicData",
|
||||
"component": "vn-client-basic-data",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Basic data",
|
||||
"icon": "settings"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/fiscal-data",
|
||||
"state": "clientCard.fiscalData",
|
||||
"component": "vn-client-fiscal-data",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Fiscal data",
|
||||
"icon": "account_balance"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/billing-data",
|
||||
"state": "clientCard.billingData",
|
||||
"component": "vn-client-billing-data",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Pay method",
|
||||
"icon": "icon-payment"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/addresses",
|
||||
"state": "clientCard.addresses",
|
||||
"component": "ui-view",
|
||||
"abstract": true
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "clientCard.addresses.list",
|
||||
"component": "vn-client-addresses",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Addresses",
|
||||
"icon": "local_shipping"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "clientCard.addresses.create",
|
||||
"component": "vn-address-create"
|
||||
},
|
||||
{
|
||||
"url": "/:addressId/edit",
|
||||
"state": "clientCard.addresses.edit",
|
||||
"component": "vn-address-edit"
|
||||
},
|
||||
{
|
||||
"url": "/web-access",
|
||||
"state": "clientCard.webAccess",
|
||||
"component": "vn-client-web-access",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Web access",
|
||||
"icon": "cloud"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/notes",
|
||||
"state": "clientCard.notes",
|
||||
"component": "ui-view",
|
||||
"abstract": true
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "clientCard.notes.list",
|
||||
"component": "vn-client-notes",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Notes",
|
||||
"icon": "insert_drive_file"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "clientCard.notes.create",
|
||||
"component": "vn-note-create"
|
||||
},
|
||||
{
|
||||
"url": "/credit",
|
||||
"abstract": true,
|
||||
"state": "clientCard.credit",
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "clientCard.credit.list",
|
||||
"component": "vn-client-credit-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Credit",
|
||||
"icon": "credit_card"
|
||||
}
|
||||
}, {
|
||||
"url": "/create",
|
||||
"state": "clientCard.credit.create",
|
||||
"component": "vn-client-credit-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/greuge",
|
||||
"abstract": true,
|
||||
"state": "clientCard.greuge",
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "clientCard.greuge.list",
|
||||
"component": "vn-client-greuge-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Greuge",
|
||||
"icon": "work"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "clientCard.greuge.create",
|
||||
"component": "vn-client-greuge-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/mandate",
|
||||
"state": "clientCard.mandate",
|
||||
"component": "vn-client-mandate",
|
||||
"menu": {
|
||||
"description": "Mandate",
|
||||
"icon": "pan_tool"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/invoices",
|
||||
"state": "clientCard.invoices",
|
||||
"component": "vn-client-invoices",
|
||||
"menu": {
|
||||
"description": "Invoices",
|
||||
"icon": "icon-invoices"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/recovery",
|
||||
"abstract": true,
|
||||
"state": "clientCard.recovery",
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "clientCard.recovery.list",
|
||||
"component": "vn-client-recovery-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Recovery",
|
||||
"icon": "icon-recovery"
|
||||
}
|
||||
}, {
|
||||
"url": "/create",
|
||||
"state": "clientCard.recovery.create",
|
||||
"component": "vn-client-recovery-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
}, {
|
||||
"url": "/summary",
|
||||
"state": "clientCard.summary",
|
||||
"component": "vn-client-summary",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="/client/api/Addresses"
|
||||
id-field="id"
|
||||
data="$ctrl.address"
|
||||
save="post"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submitGo('clientCard.addresses.list')" margin-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Address</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Default" field="$ctrl.address.isDefaultAddress"></vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Consignee" field="$ctrl.address.nickname" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Street address" field="$ctrl.address.street"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Postcode" field="$ctrl.address.postalCode"></vn-textfield>
|
||||
<vn-textfield vn-one label="Town/City" field="$ctrl.address.city"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.address.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Province">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.address.agencyModeFk"
|
||||
url="/client/api/AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-one label="Phone" field="$ctrl.address.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Mobile" field="$ctrl.address.mobile"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,16 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($state) {
|
||||
this.address = {
|
||||
clientFk: parseInt($state.params.id),
|
||||
isActive: true
|
||||
};
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$state'];
|
||||
|
||||
ngModule.component('vnAddressCreate', {
|
||||
template: require('./address-create.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
import './address-create.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnAddressCreate', () => {
|
||||
let controller;
|
||||
let $componentController;
|
||||
let $state;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$state_) => {
|
||||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$state.params.id = '1234';
|
||||
controller = $componentController('vnAddressCreate', {$state});
|
||||
}));
|
||||
|
||||
it('should define and set address property', () => {
|
||||
expect(controller.address.clientFk).toBe(1234);
|
||||
expect(controller.address.isActive).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,46 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="/client/api/Addresses"
|
||||
id-field="id"
|
||||
data="addressData.address"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="addressData.onSubmit()" pad-medium>
|
||||
<vn-card >
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Consignatario</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Predeterminado" field="addressData.address.default"></vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Consignatario" field="addressData.address.consignee" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Domicilio" field="addressData.address.street"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Código Postal" field="addressData.address.postcode"></vn-textfield>
|
||||
<vn-textfield vn-one label="Municipio" field="addressData.address.city"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="addressData.address.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Provincia">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="addressData.address.agencyFk"
|
||||
url="/client/api/AgencyServices"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agencia">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-one label="Teléfono" field="addressData.address.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Móvil" field="addressData.address.mobile"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Guardar"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,26 +0,0 @@
|
|||
import {module} from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $state) {
|
||||
this.$scope = $scope;
|
||||
this.$state = $state;
|
||||
this.address = {
|
||||
client: parseInt($state.params.id),
|
||||
enabled: true
|
||||
};
|
||||
}
|
||||
onSubmit() {
|
||||
this.$scope.watcher.submit().then(
|
||||
() => this.$state.go('clientCard.addresses')
|
||||
);
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$state'];
|
||||
|
||||
export const NAME = 'vnAddressCreate';
|
||||
export const COMPONENT = {
|
||||
template: require('./index.html'),
|
||||
controllerAs: 'addressData',
|
||||
controller: Controller
|
||||
};
|
||||
module.component(NAME, COMPONENT);
|
|
@ -0,0 +1,9 @@
|
|||
Street address: Dirección postal
|
||||
Default: Predeterminado
|
||||
Consignee: Consignatario
|
||||
Postcode: Código postal
|
||||
Town/City: Ciudad
|
||||
Province: Provincia
|
||||
Agency: Agencia
|
||||
Phone: Teléfono
|
||||
Mobile: Móvil
|
|
@ -0,0 +1,100 @@
|
|||
<mg-ajax
|
||||
path="/client/api/Addresses/{{edit.params.addressId}}"
|
||||
actions="$ctrl.address = edit.model; $ctrl._setIconAdd();"
|
||||
options="mgEdit">
|
||||
</mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="/client/api/Addresses"
|
||||
id-field="id"
|
||||
data="$ctrl.address"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.submit()" margin-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Address</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Enabled" field="$ctrl.address.isActive"></vn-check>
|
||||
<vn-check
|
||||
vn-one label="Is equalizated"
|
||||
field="$ctrl.address.isEqualizated"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Consignee" field="$ctrl.address.nickname" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Street" field="$ctrl.address.street"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Postcode" field="$ctrl.address.postalCode"></vn-textfield>
|
||||
<vn-textfield vn-one label="City" field="$ctrl.address.city"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.address.province"
|
||||
field="$ctrl.address.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Province">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.address.agencyMode"
|
||||
field="$ctrl.address.agencyModeFk"
|
||||
url="/client/api/AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-one label="Phone" field="$ctrl.address.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Mobile" field="$ctrl.address.mobile"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-one margin-medium-top>
|
||||
<vn-title>Notes</vn-title>
|
||||
<mg-ajax path="/client/api/ObservationTypes" options="mgIndex as observationsTypes"></mg-ajax>
|
||||
<vn-horizontal ng-repeat="observation in $ctrl.observations track by $index">
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
initial-data="observation.observationType"
|
||||
field="observation.observationTypeFk"
|
||||
data="observationsTypes.model"
|
||||
show-field="description"
|
||||
label="Observation type">
|
||||
<tpl-item>{{$parent.$parent.item.description}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
margin-large-right
|
||||
label="Description"
|
||||
model="observation.description"
|
||||
rule="addressObservation.description">
|
||||
</vn-textfield>
|
||||
<vn-auto pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
medium-grey
|
||||
vn-tooltip="Remove note"
|
||||
tooltip-position = "left"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.removeObservation($index)">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-icon
|
||||
pointer
|
||||
margin-medium-left
|
||||
vn-tooltip="Add note"
|
||||
tooltip-position = "right"
|
||||
orange
|
||||
icon="add_circle"
|
||||
ng-if="observationsTypes.model.length > $ctrl.observations.length"
|
||||
ng-click="$ctrl.addObservation()">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,134 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($state, $scope, $http, $q, $translate, vnApp) {
|
||||
this.$state = $state;
|
||||
this.$scope = $scope;
|
||||
this.$http = $http;
|
||||
this.$q = $q;
|
||||
this.$translate = $translate;
|
||||
this.vnApp = vnApp;
|
||||
|
||||
this.address = {
|
||||
id: parseInt($state.params.addressId)
|
||||
};
|
||||
this.observations = [];
|
||||
this.observationsOld = {};
|
||||
this.observationsRemoved = [];
|
||||
}
|
||||
|
||||
_setDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setDirty();
|
||||
}
|
||||
}
|
||||
_unsetDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setPristine();
|
||||
}
|
||||
}
|
||||
|
||||
addObservation() {
|
||||
this.observations.push({observationTypeFk: null, addressFk: this.address.id, description: null});
|
||||
}
|
||||
|
||||
removeObservation(index) {
|
||||
let item = this.observations[index];
|
||||
if (item) {
|
||||
this.observations.splice(index, 1);
|
||||
if (item.id) {
|
||||
this.observationsRemoved.push(item.id);
|
||||
this._setDirtyForm();
|
||||
}
|
||||
}
|
||||
if (this.observations.length === 0 && Object.keys(this.observationsOld).length === 0) {
|
||||
this._unsetDirtyForm();
|
||||
}
|
||||
}
|
||||
_submitObservations(objectObservations) {
|
||||
return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, objectObservations);
|
||||
}
|
||||
|
||||
_observationsEquals(ob1, ob2) {
|
||||
return ob1.id === ob2.id && ob1.observationTypeFk === ob2.observationTypeFk && ob1.description === ob2.description;
|
||||
}
|
||||
|
||||
submit() {
|
||||
if (this.$scope.form.$invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let canWatcherSubmit = this.$scope.watcher.dataChanged();
|
||||
let canObservationsSubmit;
|
||||
let repeatedTypes = false;
|
||||
let types = [];
|
||||
let observationsObj = {
|
||||
delete: this.observationsRemoved,
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
for (let i = 0; i < this.observations.length; i++) {
|
||||
let observation = this.observations[i];
|
||||
let isNewObservation = observation.id === undefined;
|
||||
|
||||
if (observation.observationTypeFk && types.indexOf(observation.observationTypeFk) !== -1) {
|
||||
repeatedTypes = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (observation.observationTypeFk)
|
||||
types.push(observation.observationTypeFk);
|
||||
|
||||
if (isNewObservation && observation.observationTypeFk && observation.description) {
|
||||
observationsObj.create.push(observation);
|
||||
} else if (!isNewObservation && !this._observationsEquals(this.observationsOld[observation.id], observation)) {
|
||||
observationsObj.update.push(observation);
|
||||
}
|
||||
}
|
||||
|
||||
canObservationsSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
||||
|
||||
if (repeatedTypes) {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('The observation type must be unique')
|
||||
);
|
||||
} else if (canWatcherSubmit && !canObservationsSubmit) {
|
||||
this.$scope.watcher.submit().then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else if (!canWatcherSubmit && canObservationsSubmit) {
|
||||
this._submitObservations(observationsObj).then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else if (canWatcherSubmit && canObservationsSubmit) {
|
||||
this.$q.all([this.$scope.watcher.submit(), this._submitObservations(observationsObj)]).then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('No changes to save')
|
||||
);
|
||||
}
|
||||
this._unsetDirtyForm();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
let filter = {
|
||||
where: {addressFk: this.address.id},
|
||||
include: {relation: 'observationType'}
|
||||
};
|
||||
this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => {
|
||||
this.observations = res.data;
|
||||
res.data.forEach(item => {
|
||||
this.observationsOld[item.id] = Object.assign({}, item);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
|
||||
|
||||
ngModule.component('vnAddressEdit', {
|
||||
template: require('./address-edit.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,55 @@
|
|||
import './address-edit.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnAddressEdit', () => {
|
||||
let $componentController;
|
||||
let $state;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$state.params.addressId = '1';
|
||||
controller = $componentController('vnAddressEdit', {$state: $state});
|
||||
}));
|
||||
|
||||
it('should define and set address property', () => {
|
||||
expect(controller.address.id).toEqual(1);
|
||||
});
|
||||
|
||||
describe('_observationsEquals', () => {
|
||||
it('should return true if two observations are equals independent of control attributes', () => {
|
||||
let ob1 = {id: 1, observationTypeFk: 1, description: 'Spiderman rocks', showAddIcon: true};
|
||||
let ob2 = {id: 1, observationTypeFk: 1, description: 'Spiderman rocks', showAddIcon: false};
|
||||
let equals = controller._observationsEquals(ob2, ob1);
|
||||
|
||||
expect(equals).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if two observations are not equals independent of control attributes', () => {
|
||||
let ob1 = {id: 1, observationTypeFk: 1, description: 'Spiderman rocks', showAddIcon: true};
|
||||
let ob2 = {id: 1, observationTypeFk: 1, description: 'Spiderman sucks', showAddIcon: true};
|
||||
let equals = controller._observationsEquals(ob2, ob1);
|
||||
|
||||
expect(equals).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onInit()', () => {
|
||||
it('should perform a GET query to receive the address observations', () => {
|
||||
let filter = {where: {addressFk: 1}, include: {relation: 'observationType'}};
|
||||
let res = ['some notes'];
|
||||
$httpBackend.when('GET', `/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).respond(res);
|
||||
$httpBackend.expectGET(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`);
|
||||
controller.$onInit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
get="true"
|
||||
url="/client/api/Addresses"
|
||||
id-field="id"
|
||||
data="addressData.address"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submitBack()" pad-medium>
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Consignatario</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Activo" field="addressData.address.enabled"></vn-check>
|
||||
<vn-check vn-one label="Predeterminado" field="addressData.address.default"></vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Consignatario" field="addressData.address.consignee" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Domicilio" field="addressData.address.street"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Código Postal" field="addressData.address.postcode"></vn-textfield>
|
||||
<vn-textfield vn-one label="Municipio" field="addressData.address.city"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="addressData.address.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Provincia">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="addressData.address.defaultAgencyFk"
|
||||
url="/client/api/AgencyServices"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agencia">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-one label="Teléfono" field="addressData.address.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Móvil" field="addressData.address.mobile"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Guardar"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,18 +0,0 @@
|
|||
import {module} from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($stateParams) {
|
||||
this.address = {
|
||||
id: $stateParams.addressId
|
||||
};
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$stateParams'];
|
||||
|
||||
export const NAME = 'vnAddressEdit';
|
||||
export const COMPONENT = {
|
||||
template: require('./index.html'),
|
||||
controllerAs: 'addressData',
|
||||
controller: Controller
|
||||
};
|
||||
module.component(NAME, COMPONENT);
|
|
@ -0,0 +1,7 @@
|
|||
Enabled: Activo
|
||||
Is equalizated: Recargo de equivalencia
|
||||
Observation type: Tipo de observación
|
||||
Description: Descripción
|
||||
The observation type must be unique: El tipo de observación ha de ser único
|
||||
Add note: Añadir nota
|
||||
Remove note: Quitar nota
|
|
@ -0,0 +1,47 @@
|
|||
<mg-ajax path="/client/api/Clients/{{index.params.id}}/listAddresses" options="mgIndex"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title vn-one>Addresses</vn-title>
|
||||
<vn-horizontal ng-repeat="address in index.model.items track by address.id" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-one border-radius class="pad-small border-solid"
|
||||
ng-class="{'bg-dark-item': address.isDefaultAddress,'bg-opacity-item': !address.isActive && !address.isDefaultAddress}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h style="color:#FFA410;">
|
||||
<i class="material-icons" ng-if="address.isDefaultAddress">star</i>
|
||||
<i class="material-icons"
|
||||
vn-tooltip="Active first to set as default"
|
||||
tooltip-position="left"
|
||||
ng-if="!address.isActive">star_border</i>
|
||||
<i class="material-icons pointer"
|
||||
ng-if="address.isActive && !address.isDefaultAddress"
|
||||
vn-tooltip="Set as default"
|
||||
tooltip-position="left"
|
||||
ng-click="$ctrl.setDefault(address)">star_border</i>
|
||||
</vn-none>
|
||||
<vn-one border-solid-right>
|
||||
<div><b>{{::address.nickname}}</b></div>
|
||||
<div>{{::address.street}}</div>
|
||||
<div>{{::address.city}}, {{::address.province}}</div>
|
||||
<div>{{::address.phone}}, {{::address.mobile}}</div>
|
||||
</vn-one>
|
||||
<vn-vertical vn-one pad-medium-h>
|
||||
<vn-one ng-repeat="observation in address.observations track by $index" ng-class="{'pad-small-top': $index}">
|
||||
<b margin-medium-right>{{::observation.observationType.description}}:</b>
|
||||
<span>{{::observation.description}}</span>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
<a vn-auto ui-sref="clientCard.addresses.edit({addressId: {{::address.id}}})">
|
||||
<vn-icon-button icon="edit"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-paging index="index" total="index.model.total"></vn-paging>
|
||||
<vn-float-button
|
||||
fixed-bottom-right
|
||||
ui-sref="clientCard.addresses.create"
|
||||
icon="add"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
</vn-vertical>
|
|
@ -0,0 +1,22 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class ClientAddresses {
|
||||
constructor($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$scope = $scope;
|
||||
}
|
||||
setDefault(address) {
|
||||
if (address.isActive) {
|
||||
let params = {isDefaultAddress: true};
|
||||
this.$http.patch(`/client/api/Addresses/${address.id}`, params).then(
|
||||
() => this.$scope.index.accept()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientAddresses.$inject = ['$http', '$scope'];
|
||||
|
||||
ngModule.component('vnClientAddresses', {
|
||||
template: require('./addresses.html'),
|
||||
controller: ClientAddresses
|
||||
});
|
|
@ -1,32 +0,0 @@
|
|||
<mg-ajax path="/client/api/Clients/{{index.params.id}}/addressesList" options="vnIndex"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-horizontal>
|
||||
<vn-title vn-one>Consignatario</vn-title>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal ng-repeat="i in index.model" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-auto style="border-radius: .5em;" class="pad-small border-solid"
|
||||
ng-class="{'bg-dark-item': i.default,'bg-opacity-item': !i.enabled && !i.default}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-auto>
|
||||
<div><b>{{i.consignee}}</b></div>
|
||||
<div>{{i.street}}</div>
|
||||
<div>{{i.city}}, {{i.province}}</div>
|
||||
<div>{{i.phone}}, {{i.mobile}}</div>
|
||||
</vn-auto>
|
||||
<a vn-empty ui-sref="clientCard.addressEdit({addressId: {{i.id}}})">
|
||||
<vn-icon-button icon="edit"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-paging index="index"></vn-paging>
|
||||
<vn-float-button
|
||||
fixed-bottom-right
|
||||
ui-sref="clientCard.addressCreate"
|
||||
icon="add">
|
||||
</vn-float-button>
|
||||
</vn-vertical>
|
|
@ -1,6 +0,0 @@
|
|||
import {module} from '../module';
|
||||
|
||||
export const component = {
|
||||
template: require('./index.html')
|
||||
};
|
||||
module.component('vnClientAddresses', component);
|
|
@ -0,0 +1,2 @@
|
|||
Set as default: Establecer como predeterminado
|
||||
Active first to set as default: Active primero para marcar como predeterminado
|
|
@ -0,0 +1,46 @@
|
|||
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submit()" margin-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Basic data</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Comercial Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Contact" field="$ctrl.client.contact"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Phone" field="$ctrl.client.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Mobile" field="$ctrl.client.mobile"></vn-textfield>
|
||||
<vn-textfield vn-one
|
||||
label="Email"
|
||||
field="$ctrl.client.email"
|
||||
info="You can save multiple emails">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.client.salesPerson"
|
||||
field="$ctrl.client.salesPersonFk"
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
select-fields="name"
|
||||
label="Salesperson"
|
||||
where="{or: [{firstName: {regexp: 'search'}}, {name: {regexp: 'search'}}]}">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.client.contactChannel"
|
||||
field="$ctrl.client.contactChannelFk"
|
||||
url="/client/api/ContactChannels"
|
||||
label="Channel">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,8 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
ngModule.component('vnClientBasicData', {
|
||||
template: require('./basic-data.html'),
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,44 +0,0 @@
|
|||
<mg-ajax path="/client/api/Clients/{{put.params.id}}" options="vnPut"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="put">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submit()" pad-medium>
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Datos básicos</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Nombre" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="NIF/CIF" field="$ctrl.client.fi"></vn-textfield>
|
||||
<vn-textfield autofocus vn-one label="Razón social" field="$ctrl.client.socialName"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Teléfono" field="$ctrl.client.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Móvil" field="$ctrl.client.mobile"></vn-textfield>
|
||||
<vn-textfield vn-one label="Fax" field="$ctrl.client.fax"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Email" field="$ctrl.client.email"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.client.salesPersonFk"
|
||||
url="/client/api/Employees"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Comercial">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.client.chanelFK"
|
||||
url="/client/api/Chanels"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Canal">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Guardar"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,9 +0,0 @@
|
|||
import {module} from '../module';
|
||||
|
||||
export const component = {
|
||||
template: require('./index.html'),
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
};
|
||||
module.component('vnClientBasicData', component);
|
|
@ -0,0 +1,14 @@
|
|||
Comercial Name: Nombre comercial
|
||||
Tax number: NIF/CIF
|
||||
Social name: Razón social
|
||||
Phone: Teléfono
|
||||
Mobile: Móvil
|
||||
Fax: Fax
|
||||
Email: Correo electrónico
|
||||
Salesperson: Comercial
|
||||
Channel: Canal
|
||||
You can save multiple emails: >-
|
||||
Puede guardar varios correos electrónicos encadenándolos mediante comas
|
||||
sin espacios, ejemplo: user@dominio.com, user2@dominio.com siendo el primer
|
||||
correo electrónico el principal
|
||||
Contact: Contacto
|
|
@ -0,0 +1,64 @@
|
|||
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.submit()" pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Pay method</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-two
|
||||
vn-acl="administrative, salesAssistant"
|
||||
field="$ctrl.client.payMethodFk"
|
||||
url="/client/api/PayMethods"
|
||||
select-fields="ibanRequired"
|
||||
initial-data="$ctrl.client.payMethod"
|
||||
label="Pay method">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-two label="IBAN"
|
||||
field="$ctrl.client.iban"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one label="Due day"
|
||||
field="$ctrl.client.dueDay"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-medium-bottom>
|
||||
<vn-one>
|
||||
<vn-check
|
||||
label="Received core VNH"
|
||||
field="$ctrl.client.hasCoreVnh"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check
|
||||
label="Received core VNL"
|
||||
field="$ctrl.client.hasCoreVnl"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check
|
||||
label="Received B2B VNL"
|
||||
field="$ctrl.client.hasSepaVnl"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save" vn-acl="administrative, salesAssistant"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<vn-confirm
|
||||
vn-id="send-mail"
|
||||
on-response="$ctrl.returnDialog(response)"
|
||||
question="Changed terms"
|
||||
message="Notify customer?">
|
||||
</vn-confirm>
|
|
@ -0,0 +1,57 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope, $http, vnApp, $translate) {
|
||||
this.$ = $scope;
|
||||
this.$http = $http;
|
||||
this.vnApp = vnApp;
|
||||
this.translate = $translate;
|
||||
this.billData = {};
|
||||
this.copyData();
|
||||
}
|
||||
$onChanges() {
|
||||
this.copyData();
|
||||
}
|
||||
copyData() {
|
||||
if (this.client) {
|
||||
this.billData.payMethodFk = this.client.payMethodFk;
|
||||
this.billData.iban = this.client.iban;
|
||||
this.billData.dueDay = this.client.dueDay;
|
||||
}
|
||||
}
|
||||
submit() {
|
||||
return this.$.watcher.submit().then(
|
||||
() => this.checkPaymentChanges());
|
||||
}
|
||||
checkPaymentChanges() {
|
||||
let equals = true;
|
||||
Object.keys(this.billData).forEach(
|
||||
val => {
|
||||
if (this.billData[val] !== this.client[val]) {
|
||||
this.billData[val] = this.client[val];
|
||||
equals = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!equals) {
|
||||
this.$.sendMail.show();
|
||||
}
|
||||
}
|
||||
returnDialog(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.$http.post(`/mailer/notification/payment-update/${this.client.id}`).then(
|
||||
() => this.vnApp.showMessage(this.translate.instant('Notification sent!'))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$http', 'vnApp', '$translate'];
|
||||
|
||||
ngModule.component('vnClientBillingData', {
|
||||
template: require('./billing-data.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,80 @@
|
|||
import './billing-data.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientBillingData', () => {
|
||||
let $componentController;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
$scope = $rootScope.$new();
|
||||
let submit = jasmine.createSpy('submit').and.returnValue(Promise.resolve());
|
||||
$scope.watcher = {submit};
|
||||
let show = jasmine.createSpy('show');
|
||||
$scope.sendMail = {show};
|
||||
controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('copyData()', () => {
|
||||
it(`should define billData using client's data`, () => {
|
||||
controller.client = {
|
||||
dueDay: 0,
|
||||
iban: null,
|
||||
payMethodFk: 1
|
||||
};
|
||||
controller.billData = {};
|
||||
controller.copyData(controller.client);
|
||||
|
||||
expect(controller.billData).toEqual(controller.client);
|
||||
});
|
||||
});
|
||||
|
||||
describe('submit()', () => {
|
||||
it(`should call submit() on the watcher then receive a callback`, done => {
|
||||
spyOn(controller, 'checkPaymentChanges');
|
||||
controller.submit()
|
||||
.then(() => {
|
||||
expect(controller.$.watcher.submit).toHaveBeenCalledWith();
|
||||
expect(controller.checkPaymentChanges).toHaveBeenCalledWith();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkPaymentChanges()', () => {
|
||||
it(`should not call sendMail.show() if there are no changes on billing data`, () => {
|
||||
controller.billData = {marvelHero: 'Silver Surfer'};
|
||||
controller.client = {marvelHero: 'Silver Surfer'};
|
||||
controller.checkPaymentChanges();
|
||||
|
||||
expect(controller.$.sendMail.show).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should call sendMail.show() if there are changes on billing data object`, () => {
|
||||
controller.billData = {marvelHero: 'Silver Surfer'};
|
||||
controller.client = {marvelHero: 'Spider-Man'};
|
||||
controller.checkPaymentChanges();
|
||||
|
||||
expect(controller.$.sendMail.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('returnDialog()', () => {
|
||||
it('should request to send notification email', () => {
|
||||
controller.client = {id: '123'};
|
||||
$httpBackend.when('POST', `/mailer/notification/payment-update/${controller.client.id}`).respond('done');
|
||||
$httpBackend.expectPOST(`/mailer/notification/payment-update/${controller.client.id}`);
|
||||
controller.returnDialog('ACCEPT');
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
Changed terms: Payment terms have changed
|
||||
Notify customer?: Do you want to notify customer?
|
||||
No: No
|
||||
Yes, notify: Yes, notify
|
||||
Notification sent!: Notification sent!
|
||||
Notification error: Error while sending notification
|
||||
Yes, propagate: Yes, propagate
|
||||
Equivalent tax spreaded: Equivalent tax spreaded
|
||||
Invoice by address: Invoice by address
|
||||
Equalization tax: Equalization tax
|
||||
Due day: Due day
|
||||
Received core VNH: VNH core received
|
||||
Received core VNL: VNL core received
|
||||
Received B2B VNL: VNL B2B received
|
||||
Save: Save
|
|
@ -0,0 +1,15 @@
|
|||
Changed terms: Has modificado las condiciones de pago
|
||||
Notify customer?: ¿Deseas notificar al cliente de dichos cambios?
|
||||
No: No
|
||||
Yes, notify: Sí, notificar
|
||||
Notification sent!: ¡Notificación enviada!
|
||||
Notification error: Error al enviar notificación
|
||||
Yes, propagate: Si, propagar
|
||||
Equivalent tax spreaded: Recargo de equivalencia propagado
|
||||
Invoice by address: Facturar por consignatario
|
||||
Equalization tax: Recargo de equivalencia
|
||||
Due day: Vencimiento
|
||||
Received core VNH: Recibido core VNH
|
||||
Received core VNL: Recibido core VNL
|
||||
Received B2B VNL: Recibido B2B VNL
|
||||
Save: Guardar
|
|
@ -0,0 +1,16 @@
|
|||
<vn-main-block>
|
||||
<mg-ajax
|
||||
path="/client/api/Clients/{{edit.params.id}}/card"
|
||||
actions="$ctrl.client = edit.model"
|
||||
options="mgEdit">
|
||||
</mg-ajax>
|
||||
<vn-horizontal>
|
||||
<vn-auto class="left-block">
|
||||
<vn-client-descriptor client="$ctrl.client"></vn-client-descriptor>
|
||||
<vn-left-menu></vn-left-menu>
|
||||
</vn-auto>
|
||||
<vn-one>
|
||||
<vn-vertical ui-view></vn-vertical>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-main-block>
|
|
@ -0,0 +1,12 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor() {
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnClientCard', {
|
||||
template: require('./card.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
import './card.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCard', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope;
|
||||
controller = $componentController('vnClientCard', {$scope: $scope});
|
||||
}));
|
||||
|
||||
it('should define and set client property to null in the module instance', () => {
|
||||
expect(controller.client).toBeDefined();
|
||||
expect(controller.client).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
<vn-horizontal>
|
||||
<vn-empty style="min-width: 18em; padding-left: 1em; padding-bottom: 1em;">
|
||||
<vn-descriptor client="card.client" active="card.client.active" class="display-block" ></vn-descriptor>
|
||||
<vn-left-menu items="card.items"></vn-left-menu>
|
||||
</vn-empty>
|
||||
<vn-auto>
|
||||
<vn-vertical style="max-width: 70em; margin: 0 auto;" ui-view></vn-vertical>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
|
@ -1,26 +0,0 @@
|
|||
import {module} from '../module';
|
||||
import './style.css';
|
||||
|
||||
export const NAME = 'vnClientCard';
|
||||
export const COMPONENT = {
|
||||
template: require('./index.html'),
|
||||
controllerAs: 'card',
|
||||
controller: function($http, $stateParams) {
|
||||
this.client = null;
|
||||
$http.get(`/client/api/Clients/${$stateParams.id}?filter[include][accountFk]`).then(
|
||||
json => this.client = json.data
|
||||
);
|
||||
|
||||
this.items = [];
|
||||
routes.client.routes.forEach(i => {
|
||||
if (i.description)
|
||||
this.items.push({
|
||||
description: i.description,
|
||||
icon: i.icon,
|
||||
href: i.state
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
COMPONENT.controller.$inject = ['$http', '$stateParams'];
|
||||
module.component(NAME, COMPONENT);
|
|
@ -1,3 +0,0 @@
|
|||
vn-descriptor{
|
||||
font-family: raleway-bold;
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
export * from './module';
|
||||
|
||||
export {NAME as CLIENT_CARD,
|
||||
COMPONENT as CLIENT_CARD_COMPONENT} from './card/index';
|
||||
export {NAME as CLIENTS,
|
||||
COMPONENT as CLIENTS_COMPONENT} from './index/index';
|
||||
export {NAME as CLIENT_FISCAL_DATA_INDEX,
|
||||
COMPONENT as CLIENT_FISCAL_DATA_INDEX_COMPONENT} from './fiscal-data/index';
|
||||
export {NAME as CLIENT_DESCRIPTOR,
|
||||
COMPONENT as CLIENT_DESCRIPTOR_COMPONENT} from './descriptor/index';
|
||||
export {NAME as CLIENT_NOTES,
|
||||
COMPONENT as CLIENT_NOTES_COMPONENT} from './notes/index';
|
||||
export {NAME as CLIENT_SEARCH_PANEL,
|
||||
COMPONENT as CLIENT_SEARCH_PANEL_COMPONENT} from './search-panel/index';
|
||||
export {NAME as CLIENT_CREATE,
|
||||
COMPONENT as CLIENT_CREATE_COMPONENT} from './create/index';
|
||||
export {NAME as CLIENT_ADDRESS_EDIT_INDEX,
|
||||
COMPONENT as CLIENT_ADDRESS_EDIT_INDEX_COMPONENT} from './address-edit/index';
|
||||
export {NAME as NEW_NOTE_INDEX,
|
||||
COMPONENT as NEW_NOTE_INDEX_COMPONENT} from './new-note/index';
|
||||
|
||||
import './addresses/index';
|
||||
import './address-create/index';
|
||||
import './basic-data/index';
|
||||
import './web-access/index';
|
||||
import './index/index';
|
||||
import './card/card';
|
||||
import './create/create';
|
||||
import './basic-data/basic-data';
|
||||
import './fiscal-data/fiscal-data';
|
||||
import './billing-data/billing-data';
|
||||
import './descriptor/descriptor';
|
||||
import './search-panel/search-panel';
|
||||
import './addresses/addresses';
|
||||
import './address-create/address-create';
|
||||
import './address-edit/address-edit';
|
||||
import './notes/notes';
|
||||
import './note-create/note-create';
|
||||
import './web-access/web-access';
|
||||
import './credit-list/credit-list';
|
||||
import './credit-create/credit-create';
|
||||
import './greuge-list/greuge-list';
|
||||
import './greuge-create/greuge-create';
|
||||
import './mandate/mandate';
|
||||
import './invoices/invoices';
|
||||
import './summary/client-summary';
|
||||
import './recovery-list/recovery-list';
|
||||
import './recovery-create/recovery-create';
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<mg-ajax path="/client/api/Clients/createWithUser" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
||||
<div style="max-width: 70em; margin: 0 auto;">
|
||||
<vn-card pad-large>
|
||||
<vn-title>Create client</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Tax number" field="$ctrl.client.fi"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Business name" field="$ctrl.client.socialName"></vn-textfield>
|
||||
<vn-textfield vn-one label="Web user" field="$ctrl.client.userName"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Email" field="$ctrl.client.email" info="You can save multiple emails"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.client.salesPersonFk"
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
select-fields="name"
|
||||
label="Salesperson"
|
||||
where="{or: [{firstName: {regexp: 'search'}}, {name: {regexp: 'search'}}]}">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Create"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
|
@ -1,23 +1,22 @@
|
|||
import {module} from '../module';
|
||||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
export default class Controller {
|
||||
constructor($scope, $state) {
|
||||
this.$scope = $scope;
|
||||
this.$ = $scope;
|
||||
this.$state = $state;
|
||||
this.client = {
|
||||
active: true
|
||||
};
|
||||
}
|
||||
onSubmit() {
|
||||
this.$scope.watcher.submit().then(
|
||||
this.$.watcher.submit().then(
|
||||
json => this.$state.go('clientCard.basicData', {id: json.data.id})
|
||||
);
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$state'];
|
||||
|
||||
export const component = {
|
||||
template: require('./index.html'),
|
||||
ngModule.component('vnClientCreate', {
|
||||
template: require('./create.html'),
|
||||
controller: Controller
|
||||
};
|
||||
module.component('vnClientCreate', component);
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
import './create.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreate', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$state = _$state_;
|
||||
$scope.watcher = {
|
||||
submit: () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback({data: {id: '1234'}});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnClientCreate', {$scope: $scope});
|
||||
}));
|
||||
|
||||
it('should define and set scope, state and client properties', () => {
|
||||
expect(controller.$).toBe($scope);
|
||||
expect(controller.$state).toBe($state);
|
||||
expect(controller.client.active).toBe(true);
|
||||
});
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it(`should call submit() on the watcher then expect a callback`, () => {
|
||||
spyOn($state, 'go');
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('clientCard.basicData', {id: '1234'});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
<mg-ajax path="/client/api/Clients" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
||||
<div style="max-width: 70em; margin: 0 auto;">
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Crear Cliente</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Nombre" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="NIF/CIF" field="$ctrl.client.fi"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Razón social" field="$ctrl.client.socialName"></vn-textfield>
|
||||
<vn-one></vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Crear y continuar"></vn-submit>
|
||||
<vn-button label="Crear" ng-click="watcher.submitBack()"></vn-button>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,11 @@
|
|||
Name: Nombre
|
||||
Tax number: NIF/CIF
|
||||
Business name: Razón social
|
||||
Web user: Usuario Web
|
||||
Email: Correo electrónico
|
||||
Create and edit: Crear y editar
|
||||
Create: Crear
|
||||
You can save multiple emails: >-
|
||||
Puede guardar varios correos electrónicos encadenándolos mediante comas
|
||||
sin espacios, ejemplo: user@dominio.com, user2@dominio.com siendo el primer
|
||||
correo electrónico el principal
|
|
@ -0,0 +1,18 @@
|
|||
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submitGo('clientCard.credit.list')" pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Add credit</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Credit" field="$ctrl.client.credit" type="number" vn-focus></vn-textfield>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,8 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
ngModule.component('vnClientCreditCreate', {
|
||||
template: require('./credit-create.html'),
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
Add credit: Añadir crédito
|
|
@ -0,0 +1,29 @@
|
|||
<mg-ajax path="/client/api/ClientCredits/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Credit</vn-title>
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h field="amount" text="Credit"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="created" text="Since" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="worker.firstName" text="Employee" order-locked></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
vn-one class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="credit in index.model.instances track by credit.id">
|
||||
<vn-one pad-medium-h>{{::credit.amount | number:2}} €</vn-one>
|
||||
<vn-two pad-medium-h>{{::credit.created | date:'dd/MM/yyyy HH:mm' }}</vn-two>
|
||||
<vn-two pad-medium-h>{{::credit.worker.firstName}} {{::credit.worker.name}}</vn-two>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
|
||||
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<a ui-sref="clientCard.credit.create" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -0,0 +1,7 @@
|
|||
import ngModule from '../module';
|
||||
import FilterClientList from '../filter-client-list';
|
||||
|
||||
ngModule.component('vnClientCreditList', {
|
||||
template: require('./credit-list.html'),
|
||||
controller: FilterClientList
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
Since : Desde
|
||||
Employee : Empleado
|
||||
No results: Sin resultados
|
|
@ -0,0 +1,54 @@
|
|||
<vn-card margin-medium-v class="vn-descriptor">
|
||||
<vn-horizontal class="header">
|
||||
<a translate-attr="{title: 'Return to module index'}" ui-sref="clients">
|
||||
<vn-icon icon="chevron_left"></vn-icon>
|
||||
</a>
|
||||
<vn-icon icon="person"></vn-icon>
|
||||
<a translate-attr="{title: 'Preview'}" ui-sref="clientCard.summary">
|
||||
<vn-icon icon="desktop_windows"></vn-icon>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
<div pad-medium>
|
||||
<h6>{{$ctrl.client.name}}</h6>
|
||||
<div>
|
||||
<vn-label translate>Id</vn-label> {{$ctrl.client.id}}
|
||||
</div>
|
||||
<div>
|
||||
<vn-label translate>Phone</vn-label> {{$ctrl.client.phone | phone}}
|
||||
</div>
|
||||
<div>
|
||||
<vn-label translate>Credit</vn-label> {{$ctrl.client.credit | currency:'€':2}}
|
||||
</div>
|
||||
<div>
|
||||
<vn-label translate>Secured credit</vn-label>
|
||||
<span ng-if="$ctrl.client.creditInsurance">{{$ctrl.client.creditInsurance | currency:'€':2}}</span>
|
||||
<span ng-if="!$ctrl.client.creditInsurance">-</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<vn-icon
|
||||
vn-tooltip="Client inactive"
|
||||
tooltip-position = "right"
|
||||
icon="person"
|
||||
ng-class="{bright: $ctrl.client.isActive == false}">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client Frozen"
|
||||
tooltip-position = "right"
|
||||
icon="mail"
|
||||
ng-class="{bright: $ctrl.client.isFreezed == true}">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Web Account inactive"
|
||||
tooltip-position = "right"
|
||||
icon="phone"
|
||||
ng-class="{bright: $ctrl.client.account.active == false}">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client has debt"
|
||||
tooltip-position = "right"
|
||||
icon="power"
|
||||
ng-class="{bright: $ctrl.clientDebt < 0}">
|
||||
</vn-icon>
|
||||
</div>
|
||||
</vn-card>
|
|
@ -0,0 +1,36 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class ClientDescriptor {
|
||||
constructor($http) {
|
||||
this.$http = $http;
|
||||
}
|
||||
_getClientDebt(clientFk) {
|
||||
this.$http.get(`/client/api/Clients/${clientFk}/getDebt`)
|
||||
.then(response => {
|
||||
this.clientDebt = response.data.debt;
|
||||
});
|
||||
}
|
||||
|
||||
_getClient(clientFk) {
|
||||
this.$http.get(`/client/api/Clients/${clientFk}/card`)
|
||||
.then(response => {
|
||||
Object.assign(this.client, response.data);
|
||||
});
|
||||
}
|
||||
|
||||
$onChanges(changes) {
|
||||
if (changes.client && this.client) {
|
||||
this._getClient(this.client.id);
|
||||
this._getClientDebt(this.client.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientDescriptor.$inject = ['$http'];
|
||||
|
||||
ngModule.component('vnClientDescriptor', {
|
||||
template: require('./descriptor.html'),
|
||||
bindings: {
|
||||
client: '<'
|
||||
},
|
||||
controller: ClientDescriptor
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
import './descriptor.js';
|
||||
|
||||
describe('Descriptor', () => {
|
||||
describe('Component vnClientDescriptor', () => {
|
||||
let $componentController;
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnClientDescriptor');
|
||||
}));
|
||||
|
||||
describe('_getClientDebt()', () => {
|
||||
it(`should call _getClientDebt() and define the clientDebt value on the controller`, () => {
|
||||
controller.client = {};
|
||||
let response = {debt: 100};
|
||||
$httpBackend.whenGET(`/client/api/Clients/101/getDebt`).respond(response);
|
||||
$httpBackend.expectGET(`/client/api/Clients/101/getDebt`);
|
||||
controller._getClientDebt(101);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.clientDebt).toEqual(100);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_getClient()', () => {
|
||||
it(`should call _getClient() and define the client value on the controller`, () => {
|
||||
controller.client = {};
|
||||
let response = {id: 101, name: 'Batman'};
|
||||
$httpBackend.whenGET(`/client/api/Clients/101/card`).respond(response);
|
||||
$httpBackend.expectGET(`/client/api/Clients/101/card`);
|
||||
controller._getClient(101);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.client.name).toEqual('Batman');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
<vn-card>
|
||||
<vn-vertical class="margin-medium" pad-medium-top pad-medium-bottom>
|
||||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<i class="material-icons descriptor-icon">person</i>
|
||||
</vn-one>
|
||||
<vn-vertical vn-two>
|
||||
<div class="margin-none">{{descriptor.client.id}}</div>
|
||||
<div class="margin-none">{{descriptor.client.name}}</div>
|
||||
<div class="margin-none">{{descriptor.client.phone}}</div>
|
||||
<vn-switch label="Activo" model="descriptor.active"></vn-switch>
|
||||
</vn-vertical>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
|
@ -1,21 +0,0 @@
|
|||
import {module} from '../module';
|
||||
import './style.css';
|
||||
|
||||
export const NAME = 'vnDescriptor';
|
||||
export const COMPONENT = {
|
||||
template: require('./index.html'),
|
||||
controllerAs: 'descriptor',
|
||||
bindings: {
|
||||
client: '<',
|
||||
active: '<'
|
||||
},
|
||||
controller: function($http, $scope) {
|
||||
var self = this;
|
||||
$scope.$watch('descriptor.active', function(newValue, oldValue) {
|
||||
if (oldValue !== undefined)
|
||||
$http.put(`/client/api/Clients/${self.client.id}/activate`);
|
||||
});
|
||||
}
|
||||
};
|
||||
COMPONENT.controller.$inject = ['$http', '$scope'];
|
||||
module.component(NAME, COMPONENT);
|
|
@ -1,3 +0,0 @@
|
|||
.descriptor-icon{
|
||||
font-size:60px;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import FilterList from 'core/src/lib/filter-list';
|
||||
|
||||
export default class FilterClientList extends FilterList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
super($scope, $timeout, $state);
|
||||
this.modelName = 'clientFk';
|
||||
}
|
||||
}
|
||||
FilterClientList.$inject = ['$scope', '$timeout', '$state'];
|
|
@ -0,0 +1,141 @@
|
|||
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.submit()" pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Fiscal data</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
vn-focus
|
||||
label="Social name"
|
||||
field="$ctrl.client.socialName"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Tax number"
|
||||
field="$ctrl.client.fi"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-textfield>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Is equalizated"
|
||||
field="$ctrl.client.isEqualizated"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
label="Street"
|
||||
field="$ctrl.client.street"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="City"
|
||||
field="$ctrl.client.city"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Postcode"
|
||||
field="$ctrl.client.postcode"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
initial-data="$ctrl.client.province"
|
||||
field="$ctrl.client.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Province"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
initial-data="$ctrl.client.country"
|
||||
field="$ctrl.client.countryFk"
|
||||
url="/client/api/Countries"
|
||||
show-field="country"
|
||||
value-field="id"
|
||||
label="Country"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-small-bottom>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Active"
|
||||
field="$ctrl.client.isActive"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Invoice by address"
|
||||
field="$ctrl.client.hasToInvoiceByAddress"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Verified data"
|
||||
field="$ctrl.client.isTaxDataChecked"
|
||||
vn-acl="administrative, salesAssistant, salesAssistant">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Has to invoice"
|
||||
field="$ctrl.client.hasToInvoice"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Invoice by mail"
|
||||
field="$ctrl.client.isToBeMailed"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Vies"
|
||||
field="$ctrl.client.isVies"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
label="Save"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<vn-confirm
|
||||
vn-id="propagate-isEqualizated"
|
||||
question="You changed the equalization tax"
|
||||
message="Do you want to spread the change?"
|
||||
on-response="$ctrl.returnDialogEt(response)">
|
||||
</vn-confirm>
|
|
@ -0,0 +1,60 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class ClientFiscalData {
|
||||
constructor($scope, $http, vnApp, $translate) {
|
||||
this.$ = $scope;
|
||||
this.$http = $http;
|
||||
this.vnApp = vnApp;
|
||||
this.translate = $translate;
|
||||
this.isEqualizated = undefined;
|
||||
this.copyData();
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
this.copyData();
|
||||
}
|
||||
|
||||
copyData() {
|
||||
if (this.client) {
|
||||
this.isEqualizated = this.client.isEqualizated;
|
||||
}
|
||||
}
|
||||
|
||||
buyerHaspermissions() {
|
||||
if (!this.client) return true;
|
||||
return !this.client.isTaxDataChecked;
|
||||
}
|
||||
|
||||
submit() {
|
||||
return this.$.watcher.submit().then(
|
||||
() => this.checkEtChanges());
|
||||
}
|
||||
|
||||
checkEtChanges() {
|
||||
let equals = this.isEqualizated == this.client.isEqualizated;
|
||||
this.isEqualizated = this.client.isEqualizated;
|
||||
|
||||
if (!equals)
|
||||
this.$.propagateIsEqualizated.show();
|
||||
}
|
||||
|
||||
returnDialogEt(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.$http.patch(`/client/api/Clients/${this.client.id}/addressesPropagateRe`, {isEqualizated: this.client.isEqualizated}).then(
|
||||
res => {
|
||||
if (res.data)
|
||||
this.vnApp.showMessage(this.translate.instant('Equivalent tax spreaded'));
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientFiscalData.$inject = ['$scope', '$http', 'vnApp', '$translate'];
|
||||
|
||||
ngModule.component('vnClientFiscalData', {
|
||||
template: require('./fiscal-data.html'),
|
||||
controller: ClientFiscalData,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
import './fiscal-data.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientFiscalData', () => {
|
||||
let $componentController;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnClientFiscalData', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('returnDialogEt()', () => {
|
||||
it('should request to patch the propagation of tax status', () => {
|
||||
controller.client = {id: 123, isEqualizated: false};
|
||||
$httpBackend.when('PATCH', `/client/api/Clients/${controller.client.id}/addressesPropagateRe`, {isEqualizated: controller.client.isEqualizated}).respond('done');
|
||||
$httpBackend.expectPATCH(`/client/api/Clients/${controller.client.id}/addressesPropagateRe`, {isEqualizated: controller.client.isEqualizated});
|
||||
controller.returnDialogEt('ACCEPT');
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,73 +0,0 @@
|
|||
<mg-ajax path="/client/api/Clients/{{put.params.id}}" options="vnPut"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="fiscal.client"
|
||||
form="form"
|
||||
save="put">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submit()" pad-medium>
|
||||
<vn-card margin-small-bottom>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Datos fiscales y de facturación</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Facturar" field="fiscal.client.hasToInvoice"></vn-check>
|
||||
<vn-check vn-one label="Factura impresa" field="fiscal.client.invoiceByEmail"></vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-two label="Domicilio fiscal" field="fiscal.client.street" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Municipio" field="fiscal.client.city"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Código postal" field="fiscal.client.postcode"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="fiscal.client.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Provincia">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
field="fiscal.client.countryFk"
|
||||
url="/client/api/Countries"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="País">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-card margin-small-bottom>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Información de facturación</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-two label="IBAN" field="fiscal.client.iban"></vn-textfield>
|
||||
<vn-autocomplete vn-two
|
||||
field="fiscal.client.payMethodFk"
|
||||
url="/client/api/PayMethods"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Forma de pago">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-one label="Vencimiento" field="fiscal.client.dueDay"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Crédito" field="fiscal.client.credit"></vn-textfield>
|
||||
<vn-textfield vn-one label="Crédito asegurado" field="fiscal.client.creditInsurance"></vn-textfield>
|
||||
<vn-check vn-three label="Recargo de equivalencia" field="fiscal.client.surcharge"></vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-card margin-small-bottom>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Documentación</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Recibido core VNH" field="fiscal.client.coreVnh"></vn-check>
|
||||
<vn-check vn-one label="Recibido core VNL" field="fiscal.client.coreVnl"></vn-check>
|
||||
<vn-check vn-one label="Recibido B2B VNL" field="fiscal.client.sepaVnl"></vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Guardar"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,11 +0,0 @@
|
|||
import {module} from '../module';
|
||||
|
||||
export const NAME = 'vnClientFiscalData';
|
||||
export const COMPONENT = {
|
||||
template: require('./index.html'),
|
||||
controllerAs: 'fiscal',
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
};
|
||||
module.component(NAME, COMPONENT);
|
|
@ -0,0 +1,4 @@
|
|||
No: No
|
||||
Yes, notify: Sí, notificar
|
||||
You changed the equalization tax: Has cambiado el recargo de equivalencia
|
||||
Do you want to spread the change: ¿Deseas propagar el cambio a sus consignatarios?
|
|
@ -0,0 +1,44 @@
|
|||
<mg-ajax path="/client/api/greuges" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.greuge"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>Add Greuge</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
margin-medium-right
|
||||
label="Amount"
|
||||
field="$ctrl.greuge.amount"
|
||||
step="1"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-date-picker vn-one
|
||||
label="Date"
|
||||
model="$ctrl.greuge.shipped"
|
||||
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i', time_24hr: true}">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
argin-medium-right
|
||||
label="Comment"
|
||||
field="$ctrl.greuge.description">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
field="$ctrl.greuge.greugeTypeFk"
|
||||
url="/client/api/greugeTypes"
|
||||
label="Type">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,25 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class ClientGreugeCreate {
|
||||
constructor($scope, $state, $filter) {
|
||||
this.$ = $scope;
|
||||
this.$state = $state;
|
||||
this.greuge = {
|
||||
shipped: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm')
|
||||
};
|
||||
}
|
||||
onSubmit() {
|
||||
this.greuge.clientFk = this.$state.params.id;
|
||||
this.$.watcher.submit().then(
|
||||
() => {
|
||||
this.$state.go('clientCard.greuge.list');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
ClientGreugeCreate.$inject = ['$scope', '$state', '$filter'];
|
||||
|
||||
ngModule.component('vnClientGreugeCreate', {
|
||||
template: require('./greuge-create.html'),
|
||||
controller: ClientGreugeCreate
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
import './greuge-create.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientGreugeCreate', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$state = _$state_;
|
||||
$scope.watcher = {
|
||||
submit: () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnClientGreugeCreate', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('should call the function go() on $state to go to the greuges list', () => {
|
||||
spyOn($state, 'go');
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('clientCard.greuge.list');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
<mg-ajax path="/client/api/greuges/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<mg-ajax path="/client/api/greuges/{{edit.params.id}}/sumAmount" options="mgEdit"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Greuge</vn-title>
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h field="shipped" text="Date" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="description" text="Comment"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="amount" text="Amount"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="greugeTypeFk" text="Type"></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="greuge in index.model.instances track by greuge.id">
|
||||
<vn-one pad-medium-h>{{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }}</vn-one>
|
||||
<vn-two pad-medium-h>{{::greuge.description}}</vn-two>
|
||||
<vn-one pad-medium-h>{{::greuge.amount | number:2}} €</vn-one>
|
||||
<vn-one pad-medium-h>{{::greuge.greugeType.name}}</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer text-center">
|
||||
<vn-one pad-medium-h></vn-one>
|
||||
<vn-two pad-medium-h></vn-two>
|
||||
<vn-one pad-medium-h ng-if="index.model.count > 0">{{edit.model.sumAmount | number:2}} €</vn-one>
|
||||
<vn-one pad-medium-h></vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-paging margin-large-top vn-one index="index" total="index.model.count"></vn-paging>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<a ui-sref="clientCard.greuge.create" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import ngModule from '../module';
|
||||
import FilterClientList from '../filter-client-list';
|
||||
|
||||
ngModule.component('vnClientGreugeList', {
|
||||
template: require('./greuge-list.html'),
|
||||
controller: FilterClientList
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
Date: Fecha
|
||||
Comment: Comentario
|
||||
Amount: Importe
|
||||
Type: Tipo
|
||||
Add Greuge: Añadir Greuge
|
|
@ -1,23 +1,32 @@
|
|||
<mg-ajax path="/client/api/Clients/filter" options="vnIndex"></mg-ajax>
|
||||
<mg-ajax path="/client/api/Clients/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<div margin-medium>
|
||||
<div style="max-width: 40em; margin: 0 auto;">
|
||||
<div class="vn-list">
|
||||
<vn-card>
|
||||
<vn-horizontal pad-medium>
|
||||
<vn-searchbar
|
||||
vn-auto
|
||||
<vn-searchbar vn-one
|
||||
index="index"
|
||||
on-search="index.accept()"
|
||||
on-search="$ctrl.search(index)"
|
||||
advanced="true"
|
||||
popover="vn-client-search-panel">
|
||||
popover="vn-client-search-panel"
|
||||
ignore-keys = "['page', 'size', 'search']">
|
||||
</vn-searchbar>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-card margin-medium-top>
|
||||
<vn-item-client ng-repeat="client in index.model" title="View client" client="client"></vn-item-client>
|
||||
<vn-item-client
|
||||
ng-repeat="client in index.model.instances"
|
||||
client="client">
|
||||
</vn-item-client>
|
||||
</vn-card>
|
||||
<vn-paging index="index"></vn-paging>
|
||||
<vn-paging index="index" total="index.model.count"></vn-paging>
|
||||
</div>
|
||||
<a ui-sref="create" fixed-bottom-right>
|
||||
<vn-float-button icon="person_add"></vn-float-button>
|
||||
</a>
|
||||
</div>
|
||||
<a ui-sref="create" fixed-bottom-right>
|
||||
<vn-float-button icon="person_add"></vn-float-button>
|
||||
</a>
|
||||
<vn-dialog class="dialog-summary"
|
||||
vn-id="dialog-summary-client">
|
||||
<tpl-body>
|
||||
<vn-client-summary client="$ctrl.clientSelected"></vn-client-summary>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
||||
|
|
|
@ -1,9 +1,22 @@
|
|||
import {module} from '../module';
|
||||
import './style.css';
|
||||
import ngModule from '../module';
|
||||
import './item-client';
|
||||
|
||||
export const NAME = 'vnClientIndex';
|
||||
export const COMPONENT = {
|
||||
template: require('./index.html')
|
||||
};
|
||||
module.component(NAME, COMPONENT);
|
||||
export default class Controller {
|
||||
constructor($scope) {
|
||||
this.$scope = $scope;
|
||||
this.clientSelected = null;
|
||||
}
|
||||
search(index) {
|
||||
index.accept();
|
||||
}
|
||||
openSummary(client) {
|
||||
this.clientSelected = client;
|
||||
this.$scope.dialogSummaryClient.show();
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope'];
|
||||
|
||||
ngModule.component('vnClientIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientIndex', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
controller = $componentController('vnClientIndex');
|
||||
}));
|
||||
|
||||
it('should define and set clientSelected property as null', () => {
|
||||
expect(controller.clientSelected).toEqual(null);
|
||||
});
|
||||
|
||||
// describe('search()', () => {
|
||||
// it(`should set model's search to the search input`, () => {
|
||||
// controller.model.search = 'batman';
|
||||
// let index = {
|
||||
// filter: {},
|
||||
// accept: () => {
|
||||
// return 'accepted';
|
||||
// }
|
||||
// };
|
||||
// controller.search(index);
|
||||
|
||||
// expect(index.filter.search).toBe('batman');
|
||||
// });
|
||||
// });
|
||||
});
|
||||
});
|
|
@ -1,7 +1,21 @@
|
|||
<a ui-sref="clientCard.basicData({ id: {{itemClient.client.id}} })" pad-medium border-solid-bottom>
|
||||
<div class="vn-item-client-name">{{itemClient.client.name}}</div>
|
||||
<div>Id Cliente: <b>{{itemClient.client.id}}</b></div>
|
||||
<div>Teléfono: <b>{{itemClient.client.phone | phone}}</b></div>
|
||||
<div>Población: <b>{{itemClient.client.city}}</b></div>
|
||||
<div>email: <b>{{itemClient.client.email}}</b></div>
|
||||
<a
|
||||
ui-sref="clientCard.basicData({ id: {{::$ctrl.client.id}} })"
|
||||
translate-attr="{title: 'View client'}"
|
||||
class="vn-list-item">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::$ctrl.client.name}}</h6>
|
||||
<div><vn-label translate>Id</vn-label> {{::$ctrl.client.id}}</div>
|
||||
<div><vn-label translate>Phone</vn-label> {{::$ctrl.client.phone | phone}}</div>
|
||||
<div><vn-label translate>Town/City</vn-label> {{::$ctrl.client.city}}</div>
|
||||
<div><vn-label translate>Email</vn-label> {{::$ctrl.client.email}}</div>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon
|
||||
ng-click="$ctrl.preview($event)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon>
|
||||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</a>
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
import {module} from '../module';
|
||||
import ngModule from '../module';
|
||||
|
||||
export const NAME = 'vnItemClient';
|
||||
export const COMPONENT = {
|
||||
class Controller {
|
||||
onClick(event) {
|
||||
if (event.defaultPrevented)
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
preview(event) {
|
||||
event.preventDefault();
|
||||
this.list.openSummary(this.client);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnItemClient', {
|
||||
template: require('./item-client.html'),
|
||||
controllerAs: 'itemClient',
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
},
|
||||
require: {
|
||||
list: '^vnClientIndex'
|
||||
}
|
||||
};
|
||||
module.component(NAME, COMPONENT);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Client id: Id cliente
|
||||
Phone: Teléfono
|
||||
Town/City: Ciudad
|
||||
Email: Correo electrónico
|
||||
Create client: Crear cliente
|
|
@ -0,0 +1,3 @@
|
|||
vn-item-client {
|
||||
display: block;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<mg-ajax path="/client/api/InvoiceOuts/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<mg-ajax path="/client/api/InvoiceOuts/{{edit.params.id}}/sumAmount" options="mgEdit"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Invoices</vn-title>
|
||||
<vn-vertical style="text-align: center;">
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one field="ref" text="Reference" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-one field="issued" text="Issue date"></vn-column-header>
|
||||
<vn-column-header vn-one field="dued" text="Due date"></vn-column-header>
|
||||
<vn-column-header vn-one field="amount" text="Amount"></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-vertical>
|
||||
<vn-one
|
||||
ng-if="index.model.count > 0"
|
||||
class="list list-content">
|
||||
<vn-horizontal
|
||||
class="list list-element"
|
||||
pad-small-bottom
|
||||
ng-repeat="invoice in index.model.instances track by greuge.id">
|
||||
<vn-one>{{::invoice.ref}}</vn-one>
|
||||
<vn-one>{{::invoice.issued | date:'dd/MM/yyyy' }}</vn-one>
|
||||
<vn-one>{{::invoice.dued | date:'dd/MM/yyyy' }}</vn-one>
|
||||
<vn-one>{{::invoice.amount | currency:'€':2}}</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one
|
||||
ng-if="index.model.count === 0"
|
||||
pad-small-v translate>
|
||||
No results
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
<vn-horizontal vn-one class="list list-footer">
|
||||
<vn-three></vn-three>
|
||||
<vn-one>{{edit.model.sumAmount | currency:'€':2}}</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
<vn-paging margin-large-top vn-one index="index" total="index.model.count"></vn-paging>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
|
@ -0,0 +1,15 @@
|
|||
import ngModule from '../module';
|
||||
import FilterClientList from '../filter-client-list';
|
||||
|
||||
class Controller extends FilterClientList {
|
||||
constructor($scope, $timeout, $state, $stateParams) {
|
||||
super($scope, $timeout, $state);
|
||||
$scope.$stateParams = $stateParams;
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$timeout', '$state', '$stateParams'];
|
||||
|
||||
ngModule.component('vnClientInvoices', {
|
||||
template: require('./invoices.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
Invoices: Facturas
|
||||
Reference: Referencia
|
||||
Issue date: Fecha de emisión
|
||||
Due date: Vencimiento
|
||||
Amount: Total
|
|
@ -1 +0,0 @@
|
|||
{}
|
|
@ -0,0 +1,2 @@
|
|||
Client: Client
|
||||
Clients: Clients
|
|
@ -1 +0,0 @@
|
|||
{}
|
|
@ -0,0 +1,23 @@
|
|||
Active: Activo
|
||||
Client: Cliente
|
||||
Clients: Clientes
|
||||
Basic data: Datos básicos
|
||||
Fiscal data: Datos Fiscales
|
||||
Addresses: Consignatarios
|
||||
Web access: Acceso web
|
||||
Notes: Notas
|
||||
Has to invoice: Factura
|
||||
Invoice by mail: Factura impresa
|
||||
Country: País
|
||||
Street: Domicilio fiscal
|
||||
City: Municipio
|
||||
Postcode: Código postal
|
||||
Province: Provincia
|
||||
Save: Guardar
|
||||
Pay method : Forma de pago
|
||||
Address: Consignatario
|
||||
Credit : Crédito
|
||||
Secured credit: Crédito asegurado
|
||||
Verified data: Datos comprobados
|
||||
Mandate: Mandato
|
||||
Amount: Importe
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue