Autocomplete geolocation from postcode #1519 and #1531
gitea/salix/dev This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-06-13 13:08:11 +02:00
parent 03205e01ae
commit 9c00e7e67c
26 changed files with 390 additions and 101 deletions

View File

@ -11,6 +11,9 @@
"Company": { "Company": {
"dataSource": "vn" "dataSource": "vn"
}, },
"Container": {
"dataSource": "storage"
},
"Delivery": { "Delivery": {
"dataSource": "vn" "dataSource": "vn"
}, },
@ -44,8 +47,11 @@
"DmsType": { "DmsType": {
"dataSource": "vn" "dataSource": "vn"
}, },
"Container": { "Town": {
"dataSource": "storage" "dataSource": "vn"
},
"Postcode": {
"dataSource": "vn"
} }
} }

50
back/models/postcode.json Normal file
View File

@ -0,0 +1,50 @@
{
"name": "Postcode",
"base": "VnModel",
"options": {
"mysql": {
"table": "postCode"
}
},
"properties": {
"code": {
"id": true,
"type": "String"
}
},
"relations": {
"town": {
"type": "belongsTo",
"model": "Town",
"foreignKey": "townFk"
},
"geo": {
"type": "belongsTo",
"model": "ZoneGeo",
"foreignKey": "geoFk"
}
},
"acls": [{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}],
"scopes": {
"location": {
"include": {
"relation": "town",
"scope": {
"include": {
"relation": "province",
"scope": {
"include": {
"relation": "country"
}
}
}
}
}
}
}
}

56
back/models/town.json Normal file
View File

@ -0,0 +1,56 @@
{
"name": "Town",
"base": "VnModel",
"options": {
"mysql": {
"table": "town"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"name": {
"type": "String"
}
},
"relations": {
"province": {
"type": "belongsTo",
"model": "Province",
"foreignKey": "provinceFk"
},
"postcodes": {
"type": "hasMany",
"model": "Postcode",
"foreignKey": "townFk"
},
"geo": {
"type": "belongsTo",
"model": "ZoneGeo",
"foreignKey": "geoFk"
}
},
"acls": [{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}],
"scopes": {
"location": {
"include": [{
"relation": "province",
"scope": {
"include": {
"relation": "country"
}
}
},
{
"relation": "postcodes"
}]
}
}
}

View File

@ -5,7 +5,7 @@ export MYSQL_PWD=root
mysql_import() { mysql_import() {
FILE=$1 FILE=$1
echo "[INFO] -> Imported $FILE" echo "[INFO] -> Imported $FILE"
mysql -u root --comments -f < "$FILE" mysql -u root --default-character-set=utf8 --comments -f < "$FILE"
} }
mysql_import dump/structure.sql mysql_import dump/structure.sql

View File

@ -147,6 +147,20 @@ INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `warehouseFk`, `zoneFk`)
(4, 'Province four', 1, NULL, 2), (4, 'Province four', 1, NULL, 2),
(5, 'Province five', 1, NULL, 1); (5, 'Province five', 1, NULL, 1);
INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`)
VALUES
(1, 'Valencia', 1),
(2, 'Silla', 1),
(3, 'Algemesi', 1),
(4, 'Alzira', 1);
INSERT INTO `vn`.`postCode`(`code`, `townFk`)
VALUES
('46000', 1),
('46460', 2),
('46680', 3),
('46600', 4);
INSERT INTO `vn`.`clientType`(`id`, `code`, `type`) INSERT INTO `vn`.`clientType`(`id`, `code`, `type`)
VALUES VALUES
(1, 'normal', 'Normal'), (1, 'normal', 'Normal'),

View File

@ -33,7 +33,10 @@ export default {
taxNumber: `${components.vnTextfield}[name="fi"]`, taxNumber: `${components.vnTextfield}[name="fi"]`,
socialName: `${components.vnTextfield}[name="socialName"]`, socialName: `${components.vnTextfield}[name="socialName"]`,
street: `${components.vnTextfield}[name="street"]`, street: `${components.vnTextfield}[name="street"]`,
city: `${components.vnTextfield}[name="city"]`, postcode: `vn-autocomplete[field="$ctrl.client.postcode"]`,
city: `vn-autocomplete[field="$ctrl.client.city"]`,
province: `vn-autocomplete[field="$ctrl.client.provinceFk"]`,
country: `vn-autocomplete[field="$ctrl.client.countryFk"]`,
userName: `${components.vnTextfield}[name="userName"]`, userName: `${components.vnTextfield}[name="userName"]`,
email: `${components.vnTextfield}[name="email"]`, email: `${components.vnTextfield}[name="email"]`,
salesPersonAutocomplete: `vn-autocomplete[field="$ctrl.client.salesPersonFk"]`, salesPersonAutocomplete: `vn-autocomplete[field="$ctrl.client.salesPersonFk"]`,
@ -62,8 +65,8 @@ export default {
equalizationTaxCheckbox: 'vn-check[label="Is equalizated"] md-checkbox', equalizationTaxCheckbox: 'vn-check[label="Is equalizated"] md-checkbox',
acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]', acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]',
addressInput: `${components.vnTextfield}[name="street"]`, addressInput: `${components.vnTextfield}[name="street"]`,
cityInput: `${components.vnTextfield}[name="city"]`, postcodeAutocomplete: `vn-autocomplete[field="$ctrl.client.postcode"]`,
postcodeInput: `${components.vnTextfield}[name="postcode"]`, cityAutocomplete: `vn-autocomplete[field="$ctrl.client.city"]`,
provinceAutocomplete: 'vn-autocomplete[field="$ctrl.client.provinceFk"]', provinceAutocomplete: 'vn-autocomplete[field="$ctrl.client.provinceFk"]',
countryAutocomplete: 'vn-autocomplete[field="$ctrl.client.countryFk"]', countryAutocomplete: 'vn-autocomplete[field="$ctrl.client.countryFk"]',
activeCheckbox: 'vn-check[label="Active"] md-checkbox', activeCheckbox: 'vn-check[label="Active"] md-checkbox',
@ -97,8 +100,8 @@ export default {
defaultCheckboxInput: 'vn-check[label="Default"] md-checkbox', defaultCheckboxInput: 'vn-check[label="Default"] md-checkbox',
consigneeInput: `${components.vnTextfield}[name="nickname"]`, consigneeInput: `${components.vnTextfield}[name="nickname"]`,
streetAddressInput: `${components.vnTextfield}[name="street"]`, streetAddressInput: `${components.vnTextfield}[name="street"]`,
postcodeInput: `${components.vnTextfield}[name="postalCode"]`, postcodeAutocomplete: `vn-autocomplete[field="$ctrl.address.postalCode"]`,
cityInput: `${components.vnTextfield}[name="city"]`, cityAutocomplete: `vn-autocomplete[field="$ctrl.address.city"]`,
provinceAutocomplete: 'vn-autocomplete[field="$ctrl.address.provinceFk"]', provinceAutocomplete: 'vn-autocomplete[field="$ctrl.address.provinceFk"]',
agencyAutocomplete: 'vn-autocomplete[field="$ctrl.address.agencyModeFk"]', agencyAutocomplete: 'vn-autocomplete[field="$ctrl.address.agencyModeFk"]',
phoneInput: `${components.vnTextfield}[name="phone"]`, phoneInput: `${components.vnTextfield}[name="phone"]`,

View File

@ -53,7 +53,7 @@ describe('Client create path', () => {
.write(selectors.createClientView.name, 'Carol Danvers') .write(selectors.createClientView.name, 'Carol Danvers')
.write(selectors.createClientView.socialName, 'AVG tax') .write(selectors.createClientView.socialName, 'AVG tax')
.write(selectors.createClientView.street, 'Many places') .write(selectors.createClientView.street, 'Many places')
.write(selectors.createClientView.city, 'Silla') .autocompleteSearch(selectors.createClientView.postcode, '46000')
.clearInput(selectors.createClientView.email) .clearInput(selectors.createClientView.email)
.write(selectors.createClientView.email, 'incorrect email format') .write(selectors.createClientView.email, 'incorrect email format')
.waitToClick(selectors.createClientView.createButton) .waitToClick(selectors.createClientView.createButton)
@ -62,6 +62,21 @@ describe('Client create path', () => {
expect(result).toEqual('Some fields are invalid'); expect(result).toEqual('Some fields are invalid');
}); });
it(`should check for autocompleted city, province and country`, async() => {
const clientCity = await nightmare
.waitToGetProperty(`${selectors.createClientView.city} input`, 'value');
const clientProvince = await nightmare
.waitToGetProperty(`${selectors.createClientView.province} input`, 'value');
const clientCountry = await nightmare
.waitToGetProperty(`${selectors.createClientView.country} input`, 'value');
expect(clientCity).toEqual('Valencia');
expect(clientProvince).toEqual('Province one');
expect(clientCountry).toEqual('España');
});
it(`should create a new user with all correct data`, async() => { it(`should create a new user with all correct data`, async() => {
const result = await nightmare const result = await nightmare
.clearInput(selectors.createClientView.email) .clearInput(selectors.createClientView.email)

View File

@ -67,11 +67,7 @@ describe('Client Edit fiscalData path', () => {
.write(selectors.clientFiscalData.fiscalIdInput, 'INVALID!') .write(selectors.clientFiscalData.fiscalIdInput, 'INVALID!')
.clearInput(selectors.clientFiscalData.addressInput) .clearInput(selectors.clientFiscalData.addressInput)
.write(selectors.clientFiscalData.addressInput, 'Somewhere edited') .write(selectors.clientFiscalData.addressInput, 'Somewhere edited')
.clearInput(selectors.clientFiscalData.postcodeInput) .autocompleteSearch(selectors.clientFiscalData.postcodeAutocomplete, '46000')
.write(selectors.clientFiscalData.postcodeInput, '12345')
.clearInput(selectors.clientFiscalData.cityInput)
.write(selectors.clientFiscalData.cityInput, 'N/A')
.autocompleteSearch(selectors.clientFiscalData.provinceAutocomplete, 'Province two')
.waitToClick(selectors.clientFiscalData.activeCheckbox) .waitToClick(selectors.clientFiscalData.activeCheckbox)
.waitToClick(selectors.clientFiscalData.frozenCheckbox) .waitToClick(selectors.clientFiscalData.frozenCheckbox)
.waitToClick(selectors.clientFiscalData.hasToInvoiceCheckbox) .waitToClick(selectors.clientFiscalData.hasToInvoiceCheckbox)
@ -197,23 +193,31 @@ describe('Client Edit fiscalData path', () => {
it('should confirm the postcode have been edited', async() => { it('should confirm the postcode have been edited', async() => {
const result = await nightmare const result = await nightmare
.waitToGetProperty(selectors.clientFiscalData.postcodeInput, 'value'); .waitToGetProperty(`${selectors.clientFiscalData.postcodeAutocomplete} input`, 'value');
expect(result).toEqual('12345'); expect(result).toContain('46000');
}); });
it('should confirm the city have been edited', async() => { it('should confirm the city have been autocompleted', async() => {
const result = await nightmare const result = await nightmare
.waitToGetProperty(selectors.clientFiscalData.cityInput, 'value'); .waitToGetProperty(`${selectors.clientFiscalData.cityAutocomplete} input`, 'value');
expect(result).toEqual('N/A'); expect(result).toEqual('Valencia');
}); });
it(`should confirm the province have been selected`, async() => {
it(`should confirm the province have been autocompleted`, async() => {
const result = await nightmare const result = await nightmare
.waitToGetProperty(`${selectors.clientFiscalData.provinceAutocomplete} input`, 'value'); .waitToGetProperty(`${selectors.clientFiscalData.provinceAutocomplete} input`, 'value');
expect(result).toEqual('Province two'); expect(result).toEqual('Province one');
});
it('should confirm the country have been autocompleted', async() => {
const result = await nightmare
.waitToGetProperty(`${selectors.clientFiscalData.countryAutocomplete} input`, 'value');
expect(result).toEqual('España');
}); });
it('should confirm active checkbox is unchecked', async() => { it('should confirm active checkbox is unchecked', async() => {

View File

@ -24,8 +24,7 @@ describe('Client Add address path', () => {
const result = await nightmare const result = await nightmare
.waitToClick(selectors.clientAddresses.defaultCheckboxInput) .waitToClick(selectors.clientAddresses.defaultCheckboxInput)
.clearInput(selectors.clientAddresses.streetAddressInput) .clearInput(selectors.clientAddresses.streetAddressInput)
.write(selectors.clientAddresses.postcodeInput, '10022') .autocompleteSearch(selectors.clientAddresses.postcodeAutocomplete, '46000')
.autocompleteSearch(selectors.clientAddresses.provinceAutocomplete, 'Province four')
.autocompleteSearch(selectors.clientAddresses.agencyAutocomplete, 'Entanglement') .autocompleteSearch(selectors.clientAddresses.agencyAutocomplete, 'Entanglement')
.write(selectors.clientAddresses.phoneInput, '999887744') .write(selectors.clientAddresses.phoneInput, '999887744')
.write(selectors.clientAddresses.mobileInput, '999887744') .write(selectors.clientAddresses.mobileInput, '999887744')
@ -35,11 +34,32 @@ describe('Client Add address path', () => {
expect(result).toEqual('Some fields are invalid'); expect(result).toEqual('Some fields are invalid');
}); });
it('should confirm the postcode have been edited', async() => {
const result = await nightmare
.waitToGetProperty(`${selectors.clientAddresses.postcodeAutocomplete} input`, 'value');
expect(result).toContain('46000');
});
it('should confirm the city have been autocompleted', async() => {
const result = await nightmare
.waitToGetProperty(`${selectors.clientAddresses.cityAutocomplete} input`, 'value');
expect(result).toEqual('Valencia');
});
it(`should confirm the province have been autocompleted`, async() => {
const result = await nightmare
.waitToGetProperty(`${selectors.clientAddresses.provinceAutocomplete} input`, 'value');
expect(result).toEqual('Province one');
});
it(`should create a new address with all it's data`, async() => { it(`should create a new address with all it's data`, async() => {
const result = await nightmare const result = await nightmare
.write(selectors.clientAddresses.consigneeInput, 'Bruce Bunner') .write(selectors.clientAddresses.consigneeInput, 'Bruce Bunner')
.write(selectors.clientAddresses.streetAddressInput, '320 Park Avenue New York') .write(selectors.clientAddresses.streetAddressInput, '320 Park Avenue New York')
.write(selectors.clientAddresses.cityInput, 'New York')
.waitToClick(selectors.clientAddresses.saveButton) .waitToClick(selectors.clientAddresses.saveButton)
.waitForLastSnackbar(); .waitForLastSnackbar();

View File

@ -19,6 +19,6 @@
</div> </div>
<vn-drop-down <vn-drop-down
vn-id="drop-down" vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(value)" on-select="$ctrl.onDropDownSelect(item)"
on-data-ready="$ctrl.onDataReady()"> on-data-ready="$ctrl.onDataReady()">
</vn-drop-down> </vn-drop-down>

View File

@ -79,10 +79,10 @@ export default class Autocomplete extends Input {
} }
set field(value) { set field(value) {
if (angular.equals(value, this._field))
return;
this._field = value; this._field = value;
if (!value) return;
this.refreshSelection(); this.refreshSelection();
this.emit('change', {value}); this.emit('change', {value});
} }
@ -125,7 +125,9 @@ export default class Autocomplete extends Input {
|| this.selectionIsValid(this._selection)) || this.selectionIsValid(this._selection))
return; return;
this.selection = this.fetchSelection(); const selection = this.fetchSelection();
if (!this.selection)
this.selection = selection;
} }
fetchSelection() { fetchSelection() {
@ -217,7 +219,9 @@ export default class Autocomplete extends Input {
if (this.form) this.form.$setDirty(); if (this.form) this.form.$setDirty();
} }
onDropDownSelect(value) { onDropDownSelect(item) {
const value = item[this.valueField];
this.selection = item;
this.setValue(value); this.setValue(value);
this.field = value; this.field = value;
} }

View File

@ -7,7 +7,7 @@
</button> </button>
<vn-drop-down <vn-drop-down
vn-id="drop-down" vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(value)" on-select="$ctrl.onDropDownSelect(item)"
ng-click="$ctrl.onDropDownClick($event)"> ng-click="$ctrl.onDropDownClick($event)">
</vn-drop-down> </vn-drop-down>
</div> </div>

View File

@ -53,7 +53,8 @@ export default class ButtonMenu extends Input {
event.preventDefault(); event.preventDefault();
} }
onDropDownSelect(value) { onDropDownSelect(item) {
const value = item[this.valueField];
this.field = value; this.field = value;
this.emit('change', {value}); this.emit('change', {value});
} }

View File

@ -7,6 +7,7 @@ describe('Component vnButtonMenu', () => {
beforeEach(inject(($compile, $rootScope) => { beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-icon-menu></vn-icon-menu>`)($rootScope); $element = $compile(`<vn-icon-menu></vn-icon-menu>`)($rootScope);
controller = $element.controller('vnIconMenu'); controller = $element.controller('vnIconMenu');
controller.valueField = 'name';
})); }));
afterEach(() => { afterEach(() => {
@ -31,10 +32,10 @@ describe('Component vnButtonMenu', () => {
describe('onDropDownSelect(value)', () => { describe('onDropDownSelect(value)', () => {
it(`should set field to the given value and emit the change event`, () => { it(`should set field to the given value and emit the change event`, () => {
spyOn(controller, 'emit'); spyOn(controller, 'emit');
controller.onDropDownSelect('mariano'); controller.onDropDownSelect({name: 'Item name'});
expect(controller.field).toBe('mariano'); expect(controller.field).toBe('Item name');
expect(controller.emit).toHaveBeenCalledWith('change', {value: 'mariano'}); expect(controller.emit).toHaveBeenCalledWith('change', {value: 'Item name'});
}); });
}); });
}); });

View File

@ -8,7 +8,7 @@
model="$ctrl.search" model="$ctrl.search"
class="search" class="search"
ng-blur="$ctrl.onFocusOut()" ng-blur="$ctrl.onFocusOut()"
label = "Search"> label="Search">
</vn-textfield> </vn-textfield>
</div> </div>
<div class="list" tabindex="-1"> <div class="list" tabindex="-1">

View File

@ -186,7 +186,7 @@ export default class DropDown extends Component {
this.field = value; this.field = value;
} }
this.emit('select', {value: value}); this.emit('select', {item});
} }
if (!this.multiple) if (!this.multiple)

View File

@ -5,7 +5,7 @@
</vn-icon> </vn-icon>
<vn-drop-down <vn-drop-down
vn-id="drop-down" vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(value)" on-select="$ctrl.onDropDownSelect(item)"
ng-click="$ctrl.onDropDownClick($event)"> ng-click="$ctrl.onDropDownClick($event)">
</vn-drop-down> </vn-drop-down>
</div> </div>

View File

@ -6,6 +6,14 @@
save="post" save="post"
form="form"> form="form">
</vn-watcher> </vn-watcher>
<vn-crud-model
vn-id="model"
url="/client/api/AddressObservations"
fields="['id', 'addressFk', 'observationTypeFk', 'description']"
link="{addressFk: $ctrl.$stateParams.addressId}"
data="observations"
auto-load="true">
</vn-crud-model>
<form name="form" ng-submit="$ctrl.onSubmit()" compact> <form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large> <vn-card pad-large>
<vn-horizontal pad-small-v> <vn-horizontal pad-small-v>
@ -16,22 +24,40 @@
<vn-textfield vn-one label="Street address" field="$ctrl.address.street"></vn-textfield> <vn-textfield vn-one label="Street address" field="$ctrl.address.street"></vn-textfield>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-textfield vn-one label="Postcode" field="$ctrl.address.postalCode"></vn-textfield> <vn-autocomplete vn-id="postcode" vn-one
<vn-textfield vn-one label="Town/City" field="$ctrl.address.city"></vn-textfield> field="$ctrl.address.postalCode"
<vn-autocomplete on-change="$ctrl.setLocation()"
vn-one search-function="{code: $search}"
url="/api/Postcodes/location"
fields="['code', 'townFk']"
show-field="code"
value-field="code"
label="Postcode">
<tpl-item>
{{code}}, {{town.name}} - {{town.province.name}}
({{town.province.country.country}})
</tpl-item>
</vn-autocomplete>
<vn-autocomplete vn-one
label="City"
url="/api/Towns"
show-field="name"
value-field="name"
field="$ctrl.address.city">
</vn-autocomplete>
<vn-autocomplete vn-one
disabled="true"
field="$ctrl.address.provinceFk" field="$ctrl.address.provinceFk"
url="/client/api/Provinces" url="/api/Provinces"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Province"> label="Province">
</vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-autocomplete <vn-autocomplete
vn-one vn-one
field="$ctrl.address.agencyModeFk" field="$ctrl.address.agencyModeFk"
url="/client/api/AgencyModes/isActive" url="/api/AgencyModes/isActive"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Agency"> label="Agency">

View File

@ -1,8 +1,8 @@
import ngModule from '../../module'; import ngModule from '../../module';
export default class Controller { export default class Controller {
constructor($scope, $state) { constructor($, $state) {
this.$scope = $scope; this.$ = $;
this.$state = $state; this.$state = $state;
this.data = { this.data = {
address: { address: {
@ -14,8 +14,20 @@ export default class Controller {
this.address = this.data.address; this.address = this.data.address;
} }
setLocation() {
const location = this.$.postcode.selection;
if (!location || !location.town) return;
const town = location.town;
const province = town.province;
const country = province.country;
this.address.city = location.town.name;
this.address.provinceFk = province.id;
this.address.countryFk = country.id;
}
onSubmit() { onSubmit() {
this.$scope.watcher.submit().then(res => { this.$.watcher.submit().then(res => {
if (res.data && this.data.isDefaultAddress) if (res.data && this.data.isDefaultAddress)
this.client.defaultAddressFk = res.data.id; this.client.defaultAddressFk = res.data.id;

View File

@ -14,8 +14,8 @@ describe('Client', () => {
$state = _$state_; $state = _$state_;
$state.params.id = '1234'; $state.params.id = '1234';
controller = $componentController('vnClientAddressCreate', {$state}); controller = $componentController('vnClientAddressCreate', {$state});
controller.$scope.watcher = watcher; controller.$.watcher = watcher;
controller.$scope.watcher.submit = () => { controller.$.watcher.submit = () => {
return { return {
then: callback => { then: callback => {
callback({data: {id: 124}}); callback({data: {id: 124}});

View File

@ -25,7 +25,7 @@
data="types" data="types"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
<form name="form" ng-submit="$ctrl.submit()" compact> <form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large> <vn-card pad-large>
<vn-horizontal pad-small-v> <vn-horizontal pad-small-v>
<vn-check vn-one label="Enabled" field="$ctrl.address.isActive"></vn-check> <vn-check vn-one label="Enabled" field="$ctrl.address.isActive"></vn-check>
@ -40,12 +40,31 @@
<vn-textfield vn-one label="Street" field="$ctrl.address.street"></vn-textfield> <vn-textfield vn-one label="Street" field="$ctrl.address.street"></vn-textfield>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-textfield vn-one label="Postcode" field="$ctrl.address.postalCode"></vn-textfield> <vn-autocomplete vn-id="postcode" vn-one
<vn-textfield vn-one label="City" field="$ctrl.address.city"></vn-textfield> field="$ctrl.address.postalCode"
on-change="$ctrl.setLocation()"
search-function="{code: $search}"
url="/api/Postcodes/location"
fields="['code', 'townFk']"
show-field="code"
value-field="code"
label="Postcode">
<tpl-item>
{{code}}, {{town.name}} - {{town.province.name}}
({{town.province.country.country}})
</tpl-item>
</vn-autocomplete>
<vn-autocomplete vn-one <vn-autocomplete vn-one
initial-data="$ctrl.address.province" label="City"
url="/api/Towns"
show-field="name"
value-field="name"
field="$ctrl.address.city">
</vn-autocomplete>
<vn-autocomplete vn-one
disabled="true"
field="$ctrl.address.provinceFk" field="$ctrl.address.provinceFk"
url="/client/api/Provinces" url="/api/Provinces"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Province"> label="Province">

View File

@ -20,7 +20,19 @@ export default class Controller {
this.$state.go('client.card.address.index'); this.$state.go('client.card.address.index');
} }
submit() { setLocation() {
const location = this.$.postcode.selection;
if (!location || !location.town) return;
const town = location.town;
const province = town.province;
const country = province.country;
this.address.city = location.town.name;
this.address.provinceFk = province.id;
this.address.countryFk = country.id;
}
onSubmit() {
this.$.watcher.check(); this.$.watcher.check();
this.$.watcher.realSubmit() this.$.watcher.realSubmit()
.then(() => this.$.model.save(true)) .then(() => this.$.model.save(true))

View File

@ -33,34 +33,45 @@
</vn-textfield> </vn-textfield>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-textfield <vn-autocomplete vn-id="postcode" vn-one
vn-one field="$ctrl.client.postcode"
label="Postcode" on-change="$ctrl.setLocation()"
field="$ctrl.client.postcode"> search-function="{code: $search}"
</vn-textfield> url="/api/Postcodes/location"
<vn-textfield fields="['code', 'townFk']"
vn-one show-field="code"
value-field="code"
label="Postcode">
<tpl-item>
{{code}}, {{town.name}} - {{town.province.name}}
({{town.province.country.country}})
</tpl-item>
</vn-autocomplete>
<vn-autocomplete vn-one
label="City" label="City"
url="/api/Towns"
show-field="name"
value-field="name"
field="$ctrl.client.city"> field="$ctrl.client.city">
</vn-textfield> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-autocomplete <vn-autocomplete vn-one
vn-one disabled="true"
field="$ctrl.client.countryFk"
url="/client/api/Countries"
show-field="country"
value-field="id"
label="Country">
</vn-autocomplete>
<vn-autocomplete
vn-one
field="$ctrl.client.provinceFk" field="$ctrl.client.provinceFk"
url="/client/api/Provinces" url="/api/Provinces"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Province"> label="Province">
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete vn-one
disabled="true"
field="$ctrl.client.countryFk"
url="/api/Countries"
show-field="country"
value-field="id"
label="Country">
</vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-textfield <vn-textfield

View File

@ -1,20 +1,34 @@
import ngModule from '../module'; import ngModule from '../module';
export default class Controller { export default class Controller {
constructor($scope, $state) { constructor($scope, $state, $http) {
this.$ = $scope; this.$ = $scope;
this.$state = $state; this.$state = $state;
this.$http = $http;
this.client = { this.client = {
active: true active: true
}; };
} }
setLocation() {
const location = this.$.postcode.selection;
if (!location || !location.town) return;
const town = location.town;
const province = town.province;
const country = province.country;
this.client.city = location.town.name;
this.client.provinceFk = province.id;
this.client.countryFk = country.id;
}
onSubmit() { onSubmit() {
this.$.watcher.submit().then( this.$.watcher.submit().then(
json => this.$state.go('client.card.basicData', {id: json.data.id}) json => this.$state.go('client.card.basicData', {id: json.data.id})
); );
} }
} }
Controller.$inject = ['$scope', '$state']; Controller.$inject = ['$scope', '$state', '$http'];
ngModule.component('vnClientCreate', { ngModule.component('vnClientCreate', {
template: require('./index.html'), template: require('./index.html'),

View File

@ -5,7 +5,7 @@
form="form" form="form"
save="patch"> save="patch">
</vn-watcher> </vn-watcher>
<form name="form" ng-submit="$ctrl.submit()" compact> <form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large> <vn-card pad-large>
<vn-horizontal> <vn-horizontal>
<vn-textfield <vn-textfield
@ -28,36 +28,45 @@
</vn-textfield> </vn-textfield>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-textfield <vn-autocomplete vn-id="postcode" vn-one
vn-one field="$ctrl.client.postcode"
label="Postcode" on-change="$ctrl.setLocation()"
field="$ctrl.client.postcode"> search-function="{code: $search}"
</vn-textfield> url="/api/Postcodes/location"
<vn-textfield fields="['code', 'townFk']"
vn-one show-field="code"
value-field="code"
label="Postcode">
<tpl-item>
{{code}}, {{town.name}} - {{town.province.name}}
({{town.province.country.country}})
</tpl-item>
</vn-autocomplete>
<vn-autocomplete vn-one
label="City" label="City"
url="/api/Towns"
show-field="name"
value-field="name"
field="$ctrl.client.city"> field="$ctrl.client.city">
</vn-textfield> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-autocomplete <vn-autocomplete vn-one
vn-one disabled="true"
initial-data="$ctrl.client.country"
field="$ctrl.client.countryFk"
url="/client/api/Countries"
show-field="country"
value-field="id"
label="Country">
</vn-autocomplete>
<vn-autocomplete
vn-one
initial-data="$ctrl.client.province"
field="$ctrl.client.provinceFk" field="$ctrl.client.provinceFk"
url="/client/api/Provinces" url="/api/Provinces"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Province"> label="Province">
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete vn-one
disabled="true"
field="$ctrl.client.countryFk"
url="/api/Countries"
show-field="country"
value-field="id"
label="Country">
</vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal pad-small-v> <vn-horizontal pad-small-v>
<vn-check <vn-check

View File

@ -24,7 +24,7 @@ export default class Controller {
return !this.client.isTaxDataChecked; return !this.client.isTaxDataChecked;
} }
submit() { onSubmit() {
if (this.isEqualizated != this.client.isEqualizated) { if (this.isEqualizated != this.client.isEqualizated) {
this.oldHasToInvoiceByAddress = this.client.hasToInvoiceByAddress; this.oldHasToInvoiceByAddress = this.client.hasToInvoiceByAddress;
this.client.hasToInvoiceByAddress = false; this.client.hasToInvoiceByAddress = false;
@ -56,6 +56,18 @@ export default class Controller {
); );
} }
} }
setLocation() {
const location = this.$.postcode.selection;
if (!location || !location.town) return;
const town = location.town;
const province = town.province;
const country = province.country;
this.client.city = location.town.name;
this.client.provinceFk = province.id;
this.client.countryFk = country.id;
}
} }
Controller.$inject = ['$scope', '$http', 'vnApp', '$translate']; Controller.$inject = ['$scope', '$http', 'vnApp', '$translate'];