diff --git a/back/model-config.json b/back/model-config.json index a0c3d8740..b24226507 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -11,6 +11,9 @@ "Company": { "dataSource": "vn" }, + "Container": { + "dataSource": "storage" + }, "Delivery": { "dataSource": "vn" }, @@ -44,8 +47,11 @@ "DmsType": { "dataSource": "vn" }, - "Container": { - "dataSource": "storage" + "Town": { + "dataSource": "vn" + }, + "Postcode": { + "dataSource": "vn" } } diff --git a/back/models/postcode.json b/back/models/postcode.json new file mode 100644 index 000000000..e28a77dc4 --- /dev/null +++ b/back/models/postcode.json @@ -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" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/back/models/town.json b/back/models/town.json new file mode 100644 index 000000000..8ae252780 --- /dev/null +++ b/back/models/town.json @@ -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" + }] + } + } +} \ No newline at end of file diff --git a/db/docker-boot.sh b/db/docker-boot.sh index 0d9eb9f35..6e04d3377 100755 --- a/db/docker-boot.sh +++ b/db/docker-boot.sh @@ -5,7 +5,7 @@ export MYSQL_PWD=root mysql_import() { FILE=$1 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 diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index c7bc0881e..eb44a0f75 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -147,6 +147,20 @@ INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `warehouseFk`, `zoneFk`) (4, 'Province four', 1, NULL, 2), (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`) VALUES (1, 'normal', 'Normal'), diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 908c22d68..3c264006b 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -33,7 +33,10 @@ export default { taxNumber: `${components.vnTextfield}[name="fi"]`, socialName: `${components.vnTextfield}[name="socialName"]`, 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"]`, email: `${components.vnTextfield}[name="email"]`, salesPersonAutocomplete: `vn-autocomplete[field="$ctrl.client.salesPersonFk"]`, @@ -62,8 +65,8 @@ export default { equalizationTaxCheckbox: 'vn-check[label="Is equalizated"] md-checkbox', acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]', addressInput: `${components.vnTextfield}[name="street"]`, - cityInput: `${components.vnTextfield}[name="city"]`, - postcodeInput: `${components.vnTextfield}[name="postcode"]`, + postcodeAutocomplete: `vn-autocomplete[field="$ctrl.client.postcode"]`, + cityAutocomplete: `vn-autocomplete[field="$ctrl.client.city"]`, provinceAutocomplete: 'vn-autocomplete[field="$ctrl.client.provinceFk"]', countryAutocomplete: 'vn-autocomplete[field="$ctrl.client.countryFk"]', activeCheckbox: 'vn-check[label="Active"] md-checkbox', @@ -97,8 +100,8 @@ export default { defaultCheckboxInput: 'vn-check[label="Default"] md-checkbox', consigneeInput: `${components.vnTextfield}[name="nickname"]`, streetAddressInput: `${components.vnTextfield}[name="street"]`, - postcodeInput: `${components.vnTextfield}[name="postalCode"]`, - cityInput: `${components.vnTextfield}[name="city"]`, + postcodeAutocomplete: `vn-autocomplete[field="$ctrl.address.postalCode"]`, + cityAutocomplete: `vn-autocomplete[field="$ctrl.address.city"]`, provinceAutocomplete: 'vn-autocomplete[field="$ctrl.address.provinceFk"]', agencyAutocomplete: 'vn-autocomplete[field="$ctrl.address.agencyModeFk"]', phoneInput: `${components.vnTextfield}[name="phone"]`, diff --git a/e2e/paths/02-client-module/01_create_client.spec.js b/e2e/paths/02-client-module/01_create_client.spec.js index 2d7b58b20..b9ea5e112 100644 --- a/e2e/paths/02-client-module/01_create_client.spec.js +++ b/e2e/paths/02-client-module/01_create_client.spec.js @@ -53,7 +53,7 @@ describe('Client create path', () => { .write(selectors.createClientView.name, 'Carol Danvers') .write(selectors.createClientView.socialName, 'AVG tax') .write(selectors.createClientView.street, 'Many places') - .write(selectors.createClientView.city, 'Silla') + .autocompleteSearch(selectors.createClientView.postcode, '46000') .clearInput(selectors.createClientView.email) .write(selectors.createClientView.email, 'incorrect email format') .waitToClick(selectors.createClientView.createButton) @@ -62,6 +62,21 @@ describe('Client create path', () => { 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() => { const result = await nightmare .clearInput(selectors.createClientView.email) diff --git a/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js b/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js index d424f0591..cd005cae0 100644 --- a/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js +++ b/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js @@ -67,11 +67,7 @@ describe('Client Edit fiscalData path', () => { .write(selectors.clientFiscalData.fiscalIdInput, 'INVALID!') .clearInput(selectors.clientFiscalData.addressInput) .write(selectors.clientFiscalData.addressInput, 'Somewhere edited') - .clearInput(selectors.clientFiscalData.postcodeInput) - .write(selectors.clientFiscalData.postcodeInput, '12345') - .clearInput(selectors.clientFiscalData.cityInput) - .write(selectors.clientFiscalData.cityInput, 'N/A') - .autocompleteSearch(selectors.clientFiscalData.provinceAutocomplete, 'Province two') + .autocompleteSearch(selectors.clientFiscalData.postcodeAutocomplete, '46000') .waitToClick(selectors.clientFiscalData.activeCheckbox) .waitToClick(selectors.clientFiscalData.frozenCheckbox) .waitToClick(selectors.clientFiscalData.hasToInvoiceCheckbox) @@ -197,23 +193,31 @@ describe('Client Edit fiscalData path', () => { it('should confirm the postcode have been edited', async() => { 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 - .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 .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() => { diff --git a/e2e/paths/02-client-module/05_add_address.spec.js b/e2e/paths/02-client-module/05_add_address.spec.js index e082b6d8c..5e21f87d8 100644 --- a/e2e/paths/02-client-module/05_add_address.spec.js +++ b/e2e/paths/02-client-module/05_add_address.spec.js @@ -24,8 +24,7 @@ describe('Client Add address path', () => { const result = await nightmare .waitToClick(selectors.clientAddresses.defaultCheckboxInput) .clearInput(selectors.clientAddresses.streetAddressInput) - .write(selectors.clientAddresses.postcodeInput, '10022') - .autocompleteSearch(selectors.clientAddresses.provinceAutocomplete, 'Province four') + .autocompleteSearch(selectors.clientAddresses.postcodeAutocomplete, '46000') .autocompleteSearch(selectors.clientAddresses.agencyAutocomplete, 'Entanglement') .write(selectors.clientAddresses.phoneInput, '999887744') .write(selectors.clientAddresses.mobileInput, '999887744') @@ -35,11 +34,32 @@ describe('Client Add address path', () => { 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() => { const result = await nightmare .write(selectors.clientAddresses.consigneeInput, 'Bruce Bunner') .write(selectors.clientAddresses.streetAddressInput, '320 Park Avenue New York') - .write(selectors.clientAddresses.cityInput, 'New York') .waitToClick(selectors.clientAddresses.saveButton) .waitForLastSnackbar(); diff --git a/front/core/components/autocomplete/autocomplete.html b/front/core/components/autocomplete/autocomplete.html index 2cd9a244a..ecb21fe2f 100755 --- a/front/core/components/autocomplete/autocomplete.html +++ b/front/core/components/autocomplete/autocomplete.html @@ -19,6 +19,6 @@ \ No newline at end of file diff --git a/front/core/components/autocomplete/autocomplete.js b/front/core/components/autocomplete/autocomplete.js index f651fd774..e9e2de374 100755 --- a/front/core/components/autocomplete/autocomplete.js +++ b/front/core/components/autocomplete/autocomplete.js @@ -79,10 +79,10 @@ export default class Autocomplete extends Input { } set field(value) { - if (angular.equals(value, this._field)) - return; - this._field = value; + + if (!value) return; + this.refreshSelection(); this.emit('change', {value}); } @@ -125,7 +125,9 @@ export default class Autocomplete extends Input { || this.selectionIsValid(this._selection)) return; - this.selection = this.fetchSelection(); + const selection = this.fetchSelection(); + if (!this.selection) + this.selection = selection; } fetchSelection() { @@ -217,7 +219,9 @@ export default class Autocomplete extends Input { if (this.form) this.form.$setDirty(); } - onDropDownSelect(value) { + onDropDownSelect(item) { + const value = item[this.valueField]; + this.selection = item; this.setValue(value); this.field = value; } diff --git a/front/core/components/button-menu/button-menu.html b/front/core/components/button-menu/button-menu.html index 80323a9d9..5beeb12fb 100644 --- a/front/core/components/button-menu/button-menu.html +++ b/front/core/components/button-menu/button-menu.html @@ -7,7 +7,7 @@ \ No newline at end of file diff --git a/front/core/components/button-menu/button-menu.js b/front/core/components/button-menu/button-menu.js index 41f26cfbe..319ca3f6f 100644 --- a/front/core/components/button-menu/button-menu.js +++ b/front/core/components/button-menu/button-menu.js @@ -53,7 +53,8 @@ export default class ButtonMenu extends Input { event.preventDefault(); } - onDropDownSelect(value) { + onDropDownSelect(item) { + const value = item[this.valueField]; this.field = value; this.emit('change', {value}); } diff --git a/front/core/components/button-menu/button-menu.spec.js b/front/core/components/button-menu/button-menu.spec.js index d8654466f..1e8c048ff 100644 --- a/front/core/components/button-menu/button-menu.spec.js +++ b/front/core/components/button-menu/button-menu.spec.js @@ -7,6 +7,7 @@ describe('Component vnButtonMenu', () => { beforeEach(inject(($compile, $rootScope) => { $element = $compile(``)($rootScope); controller = $element.controller('vnIconMenu'); + controller.valueField = 'name'; })); afterEach(() => { @@ -31,10 +32,10 @@ describe('Component vnButtonMenu', () => { describe('onDropDownSelect(value)', () => { it(`should set field to the given value and emit the change event`, () => { spyOn(controller, 'emit'); - controller.onDropDownSelect('mariano'); + controller.onDropDownSelect({name: 'Item name'}); - expect(controller.field).toBe('mariano'); - expect(controller.emit).toHaveBeenCalledWith('change', {value: 'mariano'}); + expect(controller.field).toBe('Item name'); + expect(controller.emit).toHaveBeenCalledWith('change', {value: 'Item name'}); }); }); }); diff --git a/front/core/components/drop-down/drop-down.html b/front/core/components/drop-down/drop-down.html index 9ec18044a..5fef1dd5e 100755 --- a/front/core/components/drop-down/drop-down.html +++ b/front/core/components/drop-down/drop-down.html @@ -8,7 +8,7 @@ model="$ctrl.search" class="search" ng-blur="$ctrl.onFocusOut()" - label = "Search"> + label="Search">
diff --git a/front/core/components/drop-down/drop-down.js b/front/core/components/drop-down/drop-down.js index d1cc11601..f027d1bf3 100755 --- a/front/core/components/drop-down/drop-down.js +++ b/front/core/components/drop-down/drop-down.js @@ -186,7 +186,7 @@ export default class DropDown extends Component { this.field = value; } - this.emit('select', {value: value}); + this.emit('select', {item}); } if (!this.multiple) diff --git a/front/core/components/icon-menu/icon-menu.html b/front/core/components/icon-menu/icon-menu.html index f59f24125..93de718ff 100644 --- a/front/core/components/icon-menu/icon-menu.html +++ b/front/core/components/icon-menu/icon-menu.html @@ -5,7 +5,7 @@
\ No newline at end of file diff --git a/modules/client/front/address/create/index.html b/modules/client/front/address/create/index.html index 344d56be7..58c5cf817 100644 --- a/modules/client/front/address/create/index.html +++ b/modules/client/front/address/create/index.html @@ -6,6 +6,14 @@ save="post" form="form"> + +
@@ -16,22 +24,40 @@ - - - + + {{code}}, {{town.name}} - {{town.province.name}} + ({{town.province.country.country}}) + + + + + - - + diff --git a/modules/client/front/address/create/index.js b/modules/client/front/address/create/index.js index 1334e6714..72a96d64a 100644 --- a/modules/client/front/address/create/index.js +++ b/modules/client/front/address/create/index.js @@ -1,8 +1,8 @@ import ngModule from '../../module'; export default class Controller { - constructor($scope, $state) { - this.$scope = $scope; + constructor($, $state) { + this.$ = $; this.$state = $state; this.data = { address: { @@ -14,8 +14,20 @@ export default class Controller { 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() { - this.$scope.watcher.submit().then(res => { + this.$.watcher.submit().then(res => { if (res.data && this.data.isDefaultAddress) this.client.defaultAddressFk = res.data.id; diff --git a/modules/client/front/address/create/index.spec.js b/modules/client/front/address/create/index.spec.js index cd1651b4b..5f447f0aa 100644 --- a/modules/client/front/address/create/index.spec.js +++ b/modules/client/front/address/create/index.spec.js @@ -14,8 +14,8 @@ describe('Client', () => { $state = _$state_; $state.params.id = '1234'; controller = $componentController('vnClientAddressCreate', {$state}); - controller.$scope.watcher = watcher; - controller.$scope.watcher.submit = () => { + controller.$.watcher = watcher; + controller.$.watcher.submit = () => { return { then: callback => { callback({data: {id: 124}}); diff --git a/modules/client/front/address/edit/index.html b/modules/client/front/address/edit/index.html index ea5aedde4..a19a6fa93 100644 --- a/modules/client/front/address/edit/index.html +++ b/modules/client/front/address/edit/index.html @@ -25,7 +25,7 @@ data="types" auto-load="true"> - + @@ -40,12 +40,31 @@ - - + + + {{code}}, {{town.name}} - {{town.province.name}} + ({{town.province.country.country}}) + + + + diff --git a/modules/client/front/address/edit/index.js b/modules/client/front/address/edit/index.js index c230dea91..ba5ac75c5 100644 --- a/modules/client/front/address/edit/index.js +++ b/modules/client/front/address/edit/index.js @@ -20,7 +20,19 @@ export default class Controller { 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.realSubmit() .then(() => this.$.model.save(true)) diff --git a/modules/client/front/create/index.html b/modules/client/front/create/index.html index dc80af713..605b15825 100644 --- a/modules/client/front/create/index.html +++ b/modules/client/front/create/index.html @@ -33,34 +33,45 @@ - - - + + {{code}}, {{town.name}} - {{town.province.name}} + ({{town.province.country.country}}) + + + - + - - - + + this.$state.go('client.card.basicData', {id: json.data.id}) ); } } -Controller.$inject = ['$scope', '$state']; +Controller.$inject = ['$scope', '$state', '$http']; ngModule.component('vnClientCreate', { template: require('./index.html'), diff --git a/modules/client/front/fiscal-data/index.html b/modules/client/front/fiscal-data/index.html index 14920b011..04bd1815f 100644 --- a/modules/client/front/fiscal-data/index.html +++ b/modules/client/front/fiscal-data/index.html @@ -5,7 +5,7 @@ form="form" save="patch"> - + - - - + + {{code}}, {{town.name}} - {{town.province.name}} + ({{town.province.country.country}}) + + + - + - - - + +