feat(salix): refs #6943 #6943 Client module redirect to Lilium
gitea/salix/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
6df817ea5d
commit
79f7bb4296
|
@ -1,193 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="Clients/{{$ctrl.$params.id}}/createAddress"
|
||||
id-field="id"
|
||||
data="$ctrl.address"
|
||||
params="$ctrl.address"
|
||||
insert-mode="true"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Provinces/location"
|
||||
data="provincesLocation"
|
||||
order="id">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Incoterms"
|
||||
data="incoterms"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="CustomsAgents"
|
||||
data="customsAgents"
|
||||
order="fiscalName">
|
||||
</vn-crud-model>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Default" ng-model="$ctrl.address.isDefaultAddress">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Consignee"
|
||||
ng-model="$ctrl.address.nickname"
|
||||
rule
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Street address"
|
||||
ng-model="$ctrl.address.street"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-datalist vn-one
|
||||
label="Postcode"
|
||||
ng-model="$ctrl.address.postalCode"
|
||||
selection="$ctrl.postcode"
|
||||
url="Postcodes/location"
|
||||
fields="['code','townFk']"
|
||||
order="code, townFk"
|
||||
value-field="code"
|
||||
show-field="code"
|
||||
rule>
|
||||
<tpl-item>
|
||||
{{code}} - {{town.name}} ({{town.province.name}},
|
||||
{{town.province.country.name}})
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New postcode"
|
||||
ng-click="postcode.open()"
|
||||
vn-acl="deliveryAssistant"
|
||||
vn-acl-action="remove">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-datalist>
|
||||
<vn-datalist vn-id="town" vn-one
|
||||
label="City"
|
||||
ng-model="$ctrl.address.city"
|
||||
selection="$ctrl.town"
|
||||
url="Towns/location"
|
||||
fields="['id', 'name', 'provinceFk']"
|
||||
show-field="name"
|
||||
value-field="name">
|
||||
<tpl-item>
|
||||
{{name}}, {{province.name}}
|
||||
({{province.country.name}})
|
||||
</tpl-item>
|
||||
</vn-datalist>
|
||||
<vn-autocomplete vn-id="province" vn-one
|
||||
label="Province"
|
||||
ng-model="$ctrl.address.provinceFk"
|
||||
data="provincesLocation"
|
||||
fields="['id', 'name', 'countryFk']"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
rule>
|
||||
<tpl-item>{{name}} ({{country.name}})</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.address.agencyModeFk"
|
||||
url="AgencyModes/isActive"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Phone"
|
||||
ng-model="$ctrl.address.phone"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Mobile"
|
||||
ng-model="$ctrl.address.mobile"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
ng-model="$ctrl.address.incotermsFk"
|
||||
data="incoterms"
|
||||
show-field="name"
|
||||
value-field="code"
|
||||
label="Incoterms">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
ng-model="$ctrl.address.customsAgentFk"
|
||||
data="customsAgents"
|
||||
show-field="fiscalName"
|
||||
value-field="id"
|
||||
label="Customs agent">
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New customs agent"
|
||||
ng-click="$ctrl.showCustomAgent($event)">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
<vn-button
|
||||
label="Cancel"
|
||||
ui-sref="client.card.address.index">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
|
||||
<!-- New postcode dialog -->
|
||||
<vn-geo-postcode vn-id="postcode"
|
||||
on-response="$ctrl.onResponse($response)">
|
||||
</vn-geo-postcode>
|
||||
|
||||
<!-- Create custom agent dialog -->
|
||||
<vn-dialog class="edit"
|
||||
vn-id="customAgent"
|
||||
on-accept="$ctrl.onCustomAgentAccept()"
|
||||
message="New customs agent">
|
||||
<tpl-body>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one vn-focus
|
||||
label="NIF"
|
||||
ng-model="$ctrl.newCustomsAgent.nif"
|
||||
required="true">
|
||||
</vn-textfield>
|
||||
<vn-textfield vn-one
|
||||
label="Fiscal name"
|
||||
ng-model="$ctrl.newCustomsAgent.fiscalName"
|
||||
required="true">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one
|
||||
label="Street"
|
||||
ng-model="$ctrl.newCustomsAgent.street">
|
||||
</vn-textfield>
|
||||
<vn-textfield vn-one
|
||||
label="Phone"
|
||||
ng-model="$ctrl.newCustomsAgent.phone">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Create</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -1,90 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.address = {
|
||||
isActive: true,
|
||||
isDefaultAddress: false
|
||||
};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$.watcher.submit().then(res => {
|
||||
if (this.address.isDefaultAddress)
|
||||
this.client.defaultAddressFk = res.data.id;
|
||||
|
||||
this.$state.go('client.card.address.index');
|
||||
});
|
||||
}
|
||||
|
||||
showCustomAgent(event) {
|
||||
if (event.defaultPrevented) return;
|
||||
event.preventDefault();
|
||||
|
||||
this.$.customAgent.show();
|
||||
}
|
||||
|
||||
onCustomAgentAccept() {
|
||||
return this.$http.post(`CustomsAgents`, this.newCustomsAgent)
|
||||
.then(res => this.address.customsAgentFk = res.data.id);
|
||||
}
|
||||
|
||||
get town() {
|
||||
return this._town;
|
||||
}
|
||||
|
||||
// Town auto complete
|
||||
set town(selection) {
|
||||
this._town = selection;
|
||||
|
||||
if (!selection) return;
|
||||
|
||||
const province = selection.province;
|
||||
const postcodes = selection.postcodes;
|
||||
|
||||
if (!this.address.provinceFk)
|
||||
this.address.provinceFk = province.id;
|
||||
|
||||
if (postcodes.length === 1)
|
||||
this.address.postalCode = postcodes[0].code;
|
||||
}
|
||||
|
||||
get postcode() {
|
||||
return this._postcode;
|
||||
}
|
||||
|
||||
// Postcode auto complete
|
||||
set postcode(selection) {
|
||||
this._postcode = selection;
|
||||
|
||||
if (!selection) return;
|
||||
|
||||
const town = selection.town;
|
||||
const province = town.province;
|
||||
|
||||
if (!this.address.city)
|
||||
this.address.city = town.name;
|
||||
|
||||
if (!this.address.provinceFk)
|
||||
this.address.provinceFk = province.id;
|
||||
}
|
||||
|
||||
onResponse(response) {
|
||||
this.address.postalCode = response.code;
|
||||
this.address.city = response.city;
|
||||
this.address.provinceFk = response.provinceFk;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientAddressCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,130 +0,0 @@
|
|||
import './index';
|
||||
import watcher from 'core/mocks/watcher';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientAddressCreate', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $element;
|
||||
let $state;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$state_, _$httpBackend_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$state = _$state_;
|
||||
$state.params.id = '1234';
|
||||
$element = angular.element('<vn-client-address-create></vn-client-address-create>');
|
||||
controller = $componentController('vnClientAddressCreate', {$element, $scope});
|
||||
controller.$.watcher = watcher;
|
||||
controller.$.watcher.submit = () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback({data: {id: 124}});
|
||||
}
|
||||
};
|
||||
};
|
||||
controller.client = {id: 1101, defaultAddressFk: 121};
|
||||
}));
|
||||
|
||||
it('should define and set address property', () => {
|
||||
expect(controller.address.isActive).toBe(true);
|
||||
});
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('should perform a PATCH and not set value to defaultAddressFk property', () => {
|
||||
jest.spyOn(controller.$state, 'go');
|
||||
controller.address.isDefaultAddress = false;
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.client.defaultAddressFk).toEqual(121);
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('client.card.address.index');
|
||||
});
|
||||
|
||||
it('should perform a PATCH and set a value to defaultAddressFk property', () => {
|
||||
jest.spyOn(controller.$state, 'go');
|
||||
controller.address.isDefaultAddress = true;
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.client.defaultAddressFk).toEqual(124);
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('client.card.address.index');
|
||||
});
|
||||
});
|
||||
|
||||
describe('town() setter', () => {
|
||||
it(`should set provinceFk property`, () => {
|
||||
controller.town = {
|
||||
provinceFk: 1,
|
||||
code: 46001,
|
||||
province: {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
},
|
||||
postcodes: []
|
||||
};
|
||||
|
||||
expect(controller.address.provinceFk).toEqual(1);
|
||||
});
|
||||
|
||||
it(`should set provinceFk property and fill the postalCode if there's just one`, () => {
|
||||
controller.town = {
|
||||
provinceFk: 1,
|
||||
code: 46001,
|
||||
province: {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
},
|
||||
postcodes: [{code: '46001'}]
|
||||
};
|
||||
|
||||
expect(controller.address.provinceFk).toEqual(1);
|
||||
expect(controller.address.postalCode).toEqual('46001');
|
||||
});
|
||||
});
|
||||
|
||||
describe('postcode() setter', () => {
|
||||
it(`should set the town and province properties`, () => {
|
||||
controller.postcode = {
|
||||
townFk: 1,
|
||||
code: 46001,
|
||||
town: {
|
||||
id: 1,
|
||||
name: 'New York',
|
||||
province: {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(controller.address.city).toEqual('New York');
|
||||
expect(controller.address.provinceFk).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onCustomAgentAccept()', () => {
|
||||
it(`should create a new customs agent and then set the customsAgentFk property on the address`, () => {
|
||||
const expectedResult = {id: 1, fiscalName: 'Customs agent one'};
|
||||
$httpBackend.when('POST', 'CustomsAgents').respond(200, expectedResult);
|
||||
controller.onCustomAgentAccept();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.address.customsAgentFk).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,237 +0,0 @@
|
|||
|
||||
<mg-ajax
|
||||
path="Addresses/{{edit.params.addressId}}"
|
||||
actions="$ctrl.address = edit.model"
|
||||
options="mgEdit">
|
||||
</mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="Clients/{{$ctrl.$params.id}}/updateAddress"
|
||||
id-field="id"
|
||||
data="$ctrl.address"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="AddressObservations"
|
||||
fields="['id', 'addressFk', 'observationTypeFk', 'description']"
|
||||
link="{addressFk: $ctrl.$params.addressId}"
|
||||
data="observations"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
url="ObservationTypes"
|
||||
fields="['id', 'description']"
|
||||
data="types"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Enabled"
|
||||
ng-model="$ctrl.address.isActive">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Is equalizated"
|
||||
ng-model="$ctrl.address.isEqualizated"
|
||||
vn-acl="administrative, salesAssistant">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Is Logiflora allowed"
|
||||
ng-model="$ctrl.address.isLogifloraAllowed"
|
||||
vn-acl="salesAssistant">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Consignee"
|
||||
ng-model="$ctrl.address.nickname"
|
||||
rule
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Street"
|
||||
ng-model="$ctrl.address.street"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-datalist vn-one
|
||||
label="Postcode"
|
||||
ng-model="$ctrl.address.postalCode"
|
||||
selection="$ctrl.postcode"
|
||||
url="Postcodes/location"
|
||||
fields="['code','townFk']"
|
||||
order="code, townFk"
|
||||
value-field="code"
|
||||
show-field="code"
|
||||
rule>
|
||||
<tpl-item>
|
||||
{{code}} - {{town.name}} ({{town.province.name}},
|
||||
{{town.province.country.name}})
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New postcode"
|
||||
ng-click="postcode.open()"
|
||||
vn-acl="deliveryAssistant"
|
||||
vn-acl-action="remove">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-datalist>
|
||||
<vn-datalist vn-id="town" vn-one
|
||||
label="City"
|
||||
ng-model="$ctrl.address.city"
|
||||
selection="$ctrl.town"
|
||||
url="Towns/location"
|
||||
fields="['id', 'name', 'provinceFk']"
|
||||
show-field="name"
|
||||
value-field="name">
|
||||
<tpl-item>
|
||||
{{name}}, {{province.name}}
|
||||
({{province.country.name}})
|
||||
</tpl-item>
|
||||
</vn-datalist>
|
||||
<vn-autocomplete vn-id="province" vn-one
|
||||
label="Province"
|
||||
ng-model="$ctrl.address.provinceFk"
|
||||
url="Provinces/location"
|
||||
fields="['id', 'name', 'countryFk']"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
rule>
|
||||
<tpl-item>{{name}} ({{country.name}})</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
ng-model="$ctrl.address.agencyModeFk"
|
||||
url="AgencyModes/isActive"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Phone"
|
||||
ng-model="$ctrl.address.phone"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Mobile"
|
||||
ng-model="$ctrl.address.mobile"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
ng-model="$ctrl.address.incotermsFk"
|
||||
url="Incoterms"
|
||||
show-field="name"
|
||||
value-field="code"
|
||||
label="Incoterms">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
ng-model="$ctrl.address.customsAgentFk"
|
||||
url="CustomsAgents"
|
||||
show-field="fiscalName"
|
||||
value-field="id"
|
||||
label="Customs agent">
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New customs agent"
|
||||
ng-click="$ctrl.showCustomAgent($event)">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-title>Notes</vn-title>
|
||||
<div name="observations">
|
||||
<vn-horizontal ng-repeat="observation in observations">
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
vn-focus
|
||||
data="types"
|
||||
ng-model="observation.observationTypeFk"
|
||||
show-field="description"
|
||||
label="Observation type"
|
||||
rule="AddressObservation">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
label="Description"
|
||||
ng-model="observation.description"
|
||||
rule="AddressObservation">
|
||||
</vn-textfield>
|
||||
<vn-none>
|
||||
<vn-icon-button
|
||||
vn-tooltip="Remove note"
|
||||
icon="delete"
|
||||
ng-click="$ctrl.removeObservation($index)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
<vn-icon-button
|
||||
vn-bind="+"
|
||||
vn-tooltip="Add note"
|
||||
icon="add_circle"
|
||||
ng-if="types.length > observations.length"
|
||||
ng-click="model.insert()">
|
||||
</vn-icon-button>
|
||||
</div>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
<vn-button ng-click="$ctrl.cancel()" label="Cancel"></vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
|
||||
<!-- New postcode dialog -->
|
||||
<vn-geo-postcode vn-id="postcode"
|
||||
on-response="$ctrl.onResponse($response)">
|
||||
</vn-geo-postcode>
|
||||
|
||||
<!-- Create custom agent dialog -->
|
||||
<vn-dialog class="edit"
|
||||
vn-id="customAgent"
|
||||
on-accept="$ctrl.onCustomAgentAccept()"
|
||||
message="New customs agent">
|
||||
<tpl-body>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one vn-focus
|
||||
label="NIF"
|
||||
ng-model="$ctrl.newCustomsAgent.nif"
|
||||
required="true">
|
||||
</vn-textfield>
|
||||
<vn-textfield vn-one
|
||||
label="Fiscal name"
|
||||
ng-model="$ctrl.newCustomsAgent.fiscalName"
|
||||
required="true">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one
|
||||
label="Street"
|
||||
ng-model="$ctrl.newCustomsAgent.street">
|
||||
</vn-textfield>
|
||||
<vn-textfield vn-one
|
||||
label="Phone"
|
||||
ng-model="$ctrl.newCustomsAgent.phone">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Create</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -1,94 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
removeObservation(index) {
|
||||
this.$.watcher.setDirty();
|
||||
this.$.model.remove(index);
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.goToIndex();
|
||||
}
|
||||
|
||||
goToIndex() {
|
||||
this.$state.go('client.card.address.index');
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$.watcher.submit()
|
||||
.then(() => this.$.model.save(true))
|
||||
.then(() => {
|
||||
this.card.reload();
|
||||
this.goToIndex();
|
||||
});
|
||||
}
|
||||
|
||||
showCustomAgent(event) {
|
||||
if (event.defaultPrevented) return;
|
||||
event.preventDefault();
|
||||
|
||||
this.$.customAgent.show();
|
||||
}
|
||||
|
||||
onCustomAgentAccept() {
|
||||
return this.$http.post(`CustomsAgents`, this.newCustomsAgent)
|
||||
.then(res => this.address.customsAgentFk = res.data.id);
|
||||
}
|
||||
|
||||
get town() {
|
||||
return this._town;
|
||||
}
|
||||
|
||||
// Town auto complete
|
||||
set town(selection) {
|
||||
const oldValue = this._town;
|
||||
this._town = selection;
|
||||
|
||||
if (!selection || !oldValue) return;
|
||||
|
||||
const province = selection.province;
|
||||
const postcodes = selection.postcodes;
|
||||
|
||||
if (!this.address.provinceFk)
|
||||
this.address.provinceFk = province.id;
|
||||
|
||||
if (!this.address.postalCode && postcodes.length === 1)
|
||||
this.address.postalCode = postcodes[0].code;
|
||||
}
|
||||
|
||||
get postcode() {
|
||||
return this._postcode;
|
||||
}
|
||||
|
||||
// Postcode auto complete
|
||||
set postcode(selection) {
|
||||
const oldValue = this._postcode;
|
||||
this._postcode = selection;
|
||||
|
||||
if (!selection || !oldValue) return;
|
||||
|
||||
const town = selection.town;
|
||||
const province = town.province;
|
||||
|
||||
if (!this.address.city)
|
||||
this.address.city = town.name;
|
||||
|
||||
if (!this.address.provinceFk)
|
||||
this.address.provinceFk = province.id;
|
||||
}
|
||||
|
||||
onResponse(response) {
|
||||
this.address.postalCode = response.code;
|
||||
this.address.city = response.city;
|
||||
this.address.provinceFk = response.provinceFk;
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientAddressEdit', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
require: {
|
||||
card: '^vnClientCard'
|
||||
}
|
||||
});
|
|
@ -1,77 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientAddressEdit', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $element;
|
||||
let $state;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$state_, _$httpBackend_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$state = _$state_;
|
||||
$state.params.addressId = '1';
|
||||
$element = angular.element('<vn-client-address-edit></vn-client-address-edit>');
|
||||
controller = $componentController('vnClientAddressEdit', {$element, $scope});
|
||||
controller.address = {id: 1, customsAgentFk: null};
|
||||
controller.$.watcher = {
|
||||
setDirty: () => {},
|
||||
setPristine: () => {},
|
||||
realSubmit: () => {},
|
||||
check: () => {},
|
||||
notifySaved: () => {}
|
||||
};
|
||||
controller.$.model = {
|
||||
remove: () => {},
|
||||
save: () => {}
|
||||
};
|
||||
controller.card = {
|
||||
reload: () => {}
|
||||
};
|
||||
}));
|
||||
|
||||
describe('removeObservation()', () => {
|
||||
it('should call $.watcher.setDirty() and $.model.remove(index)', () => {
|
||||
jest.spyOn(controller.$.watcher, 'setDirty');
|
||||
jest.spyOn(controller.$.model, 'remove');
|
||||
controller.removeObservation(1);
|
||||
|
||||
expect(controller.$.model.remove).toHaveBeenCalledWith(1);
|
||||
expect(controller.$.watcher.setDirty).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('cancel()', () => {
|
||||
it('should call goToIndex()', () => {
|
||||
jest.spyOn(controller, 'goToIndex');
|
||||
controller.cancel();
|
||||
|
||||
expect(controller.goToIndex).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('goToIndex()', () => {
|
||||
it('should call $state.go("client.card.address.index")', () => {
|
||||
jest.spyOn(controller.$state, 'go');
|
||||
controller.goToIndex();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('client.card.address.index');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onCustomAgentAccept()', () => {
|
||||
it(`should now create a new customs agent and then set the customsAgentFk property on the address`, () => {
|
||||
const expectedResult = {id: 1, fiscalName: 'Customs agent one'};
|
||||
$httpBackend.when('POST', 'CustomsAgents').respond(200, expectedResult);
|
||||
controller.onCustomAgentAccept();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.address.customsAgentFk).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,91 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Clients/{{$ctrl.$params.id}}/addresses"
|
||||
filter="$ctrl.filter"
|
||||
limit="10"
|
||||
data="$ctrl.addresses"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
placeholder="Search by consignee"
|
||||
info="You can search by consignee id or name"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
auto-state="false">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card class="vn-pa-md">
|
||||
<div
|
||||
ng-repeat="address in $ctrl.addresses"
|
||||
class="address">
|
||||
<a
|
||||
ui-sref="client.card.address.edit({addressId: {{::address.id}}})"
|
||||
class="vn-pa-sm border-solid border-radius"
|
||||
ng-class="{'item-disabled': !address.isActive}"
|
||||
translate-attr="{title: 'Edit consignee'}">
|
||||
<vn-none
|
||||
class="vn-pr-sm"
|
||||
ng-click="$ctrl.onStarClick($event)">
|
||||
<vn-icon-button
|
||||
ng-if="$ctrl.isDefaultAddress(address)"
|
||||
icon="star"
|
||||
translate-attr="{title: 'Default address'}">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
ng-if="!$ctrl.isDefaultAddress(address)"
|
||||
icon="star_border"
|
||||
ng-click="$ctrl.setDefault(address)"
|
||||
translate-attr="{title: 'Set as default'}">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-one
|
||||
style="overflow: hidden; min-width: 14em;">
|
||||
<div class="ellipsize"><b>{{::address.nickname}} - #{{::address.id}}</b></div>
|
||||
<div class="ellipsize" name="street">{{::address.street}}</div>
|
||||
<div class="ellipsize">
|
||||
<span ng-show="::address.postalCode">{{::address.postalCode}} -</span>
|
||||
<span ng-show="::address.city">{{::address.city}},</span>
|
||||
<span ng-show="::address.province.name">{{::address.province.name}},</span>
|
||||
{{::address.province.country.name}}
|
||||
</div>
|
||||
<div class="ellipsize">
|
||||
{{::address.phone}}<span ng-if="::address.mobile">, </span>
|
||||
{{::address.mobile}}
|
||||
</div>
|
||||
<vn-check
|
||||
vn-one label="Is equalizated"
|
||||
ng-model="address.isEqualizated"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one label="Is Logiflora allowed"
|
||||
ng-model="address.isLogifloraAllowed"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</vn-one>
|
||||
<vn-vertical
|
||||
vn-one
|
||||
ng-if="address.observations.length"
|
||||
class="vn-hide-narrow vn-px-md border-solid-left"
|
||||
style="height: 6em; overflow: auto;">
|
||||
<vn-one ng-repeat="observation in address.observations track by $index" ng-class="{'vn-pt-sm': $index}">
|
||||
<b>{{::observation.observationType.description}}:</b>
|
||||
<span>{{::observation.description}}</span>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
</a>
|
||||
</div>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
vn-bind="+"
|
||||
fixed-bottom-right
|
||||
vn-tooltip="New consignee"
|
||||
ui-sref="client.card.address.create"
|
||||
icon="add"
|
||||
label="Add">
|
||||
</vn-float-button>
|
|
@ -1,97 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.filter = {
|
||||
fields: [
|
||||
'id',
|
||||
'isDefaultAddress',
|
||||
'isActive',
|
||||
'nickname',
|
||||
'street',
|
||||
'city',
|
||||
'provinceFk',
|
||||
'phone',
|
||||
'mobile',
|
||||
'isEqualizated',
|
||||
'isLogifloraAllowed',
|
||||
'postalCode'
|
||||
],
|
||||
order: [
|
||||
'isDefaultAddress DESC',
|
||||
'isActive DESC',
|
||||
'nickname ASC'],
|
||||
include: [
|
||||
{
|
||||
relation: 'observations',
|
||||
scope: {
|
||||
include: 'observationType'
|
||||
}
|
||||
}, {
|
||||
relation: 'province',
|
||||
scope: {
|
||||
fields: ['id', 'name', 'countryFk'],
|
||||
include: {
|
||||
relation: 'country',
|
||||
scope: {
|
||||
fields: ['id', 'name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
onStarClick(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
setDefault(address) {
|
||||
let query = `Clients/${this.$params.id}`;
|
||||
let params = {defaultAddressFk: address.id};
|
||||
this.$http.patch(query, params).then(res => {
|
||||
if (res.data) {
|
||||
this.client.defaultAddressFk = res.data.defaultAddressFk;
|
||||
this.sortAddresses();
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isDefaultAddress(address) {
|
||||
return this.client && this.client.defaultAddressFk === address.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort address by default address
|
||||
*/
|
||||
sortAddresses() {
|
||||
if (!this.client || !this.addresses) return;
|
||||
this.addresses = this.addresses.sort((a, b) => {
|
||||
return this.isDefaultAddress(b) - this.isDefaultAddress(a);
|
||||
});
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {id: value}
|
||||
: {nickname: {like: `%${value}%`}};
|
||||
}
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientAddressIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,84 +0,0 @@
|
|||
import './index';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientAddressIndex', () => {
|
||||
let controller;
|
||||
let $scope;
|
||||
let $stateParams;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$stateParams_, _$httpBackend_) => {
|
||||
$stateParams = _$stateParams_;
|
||||
$stateParams.id = 1;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-client-address-index></vn-client-address-index>');
|
||||
controller = $componentController('vnClientAddressIndex', {$element, $scope});
|
||||
controller.client = {id: 1101, defaultAddressFk: 121};
|
||||
controller.$.model = crudModel;
|
||||
}));
|
||||
|
||||
describe('setDefault()', () => {
|
||||
it('should perform a PATCH and set a value to defaultAddressFk property', () => {
|
||||
jest.spyOn(controller, 'sortAddresses');
|
||||
let address = {id: 1};
|
||||
let data = {defaultAddressFk: address.id};
|
||||
let expectedResult = {defaultAddressFk: address.id};
|
||||
|
||||
$httpBackend.expect('PATCH', `Clients/1`, data).respond(200, expectedResult);
|
||||
controller.setDefault(address);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.client.defaultAddressFk).toEqual(1);
|
||||
expect(controller.sortAddresses).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDefaultAddress()', () => {
|
||||
it('should return true if a passed address is the current default one', () => {
|
||||
let address = {id: 121};
|
||||
let result = controller.isDefaultAddress(address);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if a passed address is the current default one', () => {
|
||||
let address = {id: 1};
|
||||
let result = controller.isDefaultAddress(address);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('sortAddresses()', () => {
|
||||
it('should return an array of addresses sorted by client defaultAddressFk', () => {
|
||||
controller.client.defaultAddressFk = 123;
|
||||
controller.addresses = [
|
||||
{id: 121, nickname: 'My address one'},
|
||||
{id: 122, nickname: 'My address two'},
|
||||
{id: 123, nickname: 'My address three'}];
|
||||
|
||||
controller.sortAddresses();
|
||||
|
||||
expect(controller.addresses[0].id).toEqual(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe('exprBuilder()', () => {
|
||||
it('should return a filter based on a search by id', () => {
|
||||
const filter = controller.exprBuilder('search', '123');
|
||||
|
||||
expect(filter).toEqual({id: '123'});
|
||||
});
|
||||
|
||||
it('should return a filter based on a search by name', () => {
|
||||
const filter = controller.exprBuilder('search', 'Bruce Wayne');
|
||||
|
||||
expect(filter).toEqual({nickname: {like: '%Bruce Wayne%'}});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
@import "variables";
|
||||
@import "./effects";
|
||||
|
||||
vn-client-address-index {
|
||||
.address {
|
||||
padding-bottom: $spacing-md;
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
& > a {
|
||||
@extend %clickable;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
# Index
|
||||
Set as default: Establecer como predeterminado
|
||||
Active first to set as default: Active primero para marcar como predeterminado
|
||||
Search by consignee: Buscar por consignatario
|
||||
You can search by consignee id or name: Puedes buscar por el id o nombre del consignatario
|
||||
# Edit
|
||||
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
|
||||
Remove note: Quitar nota
|
||||
Add note: Añadir nota
|
||||
Customs agent: Agente de aduanas
|
||||
New customs agent: Nuevo agente de aduanas
|
||||
# Create
|
||||
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
|
||||
|
||||
# Common
|
||||
Fiscal name: Nombre fiscal
|
||||
Street: Dirección fiscal
|
||||
Is Logiflora allowed: Compra directa en Holanda
|
|
@ -1,106 +0,0 @@
|
|||
<tpl-title translate>
|
||||
New payment
|
||||
</tpl-title>
|
||||
<tpl-body>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Companies"
|
||||
data="companies"
|
||||
order="code"
|
||||
required="true">
|
||||
</vn-crud-model>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
label="Date"
|
||||
ng-model="$ctrl.receipt.payed"
|
||||
vn-name="payed"
|
||||
required="true">
|
||||
</vn-date-picker>
|
||||
<vn-autocomplete
|
||||
data="companies"
|
||||
label="Company"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
ng-model="$ctrl.companyFk"
|
||||
vn-name="company"
|
||||
required="true">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
label="Bank"
|
||||
url="Accountings"
|
||||
show-field="bank"
|
||||
value-field="id"
|
||||
fields="['accountingTypeFk']"
|
||||
include="{relation: 'accountingType'}"
|
||||
ng-model="$ctrl.bankFk"
|
||||
vn-name="bank"
|
||||
search-function="$ctrl.bankSearchFunc($search)"
|
||||
selection="$ctrl.bankSelection"
|
||||
order="id"
|
||||
required="true">
|
||||
<tpl-item>{{id}}: {{bank}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-input-number
|
||||
vn-focus
|
||||
label="Amount"
|
||||
ng-model="$ctrl.amountPaid"
|
||||
vn-name="amountPaid"
|
||||
step="0.01"
|
||||
required="true"
|
||||
max="$ctrl.maxAmount">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-vertical ng-show="$ctrl.bankSelection.accountingType.code == 'compensation'">
|
||||
<h6 translate>Compensation</h6>
|
||||
<vn-textfield
|
||||
ng-model="$ctrl.receipt.compensationAccount"
|
||||
vn-name="compensationAccount"
|
||||
label="Compensation Account"
|
||||
on-change="$ctrl.accountShortToStandard(value)">
|
||||
</vn-textfield>
|
||||
</vn-vertical>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Reference"
|
||||
ng-model="$ctrl.receipt.description"
|
||||
vn-name="description"
|
||||
rule
|
||||
required="true">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-vertical ng-show="$ctrl.bankSelection.accountingType.code == 'cash'">
|
||||
<h6 translate>Cash</h6>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
ng-model="$ctrl.deliveredAmount"
|
||||
label="Delivered amount"
|
||||
step="0.01"
|
||||
vn-name="deliveredAmount">
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
disabled="true"
|
||||
ng-model="$ctrl.amountToReturn"
|
||||
label="Amount to return"
|
||||
vn-name="amountToReturn">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
<vn-horizontal ng-show="$ctrl.bankSelection.accountingType.code == 'cash'">
|
||||
<vn-check
|
||||
label="View receipt"
|
||||
ng-model="$ctrl.viewReceipt"
|
||||
vn-name="viewReceipt">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Send email"
|
||||
ng-model="$ctrl.sendEmail"
|
||||
vn-name="sendEmail">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate vn-focus>Accept</button>
|
||||
</tpl-buttons>
|
|
@ -1,217 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Dialog from 'core/components/dialog';
|
||||
|
||||
class Controller extends Dialog {
|
||||
constructor($element, $, $transclude, vnReport, vnEmail) {
|
||||
super($element, $, $transclude);
|
||||
this.vnReport = vnReport;
|
||||
this.vnEmail = vnEmail;
|
||||
this.receipt = {};
|
||||
}
|
||||
|
||||
set payed(value) {
|
||||
this.receipt.payed = value;
|
||||
}
|
||||
|
||||
set amountPaid(value) {
|
||||
this.receipt.amountPaid = value;
|
||||
this.amountToReturn = this.deliveredAmount - value;
|
||||
}
|
||||
|
||||
get amountPaid() {
|
||||
return this.receipt.amountPaid;
|
||||
}
|
||||
|
||||
set clientFk(value) {
|
||||
this.receipt.clientFk = value;
|
||||
|
||||
const filter = {
|
||||
fields: ['email'],
|
||||
where: {
|
||||
id: value
|
||||
}
|
||||
};
|
||||
|
||||
this.$http.get(`Clients/findOne`, {filter})
|
||||
.then(res => {
|
||||
this.receipt.email = res.data.email;
|
||||
});
|
||||
}
|
||||
|
||||
get clientFk() {
|
||||
return this.receipt.clientFk;
|
||||
}
|
||||
|
||||
get companyFk() {
|
||||
if (!this.receipt.companyFk)
|
||||
this.receipt.companyFk = this.vnConfig.companyFk;
|
||||
return this.receipt.companyFk;
|
||||
}
|
||||
|
||||
set companyFk(value) {
|
||||
this.receipt.companyFk = value;
|
||||
this.getAmountPaid();
|
||||
}
|
||||
|
||||
set description(value) {
|
||||
this.receipt.description = value;
|
||||
this.originalDescription = value;
|
||||
}
|
||||
|
||||
get description() {
|
||||
return this.receipt.description;
|
||||
}
|
||||
|
||||
get bankSelection() {
|
||||
return this._bankSelection;
|
||||
}
|
||||
|
||||
set bankSelection(value) {
|
||||
this._bankSelection = value;
|
||||
|
||||
if (value) {
|
||||
const accountingType = value.accountingType;
|
||||
|
||||
this.receipt.description = [];
|
||||
this.viewReceipt = accountingType.code == 'cash';
|
||||
if (accountingType.code == 'compensation')
|
||||
this.receipt.description = '';
|
||||
else {
|
||||
if (accountingType.receiptDescription != null && accountingType.receiptDescription != '')
|
||||
this.receipt.description.push(accountingType.receiptDescription);
|
||||
if (this.originalDescription)
|
||||
this.receipt.description.push(this.originalDescription);
|
||||
this.receipt.description = this.receipt.description.join(', ');
|
||||
}
|
||||
this.maxAmount = accountingType && accountingType.maxAmount;
|
||||
|
||||
this.receipt.payed = Date.vnNew();
|
||||
if (accountingType.daysInFuture)
|
||||
this.receipt.payed.setDate(this.receipt.payed.getDate() + accountingType.daysInFuture);
|
||||
}
|
||||
}
|
||||
|
||||
set deliveredAmount(value) {
|
||||
this._deliveredAmount = value;
|
||||
this.amountToReturn = value - this.receipt.amountPaid;
|
||||
}
|
||||
|
||||
get amountToReturn() {
|
||||
return this._amountToReturn;
|
||||
}
|
||||
|
||||
set amountToReturn(value) {
|
||||
if (isNaN(value)) return;
|
||||
|
||||
value = value.toFixed(2);
|
||||
|
||||
if (Number.isInteger(value))
|
||||
value = parseInt(value);
|
||||
else value = parseFloat(value);
|
||||
|
||||
this._amountToReturn = value;
|
||||
}
|
||||
|
||||
get deliveredAmount() {
|
||||
return this._deliveredAmount;
|
||||
}
|
||||
|
||||
get bankFk() {
|
||||
if (!this.receipt.bankFk)
|
||||
this.receipt.bankFk = this.vnConfig.bankFk;
|
||||
|
||||
return this.receipt.bankFk;
|
||||
}
|
||||
|
||||
set bankFk(value) {
|
||||
this.receipt.bankFk = value;
|
||||
}
|
||||
|
||||
accountShortToStandard(value) {
|
||||
if (value) {
|
||||
this.receipt.compensationAccount = value.replace('.', '0'.repeat(11 - value.length));
|
||||
const params = {bankAccount: this.receipt.compensationAccount};
|
||||
this.$http.get(`Clients/getClientOrSupplierReference`, {params})
|
||||
.then(res => {
|
||||
if (res.data.clientId) {
|
||||
this.receipt.description = this.$t('Client Compensation Reference', {
|
||||
clientId: res.data.clientId,
|
||||
clientName: res.data.clientName
|
||||
});
|
||||
} else {
|
||||
this.receipt.description = this.$t('Supplier Compensation Reference', {
|
||||
supplierId: res.data.supplierId,
|
||||
supplierName: res.data.supplierName
|
||||
});
|
||||
}
|
||||
});
|
||||
} else
|
||||
this.receipt.description = '';
|
||||
}
|
||||
|
||||
getAmountPaid() {
|
||||
const filter = {
|
||||
where: {
|
||||
clientFk: this.$params.id,
|
||||
companyFk: this.receipt.companyFk
|
||||
}
|
||||
};
|
||||
|
||||
this.$http.get(`ClientRisks`, {filter}).then(res => {
|
||||
this.receipt.amountPaid = (res.data.length && res.data[0].amount) || null;
|
||||
});
|
||||
}
|
||||
|
||||
responseHandler(response) {
|
||||
if (response !== 'accept')
|
||||
return super.responseHandler(response);
|
||||
|
||||
const exceededAmount = this.receipt.amountPaid > this.maxAmount;
|
||||
const isCash = this.bankSelection.accountingType.code == 'cash';
|
||||
if (isCash && exceededAmount)
|
||||
return this.vnApp.showError(this.$t('Amount exceeded', {maxAmount: this.maxAmount}));
|
||||
|
||||
if (isCash && this.sendEmail && !this.receipt.email)
|
||||
return this.vnApp.showError(this.$t('There is no assigned email for this client'));
|
||||
|
||||
let receiptId;
|
||||
return this.$http.post(`Clients/${this.clientFk}/createReceipt`, this.receipt)
|
||||
.then(res => {
|
||||
receiptId = res.data.id;
|
||||
super.responseHandler(response);
|
||||
})
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')))
|
||||
.then(() => {
|
||||
if (!this.sendEmail || !isCash) return;
|
||||
const params = {
|
||||
recipient: this.receipt.email
|
||||
};
|
||||
this.vnEmail.send(`Receipts/${receiptId}/receipt-email`, params);
|
||||
})
|
||||
.then(() => {
|
||||
if (this.viewReceipt)
|
||||
this.vnReport.show(`Receipts/${receiptId}/receipt-pdf`);
|
||||
});
|
||||
}
|
||||
|
||||
bankSearchFunc($search) {
|
||||
return /^\d+$/.test($search)
|
||||
? {id: $search}
|
||||
: {bank: {like: '%' + $search + '%'}};
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$transclude', 'vnReport', 'vnEmail'];
|
||||
|
||||
ngModule.vnComponent('vnClientBalanceCreate', {
|
||||
slotTemplate: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
payed: '<?',
|
||||
bankFk: '<?',
|
||||
amountPaid: '<?',
|
||||
companyFk: '<?',
|
||||
description: '<?',
|
||||
clientFk: '<?'
|
||||
}
|
||||
});
|
|
@ -1,140 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientBalancCreate', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
let $scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-client-balance-create></vn-client-balance-create>');
|
||||
const $transclude = {
|
||||
$$boundTransclude: {
|
||||
$$slots: []
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnClientBalanceCreate', {$element, $scope, $transclude});
|
||||
controller.receipt = {
|
||||
clientFk: 1101,
|
||||
companyFk: 442
|
||||
};
|
||||
controller.bankSelection = {accountingType: {code: 'myCode'}};
|
||||
}));
|
||||
|
||||
describe('bankSelection() setter', () => {
|
||||
it('should set the receipt description property', () => {
|
||||
controller.originalDescription = 'Albaran: 1, 2';
|
||||
controller.bankSelection = {
|
||||
id: 1,
|
||||
bank: 'Cash',
|
||||
accountingType: {
|
||||
id: 2,
|
||||
receiptDescription: 'Cash'
|
||||
}
|
||||
};
|
||||
|
||||
expect(controller.receipt.description).toEqual('Cash, Albaran: 1, 2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('amountToReturn() setter', () => {
|
||||
it('should set the amount to return with a maximum of two decimals', () => {
|
||||
controller.amountToReturn = 200.1451789;
|
||||
|
||||
expect(controller.amountToReturn).toEqual(200.15);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAmountPaid()', () => {
|
||||
it('should make an http GET query and then set the receipt amountPaid property', () => {
|
||||
controller.$params = {id: 1101};
|
||||
const receipt = controller.receipt;
|
||||
const filter = {
|
||||
where: {
|
||||
clientFk: 1101,
|
||||
companyFk: 442
|
||||
}
|
||||
};
|
||||
const serializedParams = $httpParamSerializer({filter});
|
||||
$httpBackend.expect('GET', `ClientRisks?${serializedParams}`).respond([{amount: 20}]);
|
||||
controller.getAmountPaid();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(receipt.amountPaid).toEqual(20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('responseHandler()', () => {
|
||||
it('should make an http POST query and then call to the parent responseHandler() method', () => {
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
jest.spyOn(controller.vnReport, 'show');
|
||||
|
||||
controller.$params = {id: 1101};
|
||||
|
||||
$httpBackend.expect('POST', `Clients/1101/createReceipt`).respond({id: 1});
|
||||
controller.responseHandler('accept');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||
expect(controller.vnReport.show).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should make an http POST query and then call to the report show() method', () => {
|
||||
const receiptId = 1;
|
||||
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
jest.spyOn(controller.vnReport, 'show');
|
||||
window.open = jest.fn();
|
||||
|
||||
controller.$params = {id: 1101};
|
||||
controller.viewReceipt = true;
|
||||
|
||||
$httpBackend.expect('POST', `Clients/1101/createReceipt`).respond({id: receiptId});
|
||||
controller.responseHandler('accept');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||
expect(controller.vnReport.show).toHaveBeenCalledWith(`Receipts/${receiptId}/receipt-pdf`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deliveredAmount() setter', () => {
|
||||
it('should set the deliveredAmount property', () => {
|
||||
controller.amountPaid = 999;
|
||||
controller.deliveredAmount = 1000;
|
||||
|
||||
expect(controller.amountToReturn).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('accountShortToStandard()', () => {
|
||||
it('should get de account in stardard format', () => {
|
||||
const shortAccount = '4.3';
|
||||
controller.accountShortToStandard(shortAccount);
|
||||
|
||||
expect(controller.receipt.compensationAccount).toEqual('4000000003');
|
||||
});
|
||||
});
|
||||
|
||||
describe('bankSearchFunc()', () => {
|
||||
it('should return the filter by id property for an input of a number', () => {
|
||||
const bankId = 1;
|
||||
const result = controller.bankSearchFunc(bankId);
|
||||
|
||||
expect(result).toEqual({id: bankId});
|
||||
});
|
||||
|
||||
it('should return the filter by bank property for an input of an string', () => {
|
||||
const bankName = 'Bank of America';
|
||||
const result = controller.bankSearchFunc(bankName);
|
||||
|
||||
expect(result).toEqual({bank: {like: '%' + bankName + '%'}});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,4 +0,0 @@
|
|||
View receipt: Ver recibo
|
||||
Amount exceeded: Según ley contra el fraude no se puede recibir cobros por importe igual o superior a {{maxAmount}}
|
||||
Client Compensation Reference: "({{clientId}}) Ntro Cliente: {{clientName}}"
|
||||
Supplier Compensation Reference: "({{supplierId}}) Ntro Proveedor: {{supplierName}}"
|
|
@ -1,163 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Receipts/filter"
|
||||
limit="20"
|
||||
data="$ctrl.balances">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
vn-id="riskModel"
|
||||
url="ClientRisks"
|
||||
filter="$ctrl.filter"
|
||||
data="$ctrl.clientRisks">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Companies"
|
||||
data="companies"
|
||||
order="code">
|
||||
</vn-crud-model>
|
||||
<vn-side-menu side="right">
|
||||
<div class="vn-pa-md">
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
vn-id="company"
|
||||
ng-model="$ctrl.companyId"
|
||||
data="companies"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
label="Company">
|
||||
</vn-autocomplete>
|
||||
<div
|
||||
class="totalBox"
|
||||
style="text-align: center;"
|
||||
ng-if="$ctrl.clientRisks.length">
|
||||
<h6 translate>Total by company</h6>
|
||||
<vn-label-value
|
||||
ng-repeat="riskByCompany in $ctrl.clientRisks"
|
||||
label="{{riskByCompany.company.code}}"
|
||||
value="{{riskByCompany.amount | currency: 'EUR':2}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
</div>
|
||||
</vn-side-menu>
|
||||
<div class="vn-w-lg">
|
||||
<vn-data-viewer model="model">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th expand>Date</vn-th>
|
||||
<vn-th>Creation date</vn-th>
|
||||
<vn-th>Employee</vn-th>
|
||||
<vn-th>Reference</vn-th>
|
||||
<vn-th number>Bank</vn-th>
|
||||
<vn-th number>Debit</vn-th>
|
||||
<vn-th number>Havings</vn-th>
|
||||
<vn-th number>Balance</vn-th>
|
||||
<vn-th center>Conciliated</vn-th>
|
||||
<vn-th></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="balance in $ctrl.balances">
|
||||
<vn-td expand>
|
||||
<span title="{{::balance.payed | date:'dd/MM/yyyy'}}">
|
||||
{{::balance.payed | date:'dd/MM/yyyy'}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink-datetime>
|
||||
<span title="{{::balance.created | date:'dd/MM/yyyy HH:mm'}}">
|
||||
{{::balance.created | date:'dd/MM/yyyy HH:mm'}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
vn-click-stop="workerDescriptor.show($event, balance.workerFk)"
|
||||
class="link">
|
||||
{{::balance.userName}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td-editable disabled="balance.isInvoice || !$ctrl.isAdministrative" expand>
|
||||
<text>
|
||||
<div ng-show="::balance.description">
|
||||
<span
|
||||
ng-if="balance.isInvoice"
|
||||
title="{{'BILL' | translate: {ref: balance.description} }}"
|
||||
vn-click-stop="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||
class="link">
|
||||
{{'BILL' | translate: {ref: balance.description} }}
|
||||
</span>
|
||||
<span
|
||||
ng-if="!balance.isInvoice"
|
||||
title="{{::balance.description}}">
|
||||
{{balance.description}}
|
||||
</span>
|
||||
</div>
|
||||
</text>
|
||||
<field>
|
||||
<vn-textfield vn-acl="administrative" class="dense" vn-focus
|
||||
ng-model="balance.description"
|
||||
on-change="$ctrl.changeDescription(balance)">
|
||||
</vn-textfield>
|
||||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td number>{{::balance.bankFk}}</vn-td>
|
||||
<vn-td number expand>{{::balance.debit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number expand>{{::balance.credit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number expand>{{balance.balance | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td center shrink>
|
||||
<vn-check
|
||||
ng-model="balance.isConciliate"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td center shrink>
|
||||
<a ng-show="balance.hasPdf"
|
||||
target="_blank"
|
||||
href="api/InvoiceOuts/{{::balance.id}}/download?access_token={{::$ctrl.vnToken.tokenMultimedia}}">
|
||||
<vn-icon-button
|
||||
icon="cloud_download"
|
||||
title="{{'Download PDF' | translate}}">
|
||||
</vn-icon-button>
|
||||
</a>
|
||||
</vn-td>
|
||||
<vn-td center shrink ng-if="balance.isCompensation">
|
||||
<vn-icon-button
|
||||
vn-dialog="send_compensation"
|
||||
icon="outgoing_mail"
|
||||
title="{{'Send compensation' | translate}}">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-confirm
|
||||
vn-id="send_compensation"
|
||||
on-accept="$ctrl.sendEmail(balance)"
|
||||
question="Notify compensation"
|
||||
message="Send compensation">
|
||||
</vn-confirm>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-float-button
|
||||
vn-acl="salesAssistant"
|
||||
vn-acl-action="remove"
|
||||
icon="add"
|
||||
vn-tooltip="New payment"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right
|
||||
ng-click="balanceCreate.show()">
|
||||
</vn-float-button>
|
||||
<vn-client-balance-create
|
||||
vn-id="balance-create"
|
||||
on-accept="$ctrl.getData()"
|
||||
company-fk="$ctrl.companyId"
|
||||
client-fk="$ctrl.$params.id">
|
||||
</vn-client-balance-create>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-invoice-out-descriptor-popover
|
||||
vn-id="invoiceOutDescriptor">
|
||||
</vn-invoice-out-descriptor-popover>
|
|
@ -1,105 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $, vnEmail) {
|
||||
super($element, $);
|
||||
this.vnEmail = vnEmail;
|
||||
this.filter = {
|
||||
include: {
|
||||
relation: 'company',
|
||||
scope: {
|
||||
fields: ['code'],
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get companyId() {
|
||||
if (!this._companyId)
|
||||
this.companyId = this.vnConfig.companyFk;
|
||||
|
||||
return this._companyId;
|
||||
}
|
||||
|
||||
set companyId(value) {
|
||||
this._companyId = value;
|
||||
|
||||
if (value) this.getData();
|
||||
}
|
||||
|
||||
get balances() {
|
||||
return this._balances;
|
||||
}
|
||||
|
||||
set balances(value) {
|
||||
this._balances = value;
|
||||
|
||||
const riskModel = this.$.riskModel;
|
||||
if (value && riskModel.data)
|
||||
this.getBalances();
|
||||
}
|
||||
|
||||
get isAdministrative() {
|
||||
return this.aclService.hasAny(['administrative']);
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.$.model.applyFilter(null, {
|
||||
clientId: this.$params.id,
|
||||
companyId: this.companyId
|
||||
}).then(() => this.$.riskModel.applyFilter({
|
||||
where: {
|
||||
clientFk: this.$params.id,
|
||||
companyFk: this.companyId
|
||||
}
|
||||
})).then(() => this.getBalances());
|
||||
}
|
||||
|
||||
getCurrentBalance() {
|
||||
const clientRisks = this.$.riskModel.data;
|
||||
const selectedCompany = this.companyId;
|
||||
const currentBalance = clientRisks.find(balance => {
|
||||
return balance.companyFk === selectedCompany;
|
||||
});
|
||||
|
||||
return currentBalance && currentBalance.amount;
|
||||
}
|
||||
|
||||
getBalances() {
|
||||
const balances = this.$.model.data;
|
||||
balances.forEach((balance, index) => {
|
||||
if (index === 0)
|
||||
balance.balance = this.getCurrentBalance();
|
||||
if (index > 0) {
|
||||
let previousBalance = balances[index - 1];
|
||||
balance.balance = previousBalance.balance - (previousBalance.debit - previousBalance.credit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showInvoiceOutDescriptor(event, balance) {
|
||||
if (!balance.isInvoice) return;
|
||||
if (event.defaultPrevented) return;
|
||||
|
||||
this.$.invoiceOutDescriptor.show(event.target, balance.id);
|
||||
}
|
||||
|
||||
changeDescription(balance) {
|
||||
const params = {description: balance.description};
|
||||
const endpoint = `Receipts/${balance.id}`;
|
||||
this.$http.patch(endpoint, params)
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
|
||||
}
|
||||
|
||||
sendEmail(balance) {
|
||||
return this.vnEmail.send(`Receipts/${balance.id}/balance-compensation-email`);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'vnEmail'];
|
||||
|
||||
ngModule.vnComponent('vnClientBalanceIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
});
|
|
@ -1,169 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientBalanceIndex', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
let $scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-client-balance-index></vn-client-balance-index>');
|
||||
controller = $componentController('vnClientBalanceIndex', {$element, $scope});
|
||||
controller.$.model = {applyFilter: () => {}};
|
||||
controller.$.riskModel = {
|
||||
applyFilter: () => {},
|
||||
data:
|
||||
[{
|
||||
clientFk: 1101,
|
||||
companyFk: 442,
|
||||
amount: 713.24,
|
||||
company: {
|
||||
id: 442,
|
||||
code: 'VNL'
|
||||
}
|
||||
}]
|
||||
};
|
||||
}));
|
||||
|
||||
describe('getData()', () => {
|
||||
it('should apply the filters on he models and get the client balance', () => {
|
||||
controller._companyId = 442;
|
||||
controller.$params.id = 1101;
|
||||
jest.spyOn(controller, 'getBalances').mockReturnThis();
|
||||
jest.spyOn(controller.$.model, 'applyFilter').mockReturnValue(Promise.resolve());
|
||||
jest.spyOn(controller.$.riskModel, 'applyFilter').mockReturnValue(Promise.resolve());
|
||||
|
||||
controller.getData().then(() => {
|
||||
expect(controller.$.model.applyFilter).toHaveBeenCalledWith(null, {'clientId': 1101, 'companyId': 442});
|
||||
expect(controller.$.riskModel.applyFilter).toHaveBeenCalledWith({'where': {'clientFk': 1101, 'companyFk': 442}});
|
||||
expect(controller.getBalances).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('company setter/getter', () => {
|
||||
it('should return the company and then call getData()', () => {
|
||||
jest.spyOn(controller, 'getData').mockReturnThis();
|
||||
controller.companyId = 442;
|
||||
|
||||
expect(controller._companyId).toEqual(442);
|
||||
expect(controller.getData).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCurrentBalance()', () => {
|
||||
it('should return the client balance amount', () => {
|
||||
controller._companyId = 442;
|
||||
let result = controller.getCurrentBalance();
|
||||
|
||||
expect(result).toEqual(713.24);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalances()', () => {
|
||||
it('should return the total client balance amount', () => {
|
||||
jest.spyOn(controller, 'getCurrentBalance');
|
||||
controller._companyId = 442;
|
||||
controller.$.model = {data:
|
||||
[{
|
||||
id: 1,
|
||||
debit: 1000,
|
||||
credit: null
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
debit: null,
|
||||
credit: 500
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
debit: null,
|
||||
credit: 300
|
||||
}
|
||||
]};
|
||||
controller.getBalances();
|
||||
const expectedBalances = controller.$.model.data;
|
||||
|
||||
expect(expectedBalances[0].balance).toEqual(713.24);
|
||||
expect(expectedBalances[1].balance).toEqual(-286.76);
|
||||
expect(expectedBalances[2].balance).toEqual(213.24);
|
||||
});
|
||||
});
|
||||
|
||||
describe('balances() setter', () => {
|
||||
it('should set the balances data and not call the getBalances() method', () => {
|
||||
jest.spyOn(controller, 'getBalances');
|
||||
controller.$.riskModel.data = null;
|
||||
controller.balances = [{
|
||||
id: 1,
|
||||
debit: 1000,
|
||||
credit: null
|
||||
}, {
|
||||
id: 2,
|
||||
debit: null,
|
||||
credit: 500
|
||||
}, {
|
||||
id: 3,
|
||||
debit: null,
|
||||
credit: 300
|
||||
}];
|
||||
|
||||
expect(controller.balances).toBeDefined();
|
||||
expect(controller.getBalances).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should set the balances data and then call the getBalances() method', () => {
|
||||
jest.spyOn(controller, 'getBalances').mockReturnThis();
|
||||
controller.balances = [{
|
||||
id: 1,
|
||||
debit: 1000,
|
||||
credit: null
|
||||
}, {
|
||||
id: 2,
|
||||
debit: null,
|
||||
credit: 500
|
||||
}, {
|
||||
id: 3,
|
||||
debit: null,
|
||||
credit: 300
|
||||
}];
|
||||
|
||||
expect(controller.balances).toBeDefined();
|
||||
expect(controller.getBalances).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('changeDescription()', () => {
|
||||
it('should make an http PATCH query', () => {
|
||||
const expectedParams = {description: 'Web'};
|
||||
|
||||
$httpBackend.expect('PATCH', `Receipts/1`, expectedParams).respond(200);
|
||||
controller.changeDescription({
|
||||
id: 1,
|
||||
description: 'Web',
|
||||
accountingType: {
|
||||
description: 'Cash'
|
||||
}
|
||||
});
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
||||
describe('sendEmail()', () => {
|
||||
it('should send an email', () => {
|
||||
jest.spyOn(controller.vnEmail, 'send');
|
||||
|
||||
const $data = {id: 1103};
|
||||
|
||||
controller.sendEmail($data);
|
||||
|
||||
const expectedPath = `Receipts/${$data.id}/balance-compensation-email`;
|
||||
|
||||
expect(controller.vnEmail.send).toHaveBeenCalledWith(expectedPath);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
BILL: N/INV {{ref}}
|
||||
Notify compensation: Do you want to report compensation to the client by mail?
|
||||
Send compensation: Send compensation
|
|
@ -1,13 +0,0 @@
|
|||
Creation date: Fecha de creación
|
||||
Reference: Referencia
|
||||
Bank: Caja
|
||||
Debit: Debe
|
||||
Conciliated: Conciliado
|
||||
New payment: Añadir pago
|
||||
Havings: Haber
|
||||
Balance: Balance
|
||||
Total by company: Total por empresa
|
||||
Download PDF: Descargar PDF
|
||||
Send compensation: Enviar compensación
|
||||
BILL: N/FRA {{ref}}
|
||||
Notify compensation: ¿Desea informar de la compensación al cliente por correo?
|
|
@ -1,2 +0,0 @@
|
|||
Compensation: Compensación
|
||||
Cash: Efectivo
|
|
@ -1,103 +0,0 @@
|
|||
<mg-ajax path="Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="ContactChannels"
|
||||
data="contactChannels">
|
||||
</vn-crud-model>
|
||||
<form name="form" vn-http-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Comercial Name"
|
||||
ng-model="$ctrl.client.name"
|
||||
rule
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.client.businessTypeFk"
|
||||
url="BusinessTypes"
|
||||
show-field="description"
|
||||
value-field="code"
|
||||
label="Business type">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Contact"
|
||||
ng-model="$ctrl.client.contact"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Email"
|
||||
ng-model="$ctrl.client.email"
|
||||
rule
|
||||
info="You can save multiple emails">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Phone"
|
||||
ng-model="$ctrl.client.phone"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Mobile"
|
||||
ng-model="$ctrl.client.mobile"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-worker-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.client.salesPersonFk"
|
||||
departments="['VT', 'shopping']"
|
||||
show-field="nickname"
|
||||
label="Salesperson"
|
||||
vn-acl="salesAssistant">
|
||||
</vn-worker-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.client.contactChannelFk"
|
||||
data="contactChannels"
|
||||
label="Channel">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
ng-model="$ctrl.client.transferorFk"
|
||||
url="Clients"
|
||||
search-function="$ctrl.transferorSearchFunction($search)"
|
||||
where="{id: {neq: $ctrl.client.id}}"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Previous client"
|
||||
info="In case of a company succession, specify the grantor company"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Undo changes"
|
||||
disabled="!watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,22 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
transferorSearchFunction($search) {
|
||||
return /^\d+$/.test($search)
|
||||
? {id: $search}
|
||||
: {name: {like: '%' + $search + '%'}};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
return this.$.watcher.submit();
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientBasicData', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,16 +0,0 @@
|
|||
Comercial Name: Nombre comercial
|
||||
Tax number: NIF/CIF
|
||||
Social name: Razón social
|
||||
Phone: Teléfono
|
||||
Mobile: Móvil
|
||||
Fax: Fax
|
||||
Email: E-mail
|
||||
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
|
||||
Undo changes: Deshacer cambios
|
||||
Business type: Tipo de negocio
|
|
@ -1,103 +0,0 @@
|
|||
<mg-ajax path="Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="PayMethods"
|
||||
data="paymethods">
|
||||
</vn-crud-model>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
label="Billing data"
|
||||
vn-acl="salesAssistant, hr"
|
||||
ng-model="$ctrl.client.payMethodFk"
|
||||
data="paymethods"
|
||||
fields="['isIbanRequiredForClients']"
|
||||
initial-data="$ctrl.client.payMethod">
|
||||
</vn-autocomplete>
|
||||
<vn-input-number
|
||||
min="0"
|
||||
step="1"
|
||||
label="Due day"
|
||||
ng-model="$ctrl.client.dueDay"
|
||||
vn-acl="salesAssistant, hr"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="IBAN"
|
||||
ng-keyup="$ctrl.client.iban = $ctrl.client.iban.toUpperCase()"
|
||||
ng-model="$ctrl.client.iban"
|
||||
rule
|
||||
on-change="$ctrl.autofillBic()"
|
||||
vn-acl="salesAssistant, hr">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
label="Swift / BIC"
|
||||
url="BankEntities"
|
||||
ng-model="$ctrl.client.bankEntityFk"
|
||||
fields="['name', 'bic']"
|
||||
initial-data="$ctrl.client.bankEntityFk"
|
||||
on-change="$ctrl.autofillBic()"
|
||||
search-function="{or: [{bic: {like: $search +'%'}}, {name: {like: '%'+ $search +'%'}}]}"
|
||||
value-field="id"
|
||||
show-field="bic"
|
||||
vn-acl="salesAssistant, hr"
|
||||
disabled="$ctrl.ibanCountry == 'ES'">
|
||||
<tpl-item>
|
||||
<div>{{::bic}}</div>
|
||||
<div class="text-secondary text-caption">{{::name}}</div>
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
vn-auto
|
||||
icon="add_circle"
|
||||
vn-click-stop="bankEntity.show({countryFk: $ctrl.client.countryFk})"
|
||||
vn-tooltip="New bank entity"
|
||||
vn-acl="salesAssistant, hr">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Received LCR"
|
||||
ng-model="$ctrl.client.hasLcr"
|
||||
vn-acl="salesAssistant, hr">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Received core VNL"
|
||||
ng-model="$ctrl.client.hasCoreVnl"
|
||||
vn-acl="salesAssistant, hr">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Received B2B VNL"
|
||||
ng-model="$ctrl.client.hasSepaVnl"
|
||||
vn-acl="salesAssistant, hr">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Undo changes"
|
||||
disabled="!watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<vn-new-bank-entity
|
||||
vn-id="bankEntity"
|
||||
on-accept="$ctrl.onAccept($data)">
|
||||
</vn-new-bank-entity>
|
|
@ -1,77 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
get client() {
|
||||
return this._client;
|
||||
}
|
||||
|
||||
set client(value) {
|
||||
this._client = value;
|
||||
|
||||
if (!value) return;
|
||||
|
||||
if (!value.bankEntityFk)
|
||||
this.autofillBic();
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
let shouldNotify = false;
|
||||
|
||||
if (this.hasPaymethodChanges())
|
||||
shouldNotify = true;
|
||||
|
||||
this.$.watcher.submit().then(() => {
|
||||
if (shouldNotify)
|
||||
this.vnApp.showMessage(this.$t('Notification sent!'));
|
||||
});
|
||||
}
|
||||
|
||||
hasPaymethodChanges() {
|
||||
let orgData = this.$.watcher.orgData;
|
||||
|
||||
let payMethod = orgData.payMethodFk != this.client.payMethodFk;
|
||||
let iban = orgData.iban != this.client.iban;
|
||||
let dueDay = orgData.dueDay != this.client.dueDay;
|
||||
|
||||
return payMethod || iban || dueDay;
|
||||
}
|
||||
|
||||
onAccept(data) {
|
||||
this.client.bankEntityFk = data.id;
|
||||
}
|
||||
|
||||
get ibanCountry() {
|
||||
if (!this.client || !this.client.iban) return false;
|
||||
|
||||
let countryCode = this.client.iban.substr(0, 2);
|
||||
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
autofillBic() {
|
||||
if (!this.client || !this.client.iban) return;
|
||||
|
||||
let bankEntityId = parseInt(this.client.iban.substr(4, 4));
|
||||
let filter = {where: {id: bankEntityId}};
|
||||
|
||||
if (this.ibanCountry != 'ES') return;
|
||||
|
||||
this.$http.get(`BankEntities`, {filter}).then(response => {
|
||||
const hasData = response.data && response.data[0];
|
||||
|
||||
if (hasData)
|
||||
this.client.bankEntityFk = response.data[0].id;
|
||||
else if (!hasData)
|
||||
this.client.bankEntityFk = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientBillingData', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,94 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientBillingData', () => {
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
let controller;
|
||||
let vnApp;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => {
|
||||
let $element = angular.element('<vn-client-billing-data></vn-client-billing-data>');
|
||||
$httpBackend = _$httpBackend_;
|
||||
vnApp = _vnApp_;
|
||||
$scope = $rootScope.$new();
|
||||
$scope.watcher = {};
|
||||
jest.spyOn(vnApp, 'showError');
|
||||
controller = $componentController('vnClientBillingData', {$element, $scope});
|
||||
controller.client = {id: 1101, name: 'Client name', payMethodFk: 4};
|
||||
$scope.watcher.orgData = {id: 1101, name: 'Client name', payMethodFk: 4};
|
||||
}));
|
||||
|
||||
describe('hasPaymethodChanges()', () => {
|
||||
it(`should return true if there are changes on payMethod data`, () => {
|
||||
controller.client.payMethodFk = 5;
|
||||
|
||||
expect(controller.hasPaymethodChanges()).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should return false if there are no changes on payMethod data`, () => {
|
||||
controller.client.payMethodFk = 4;
|
||||
|
||||
expect(controller.hasPaymethodChanges()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onAccept()', () => {
|
||||
it('should assign the response id to the client bankEntityFk', () => {
|
||||
const expectedResponse = {id: 999};
|
||||
controller.onAccept(expectedResponse);
|
||||
|
||||
expect(controller.client.bankEntityFk).toEqual(expectedResponse.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('autofillBic()', () => {
|
||||
it(`Should do nothing if there is not client`, () => {
|
||||
controller.client = undefined;
|
||||
|
||||
controller.autofillBic();
|
||||
|
||||
expect(controller.client).toBeUndefined();
|
||||
});
|
||||
|
||||
it(`Should do nothing if the iban is not spanish`, () => {
|
||||
controller.client.iban = 'FR9121000418450200051332';
|
||||
|
||||
controller.autofillBic();
|
||||
|
||||
expect(controller.client.bankEntityFk).toBeUndefined();
|
||||
});
|
||||
|
||||
it(`Should set the bankEntityId in the client`, () => {
|
||||
controller.client.iban = 'ES9121000418450200051332';
|
||||
|
||||
$httpBackend.whenRoute('GET', `BankEntities`).respond([{id: 123}]);
|
||||
controller.autofillBic();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.client.bankEntityFk).toEqual(123);
|
||||
});
|
||||
|
||||
it(`Should set clients bankEntityFk to null if no bank entity founds`, () => {
|
||||
controller.client.iban = 'ES9121000418450200051332';
|
||||
|
||||
$httpBackend.whenRoute('GET', `BankEntities`).respond([]);
|
||||
controller.autofillBic();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.client.bankEntityFk).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ibanCountry()', () => {
|
||||
it('should return a country code from iban', () => {
|
||||
controller.client.iban = 'ES123';
|
||||
let countryCode = controller.ibanCountry;
|
||||
|
||||
expect(countryCode).toEqual('ES');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
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 VNL: VNL core received
|
||||
Received B2B VNL: VNL B2B received
|
||||
Save: Save
|
|
@ -1,17 +0,0 @@
|
|||
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 LCR: Recibido LCR
|
||||
Received core VNL: Recibido core VNL
|
||||
Received B2B VNL: Recibido B2B VNL
|
||||
Save: Guardar
|
||||
New bank entity: Nueva entidad bancaria
|
||||
Name can't be empty: El nombre no puede quedar vacío
|
|
@ -1,5 +0,0 @@
|
|||
<vn-portal slot="menu">
|
||||
<vn-client-descriptor client="$ctrl.client"></vn-client-descriptor>
|
||||
<vn-left-menu source="card"></vn-left-menu>
|
||||
</vn-portal>
|
||||
<ui-view></ui-view>
|
|
@ -1,15 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import ModuleCard from 'salix/components/module-card';
|
||||
|
||||
export default class Controller extends ModuleCard {
|
||||
reload() {
|
||||
this.$http.get(`Clients/${this.$params.id}/getCard`)
|
||||
.then(res => this.client = res.data);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientCard', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCard', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let data = {id: 1, name: 'fooName'};
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, $stateParams) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
let $element = angular.element('<div></div>');
|
||||
controller = $componentController('vnClientCard', {$element});
|
||||
|
||||
$stateParams.id = data.id;
|
||||
$httpBackend.whenRoute('GET', 'Clients/:id/getCard').respond(data);
|
||||
}));
|
||||
|
||||
it('should request data and set it on the controller', () => {
|
||||
controller.$onInit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.client).toEqual(data);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,85 +0,0 @@
|
|||
<div class="search-panel">
|
||||
<form class="vn-pa-lg" ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-focus
|
||||
vn-one
|
||||
label="General search"
|
||||
ng-model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Item id"
|
||||
ng-model="filter.itemId">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.buyerId"
|
||||
url="TicketRequests/getItemTypeWorker"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="nickname"
|
||||
value-field="id"
|
||||
label="Buyer">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
ng-model="filter.typeId"
|
||||
url="ItemTypes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Type"
|
||||
fields="['categoryFk']"
|
||||
include="'category'">
|
||||
<tpl-item>
|
||||
<div>{{name}}</div>
|
||||
<div class="text-caption text-secondary">
|
||||
{{category.name}}
|
||||
</div>
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
url="ItemCategories"
|
||||
label="Category"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
ng-model="filter.categoryId">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
url="Campaigns/latest"
|
||||
label="Campaign"
|
||||
translate-fields="['code']"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
ng-model="filter.campaign"
|
||||
order="dated DESC"
|
||||
selection="$ctrl.campaignSelection"
|
||||
search-function="{dated: {like: '%'+ $search +'%'}}">
|
||||
<tpl-item>
|
||||
{{code}} {{dated | date: 'yyyy'}}
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="From"
|
||||
ng-model="filter.from"
|
||||
on-change="$ctrl.onChangeDate(value)">
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="To"
|
||||
ng-model="filter.to"
|
||||
on-change="$ctrl.onChangeDate(value)">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-mt-lg">
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
|
@ -1,56 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
||||
|
||||
class Controller extends SearchPanel {
|
||||
constructor($, $element) {
|
||||
super($, $element);
|
||||
|
||||
this.filter = this.$.filter;
|
||||
|
||||
if (!this.dateParams)
|
||||
this.getUpcomingCampaing();
|
||||
}
|
||||
|
||||
get dateParams() {
|
||||
if (this.$params.q) {
|
||||
const params = JSON.parse(this.$params.q);
|
||||
|
||||
if (params.from || params.to)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getUpcomingCampaing() {
|
||||
this.$http.get('Campaigns/upcoming').then(res => {
|
||||
this.filter.campaign = res.data.id;
|
||||
});
|
||||
}
|
||||
|
||||
onChangeDate(value) {
|
||||
if (value)
|
||||
this.filter.campaign = null;
|
||||
}
|
||||
|
||||
get campaignSelection() {
|
||||
return this._campaignSelection;
|
||||
}
|
||||
|
||||
set campaignSelection(value) {
|
||||
this._campaignSelection = value;
|
||||
|
||||
if (value) {
|
||||
const from = new Date(value.dated);
|
||||
from.setDate(from.getDate() - value.scopeDays);
|
||||
|
||||
this.filter.to = value.dated;
|
||||
this.filter.from = from;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnConsumptionSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,31 +0,0 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnConsumptionSearchPanel', () => {
|
||||
let $httpBackend;
|
||||
let $element;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$element = angular.element(`<div></div>`);
|
||||
controller = $componentController('vnConsumptionSearchPanel', {$element});
|
||||
controller.$.filter = {};
|
||||
$httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 1});
|
||||
}));
|
||||
|
||||
describe('getUpcomingCampaing()', () => {
|
||||
it(`should make an HTTP query and then set the campaign property`, () => {
|
||||
$httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 2, code: 'allSaints'});
|
||||
controller.getUpcomingCampaing();
|
||||
$httpBackend.flush();
|
||||
|
||||
const filter = controller.$.filter;
|
||||
|
||||
expect(filter.campaign).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
allSaints: All Saints Day
|
||||
valentinesDay: Valentine's Day
|
||||
mothersDay: Mother's day
|
|
@ -1,7 +0,0 @@
|
|||
Item id: Id artículo
|
||||
From: Desde
|
||||
To: Hasta
|
||||
Campaign: Campaña
|
||||
allSaints: Día de todos los Santos
|
||||
valentinesDay: Día de San Valentín
|
||||
mothersDay: Día de la madre
|
|
@ -1,97 +0,0 @@
|
|||
<vn-crud-model vn-id="model"
|
||||
url="Clients/consumption"
|
||||
link="{clientFk: $ctrl.$params.id}"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
user-params="::$ctrl.filterParams"
|
||||
data="sales"
|
||||
order="itemTypeFk, itemName, itemSize, description">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
panel="vn-consumption-search-panel"
|
||||
suggested-filter="$ctrl.filterParams"
|
||||
info="Search by item id or name"
|
||||
model="model"
|
||||
auto-state="false">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-data-viewer model="model">
|
||||
<vn-card class="vn-pa-lg vn-w-lg">
|
||||
<section class="header">
|
||||
<vn-tool-bar class="vn-mb-md">
|
||||
<vn-button disabled="!model.userParams.from || !model.userParams.to"
|
||||
icon="picture_as_pdf"
|
||||
ng-click="$ctrl.showReport()"
|
||||
vn-tooltip="Open as PDF">
|
||||
</vn-button>
|
||||
<vn-button disabled="!model.userParams.from || !model.userParams.to"
|
||||
icon="email"
|
||||
ng-click="confirm.show()"
|
||||
vn-tooltip="Send to email">
|
||||
</vn-button>
|
||||
<vn-check
|
||||
label="Group by item"
|
||||
on-change="$ctrl.changeGrouped(value)">
|
||||
</vn-check>
|
||||
</vn-tool-bar>
|
||||
</section>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="itemFk" number>Item</vn-th>
|
||||
<vn-th field="ticketFk" number>Ticket</vn-th>
|
||||
<vn-th field="shipped" expand>Fecha</vn-th>
|
||||
<vn-th field="description" expand>Description</vn-th>
|
||||
<vn-th field="quantity" number>Quantity</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr
|
||||
ng-repeat="sale in sales">
|
||||
<vn-td number>
|
||||
<span
|
||||
ng-click="itemDescriptor.show($event, sale.itemFk)"
|
||||
class="link">
|
||||
{{::sale.itemFk}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>
|
||||
<span
|
||||
ng-click="ticketDescriptor.show($event, sale.ticketFk)"
|
||||
class="link">
|
||||
{{::sale.ticketFk}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>{{::sale.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td vn-fetched-tags wide>
|
||||
<div>
|
||||
<vn-one title="{{::sale.concept}}">{{::sale.concept}}</vn-one>
|
||||
<vn-one ng-if="::sale.subName">
|
||||
<h3 title="{{::sale.subName}}">{{::sale.subName}}</h3>
|
||||
</vn-one>
|
||||
</div>
|
||||
<vn-fetched-tags
|
||||
max-length="6"
|
||||
item="::sale"
|
||||
tabindex="-1">
|
||||
</vn-fetched-tags>
|
||||
</vn-td>
|
||||
<vn-td number>{{::sale.quantity | dashIfEmpty}}</vn-td>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-item-descriptor-popover
|
||||
vn-id="item-descriptor"
|
||||
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
||||
</vn-item-descriptor-popover>
|
||||
<vn-ticket-descriptor-popover
|
||||
vn-id="ticket-descriptor">
|
||||
</vn-ticket-descriptor-popover>
|
||||
<vn-confirm
|
||||
vn-id="confirm"
|
||||
question="Please, confirm"
|
||||
message="The consumption report will be sent"
|
||||
on-accept="$ctrl.sendEmail()">
|
||||
</vn-confirm>
|
|
@ -1,75 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $, vnReport, vnEmail) {
|
||||
super($element, $);
|
||||
this.vnReport = vnReport;
|
||||
this.vnEmail = vnEmail;
|
||||
|
||||
this.filter = {
|
||||
where: {
|
||||
isPackaging: false
|
||||
}
|
||||
};
|
||||
|
||||
this.setDefaultFilter();
|
||||
}
|
||||
|
||||
setDefaultFilter() {
|
||||
const minDate = Date.vnNew();
|
||||
minDate.setHours(0, 0, 0, 0);
|
||||
minDate.setMonth(minDate.getMonth() - 2);
|
||||
|
||||
const maxDate = Date.vnNew();
|
||||
maxDate.setHours(23, 59, 59, 59);
|
||||
|
||||
this.filterParams = {
|
||||
from: minDate,
|
||||
to: maxDate
|
||||
};
|
||||
}
|
||||
|
||||
get reportParams() {
|
||||
const userParams = this.$.model.userParams;
|
||||
return Object.assign({
|
||||
recipient: this.client.email,
|
||||
recipientId: this.client.id
|
||||
}, userParams);
|
||||
}
|
||||
|
||||
showTicketDescriptor(event, sale) {
|
||||
if (!sale.isTicket) return;
|
||||
|
||||
this.$.ticketDescriptor.show(event.target, sale.origin);
|
||||
}
|
||||
|
||||
showReport() {
|
||||
const path = `Clients/${this.client.id}/campaign-metrics-pdf`;
|
||||
this.vnReport.show(path, this.reportParams);
|
||||
}
|
||||
|
||||
sendEmail() {
|
||||
const path = `Clients/${this.client.id}/campaign-metrics-email`;
|
||||
this.vnEmail.send(path, this.reportParams);
|
||||
}
|
||||
|
||||
changeGrouped(value) {
|
||||
const model = this.$.model;
|
||||
|
||||
model.addFilter({}, {grouped: value});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail'];
|
||||
|
||||
ngModule.vnComponent('vnClientConsumption', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
},
|
||||
require: {
|
||||
card: '^vnClientCard'
|
||||
}
|
||||
});
|
|
@ -1,67 +0,0 @@
|
|||
import './index.js';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientConsumption', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpParamSerializer;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpParamSerializer_, _$httpBackend_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
const $element = angular.element('<vn-client-consumption></vn-client-consumption');
|
||||
controller = $componentController('vnClientConsumption', {$element, $scope});
|
||||
controller.$.model = crudModel;
|
||||
controller.client = {
|
||||
id: 1101
|
||||
};
|
||||
}));
|
||||
|
||||
describe('showReport()', () => {
|
||||
it('should call the window.open function', () => {
|
||||
jest.spyOn(window, 'open').mockReturnThis();
|
||||
|
||||
const now = Date.vnNew();
|
||||
controller.$.model.userParams = {
|
||||
from: now,
|
||||
to: now
|
||||
};
|
||||
|
||||
controller.showReport();
|
||||
|
||||
const clientId = controller.client.id;
|
||||
const expectedParams = {
|
||||
recipientId: clientId,
|
||||
from: now,
|
||||
to: now
|
||||
};
|
||||
const serializedParams = $httpParamSerializer(expectedParams);
|
||||
const expectedPath = `api/Clients/${clientId}/campaign-metrics-pdf?${serializedParams}`;
|
||||
|
||||
expect(window.open).toHaveBeenCalledWith(expectedPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sendEmail()', () => {
|
||||
it('should make a GET query sending the report', () => {
|
||||
const now = Date.vnNew();
|
||||
controller.$.model.userParams = {
|
||||
from: now,
|
||||
to: now
|
||||
};
|
||||
const clientId = controller.client.id;
|
||||
const expectedPath = `Clients/${clientId}/campaign-metrics-email`;
|
||||
|
||||
$httpBackend.expect('POST', expectedPath).respond({});
|
||||
controller.sendEmail();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
Group by item: Agrupar por artículo
|
||||
Open as PDF: Abrir como PDF
|
||||
Send to email: Enviar por email
|
||||
Search by item id or name: Buscar por id de artículo o nombre
|
||||
The consumption report will be sent: Se enviará el informe de consumo
|
||||
Please, confirm: Por favor, confirma
|
|
@ -1,61 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="ClientContacts"
|
||||
fields="['id', 'name', 'phone', 'clientFk']"
|
||||
link="{clientFk: $ctrl.$params.id}"
|
||||
data="contacts"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="contacts"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal ng-repeat="contact in contacts">
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
ng-model="contact.name"
|
||||
rule="ClientContact">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Phone"
|
||||
ng-model="contact.phone"
|
||||
rule="ClientContact"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-none>
|
||||
<vn-icon-button
|
||||
vn-tooltip="Remove contact"
|
||||
icon="delete"
|
||||
tabindex="-1"
|
||||
ng-click="model.remove($index)">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-icon-button
|
||||
vn-bind="+"
|
||||
vn-tooltip="Add contact"
|
||||
icon="add_circle"
|
||||
ng-click="$ctrl.add()">
|
||||
</vn-icon-button>
|
||||
</vn-one>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<!-- # #2680 Undo changes button bugs -->
|
||||
<!-- <vn-button
|
||||
class="cancel"
|
||||
label="Undo changes"
|
||||
disabled="!watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button> -->
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,28 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
add() {
|
||||
this.$.model.insert({
|
||||
clientFk: this.client.id,
|
||||
name: this.$t('Phone'),
|
||||
phone: null
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$.watcher.check();
|
||||
this.$.model.save().then(() => {
|
||||
this.$.watcher.notifySaved();
|
||||
this.$.watcher.updateOriginalData();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientContact', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,150 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="Clients/createWithUser"
|
||||
data="$ctrl.client"
|
||||
insert-mode="true"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" vn-http-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
label="Comercial Name"
|
||||
ng-model="$ctrl.client.name"
|
||||
rule
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-worker-autocomplete
|
||||
label="Salesperson"
|
||||
ng-model="$ctrl.client.salesPersonFk"
|
||||
departments="['VT']"
|
||||
show-field="nickname">
|
||||
</vn-worker-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-id="businessTypeFk"
|
||||
ng-model="$ctrl.client.businessTypeFk"
|
||||
url="BusinessTypes"
|
||||
show-field="description"
|
||||
value-field="code"
|
||||
label="Business type"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
label="Tax number"
|
||||
ng-model="$ctrl.client.fi"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Business name"
|
||||
ng-model="$ctrl.client.socialName"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
label="Street"
|
||||
ng-model="$ctrl.client.street"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-datalist
|
||||
label="Postcode"
|
||||
ng-model="$ctrl.client.postcode"
|
||||
selection="$ctrl.postcode"
|
||||
url="Postcodes/location"
|
||||
fields="['code','townFk']"
|
||||
order="code, townFk"
|
||||
value-field="code"
|
||||
show-field="code"
|
||||
rule>
|
||||
<tpl-item>
|
||||
{{code}} - {{town.name}} ({{town.province.name}},
|
||||
{{town.province.country.name}})
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New postcode"
|
||||
ng-click="postcode.open()"
|
||||
vn-acl="deliveryAssistant"
|
||||
vn-acl-action="remove">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-datalist>
|
||||
<vn-datalist
|
||||
vn-id="town"
|
||||
label="City"
|
||||
ng-model="$ctrl.client.city"
|
||||
selection="$ctrl.town"
|
||||
url="Towns/location"
|
||||
fields="['id', 'name', 'provinceFk']"
|
||||
value-field="name">
|
||||
<tpl-item>
|
||||
{{name}}, {{province.name}}
|
||||
({{province.country.name}})
|
||||
</tpl-item>
|
||||
</vn-datalist>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-id="province"
|
||||
label="Province"
|
||||
ng-model="$ctrl.client.provinceFk"
|
||||
selection="$ctrl.province"
|
||||
url="Provinces/location"
|
||||
fields="['id', 'name', 'countryFk']"
|
||||
rule>
|
||||
<tpl-item>{{name}} ({{country.name}})</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-id="country"
|
||||
label="Country"
|
||||
ng-model="$ctrl.client.countryFk"
|
||||
url="Countries"
|
||||
show-field="name">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Web user"
|
||||
ng-model="$ctrl.client.userName"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
label="Email"
|
||||
ng-model="$ctrl.client.email"
|
||||
rule
|
||||
info="You can save multiple emails">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Is equalizated"
|
||||
ng-model="$ctrl.client.isEqualizated">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Create">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Cancel"
|
||||
ui-sref="client.index">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<!-- New postcode dialog -->
|
||||
<vn-geo-postcode
|
||||
vn-id="postcode"
|
||||
on-response="$ctrl.onResponse($response)">
|
||||
</vn-geo-postcode>
|
|
@ -1,95 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.client = {
|
||||
active: true
|
||||
};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
return this.$.watcher.submit().then(json => {
|
||||
this.$state.go('client.card.basicData', {id: json.data.id});
|
||||
});
|
||||
}
|
||||
|
||||
get province() {
|
||||
return this._province;
|
||||
}
|
||||
|
||||
// Province auto complete
|
||||
set province(selection) {
|
||||
this._province = selection;
|
||||
|
||||
if (!selection) return;
|
||||
|
||||
const country = selection.country;
|
||||
|
||||
if (!this.client.countryFk)
|
||||
this.client.countryFk = country.id;
|
||||
}
|
||||
|
||||
get town() {
|
||||
return this._town;
|
||||
}
|
||||
|
||||
// Town auto complete
|
||||
set town(selection) {
|
||||
this._town = selection;
|
||||
|
||||
if (!selection) return;
|
||||
|
||||
const province = selection.province;
|
||||
const country = province.country;
|
||||
const postcodes = selection.postcodes;
|
||||
|
||||
if (!this.client.provinceFk)
|
||||
this.client.provinceFk = province.id;
|
||||
|
||||
if (!this.client.countryFk)
|
||||
this.client.countryFk = country.id;
|
||||
|
||||
if (postcodes.length === 1)
|
||||
this.client.postcode = postcodes[0].code;
|
||||
}
|
||||
|
||||
get postcode() {
|
||||
return this._postcode;
|
||||
}
|
||||
|
||||
// Postcode auto complete
|
||||
set postcode(selection) {
|
||||
this._postcode = selection;
|
||||
|
||||
if (!selection) return;
|
||||
|
||||
const town = selection.town;
|
||||
const province = town.province;
|
||||
const country = province.country;
|
||||
|
||||
if (!this.client.city)
|
||||
this.client.city = town.name;
|
||||
|
||||
if (!this.client.provinceFk)
|
||||
this.client.provinceFk = province.id;
|
||||
|
||||
if (!this.client.countryFk)
|
||||
this.client.countryFk = country.id;
|
||||
}
|
||||
|
||||
onResponse(response) {
|
||||
this.client.postcode = response.code;
|
||||
this.client.city = response.city;
|
||||
this.client.provinceFk = response.provinceFk;
|
||||
this.client.countryFk = response.countryFk;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,122 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreate', () => {
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$state_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$state = _$state_;
|
||||
$scope.watcher = {
|
||||
submit: () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback({data: {id: '1234'}});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const $element = angular.element('<vn-client-create></vn-client-create>');
|
||||
controller = $componentController('vnClientCreate', {$element, $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`, () => {
|
||||
jest.spyOn($state, 'go');
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('client.card.basicData', {id: '1234'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('province() setter', () => {
|
||||
it(`should set countryFk property`, () => {
|
||||
controller.client.countryFk = null;
|
||||
controller.province = {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
};
|
||||
|
||||
expect(controller.client.countryFk).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('town() setter', () => {
|
||||
it(`should set provinceFk property`, () => {
|
||||
controller.town = {
|
||||
provinceFk: 1,
|
||||
code: 46001,
|
||||
province: {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
},
|
||||
postcodes: []
|
||||
};
|
||||
|
||||
expect(controller.client.provinceFk).toEqual(1);
|
||||
});
|
||||
|
||||
it(`should set provinceFk property and fill the postalCode if there's just one`, () => {
|
||||
controller.town = {
|
||||
provinceFk: 1,
|
||||
code: 46001,
|
||||
province: {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
},
|
||||
postcodes: [{code: '46001'}]
|
||||
};
|
||||
|
||||
expect(controller.client.provinceFk).toEqual(1);
|
||||
expect(controller.client.postcode).toEqual('46001');
|
||||
});
|
||||
});
|
||||
|
||||
describe('postcode() setter', () => {
|
||||
it(`should set the town, provinceFk and contryFk properties`, () => {
|
||||
controller.postcode = {
|
||||
townFk: 1,
|
||||
code: 46001,
|
||||
town: {
|
||||
id: 1,
|
||||
name: 'New York',
|
||||
province: {
|
||||
id: 1,
|
||||
name: 'New york',
|
||||
country: {
|
||||
id: 2,
|
||||
name: 'USA'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(controller.client.city).toEqual('New York');
|
||||
expect(controller.client.provinceFk).toEqual(1);
|
||||
expect(controller.client.countryFk).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
Name: Nombre
|
||||
Tax number: NIF/CIF
|
||||
Business name: Razón social
|
||||
Web user: Usuario Web
|
||||
Email: E-mail
|
||||
Create and edit: Crear y editar
|
||||
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
|
||||
The type of business must be filled in basic data: El tipo de negocio debe estar rellenado en datos básicos
|
|
@ -1,37 +0,0 @@
|
|||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
min="0"
|
||||
label="Credit"
|
||||
ng-model="$ctrl.creditClassification.credit"
|
||||
rule
|
||||
vn-focus>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
min="0"
|
||||
step="1"
|
||||
label="Grade"
|
||||
ng-model="$ctrl.creditClassification.grade"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Since"
|
||||
ng-model="$ctrl.creditClassification.started">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Cancel"
|
||||
ui-sref="client.card.creditInsurance.index"></vn-button>
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,40 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.creditClassification = {
|
||||
started: this.$filter('date')(Date.vnNew(), 'yyyy-MM-dd HH:mm')
|
||||
};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
if (this.$.form.$invalid)
|
||||
return this.vnApp.showError(this.$t('Some fields are invalid'));
|
||||
|
||||
let query = `creditClassifications/createWithInsurance`;
|
||||
let data = this.creditClassification;
|
||||
data.clientFk = this.client.id;
|
||||
|
||||
this.$http.post(query, data).then(res => {
|
||||
if (res.data) {
|
||||
this.card.reload();
|
||||
this.$state.go('client.card.creditInsurance.index');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientCreditInsuranceCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
require: {
|
||||
card: '^vnClientCard'
|
||||
},
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreditInsuranceCreate', () => {
|
||||
let controller;
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
$scope.form = {
|
||||
$invalid: false
|
||||
};
|
||||
const $element = angular.element('<vn-client-credit-insurance-create></vn-client-credit-insurance-create>');
|
||||
controller = $componentController('vnClientCreditInsuranceCreate', {$element, $scope});
|
||||
controller.client = {id: 1101};
|
||||
controller.card = {
|
||||
reload: () => {}
|
||||
};
|
||||
}));
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('should perform a POST query', () => {
|
||||
let started = Date.vnNew();
|
||||
controller.creditClassification = {
|
||||
started: started,
|
||||
credit: 300,
|
||||
grade: 1
|
||||
};
|
||||
|
||||
let newData = {
|
||||
started: started,
|
||||
credit: 300,
|
||||
grade: 1,
|
||||
clientFk: 1101
|
||||
};
|
||||
|
||||
$httpBackend.whenPOST(`creditClassifications/createWithInsurance`, newData).respond(200, true);
|
||||
$httpBackend.expectPOST(`creditClassifications/createWithInsurance`, newData);
|
||||
controller.onSubmit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,68 +0,0 @@
|
|||
<vn-data-viewer
|
||||
data="$ctrl.classifications"
|
||||
class="vn-w-md">
|
||||
<vn-card class="vn-pa-md">
|
||||
<vn-horizontal
|
||||
ng-repeat="classification in $ctrl.classifications track by classification.id"
|
||||
class="vn-pb-md insurance"
|
||||
style="align-items: center;">
|
||||
<vn-one
|
||||
class="vn-pa-sm border-solid border-radius"
|
||||
ng-class="{'item-hightlight': !classification.finished,'item-disabled': classification.finished}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none class="vn-px-md">
|
||||
<vn-icon-button
|
||||
ng-if="!classification.finished"
|
||||
icon="lock"
|
||||
vn-tooltip="Close contract"
|
||||
ng-click="$ctrl.closeContract(classification)">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-one class="border-solid-right">
|
||||
<div><vn-label translate>Since</vn-label> {{::classification.started | date:'dd/MM/yyyy'}}</div>
|
||||
<div><vn-label translate>To</vn-label> {{classification.finished | date:'dd/MM/yyyy'}}</div>
|
||||
</vn-one>
|
||||
<vn-vertical vn-one class="vn-px-md">
|
||||
<vn-horizontal ng-repeat="insurance in classification.insurances track by insurance.id">
|
||||
<vn-one>
|
||||
<vn-label-value label="Credit"
|
||||
value="{{::insurance.credit}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Grade"
|
||||
value="{{::insurance.grade}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Date"
|
||||
value="{{::insurance.created | date:'dd/MM/yyyy' }}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
<a vn-auto ui-sref="client.card.creditInsurance.insurance.index({classificationId: {{classification.id}}})">
|
||||
<vn-icon-button icon="preview" vn-tooltip="View credits"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
ng-if="$ctrl.canCreateNew()"
|
||||
vn-acl="insurance"
|
||||
vn-acl-action="remove"
|
||||
vn-tooltip="New contract"
|
||||
fixed-bottom-right
|
||||
ui-sref="client.card.creditInsurance.create"
|
||||
icon="add"
|
||||
vn-bind="+"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
<vn-confirm
|
||||
vn-id="close-contract"
|
||||
on-accept="$ctrl.returnDialog()"
|
||||
question="Close contract"
|
||||
message="Are you sure you want to close this contract?">
|
||||
</vn-confirm>
|
|
@ -1,68 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
$onChanges() {
|
||||
if (this.client && this.client.id)
|
||||
this._getClassifications(this.client.id);
|
||||
}
|
||||
|
||||
_getClassifications(clientId) {
|
||||
let filter = {
|
||||
order: 'finished ASC, started DESC',
|
||||
include: [
|
||||
{
|
||||
relation: 'insurances',
|
||||
scope: {
|
||||
fields: ['id', 'credit', 'created', 'grade'],
|
||||
order: 'created DESC',
|
||||
limit: 2
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
where: {client: clientId}
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let query = `CreditClassifications?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.classifications = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
canCreateNew() {
|
||||
if (!this.classifications)
|
||||
return false;
|
||||
|
||||
let items = this.classifications;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (!items[i].finished)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
closeContract(classification) {
|
||||
this.classificationId = classification.id;
|
||||
this.$.closeContract.show();
|
||||
}
|
||||
|
||||
returnDialog() {
|
||||
let params = {finished: Date.vnNow()};
|
||||
this.$http.patch(`CreditClassifications/${this.classificationId}`, params).then(() => {
|
||||
this._getClassifications(this.client.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientCreditInsuranceIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,88 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreditInsuranceIndex', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-client-credit-insurance-index></vn-client-credit-insurance-index>');
|
||||
controller = $componentController('vnClientCreditInsuranceIndex', {$element, $scope});
|
||||
controller.client = {id: 1101};
|
||||
}));
|
||||
|
||||
describe('_getClassifications()', () => {
|
||||
it('should perform a GET query to define the classifications property in the controller', () => {
|
||||
let res = ['some classifications'];
|
||||
let query = 'CreditClassifications?filter=%7B%22order%22%3A%22finished%20ASC%2C%20started%20DESC%22%2C%22include%22%3A%5B%7B%22relation%22%3A%22insurances%22%2C%22scope%22%3A%7B%22fields%22%3A%5B%22id%22%2C%22credit%22%2C%22created%22%2C%22grade%22%5D%2C%22order%22%3A%22created%20DESC%22%2C%22limit%22%3A2%7D%7D%5D%2C%22where%22%3A%7B%7D%7D';
|
||||
|
||||
$httpBackend.whenGET(query).respond(res);
|
||||
$httpBackend.expectGET(query);
|
||||
controller._getClassifications();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.classifications).toEqual(['some classifications']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('canCreateNew()', () => {
|
||||
it(`should return false if doesn't have classifications`, () => {
|
||||
let result = controller.canCreateNew();
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it(`should return false if finds a classification without due date`, () => {
|
||||
controller.classifications = [
|
||||
{finished: Date.vnNow()},
|
||||
{finished: null}
|
||||
];
|
||||
|
||||
let result = controller.canCreateNew();
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it(`should return true if all classifications are defined with due date`, () => {
|
||||
controller.classifications = [
|
||||
{finished: Date.vnNow()},
|
||||
{finished: Date.vnNow()}
|
||||
];
|
||||
|
||||
let result = controller.canCreateNew();
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('closeContract()', () => {
|
||||
it('should define the classificationId property of the controller and then call the show method()', () => {
|
||||
controller.$.closeContract = {show: () => {}};
|
||||
jest.spyOn(controller.$.closeContract, 'show');
|
||||
|
||||
expect(controller.classificationId).toBeFalsy();
|
||||
controller.closeContract({id: 1});
|
||||
|
||||
expect(controller.classificationId).toEqual(1);
|
||||
expect(controller.$.closeContract.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('returnDialog()', () => {
|
||||
it('should call the returnDialog method and perform a PATCH query, then call _getClassifications method', () => {
|
||||
jest.spyOn(controller, '_getClassifications').mockReturnThis();
|
||||
controller.classificationId = 1;
|
||||
$httpBackend.expect('PATCH', `CreditClassifications/1`).respond(200);
|
||||
controller.returnDialog();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller._getClassifications).toHaveBeenCalledWith(1101);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,4 +0,0 @@
|
|||
Contract credit insurance: Contratos de seguro de crédito
|
||||
Close contract: Cerrar contrato
|
||||
View credits: Ver créditos
|
||||
Are you sure you want to close this contract?: ¿Seguro que quieres cerrar este contrato?
|
|
@ -1,5 +0,0 @@
|
|||
vn-client-credit-insurance-index{
|
||||
.insurance:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="CreditClassifications/{{$ctrl.$params.classificationId}}/insurances"
|
||||
data="$ctrl.insurance"
|
||||
insert-mode="true"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
min="0"
|
||||
label="Credit"
|
||||
ng-model="$ctrl.insurance.credit"
|
||||
rule="CreditInsurance"
|
||||
vn-focus>
|
||||
</vn-input-number>
|
||||
<vn-date-picker
|
||||
label="Date"
|
||||
ng-model="$ctrl.insurance.created">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
min="0"
|
||||
step="1"
|
||||
label="Grade"
|
||||
ng-model="$ctrl.insurance.grade"
|
||||
rule="CreditInsurance">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
<vn-button
|
||||
label="Cancel"
|
||||
ui-sref="client.card.creditInsurance.insurance.index({classificationId: $ctrl.$params.classificationId})">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,33 +0,0 @@
|
|||
import ngModule from '../../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.insurance = {
|
||||
created: this.$filter('date')(Date.vnNew(), 'yyyy-MM-dd HH:mm:ss')
|
||||
};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
let params = {classificationId: this.$params.classificationId};
|
||||
let state = 'client.card.creditInsurance.insurance.index';
|
||||
|
||||
this.$.watcher.submitGo(state, params).then(() => {
|
||||
this.card.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientCreditInsuranceInsuranceCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
require: {
|
||||
card: '^vnClientCard'
|
||||
},
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,40 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="CreditInsurances"
|
||||
link="{creditClassificationFk: $ctrl.$params.classificationId}"
|
||||
limit="20"
|
||||
data="insurances"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<div class="vn-w-xs">
|
||||
<vn-data-viewer model="model">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th>Created</vn-th>
|
||||
<vn-th number>Grade</vn-th>
|
||||
<vn-th number>Credit</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="insurance in insurances">
|
||||
<vn-td>{{::insurance.created | date: 'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td number>{{::insurance.grade}}</vn-td>
|
||||
<vn-td number>{{::insurance.credit | currency: 'EUR': 2}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<a
|
||||
ng-if="!$ctrl.isClosed"
|
||||
vn-acl="insurance"
|
||||
vn-acl-action="remove"
|
||||
ui-sref="client.card.creditInsurance.insurance.create({classificationId: {{$ctrl.$params.classificationId}}})"
|
||||
fixed-bottom-right
|
||||
vn-tooltip="New credit"
|
||||
vn-bind="+">
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -1,38 +0,0 @@
|
|||
import ngModule from '../../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.isClosed = true;
|
||||
this.filter = {
|
||||
include: [
|
||||
{relation: 'classification'}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
let filter = {
|
||||
fields: ['finished'],
|
||||
where: {id: this.$params.classificationId}
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let query = `CreditClassifications?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.isClosed = res.data[0].finished != null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientCreditInsuranceInsuranceIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreditInsuranceInsuranceIndex', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
const $element = angular.element('<vn-client-credit-insurance-insurance-index></vn-client-credit-insurance-insurance-index>');
|
||||
controller = $componentController('vnClientCreditInsuranceInsuranceIndex', {$element, $scope});
|
||||
controller.$params = {classificationId: 1};
|
||||
}));
|
||||
|
||||
describe('$onInit()', () => {
|
||||
it('should perform a query to GET credit the credit classification', () => {
|
||||
let res = [{finished: 'some value'}];
|
||||
let query = 'CreditClassifications?filter=%7B%22fields%22%3A%5B%22finished%22%5D%2C%22where%22%3A%7B%22id%22%3A1%7D%7D';
|
||||
|
||||
$httpBackend.whenGET(query).respond(res);
|
||||
$httpBackend.expectGET(query);
|
||||
controller.$onInit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.isClosed).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1 +0,0 @@
|
|||
Created: Creado
|
|
@ -1,79 +0,0 @@
|
|||
<mg-ajax path="Clients/{{post.params.id}}/setRating" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="Clients"
|
||||
data="$ctrl.client"
|
||||
id-value="$ctrl.$params.id"
|
||||
insert-mode="true"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
label="Rating"
|
||||
ng-model="$ctrl.client.rating"
|
||||
vn-focus
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
label="Recommended credit"
|
||||
ng-model="$ctrl.client.recommendedCredit"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="ClientInformas"
|
||||
filter="$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$params.id}"
|
||||
limit="20"
|
||||
data="clientInformas"
|
||||
order="created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model" class="vn-mt-lg">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th shrink-date field="created">Since</vn-th>
|
||||
<vn-th field="workerFk">Employee</vn-th>
|
||||
<vn-th field="rating" number>Rating</vn-th>
|
||||
<vn-th field="recommendedCredit" number>Recommended credit</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="clientInforma in clientInformas">
|
||||
<vn-td shrink-datetime>{{::clientInforma.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<span
|
||||
ng-click="workerDescriptor.show($event, clientInforma.workerFk)"
|
||||
class="link">
|
||||
{{::clientInforma.worker.user.nickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>{{::clientInforma.rating}}</vn-td>
|
||||
<vn-td number>{{::clientInforma.recommendedCredit | currency: 'EUR'}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
|
@ -1,32 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.filter = {
|
||||
include: [{
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
fields: ['id'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['nickname']
|
||||
}
|
||||
}
|
||||
}
|
||||
}],
|
||||
};
|
||||
}
|
||||
onSubmit() {
|
||||
this.$.watcher.submit()
|
||||
.then(() => this.$state.reload());
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientCreditManagement', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,2 +0,0 @@
|
|||
Recommended credit: Crédito recomendado
|
||||
Rating: Clasificación
|
|
@ -1,37 +0,0 @@
|
|||
<mg-ajax path="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.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
min="0"
|
||||
label="Credit"
|
||||
ng-model="$ctrl.client.credit"
|
||||
vn-focus
|
||||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
ng-if="watcher.dataChanged()"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
ng-click="$ctrl.cancel()"
|
||||
label="Cancel">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<vn-confirm
|
||||
vn-id="confirmation"
|
||||
on-accept="$ctrl.returnDialog()"
|
||||
question="Esta modificación retrasará el plazo del próximo recobro"
|
||||
message="¿Desea continuar?">
|
||||
</vn-confirm>
|
|
@ -1,42 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
onSubmit() {
|
||||
this.$http.get(`Recoveries/${this.$params.id}/hasActiveRecovery`).then(res => {
|
||||
let activeRecovery = res.data;
|
||||
if (activeRecovery)
|
||||
this.$.confirmation.show();
|
||||
else
|
||||
this.addCredit();
|
||||
});
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.goToIndex();
|
||||
}
|
||||
|
||||
returnDialog() {
|
||||
this.addCredit();
|
||||
}
|
||||
|
||||
goToIndex() {
|
||||
this.$state.go('client.card.credit.index');
|
||||
}
|
||||
|
||||
addCredit() {
|
||||
this.$.watcher.submit().then(
|
||||
() => {
|
||||
this.goToIndex();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientCreditCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,94 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreditCreate', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $state;
|
||||
let $scope;
|
||||
let client;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, $rootScope, _$state_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$scope.confirmation = {show: () => {
|
||||
return {
|
||||
then: () => {}
|
||||
};
|
||||
}};
|
||||
$scope.watcher = {
|
||||
submit: () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
client = {credit: 0};
|
||||
$state = _$state_;
|
||||
$state.params.id = 1101;
|
||||
$httpBackend = _$httpBackend_;
|
||||
const $element = angular.element('<vn-client-credit-create></vn-client-credit-create>');
|
||||
controller = $componentController('vnClientCreditCreate', {$element, $scope});
|
||||
}));
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('should perform a query to check (GET) if the client has an active recovery', () => {
|
||||
$httpBackend.whenGET(`Recoveries/1101/hasActiveRecovery`).respond(true);
|
||||
$httpBackend.expectGET(`Recoveries/1101/hasActiveRecovery`);
|
||||
controller.onSubmit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should call show() method when the client have a recovery', () => {
|
||||
jest.spyOn(controller.$.confirmation, 'show');
|
||||
$httpBackend.whenGET(`Recoveries/1101/hasActiveRecovery`).respond(true);
|
||||
$httpBackend.expectGET(`Recoveries/1101/hasActiveRecovery`);
|
||||
controller.onSubmit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.confirmation.show).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should call addCredit() method when the client doesnt have a recovery', () => {
|
||||
jest.spyOn(controller, 'addCredit');
|
||||
$httpBackend.whenGET(`Recoveries/1101/hasActiveRecovery`).respond(false);
|
||||
$httpBackend.expectGET(`Recoveries/1101/hasActiveRecovery`);
|
||||
controller.onSubmit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.addCredit).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('cancel()', () => {
|
||||
it('should call goToIndex()', () => {
|
||||
jest.spyOn(controller, 'goToIndex');
|
||||
controller.cancel();
|
||||
|
||||
expect(controller.goToIndex).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('returnDialog()', () => {
|
||||
it('should call addCredit() when is called with accept', () => {
|
||||
jest.spyOn(controller, 'addCredit');
|
||||
controller.returnDialog();
|
||||
|
||||
expect(controller.addCredit).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('addCredit()', () => {
|
||||
it('should call the function go() on $state to go to the credit list', () => {
|
||||
jest.spyOn($state, 'go');
|
||||
client.credit = 1;
|
||||
controller.addCredit();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('client.card.credit.index');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="ClientCredits"
|
||||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$params.id}"
|
||||
limit="20"
|
||||
data="credits"
|
||||
order="created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="created">Since</vn-th>
|
||||
<vn-th field="workerFk">Employee</vn-th>
|
||||
<vn-th field="amount" number>Credit</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="credit in credits track by credit.id">
|
||||
<vn-td shrink-datetime>{{::credit.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
ng-click="workerDescriptor.show($event, credit.worker.id)"
|
||||
class="link">
|
||||
{{::credit.worker.user.name}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>{{::credit.amount | currency:'EUR':2}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
ui-sref="client.card.credit.create"
|
||||
vn-acl="teamBoss"
|
||||
vn-acl-action="remove"
|
||||
vn-tooltip="New credit"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
</vn-float-button>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
|
@ -1,31 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
fields: ['id'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientCreditIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,2 +0,0 @@
|
|||
Since : Desde
|
||||
Employee : Empleado
|
|
@ -1,200 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Defaulters/filter"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
order="amount DESC"
|
||||
data="$ctrl.defaulters"
|
||||
on-data-change="$ctrl.reCheck()"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
vn-focus
|
||||
placeholder="Search client"
|
||||
info="Search client by id or name"
|
||||
auto-state="false"
|
||||
model="model">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-card>
|
||||
<smart-table
|
||||
model="model"
|
||||
options="$ctrl.smartTableOptions"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-actions>
|
||||
<div>
|
||||
<div class="totalBox" style="text-align: center;">
|
||||
<h6 translate>Total</h6>
|
||||
<vn-label-value
|
||||
label="Balance due"
|
||||
value="{{$ctrl.balanceDueTotal | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vn-pa-md">
|
||||
<vn-button
|
||||
disabled="$ctrl.checked.length == 0"
|
||||
ng-click="notesDialog.show()"
|
||||
name="notesDialog"
|
||||
vn-tooltip="Add observation"
|
||||
icon="icon-notes">
|
||||
</vn-button>
|
||||
</div>
|
||||
</slot-actions>
|
||||
<slot-table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th shrink>
|
||||
<vn-multi-check
|
||||
model="model">
|
||||
</vn-multi-check>
|
||||
</th>
|
||||
<th field="clientFk">
|
||||
<span translate>Client</span>
|
||||
</th>
|
||||
<th>
|
||||
<span translate>Es trabajador</span>
|
||||
</th>
|
||||
<th field="salesPersonFk">
|
||||
<span translate>Comercial</span>
|
||||
</th>
|
||||
<th field="countryFk">
|
||||
<span translate>Country</span>
|
||||
</th>
|
||||
<th field="payMethod"
|
||||
vn-tooltip="Pay Method">
|
||||
<span translate>P.Method</span>
|
||||
</th>
|
||||
<th
|
||||
field="amount"
|
||||
vn-tooltip="Balance due">
|
||||
<span translate>Balance D.</span>
|
||||
</th>
|
||||
<th
|
||||
field="workerFk"
|
||||
vn-tooltip="Worker who made the last observation">
|
||||
<span translate>Author</span>
|
||||
</th>
|
||||
<th field="observation" expand>
|
||||
<span translate>Last observation</span>
|
||||
</th>
|
||||
<th
|
||||
vn-tooltip="Last observation date"
|
||||
field="created">
|
||||
<span translate>L. O. Date</span>
|
||||
</th>
|
||||
<th
|
||||
vn-tooltip="Credit insurance"
|
||||
field="creditInsurance"
|
||||
shrink>
|
||||
<span translate>Credit I.</span>
|
||||
</th>
|
||||
<th field="defaulterSinced">
|
||||
<span translate>From</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="defaulter in $ctrl.defaulters">
|
||||
<td shrink>
|
||||
<vn-check
|
||||
ng-model="defaulter.checked"
|
||||
on-change="$ctrl.saveChecked(defaulter.clientFk)"
|
||||
vn-click-stop>
|
||||
</vn-check>
|
||||
</td>
|
||||
<td title="{{::defaulter.clientName}}">
|
||||
<span
|
||||
vn-click-stop="clientDescriptor.show($event, defaulter.clientFk)"
|
||||
title ="{{::defaulter.clientName}}"
|
||||
class="link">
|
||||
{{::defaulter.clientName}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<vn-check
|
||||
ng-model="defaulter.isWorker"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
title="{{::defaulter.salesPersonName}}"
|
||||
vn-click-stop="workerDescriptor.show($event, defaulter.salesPersonFk)"
|
||||
class="link">
|
||||
{{::defaulter.salesPersonName | dashIfEmpty}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{{::defaulter.country}}
|
||||
</td>
|
||||
<td>
|
||||
{{::defaulter.payMethod}}
|
||||
</td>
|
||||
<td>{{::defaulter.amount | currency: 'EUR': 2}}</td>
|
||||
<td>
|
||||
<span
|
||||
title="{{::defaulter.workerName}}"
|
||||
vn-click-stop="workerDescriptor.show($event, defaulter.workerFk)"
|
||||
class="link">
|
||||
{{::defaulter.workerName | dashIfEmpty}}
|
||||
</span>
|
||||
</td>
|
||||
<td expand>
|
||||
<vn-textarea
|
||||
vn-three
|
||||
disabled="true"
|
||||
ng-model="defaulter.observation">
|
||||
</vn-textarea>
|
||||
</td>
|
||||
<td shrink-date>
|
||||
<span class="chip {{::$ctrl.chipColor(defaulter.created)}}">
|
||||
{{::defaulter.created | date: 'dd/MM/yyyy'}}
|
||||
</span>
|
||||
</td>
|
||||
<td shrink>{{::defaulter.creditInsurance | currency: 'EUR': 2}}</td>
|
||||
<td shrink-date>{{::defaulter.defaulterSinced | date: 'dd/MM/yyyy'}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</slot-table>
|
||||
</smart-table>
|
||||
</vn-card>
|
||||
<vn-client-descriptor-popover
|
||||
vn-id="client-descriptor">
|
||||
</vn-client-descriptor-popover>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="worker-descriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-popup vn-id="dialog-summary-client">
|
||||
<vn-client-summary
|
||||
client="$ctrl.clientSelected">
|
||||
</vn-client-summary>
|
||||
</vn-popup>
|
||||
|
||||
<!-- Dialog of add notes button -->
|
||||
<vn-dialog
|
||||
vn-id="notesDialog"
|
||||
on-accept="$ctrl.onResponse()">
|
||||
<tpl-body>
|
||||
<section class="SMSDialog">
|
||||
<h5 class="vn-py-sm">{{$ctrl.$t('Add observation to all selected clients', {total: $ctrl.checked.length})}}</h5>
|
||||
<vn-horizontal>
|
||||
<vn-textarea vn-one
|
||||
vn-id="message"
|
||||
label="Message"
|
||||
ng-model="$ctrl.defaulter.observation"
|
||||
rows="3"
|
||||
required="true"
|
||||
rule>
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
</section>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Save</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -1,199 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import UserError from 'core/lib/user-error';
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.defaulter = {};
|
||||
this.defaulters = [];
|
||||
this.checkedDefaulers = [];
|
||||
|
||||
this.smartTableOptions = {
|
||||
activeButtons: {
|
||||
search: true
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'clientFk',
|
||||
autocomplete: {
|
||||
url: 'Clients',
|
||||
showField: 'name',
|
||||
valueField: 'id'
|
||||
}
|
||||
}, {
|
||||
field: 'salesPersonFk',
|
||||
autocomplete: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
where: `{role: 'salesPerson'}`,
|
||||
searchFunction: '{firstName: $search}',
|
||||
showField: 'name',
|
||||
valueField: 'id',
|
||||
}
|
||||
}, {
|
||||
field: 'countryFk',
|
||||
autocomplete: {
|
||||
url: 'Countries',
|
||||
showField: 'country',
|
||||
valueField: 'id'
|
||||
}
|
||||
}, {
|
||||
field: 'payMethodFk',
|
||||
autocomplete: {
|
||||
showField: 'name',
|
||||
valueField: 'id'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'workerFk',
|
||||
autocomplete: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
searchFunction: '{firstName: $search}',
|
||||
showField: 'name',
|
||||
valueField: 'id',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'observation',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
field: 'created',
|
||||
datepicker: true
|
||||
},
|
||||
{
|
||||
field: 'defaulterSinced',
|
||||
datepicker: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.getBalanceDueTotal();
|
||||
}
|
||||
|
||||
set defaulters(value) {
|
||||
if (!value || !value.length) return;
|
||||
for (let defaulter of value)
|
||||
defaulter.isWorker = defaulter.businessTypeFk === 'worker';
|
||||
|
||||
this._defaulters = value;
|
||||
}
|
||||
|
||||
get defaulters() {
|
||||
return this._defaulters;
|
||||
}
|
||||
|
||||
get checked() {
|
||||
const clients = this.$.model.data || [];
|
||||
const checkedLines = [];
|
||||
for (let defaulter of clients) {
|
||||
if (defaulter.checked)
|
||||
checkedLines.push(defaulter);
|
||||
}
|
||||
|
||||
return checkedLines;
|
||||
}
|
||||
|
||||
saveChecked(clientId) {
|
||||
this.checkedDefaulers = this.checkedDefaulers.includes(clientId) ?
|
||||
this.checkedDefaulers.filter(id => id !== clientId) : [...this.checkedDefaulers, clientId];
|
||||
}
|
||||
|
||||
reCheck() {
|
||||
if (!this.$.model.data || !this.checkedDefaulers.length) return;
|
||||
|
||||
this.$.model.data.forEach(defaulter => {
|
||||
defaulter.checked = this.checkedDefaulers.includes(defaulter.clientFk);
|
||||
});
|
||||
}
|
||||
|
||||
getBalanceDueTotal() {
|
||||
this.$http.get('Defaulters/filter')
|
||||
.then(res => {
|
||||
if (!res.data) return 0;
|
||||
|
||||
this.balanceDueTotal = res.data.reduce(
|
||||
(accumulator, currentValue) => {
|
||||
return accumulator + (currentValue['amount'] || 0);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
chipColor(date) {
|
||||
const day = 24 * 60 * 60 * 1000;
|
||||
const today = Date.vnNew();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const observationShipped = new Date(date);
|
||||
observationShipped.setHours(0, 0, 0, 0);
|
||||
|
||||
const difference = today - observationShipped;
|
||||
|
||||
if (difference > (day * 20))
|
||||
return 'alert';
|
||||
if (difference > (day * 10))
|
||||
return 'warning';
|
||||
}
|
||||
|
||||
onResponse() {
|
||||
if (!this.defaulter.observation)
|
||||
throw new UserError(`The message can't be empty`);
|
||||
|
||||
const params = [];
|
||||
for (let defaulter of this.checked) {
|
||||
params.push({
|
||||
text: this.defaulter.observation,
|
||||
clientFk: defaulter.clientFk
|
||||
});
|
||||
}
|
||||
|
||||
this.$http.post(`ClientObservations`, params) .then(() => {
|
||||
this.vnApp.showSuccess(this.$t('Observation saved!'));
|
||||
this.sendMail();
|
||||
this.$state.reload();
|
||||
});
|
||||
}
|
||||
|
||||
sendMail() {
|
||||
const params = {
|
||||
defaulters: this.checked,
|
||||
observation: this.defaulter.observation,
|
||||
};
|
||||
this.$http.post(`Defaulters/observationEmail`, params);
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'creditInsurance':
|
||||
case 'amount':
|
||||
case 'clientFk':
|
||||
case 'workerFk':
|
||||
case 'countryFk':
|
||||
case 'payMethod':
|
||||
case 'salesPersonFk':
|
||||
return {[`d.${param}`]: value};
|
||||
case 'created':
|
||||
return {'d.created': {
|
||||
between: this.dateRange(value)}
|
||||
};
|
||||
case 'defaulterSinced':
|
||||
return {'d.defaulterSinced': {
|
||||
between: this.dateRange(value)}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
dateRange(value) {
|
||||
const minHour = new Date(value);
|
||||
minHour.setHours(0, 0, 0, 0);
|
||||
const maxHour = new Date(value);
|
||||
maxHour.setHours(23, 59, 59, 59);
|
||||
|
||||
return [minHour, maxHour];
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientDefaulter', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,179 +0,0 @@
|
|||
import './index';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('client defaulter', () => {
|
||||
describe('Component vnClientDefaulter', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
const $element = angular.element('<vn-client-defaulter></vn-client-defaulter>');
|
||||
controller = $componentController('vnClientDefaulter', {$element});
|
||||
controller.$.model = crudModel;
|
||||
controller.$.model.data = [
|
||||
{clientFk: 1101, amount: 125},
|
||||
{clientFk: 1102, amount: 500},
|
||||
{clientFk: 1103, amount: 250}
|
||||
];
|
||||
}));
|
||||
|
||||
describe('checked() getter', () => {
|
||||
it('should return the checked lines', () => {
|
||||
const data = controller.$.model.data;
|
||||
data[1].checked = true;
|
||||
data[2].checked = true;
|
||||
|
||||
const checkedRows = controller.checked;
|
||||
|
||||
const firstCheckedRow = checkedRows[0];
|
||||
const secondCheckedRow = checkedRows[1];
|
||||
|
||||
expect(firstCheckedRow.clientFk).toEqual(1102);
|
||||
expect(secondCheckedRow.clientFk).toEqual(1103);
|
||||
});
|
||||
});
|
||||
|
||||
describe('chipColor()', () => {
|
||||
it('should return undefined when the date is the present', () => {
|
||||
let today = Date.vnNew();
|
||||
let result = controller.chipColor(today);
|
||||
|
||||
expect(result).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should return warning when the date is 10 days in the past', () => {
|
||||
let pastDate = Date.vnNew();
|
||||
pastDate = pastDate.setDate(pastDate.getDate() - 11);
|
||||
let result = controller.chipColor(pastDate);
|
||||
|
||||
expect(result).toEqual('warning');
|
||||
});
|
||||
|
||||
it('should return alert when the date is 20 days in the past', () => {
|
||||
let pastDate = Date.vnNew();
|
||||
pastDate = pastDate.setDate(pastDate.getDate() - 21);
|
||||
let result = controller.chipColor(pastDate);
|
||||
|
||||
expect(result).toEqual('alert');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onResponse()', () => {
|
||||
it('should return error for empty message', () => {
|
||||
let error;
|
||||
try {
|
||||
controller.onResponse();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toBe(`The message can't be empty`);
|
||||
});
|
||||
|
||||
it('should return saved message', () => {
|
||||
const data = controller.$.model.data;
|
||||
data[1].checked = true;
|
||||
controller.defaulter = {observation: 'My new observation'};
|
||||
|
||||
const params = [{text: controller.defaulter.observation, clientFk: data[1].clientFk}];
|
||||
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
$httpBackend.expect('GET', `Defaulters/filter`).respond(200);
|
||||
$httpBackend.expect('POST', `ClientObservations`, params).respond(200, params);
|
||||
$httpBackend.expect('POST', `Defaulters/observationEmail`).respond(200);
|
||||
|
||||
controller.onResponse();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Observation saved!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('exprBuilder()', () => {
|
||||
it('should search by sales person', () => {
|
||||
const expr = controller.exprBuilder('salesPersonFk', '5');
|
||||
|
||||
expect(expr).toEqual({'d.salesPersonFk': '5'});
|
||||
});
|
||||
|
||||
it('should search by client', () => {
|
||||
const expr = controller.exprBuilder('clientFk', '5');
|
||||
|
||||
expect(expr).toEqual({'d.clientFk': '5'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalanceDueTotal()', () => {
|
||||
it('should return balance due total', () => {
|
||||
const defaulters = controller.$.model.data;
|
||||
$httpBackend.when('GET', `Defaulters/filter`).respond(defaulters);
|
||||
|
||||
controller.getBalanceDueTotal();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.balanceDueTotal).toEqual(875);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dateRange()', () => {
|
||||
it('should return two dates with the hours at the start and end of the given date', () => {
|
||||
const now = Date.vnNew();
|
||||
|
||||
const today = now.getDate();
|
||||
|
||||
const dateRange = controller.dateRange(now);
|
||||
const start = dateRange[0].toString();
|
||||
const end = dateRange[1].toString();
|
||||
|
||||
expect(start).toContain(today);
|
||||
expect(start).toContain('00:00:00');
|
||||
|
||||
expect(end).toContain(today);
|
||||
expect(end).toContain('23:59:59');
|
||||
});
|
||||
});
|
||||
|
||||
describe('reCheck()', () => {
|
||||
it(`should recheck buys`, () => {
|
||||
controller.$.model.data = [
|
||||
{checked: false, clientFk: 1},
|
||||
{checked: false, clientFk: 2},
|
||||
{checked: false, clientFk: 3},
|
||||
{checked: false, clientFk: 4},
|
||||
];
|
||||
controller.checkedDefaulers = [1, 2];
|
||||
|
||||
controller.reCheck();
|
||||
|
||||
expect(controller.$.model.data[0].checked).toEqual(true);
|
||||
expect(controller.$.model.data[1].checked).toEqual(true);
|
||||
expect(controller.$.model.data[2].checked).toEqual(false);
|
||||
expect(controller.$.model.data[3].checked).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('saveChecked()', () => {
|
||||
it(`should check buy`, () => {
|
||||
const buyCheck = 3;
|
||||
controller.checkedDefaulers = [1, 2];
|
||||
|
||||
controller.saveChecked(buyCheck);
|
||||
|
||||
expect(controller.checkedDefaulers[2]).toEqual(buyCheck);
|
||||
});
|
||||
|
||||
it(`should uncheck buy`, () => {
|
||||
const buyUncheck = 3;
|
||||
controller.checkedDefaulers = [1, 2, 3];
|
||||
|
||||
controller.saveChecked(buyUncheck);
|
||||
|
||||
expect(controller.checkedDefaulers[2]).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
Add observation: Añadir observación
|
||||
Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s)
|
||||
Balance D.: Saldo V.
|
||||
Credit I.: Crédito A.
|
||||
Last observation: Última observación
|
||||
L. O. Date: Fecha Ú. O.
|
||||
Last observation date: Fecha última observación
|
||||
Search client: Buscar clientes
|
||||
Worker who made the last observation: Trabajador que ha realizado la última observación
|
||||
Email sended!: Email enviado!
|
||||
Observation saved!: Observación añadida!
|
||||
P.Method: F.Pago
|
||||
Pay Method: Forma de Pago
|
||||
Country: Pais
|
|
@ -1,3 +0,0 @@
|
|||
<slot-descriptor>
|
||||
<vn-client-descriptor></vn-client-descriptor>
|
||||
</slot-descriptor>
|
|
@ -1,9 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import DescriptorPopover from 'salix/components/descriptor-popover';
|
||||
|
||||
class Controller extends DescriptorPopover {}
|
||||
|
||||
ngModule.vnComponent('vnClientDescriptorPopover', {
|
||||
slotTemplate: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,136 +0,0 @@
|
|||
<vn-descriptor-content
|
||||
module="client"
|
||||
description="$ctrl.client.name"
|
||||
summary="$ctrl.$.summary">
|
||||
<slot-menu>
|
||||
<a class="vn-item"
|
||||
ui-sref="ticket.create({clientFk: $ctrl.client.id})"
|
||||
name="simpleTicket"
|
||||
translate>
|
||||
Simple ticket
|
||||
</a>
|
||||
<vn-item
|
||||
ng-click="$ctrl.showSMSDialog()"
|
||||
translate>
|
||||
Send SMS
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
<slot-body>
|
||||
<div class="attributes">
|
||||
<vn-label-value
|
||||
label="Pay method"
|
||||
value="{{$ctrl.client.payMethod.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Credit"
|
||||
value="{{$ctrl.client.credit | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Secured credit"
|
||||
value="{{$ctrl.client.creditInsurance | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Risk"
|
||||
value="{{$ctrl.client.debt | currency: 'EUR':2}}"
|
||||
ng-class="{alert: $ctrl.client.debt > $ctrl.client.credit}"
|
||||
info="Invoices minus payments plus orders not yet invoiced">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Sales person">
|
||||
<span
|
||||
ng-click="workerDescriptor.show($event, $ctrl.client.salesPersonFk)"
|
||||
class="link">
|
||||
{{$ctrl.client.salesPersonUser.name}}
|
||||
</span>
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Business type"
|
||||
value="{{$ctrl.client.businessType.description}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
<div class="icons">
|
||||
<vn-icon
|
||||
vn-tooltip="Client inactive"
|
||||
icon="icon-disabled"
|
||||
ng-if="$ctrl.client.isActive == false">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client frozen"
|
||||
icon="icon-frozen"
|
||||
ng-if="$ctrl.client.isFreezed == true">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Web Account inactive"
|
||||
icon="icon-noweb"
|
||||
ng-if="$ctrl.client.account.active == false">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client has debt"
|
||||
icon="icon-risk"
|
||||
ng-if="$ctrl.client.debt > $ctrl.client.credit">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client not checked"
|
||||
icon="icon-no036"
|
||||
ng-if="$ctrl.client.isTaxDataChecked == false">
|
||||
</vn-icon>
|
||||
<vn-icon-button
|
||||
vn-tooltip="{{$ctrl.clientUnpaid()}}"
|
||||
icon="icon-clientUnpaid"
|
||||
ui-sref="client.card.unpaid"
|
||||
ng-if="$ctrl.client.unpaid">
|
||||
</vn-icon-button>
|
||||
</div>
|
||||
<div class="quicklinks">
|
||||
<div ng-transclude="btnOne">
|
||||
<vn-quick-link
|
||||
tooltip="Client ticket list"
|
||||
state="['ticket.index', {q: $ctrl.filter}]"
|
||||
icon="icon-ticket">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnTwo">
|
||||
<vn-quick-link
|
||||
tooltip="Client invoices list"
|
||||
state="['invoiceOut.index', {q: $ctrl.filter}]"
|
||||
icon="icon-invoice">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnThree">
|
||||
<vn-quick-link
|
||||
tooltip="New order"
|
||||
state="['order.create', {clientFk: $ctrl.id}]"
|
||||
icon="icon-basketadd">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnFour">
|
||||
<vn-quick-link
|
||||
vn-acl="hr"
|
||||
vn-acl-action="remove"
|
||||
tooltip="Go to user"
|
||||
state="['account.card.summary', {id: $ctrl.id}]"
|
||||
icon="face">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnFive">
|
||||
<vn-quick-link
|
||||
ng-if="$ctrl.client.supplier.nif"
|
||||
tooltip="Go to supplier"
|
||||
state="['supplier.card.summary', {id: $ctrl.client.supplier.id}]"
|
||||
icon="icon-supplier">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
</div>
|
||||
</slot-body>
|
||||
</vn-descriptor-content>
|
||||
<vn-sms-dialog
|
||||
vn-id="sms"
|
||||
on-send="$ctrl.onSmsSend($sms)"
|
||||
sms="$ctrl.newSMS">
|
||||
</vn-sms-dialog>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-client-summary client="$ctrl.client"></vn-client-summary>
|
||||
</vn-popup>
|
|
@ -1,61 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Descriptor from 'salix/components/descriptor';
|
||||
|
||||
class Controller extends Descriptor {
|
||||
get entity() {
|
||||
return super.entity;
|
||||
}
|
||||
|
||||
set entity(value) {
|
||||
super.entity = value;
|
||||
|
||||
if (value && this.$params.sendSMS)
|
||||
this.showSMSDialog();
|
||||
}
|
||||
|
||||
get client() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
set client(value) {
|
||||
this.entity = value;
|
||||
}
|
||||
|
||||
get filter() {
|
||||
return JSON.stringify({clientFk: this.id});
|
||||
}
|
||||
|
||||
loadData() {
|
||||
return this.getData(`Clients/${this.id}/getCard`)
|
||||
.then(res => this.entity = res.data);
|
||||
}
|
||||
|
||||
showSMSDialog() {
|
||||
const client = this.client || {};
|
||||
this.newSMS = {
|
||||
destinationFk: this.id,
|
||||
destination: this.$params.phone || client.mobile || client.phone,
|
||||
message: this.$params.message || ''
|
||||
};
|
||||
this.$.sms.open();
|
||||
}
|
||||
|
||||
onSmsSend(sms) {
|
||||
return this.$http.post(`Clients/${this.id}/sendSms`, sms)
|
||||
.then(() => this.vnApp.showSuccess(this.$t('SMS sent')));
|
||||
}
|
||||
|
||||
clientUnpaid() {
|
||||
return this.$t(`Unpaid`) + '<br/>'
|
||||
+ this.$t(`Unpaid Dated`, {dated: this.client.unpaid.dated}) + '<br/>'
|
||||
+ this.$t(`Unpaid Amount`, {amount: this.client.unpaid.amount});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientDescriptor', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('vnClientDescriptor', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnClientDescriptor', {$element: null});
|
||||
}));
|
||||
|
||||
describe('loadData()', () => {
|
||||
it(`should perform a get query to store the client data into the controller`, () => {
|
||||
const id = 1;
|
||||
const response = 'foo';
|
||||
|
||||
$httpBackend.expectGET(`Clients/${id}/getCard`).respond(response);
|
||||
controller.id = id;
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.client).toEqual(response);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
Simple ticket: Ticket simple
|
||||
View consumer report: Ver informe de consumo
|
||||
From date: Fecha desde
|
||||
To date: Fecha hasta
|
||||
Go to user: Ir al usuario
|
||||
Go to supplier: Ir al proveedor
|
||||
Client invoices list: Listado de facturas del cliente
|
||||
Pay method: Forma de pago
|
||||
Unpaid Dated: "Fecha: {{dated | date:'dd/MM/yyyy'}}"
|
||||
Unpaid Amount: "Importe: {{amount | currency: 'EUR':2}}"
|
||||
Business type: Tipo de negocio
|
|
@ -1,108 +0,0 @@
|
|||
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.dms">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Companies"
|
||||
data="companies"
|
||||
order="code">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Warehouses"
|
||||
data="warehouses"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="DmsTypes"
|
||||
data="dmsTypes"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<form
|
||||
name="form"
|
||||
ng-submit="$ctrl.onSubmit()"
|
||||
class="vn-ma-md"
|
||||
enctype="multipart/form-data">
|
||||
<div class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
vn-focus
|
||||
label="Reference"
|
||||
ng-model="$ctrl.dms.reference"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
label="Company"
|
||||
ng-model="$ctrl.dms.companyId"
|
||||
data="companies"
|
||||
show-field="code"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
label="Warehouse"
|
||||
ng-model="$ctrl.dms.warehouseId"
|
||||
data="warehouses"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
label="Type"
|
||||
ng-model="$ctrl.dms.dmsTypeId"
|
||||
data="dmsTypes"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textarea
|
||||
vn-one
|
||||
label="Description"
|
||||
ng-model="$ctrl.dms.description"
|
||||
rule>
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-file
|
||||
vn-one
|
||||
label="File"
|
||||
ng-model="$ctrl.dms.files"
|
||||
on-change="$ctrl.onFileChange($files)"
|
||||
accept="{{$ctrl.allowedContentTypes}}"
|
||||
required="true"
|
||||
multiple="true">
|
||||
<append>
|
||||
<vn-icon vn-none
|
||||
color-marginal
|
||||
title="{{$ctrl.contentTypesInfo}}"
|
||||
icon="info">
|
||||
</vn-icon>
|
||||
</append>
|
||||
</vn-input-file>
|
||||
</vn-horizontal>
|
||||
<vn-vertical>
|
||||
<vn-check
|
||||
label="Generate identifier for original file"
|
||||
ng-model="$ctrl.dms.hasFile">
|
||||
</vn-check>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Upload">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Cancel"
|
||||
ui-sref="client.card.dms.index">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
|
@ -1,113 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.dms = {
|
||||
files: [],
|
||||
hasFile: false,
|
||||
hasFileAttached: false
|
||||
};
|
||||
}
|
||||
|
||||
get client() {
|
||||
return this._client;
|
||||
}
|
||||
|
||||
set client(value) {
|
||||
this._client = value;
|
||||
|
||||
if (value) {
|
||||
this.setDefaultParams();
|
||||
this.getAllowedContentTypes();
|
||||
}
|
||||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
}
|
||||
|
||||
get contentTypesInfo() {
|
||||
return this.$t('ContentTypesInfo', {
|
||||
allowedContentTypes: this.allowedContentTypes
|
||||
});
|
||||
}
|
||||
|
||||
setDefaultParams() {
|
||||
const params = {filter: {
|
||||
where: {code: 'paymentsLaw'}
|
||||
}};
|
||||
this.$http.get('DmsTypes/findOne', {params}).then(res => {
|
||||
const dmsType = res.data && res.data;
|
||||
const companyId = this.vnConfig.companyFk;
|
||||
const warehouseId = this.vnConfig.warehouseFk;
|
||||
const defaultParams = {
|
||||
reference: this.client.id,
|
||||
warehouseId: warehouseId,
|
||||
companyId: companyId,
|
||||
dmsTypeId: dmsType.id,
|
||||
description: this.$t('ClientFileDescription', {
|
||||
dmsTypeName: dmsType.name,
|
||||
clientId: this.client.id,
|
||||
clientName: this.client.name
|
||||
}).toUpperCase()
|
||||
};
|
||||
|
||||
this.dms = Object.assign(this.dms, defaultParams);
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
const query = `clients/${this.client.id}/uploadFile`;
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: query,
|
||||
params: this.dms,
|
||||
headers: {
|
||||
'Content-Type': undefined
|
||||
},
|
||||
transformRequest: files => {
|
||||
const formData = new FormData();
|
||||
|
||||
for (let i = 0; i < files.length; i++)
|
||||
formData.append(files[i].name, files[i]);
|
||||
|
||||
return formData;
|
||||
},
|
||||
data: this.dms.files
|
||||
};
|
||||
this.$http(options).then(res => {
|
||||
if (res) {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.$.watcher.updateOriginalData();
|
||||
this.$state.go('client.card.dms.index');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onFileChange(files) {
|
||||
let hasFileAttached = false;
|
||||
|
||||
if (files.length > 0)
|
||||
hasFileAttached = true;
|
||||
|
||||
this.$.$applyAsync(() => {
|
||||
this.dms.hasFileAttached = hasFileAttached;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnClientDmsCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,74 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientDmsCreate', () => {
|
||||
let controller;
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
const $element = angular.element('<vn-client-create></vn-client-create>');
|
||||
controller = $componentController('vnClientDmsCreate', {$element, $scope});
|
||||
controller._client = {id: 1101, name: 'Bruce wayne'};
|
||||
}));
|
||||
|
||||
describe('client() setter', () => {
|
||||
it('should set the client data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
||||
jest.spyOn(controller, 'setDefaultParams');
|
||||
jest.spyOn(controller, 'getAllowedContentTypes');
|
||||
controller.client = {
|
||||
id: 15,
|
||||
name: 'Bruce wayne'
|
||||
};
|
||||
|
||||
expect(controller.client).toBeDefined();
|
||||
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
||||
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setDefaultParams()', () => {
|
||||
it('should perform a GET query and define the dms property on controller', () => {
|
||||
const params = {filter: {
|
||||
where: {code: 'paymentsLaw'}
|
||||
}};
|
||||
let serializedParams = $httpParamSerializer(params);
|
||||
$httpBackend.expect('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 12, code: 'paymentsLaw'});
|
||||
controller.setDefaultParams();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.dms).toBeDefined();
|
||||
expect(controller.dms.reference).toEqual(1101);
|
||||
expect(controller.dms.dmsTypeId).toEqual(12);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFileChange()', () => {
|
||||
it('should set dms hasFileAttached property to true if has any files', () => {
|
||||
const files = [{id: 1, name: 'MyFile'}];
|
||||
controller.onFileChange(files);
|
||||
$scope.$apply();
|
||||
|
||||
expect(controller.dms.hasFileAttached).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllowedContentTypes()', () => {
|
||||
it('should make an HTTP GET request to get the allowed content types', () => {
|
||||
const expectedResponse = ['image/png', 'image/jpg'];
|
||||
$httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond(expectedResponse);
|
||||
controller.getAllowedContentTypes();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.allowedContentTypes).toBeDefined();
|
||||
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
vn-ticket-request {
|
||||
.vn-textfield {
|
||||
margin: 0!important;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.dms">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Warehouses"
|
||||
data="warehouses">
|
||||
</vn-crud-model>
|
||||
<form
|
||||
name="form"
|
||||
ng-submit="$ctrl.onSubmit()"
|
||||
class="vn-ma-md"
|
||||
enctype="multipart/form-data">
|
||||
<div class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
vn-focus
|
||||
label="Reference"
|
||||
ng-model="$ctrl.dms.reference"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-autocomplete vn-one required="true"
|
||||
label="Company"
|
||||
ng-model="$ctrl.dms.companyId"
|
||||
url="Companies"
|
||||
show-field="code"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one required="true"
|
||||
label="Warehouse"
|
||||
ng-model="$ctrl.dms.warehouseId"
|
||||
data="warehouses"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one required="true"
|
||||
label="Type"
|
||||
ng-model="$ctrl.dms.dmsTypeId"
|
||||
url="DmsTypes"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textarea
|
||||
vn-one
|
||||
required="true"
|
||||
label="Description"
|
||||
ng-model="$ctrl.dms.description"
|
||||
rule>
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-file
|
||||
vn-one
|
||||
label="File"
|
||||
ng-model="$ctrl.dms.files"
|
||||
on-change="$ctrl.onFileChange($files)"
|
||||
accept="{{$ctrl.allowedContentTypes}}"
|
||||
required="true"
|
||||
multiple="true">
|
||||
<append>
|
||||
<vn-icon vn-none
|
||||
color-marginal
|
||||
title="{{$ctrl.contentTypesInfo}}"
|
||||
icon="info">
|
||||
</vn-icon>
|
||||
</append>
|
||||
</vn-input-file>
|
||||
</vn-horizontal>
|
||||
<vn-vertical>
|
||||
<vn-check disabled="true"
|
||||
label="Generate identifier for original file"
|
||||
ng-model="$ctrl.dms.hasFile">
|
||||
</vn-check>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
<vn-button ui-sref="client.card.dms.index" label="Cancel"></vn-button>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
|
@ -1,94 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
get client() {
|
||||
return this._client;
|
||||
}
|
||||
|
||||
set client(value) {
|
||||
this._client = value;
|
||||
|
||||
if (value) {
|
||||
this.setDefaultParams();
|
||||
this.getAllowedContentTypes();
|
||||
}
|
||||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
}
|
||||
|
||||
get contentTypesInfo() {
|
||||
return this.$t('ContentTypesInfo', {
|
||||
allowedContentTypes: this.allowedContentTypes
|
||||
});
|
||||
}
|
||||
|
||||
setDefaultParams() {
|
||||
const path = `Dms/${this.$params.dmsId}`;
|
||||
this.$http.get(path).then(res => {
|
||||
const dms = res.data && res.data;
|
||||
this.dms = {
|
||||
reference: dms.reference,
|
||||
warehouseId: dms.warehouseFk,
|
||||
companyId: dms.companyFk,
|
||||
dmsTypeId: dms.dmsTypeFk,
|
||||
description: dms.description,
|
||||
hasFile: dms.hasFile,
|
||||
hasFileAttached: false,
|
||||
files: []
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
const query = `dms/${this.$params.dmsId}/updateFile`;
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: query,
|
||||
params: this.dms,
|
||||
headers: {
|
||||
'Content-Type': undefined
|
||||
},
|
||||
transformRequest: files => {
|
||||
const formData = new FormData();
|
||||
|
||||
for (let i = 0; i < files.length; i++)
|
||||
formData.append(files[i].name, files[i]);
|
||||
|
||||
return formData;
|
||||
},
|
||||
data: this.dms.files
|
||||
};
|
||||
this.$http(options).then(res => {
|
||||
if (res) {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.$.watcher.updateOriginalData();
|
||||
this.$state.go('client.card.dms.index');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onFileChange(files) {
|
||||
let hasFileAttached = false;
|
||||
if (files.length > 0)
|
||||
hasFileAttached = true;
|
||||
|
||||
this.$.$applyAsync(() => {
|
||||
this.dms.hasFileAttached = hasFileAttached;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientDmsEdit', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -1,81 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientDmsEdit', () => {
|
||||
let controller;
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
const $element = angular.element('<vn-client-dms-edit></vn-client-dms-edit>');
|
||||
controller = $componentController('vnClientDmsEdit', {$element, $scope});
|
||||
controller._client = {id: 1};
|
||||
controller.$params = {dmsId: 1};
|
||||
}));
|
||||
|
||||
describe('client() setter', () => {
|
||||
it('should set the client data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
||||
jest.spyOn(controller, 'setDefaultParams');
|
||||
jest.spyOn(controller, 'getAllowedContentTypes');
|
||||
controller._client = undefined;
|
||||
controller.client = {
|
||||
id: 15
|
||||
};
|
||||
|
||||
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
||||
expect(controller.client).toBeDefined();
|
||||
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setDefaultParams()', () => {
|
||||
it('should perform a GET query and define the dms property on controller', () => {
|
||||
const dmsId = 1;
|
||||
const expectedResponse = {
|
||||
reference: 1101,
|
||||
warehouseFk: 1,
|
||||
companyFk: 442,
|
||||
dmsTypeFk: 12,
|
||||
description: 'Test',
|
||||
hasFile: false,
|
||||
hasFileAttached: false
|
||||
};
|
||||
|
||||
$httpBackend.expect('GET', `Dms/${dmsId}`).respond(expectedResponse);
|
||||
controller.setDefaultParams();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.dms).toBeDefined();
|
||||
expect(controller.dms.reference).toEqual(1101);
|
||||
expect(controller.dms.dmsTypeId).toEqual(12);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFileChange()', () => {
|
||||
it('should set dms hasFileAttached property to true if has any files', () => {
|
||||
const files = [{id: 1, name: 'MyFile'}];
|
||||
controller.dms = {hasFileAttached: false};
|
||||
controller.onFileChange(files);
|
||||
$scope.$apply();
|
||||
|
||||
expect(controller.dms.hasFileAttached).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllowedContentTypes()', () => {
|
||||
it('should make an HTTP GET request to get the allowed content types', () => {
|
||||
const expectedResponse = ['image/png', 'image/jpg'];
|
||||
$httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond(expectedResponse);
|
||||
controller.getAllowedContentTypes();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.allowedContentTypes).toBeDefined();
|
||||
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
vn-ticket-request {
|
||||
.vn-textfield {
|
||||
margin: 0!important;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="ClientDms"
|
||||
link="{clientFk: $ctrl.$params.id}"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
data="$ctrl.clientDms"
|
||||
order="dmsFk DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-lg">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="dmsFk" shrink>Id</vn-th>
|
||||
<vn-th field="dmsTypeFk" shrink>Type</vn-th>
|
||||
<vn-th field="hardCopyNumber" shrink number>Order</vn-th>
|
||||
<vn-th field="reference" shrink>Reference</vn-th>
|
||||
<vn-th expand>Description</vn-th>
|
||||
<vn-th field="hasFile" shrink>Original</vn-th>
|
||||
<vn-th shrink>File</vn-th>
|
||||
<vn-th>Employee</vn-th>
|
||||
<vn-th field="created">Created</vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="document in $ctrl.clientDms">
|
||||
<vn-td number shrink>{{::document.dmsFk}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{::document.dms.dmsType.name}}">
|
||||
{{::document.dms.dmsType.name}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink number>
|
||||
<span class="chip" title="{{::document.dms.hardCopyNumber}}"
|
||||
ng-class="{'message': document.dms.hardCopyNumber}">
|
||||
{{::document.dms.hardCopyNumber}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{::document.dms.reference}}">
|
||||
{{::document.dms.reference}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>
|
||||
<span title="{{::document.dms.description}}">
|
||||
{{::document.dms.description}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-check
|
||||
ng-model="document.dms.hasFile"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{'Download file' | translate}}" class="link"
|
||||
ng-click="$ctrl.downloadFile(document.dmsFk)">
|
||||
{{::document.dms.file}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span class="link"
|
||||
ng-click="workerDescriptor.show($event, document.dms.workerFk)">
|
||||
{{::document.dms.worker.user.name | dashIfEmpty}}
|
||||
</span></vn-td>
|
||||
<vn-td shrink-datetime>
|
||||
{{::document.dms.created | date:'dd/MM/yyyy HH:mm'}}
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button title="{{'Download file' | translate}}"
|
||||
icon="cloud_download"
|
||||
ng-click="$ctrl.downloadFile(document.dmsFk)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button ui-sref="client.card.dms.edit({dmsId: {{::document.dmsFk}}})"
|
||||
icon="edit"
|
||||
title="{{'Edit file' | translate}}">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
icon="delete"
|
||||
ng-click="confirm.show($index)"
|
||||
title="{{'Remove file' | translate}}"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<a ui-sref="client.card.dms.create"
|
||||
vn-tooltip="Upload file"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
||||
<vn-confirm
|
||||
vn-id="confirm"
|
||||
message="This file will be deleted"
|
||||
question="Are you sure you want to continue?"
|
||||
on-accept="$ctrl.deleteDms($data)">
|
||||
</vn-confirm>
|
|
@ -1,64 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $, vnFile) {
|
||||
super($element, $, vnFile);
|
||||
this.vnFile = vnFile;
|
||||
this.filter = {
|
||||
include: {
|
||||
relation: 'dms',
|
||||
scope: {
|
||||
fields: [
|
||||
'dmsTypeFk',
|
||||
'reference',
|
||||
'hardCopyNumber',
|
||||
'workerFk',
|
||||
'description',
|
||||
'hasFile',
|
||||
'file',
|
||||
'created',
|
||||
],
|
||||
include: [{
|
||||
relation: 'dmsType',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}, {
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
fields: ['id'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
}
|
||||
}]
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
deleteDms(index) {
|
||||
const dmsFk = this.clientDms[index].dmsFk;
|
||||
return this.$http.post(`ClientDms/${dmsFk}/removeFile`)
|
||||
.then(() => {
|
||||
this.$.model.remove(index);
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
});
|
||||
}
|
||||
|
||||
downloadFile(dmsId) {
|
||||
this.vnFile.download(`api/dms/${dmsId}/downloadFile`);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'vnFile'];
|
||||
|
||||
ngModule.vnComponent('vnClientDmsIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
});
|
|
@ -1,37 +0,0 @@
|
|||
import './index';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientDmsIndex', () => {
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnClientDmsIndex', {$element: null, $scope});
|
||||
controller.$.model = crudModel;
|
||||
}));
|
||||
|
||||
describe('deleteDms()', () => {
|
||||
it('should make an HTTP Post query', () => {
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
jest.spyOn(controller.$.model, 'remove');
|
||||
|
||||
const dmsId = 1;
|
||||
const dmsIndex = 0;
|
||||
controller.clientDms = [{dmsFk: 1}];
|
||||
|
||||
$httpBackend.expectPOST(`ClientDms/${dmsId}/removeFile`).respond();
|
||||
controller.deleteDms(dmsIndex);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.model.remove).toHaveBeenCalledWith(dmsIndex);
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
Type: Tipo
|
||||
File management: Gestión documental
|
||||
File: Fichero
|
||||
Hard copy: Copia
|
||||
This file will be deleted: Este fichero va a ser borrado
|
||||
Are you sure?: Estas seguro?
|
||||
File deleted: Fichero eliminado
|
||||
Remove file: Eliminar fichero
|
||||
Download file: Descargar fichero
|
|
@ -1,6 +0,0 @@
|
|||
vn-client-risk-index {
|
||||
.totalBox {
|
||||
display: table;
|
||||
float: right;
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
ClientFileDescription: "{{dmsTypeName}} from client {{clientName}} id {{clientId}}"
|
||||
ContentTypesInfo: Allowed file types {{allowedContentTypes}}
|
|
@ -1,14 +0,0 @@
|
|||
Upload file: Subir fichero
|
||||
Edit file: Editar fichero
|
||||
Upload: Subir
|
||||
File: Fichero
|
||||
ClientFileDescription: "{{dmsTypeName}} del cliente {{clientName}} id {{clientId}}"
|
||||
ContentTypesInfo: "Tipos de archivo permitidos: {{allowedContentTypes}}"
|
||||
Generate identifier for original file: Generar identificador para archivo original
|
||||
File management: Gestión documental
|
||||
Hard copy: Copia
|
||||
This file will be deleted: Este fichero va a ser borrado
|
||||
Are you sure?: Estas seguro?
|
||||
File deleted: Fichero eliminado
|
||||
Remove file: Eliminar fichero
|
||||
Download file: Descargar fichero
|
|
@ -1,319 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Clients/extendedListFilter"
|
||||
limit="20">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
vn-focus
|
||||
panel="vn-client-search-panel"
|
||||
placeholder="Search client"
|
||||
info="Search client by id or name"
|
||||
auto-state="false"
|
||||
model="model">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-card>
|
||||
<smart-table
|
||||
model="model"
|
||||
view-config-id="clientsDetail"
|
||||
options="$ctrl.smartTableOptions"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th field="id">
|
||||
<span translate>Identifier</span>
|
||||
</th>
|
||||
<th field="name">
|
||||
<span translate>Name</span>
|
||||
</th>
|
||||
<th field="socialName">
|
||||
<span translate>Social name</span>
|
||||
</th>
|
||||
<th field="fi">
|
||||
<span translate>Tax number</span>
|
||||
</th>
|
||||
<th field="salesPersonFk">
|
||||
<span translate>Salesperson</span>
|
||||
</th>
|
||||
<th field="credit">
|
||||
<span translate>Credit</span>
|
||||
</th>
|
||||
<th field="creditInsurance">
|
||||
<span translate>Credit insurance</span>
|
||||
</th>
|
||||
<th field="phone">
|
||||
<span translate>Phone</span>
|
||||
</th>
|
||||
<th field="mobile">
|
||||
<span translate>Mobile</span>
|
||||
</th>
|
||||
<th field="street">
|
||||
<span translate>Street</span>
|
||||
</th>
|
||||
<th field="countryFk">
|
||||
<span translate>Country</span>
|
||||
</th>
|
||||
<th field="provinceFk">
|
||||
<span translate>Province</span>
|
||||
</th>
|
||||
<th field="city">
|
||||
<span translate>City</span>
|
||||
</th>
|
||||
<th field="postcode">
|
||||
<span translate>Postcode</span>
|
||||
</th>
|
||||
<th field="email">
|
||||
<span translate>Email</span>
|
||||
</th>
|
||||
<th field="created">
|
||||
<span translate>Created</span>
|
||||
</th>
|
||||
<th field="businessTypeFk">
|
||||
<span translate>Business type</span>
|
||||
</th>
|
||||
<th field="payMethodFk">
|
||||
<span translate>Billing data</span>
|
||||
</th>
|
||||
<th field="sageTaxTypeFk">
|
||||
<span translate>Sage tax type</span>
|
||||
</th>
|
||||
<th field="sageTransactionTypeFk">
|
||||
<span translate>Sage tr. type</span>
|
||||
</th>
|
||||
<th field="isActive" centered>
|
||||
<span translate>Active</span>
|
||||
</th>
|
||||
<th field="isVies" centered>
|
||||
<span translate>Vies</span>
|
||||
</th>
|
||||
<th field="isTaxDataChecked" centered>
|
||||
<span translate>Verified data</span>
|
||||
</th>
|
||||
<th field="isEqualizated" centered>
|
||||
<span translate>Is equalizated</span>
|
||||
</th>
|
||||
<th field="isFreezed" centered>
|
||||
<span translate>Freezed</span>
|
||||
</th>
|
||||
<th field="hasToInvoice" centered>
|
||||
<span translate>Invoice</span>
|
||||
</th>
|
||||
<th field="hasToInvoiceByAddress" centered>
|
||||
<span translate>Invoice by address</span>
|
||||
</th>
|
||||
<th field="isToBeMailed" centered>
|
||||
<span translate>Mailing</span>
|
||||
</th>
|
||||
<th field="hasLcr" centered>
|
||||
<span translate>Received LCR</span>
|
||||
</th>
|
||||
<th field="hasCoreVnl" centered>
|
||||
<span translate>Received core VNL</span>
|
||||
</th>
|
||||
<th field="hasSepaVnl" centered>
|
||||
<span translate>Received B2B VNL</span>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="client in model.data"
|
||||
vn-anchor="::{
|
||||
state: 'client.card.summary',
|
||||
params: {id: client.id}
|
||||
}">
|
||||
<td>
|
||||
<vn-icon-button ng-show="::client.isActive == false"
|
||||
vn-tooltip="Client inactive"
|
||||
icon="icon-disabled">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button ng-show="::client.isActive && client.isFreezed == true"
|
||||
vn-tooltip="Client frozen"
|
||||
icon="icon-frozen">
|
||||
</vn-icon-button>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
vn-click-stop="clientDescriptor.show($event, client.id)"
|
||||
class="link">
|
||||
{{::client.id}}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{::client.name}}</td>
|
||||
<td>{{::client.socialName}}</td>
|
||||
<td>{{::client.fi}}</td>
|
||||
<td>
|
||||
<span
|
||||
vn-click-stop="workerDescriptor.show($event, client.salesPersonFk)"
|
||||
ng-class="{'link': client.salesPersonFk}">
|
||||
{{::client.salesPerson | dashIfEmpty}}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{::client.credit}}</td>
|
||||
<td>{{::client.creditInsurance | dashIfEmpty}}</td>
|
||||
<td>{{::client.phone | dashIfEmpty}}</td>
|
||||
<td>{{::client.mobile | dashIfEmpty}}</td>
|
||||
<td>{{::client.street | dashIfEmpty}}</td>
|
||||
<td>{{::client.country | dashIfEmpty}}</td>
|
||||
<td>{{::client.province | dashIfEmpty}}</td>
|
||||
<td>{{::client.city | dashIfEmpty}}</td>
|
||||
<td>{{::client.postcode | dashIfEmpty}}</td>
|
||||
<td class="vn-w-xs" title="{{::client.email}}">{{::client.email | dashIfEmpty}}</td>
|
||||
<td>{{::client.created | date:'dd/MM/yyyy'}}</td>
|
||||
<td>{{::client.businessType | dashIfEmpty}}</td>
|
||||
<td>{{::client.payMethod | dashIfEmpty}}</td>
|
||||
<td>{{::client.sageTaxType | dashIfEmpty}}</td>
|
||||
<td>{{::client.sageTransactionType | dashIfEmpty}}</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.isActive,
|
||||
'alert': !client.isActive,
|
||||
}">
|
||||
{{ ::client.isActive ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.isVies,
|
||||
'alert': !client.isVies,
|
||||
}">
|
||||
{{ ::client.isVies ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.isTaxDataChecked,
|
||||
'alert': !client.isTaxDataChecked,
|
||||
}">
|
||||
{{ ::client.isTaxDataChecked ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.isEqualizated,
|
||||
'alert': !client.isEqualizated,
|
||||
}">
|
||||
{{ ::client.isEqualizated ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.isFreezed,
|
||||
'alert': !client.isFreezed,
|
||||
}">
|
||||
{{ ::client.isFreezed ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.hasToInvoice,
|
||||
'alert': !client.hasToInvoice,
|
||||
}">
|
||||
{{ ::client.hasToInvoice ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.hasToInvoiceByAddress,
|
||||
'alert': !client.hasToInvoiceByAddress,
|
||||
}">
|
||||
{{ ::client.hasToInvoiceByAddress ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.isToBeMailed,
|
||||
'alert': !client.isToBeMailed,
|
||||
}">
|
||||
{{ ::client.isToBeMailed ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.hasLcr,
|
||||
'alert': !client.hasLcr,
|
||||
}">
|
||||
{{ ::client.hasLcr ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.hasCoreVnl,
|
||||
'alert': !client.hasCoreVnl,
|
||||
}">
|
||||
{{ ::client.hasCoreVnl ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td centered>
|
||||
<vn-chip ng-class="::{
|
||||
'success': client.hasSepaVnl,
|
||||
'alert': !client.hasSepaVnl,
|
||||
}">
|
||||
{{ ::client.hasSepaVnl ? 'Yes' : 'No' | translate}}
|
||||
</vn-chip>
|
||||
</td>
|
||||
<td shrink>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button vn-anchor="{state: 'ticket.index', params: {q: {clientFk: client.id} } }"
|
||||
vn-tooltip="Client tickets"
|
||||
icon="icon-ticket">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
vn-click-stop="$ctrl.preview(client)"
|
||||
vn-tooltip="Preview"
|
||||
icon="preview">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</slot-table>
|
||||
</smart-table>
|
||||
</vn-card>
|
||||
<a ui-sref="client.create" vn-tooltip="New client" vn-bind="+" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
||||
<vn-client-descriptor-popover
|
||||
vn-id="client-descriptor">
|
||||
</vn-client-descriptor-popover>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="worker-descriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
|
||||
<vn-popup vn-id="preview">
|
||||
<vn-client-summary
|
||||
client="$ctrl.clientSelected">
|
||||
</vn-client-summary>
|
||||
</vn-popup>
|
||||
<vn-contextmenu
|
||||
vn-id="contextmenu"
|
||||
targets="['smart-table']"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-menu>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.filterBySelection()">
|
||||
Filter by selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.excludeSelection()">
|
||||
Exclude selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.removeFilter()">
|
||||
Remove filter
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-click="contextmenu.removeAllFilters()">
|
||||
Remove all filters
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
</vn-contextmenu>
|
|
@ -1,184 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.smartTableOptions = {
|
||||
activeButtons: {
|
||||
search: true,
|
||||
shownColumns: true,
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'socialName',
|
||||
autocomplete: {
|
||||
url: 'Clients',
|
||||
showField: 'socialName',
|
||||
valueField: 'socialName',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'created',
|
||||
datepicker: true
|
||||
},
|
||||
{
|
||||
field: 'countryFk',
|
||||
autocomplete: {
|
||||
url: 'Countries',
|
||||
showField: 'name',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'provinceFk',
|
||||
autocomplete: {
|
||||
url: 'Provinces'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'salesPersonFk',
|
||||
autocomplete: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
where: `{role: 'salesPerson'}`,
|
||||
searchFunction: '{firstName: $search}',
|
||||
showField: 'nickname',
|
||||
valueField: 'id',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'businessTypeFk',
|
||||
autocomplete: {
|
||||
url: 'BusinessTypes',
|
||||
valueField: 'code',
|
||||
showField: 'description',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'payMethodFk',
|
||||
autocomplete: {
|
||||
url: 'PayMethods',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'sageTaxTypeFk',
|
||||
autocomplete: {
|
||||
url: 'SageTaxTypes',
|
||||
showField: 'vat',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'sageTransactionTypeFk',
|
||||
autocomplete: {
|
||||
url: 'SageTransactionTypes',
|
||||
showField: 'transaction',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'isActive',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'isVies',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'isTaxDataChecked',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'isEqualizated',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'isFreezed',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'hasToInvoice',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'hasToInvoiceByAddress',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'isToBeMailed',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'hasSepaVnl',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'hasLcr',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'hasCoreVnl',
|
||||
checkbox: true
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'created':
|
||||
return {'c.created': {
|
||||
between: this.dateRange(value)}
|
||||
};
|
||||
case 'id':
|
||||
case 'name':
|
||||
case 'socialName':
|
||||
case 'fi':
|
||||
case 'credit':
|
||||
case 'creditInsurance':
|
||||
case 'phone':
|
||||
case 'mobile':
|
||||
case 'street':
|
||||
case 'city':
|
||||
case 'postcode':
|
||||
case 'email':
|
||||
case 'isActive':
|
||||
case 'isVies':
|
||||
case 'isTaxDataChecked':
|
||||
case 'isEqualizated':
|
||||
case 'isFreezed':
|
||||
case 'hasToInvoice':
|
||||
case 'hasToInvoiceByAddress':
|
||||
case 'isToBeMailed':
|
||||
case 'hasSepaVnl':
|
||||
case 'hasLcr':
|
||||
case 'hasCoreVnl':
|
||||
case 'countryFk':
|
||||
case 'provinceFk':
|
||||
case 'salesPersonFk':
|
||||
case 'businessTypeFk':
|
||||
case 'payMethodFk':
|
||||
case 'sageTaxTypeFk':
|
||||
case 'sageTransactionTypeFk':
|
||||
return {[`c.${param}`]: value};
|
||||
}
|
||||
}
|
||||
|
||||
dateRange(value) {
|
||||
const minHour = new Date(value);
|
||||
minHour.setHours(0, 0, 0, 0);
|
||||
const maxHour = new Date(value);
|
||||
maxHour.setHours(23, 59, 59, 59);
|
||||
|
||||
return [minHour, maxHour];
|
||||
}
|
||||
|
||||
preview(client) {
|
||||
this.clientSelected = client;
|
||||
this.$.preview.show();
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClientExtendedList', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
Mailing: Env. emails
|
||||
Sage tr. type: Tipo tr. sage
|
||||
Yes: Sí
|
|
@ -1,6 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
vn-chip.success,
|
||||
vn-chip.alert {
|
||||
color: $color-font-bg
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
<mg-ajax path="Clients/{{patch.params.id}}/updateFiscalData" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
id-field="id"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Provinces/location"
|
||||
data="provincesLocation"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Countries"
|
||||
data="countries"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="SageTaxTypes"
|
||||
data="sageTaxTypes"
|
||||
order="vat">
|
||||
</vn-crud-model>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-focus
|
||||
label="Social name"
|
||||
ng-model="$ctrl.client.socialName"
|
||||
info="Only letters, numbers and spaces can be used"
|
||||
required="true"
|
||||
ng-keyup="$ctrl.client.socialName = $ctrl.client.socialName.toUpperCase()"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
label="Tax number"
|
||||
ng-model="$ctrl.client.fi"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
label="Street"
|
||||
ng-model="$ctrl.client.street"
|
||||
ng-keyup="$ctrl.client.street = $ctrl.client.street.toUpperCase()"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
ng-model="$ctrl.client.sageTaxTypeFk"
|
||||
data="sageTaxTypes"
|
||||
show-field="vat"
|
||||
value-field="id"
|
||||
label="Sage tax type"
|
||||
vn-acl="salesAssistant"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
ng-model="$ctrl.client.sageTransactionTypeFk"
|
||||
url="SageTransactionTypes"
|
||||
show-field="transaction"
|
||||
value-field="id"
|
||||
label="Sage transaction type"
|
||||
search-function="{or: [{id: $search}, {transaction: {like: '%'+ $search +'%'}}]}"
|
||||
vn-acl="salesAssistant"
|
||||
order="transaction"
|
||||
rule>
|
||||
<tpl-item>{{id}}: {{transaction}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-datalist
|
||||
label="Postcode"
|
||||
ng-model="$ctrl.client.postcode"
|
||||
selection="$ctrl.postcode"
|
||||
url="Postcodes/location"
|
||||
fields="['code','townFk']"
|
||||
order="code, townFk"
|
||||
value-field="code"
|
||||
show-field="code"
|
||||
rule>
|
||||
<tpl-item>
|
||||
{{code}} - {{town.name}} ({{town.province.name}},
|
||||
{{town.province.country.name}})
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New postcode"
|
||||
ng-click="postcode.open()"
|
||||
vn-acl="deliveryAssistant"
|
||||
vn-acl-action="remove">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-datalist>
|
||||
<vn-datalist
|
||||
vn-id="town"
|
||||
label="City"
|
||||
ng-model="$ctrl.client.city"
|
||||
selection="$ctrl.town"
|
||||
url="Towns/location"
|
||||
fields="['id', 'name', 'provinceFk']"
|
||||
show-field="name"
|
||||
value-field="name">
|
||||
<tpl-item>
|
||||
{{name}}, {{province.name}}
|
||||
({{province.country.name}})
|
||||
</tpl-item>
|
||||
</vn-datalist>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
vn-id="province"
|
||||
label="Province"
|
||||
ng-model="$ctrl.client.provinceFk"
|
||||
selection="$ctrl.province"
|
||||
data="provincesLocation"
|
||||
fields="['id', 'name', 'countryFk']"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
rule>
|
||||
<tpl-item>{{name}} ({{country.name}})</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
vn-id="country"
|
||||
ng-model="$ctrl.client.countryFk"
|
||||
data="countries"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Country"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Active"
|
||||
ng-model="$ctrl.client.isActive">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Frozen"
|
||||
ng-model="$ctrl.client.isFreezed">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Has to invoice"
|
||||
ng-model="$ctrl.client.hasToInvoice">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Vies"
|
||||
info="When activating it, do not enter the country code in the ID field."
|
||||
ng-model="$ctrl.client.isVies">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Notify by email"
|
||||
ng-model="$ctrl.client.isToBeMailed">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Invoice by address"
|
||||
ng-model="$ctrl.client.hasToInvoiceByAddress">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Is equalizated"
|
||||
ng-model="$ctrl.client.isEqualizated"
|
||||
info="In order to invoice, this field is not consulted, but the consignee's ET. When modifying this field if the invoice by address option is not checked, the change will be automatically propagated to all addresses, otherwise the user will be asked if he wants to propagate it or not."
|
||||
on-change="$ctrl.onChangeEqualizated(value)">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Verified data"
|
||||
ng-model="$ctrl.client.isTaxDataChecked"
|
||||
vn-acl="salesAssistant">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Electronic invoice"
|
||||
ng-model="$ctrl.client.hasElectronicInvoice"
|
||||
vn-acl="administrative">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit disabled="!watcher.dataChanged()" label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Undo changes"
|
||||
disabled="!watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button>
|
||||
</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-accept="$ctrl.onAcceptEt()">
|
||||
</vn-confirm>
|
||||
<vn-confirm
|
||||
vn-id="confirm-duplicatedClient"
|
||||
message="Found a client with this data"
|
||||
on-accept="$ctrl.onAcceptDuplication()">
|
||||
</vn-confirm>
|
||||
<vn-geo-postcode
|
||||
vn-id="postcode"
|
||||
on-response="$ctrl.onResponse($response)">
|
||||
</vn-geo-postcode>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue