diff --git a/back/models/postcode.js b/back/models/postcode.js
new file mode 100644
index 000000000..b08fdaa40
--- /dev/null
+++ b/back/models/postcode.js
@@ -0,0 +1,9 @@
+let UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.rewriteDbError(function(err) {
+ if (err.code === 'ER_DUP_ENTRY')
+ return new UserError(`This postcode already exists`);
+ return err;
+ });
+};
diff --git a/back/models/town.json b/back/models/town.json
index 8ae252780..41633fe0a 100644
--- a/back/models/town.json
+++ b/back/models/town.json
@@ -41,16 +41,17 @@
"scopes": {
"location": {
"include": [{
+ "relation": "postcodes"
+ },
+ {
"relation": "province",
"scope": {
"include": {
"relation": "country"
}
}
- },
- {
- "relation": "postcodes"
- }]
+ }],
+ "fields": ["id", "name", "provinceFk"]
}
}
}
\ No newline at end of file
diff --git a/db/changes/10060-summer/00-ACL.sql b/db/changes/10060-summer/00-ACL.sql
index fab3cbe72..90f25f089 100644
--- a/db/changes/10060-summer/00-ACL.sql
+++ b/db/changes/10060-summer/00-ACL.sql
@@ -1,4 +1,5 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Zone', 'editPrices', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss'),
+ ('Postcode', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'addSale', 'WRITE', 'ALLOW', 'ROLE', 'employee');
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index 89830c372..7586b1846 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -116,7 +116,7 @@ export default {
firstObservationDescriptionInput: 'vn-client-address-edit [name=observations] :nth-child(1) [model="observation.description"] input',
secondObservationTypeAutocomplete: 'vn-client-address-edit [name=observations] :nth-child(2) [field="observation.observationTypeFk"]',
secondObservationDescriptionInput: 'vn-client-address-edit [name=observations] :nth-child(2) [model="observation.description"] input',
- addObservationButton: 'vn-client-address-edit vn-icon-button[icon="add_circle"]',
+ addObservationButton: 'vn-client-address-edit div[name="observations"] vn-icon-button[icon="add_circle"]',
saveButton: `${components.vnSubmit}`,
cancelCreateAddressButton: 'button[ui-sref="client.card.address.index"]',
cancelEditAddressButton: 'vn-client-address-edit > form > vn-button-bar > vn-button > button'
diff --git a/front/core/components/autocomplete/autocomplete.html b/front/core/components/autocomplete/autocomplete.html
index c616c794a..4caca44bc 100755
--- a/front/core/components/autocomplete/autocomplete.html
+++ b/front/core/components/autocomplete/autocomplete.html
@@ -16,7 +16,7 @@
diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js
index c2bf8463e..d03d52ae8 100644
--- a/loopback/common/models/vn-model.js
+++ b/loopback/common/models/vn-model.js
@@ -152,8 +152,9 @@ module.exports = function(Self) {
}
try {
- await realMethod.call(this, data, options);
- if (cb) cb();
+ const result = await realMethod.call(this, data, options);
+
+ if (cb) cb(null, result);
} catch (err) {
let myErr = replaceErr(err, replaceErrFunc);
if (cb)
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 34be59419..256b51205 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -93,5 +93,6 @@
"Extension format is invalid": "El formato de la extensión es inválido",
"Invalid parameters to create a new ticket": "Parámetros inválidos para crear un nuevo ticket",
"This item is not available": "Este artículo no está disponible",
+ "This postcode already exists": "Este código postal ya existe",
"Concept cannot be blank": "Concept cannot be blank"
}
\ 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 58c5cf817..9b3dc2ac2 100644
--- a/modules/client/front/address/create/index.html
+++ b/modules/client/front/address/create/index.html
@@ -24,9 +24,9 @@
-
+
+
+
+
+
+
diff --git a/modules/client/front/address/create/index.js b/modules/client/front/address/create/index.js
index 72a96d64a..bcccc0730 100644
--- a/modules/client/front/address/create/index.js
+++ b/modules/client/front/address/create/index.js
@@ -14,18 +14,28 @@ export default class Controller {
this.address = this.data.address;
}
- setLocation() {
- const location = this.$.postcode.selection;
- if (!location || !location.town) return;
- const town = location.town;
+ get postcodeSelection() {
+ return this._postcodeSelection;
+ }
+
+ set postcodeSelection(selection) {
+ this._postcodeSelection = selection;
+
+ if (!selection) return;
+
+ const town = selection.town;
const province = town.province;
const country = province.country;
- this.address.city = location.town.name;
+ this.address.city = town.name;
this.address.provinceFk = province.id;
this.address.countryFk = country.id;
}
+ onResponse(response) {
+ this.address.postalCode = response.code;
+ }
+
onSubmit() {
this.$.watcher.submit().then(res => {
if (res.data && this.data.isDefaultAddress)
diff --git a/modules/client/front/address/create/index.spec.js b/modules/client/front/address/create/index.spec.js
index 5f447f0aa..45b009de7 100644
--- a/modules/client/front/address/create/index.spec.js
+++ b/modules/client/front/address/create/index.spec.js
@@ -49,5 +49,30 @@ describe('Client', () => {
expect(controller.$state.go).toHaveBeenCalledWith('client.card.address.index');
});
});
+
+ describe('postcodeSelection() setter', () => {
+ it(`should set the town, province and contry properties`, () => {
+ controller.postcodeSelection = {
+ 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);
+ expect(controller.address.countryFk).toEqual(2);
+ });
+ });
});
});
diff --git a/modules/client/front/address/edit/index.html b/modules/client/front/address/edit/index.html
index a19a6fa93..b7361b71b 100644
--- a/modules/client/front/address/edit/index.html
+++ b/modules/client/front/address/edit/index.html
@@ -40,7 +40,7 @@
-
+
+
+
+
-
-
+
+
+
+
+
diff --git a/modules/client/front/address/edit/index.js b/modules/client/front/address/edit/index.js
index ba5ac75c5..14c5880bc 100644
--- a/modules/client/front/address/edit/index.js
+++ b/modules/client/front/address/edit/index.js
@@ -20,18 +20,28 @@ export default class Controller {
this.$state.go('client.card.address.index');
}
- setLocation() {
- const location = this.$.postcode.selection;
- if (!location || !location.town) return;
- const town = location.town;
+ get postcodeSelection() {
+ return this._postcodeSelection;
+ }
+
+ set postcodeSelection(selection) {
+ this._postcodeSelection = selection;
+
+ if (!selection) return;
+
+ const town = selection.town;
const province = town.province;
const country = province.country;
- this.address.city = location.town.name;
+ this.address.city = town.name;
this.address.provinceFk = province.id;
this.address.countryFk = country.id;
}
+ onResponse(response) {
+ this.address.postalCode = response.code;
+ }
+
onSubmit() {
this.$.watcher.check();
this.$.watcher.realSubmit()
diff --git a/modules/client/front/address/edit/index.spec.js b/modules/client/front/address/edit/index.spec.js
index aa1f59669..ea0da9559 100644
--- a/modules/client/front/address/edit/index.spec.js
+++ b/modules/client/front/address/edit/index.spec.js
@@ -55,5 +55,31 @@ describe('Client', () => {
expect(controller.$state.go).toHaveBeenCalledWith('client.card.address.index');
});
});
+
+ describe('postcodeSelection() setter', () => {
+ it(`should set the town, province and contry properties`, () => {
+ controller.address = {};
+ controller.postcodeSelection = {
+ 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);
+ expect(controller.address.countryFk).toEqual(2);
+ });
+ });
});
});
diff --git a/modules/client/front/address/index/index.html b/modules/client/front/address/index/index.html
index cdfd4d5a7..8696e321f 100644
--- a/modules/client/front/address/index/index.html
+++ b/modules/client/front/address/index/index.html
@@ -4,72 +4,70 @@
limit="10"
link="{clientFk: $ctrl.$stateParams.id}"
data="$ctrl.addresses"
- auto-load="false">
+ auto-load="true">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{::address.nickname}}
- {{::address.street}}
- {{::address.city}}, {{::address.province}}
- {{::address.phone}}, {{::address.mobile}}
-
-
-
-
-
-
-
-
-
- {{::observation.observationType.description}}:
- {{::observation.description}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{::address.nickname}}
+ {{::address.street}}
+ {{::address.city}}, {{::address.province}}
+ {{::address.phone}}, {{::address.mobile}}
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {{::observation.observationType.description}}:
+ {{::observation.description}}
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/client/front/create/index.js b/modules/client/front/create/index.js
index ec9c2817c..241de110f 100644
--- a/modules/client/front/create/index.js
+++ b/modules/client/front/create/index.js
@@ -1,34 +1,46 @@
import ngModule from '../module';
export default class Controller {
- constructor($scope, $state, $http) {
+ constructor($scope, $state, $http, $translate, vnApp) {
this.$ = $scope;
this.$state = $state;
this.$http = $http;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
this.client = {
active: true
};
}
- setLocation() {
- const location = this.$.postcode.selection;
- if (!location || !location.town) return;
- const town = location.town;
+ get postcodeSelection() {
+ return this._postcodeSelection;
+ }
+
+ set postcodeSelection(selection) {
+ this._postcodeSelection = selection;
+
+ if (!selection) return;
+
+ const town = selection.town;
const province = town.province;
const country = province.country;
- this.client.city = location.town.name;
+ this.client.city = town.name;
this.client.provinceFk = province.id;
this.client.countryFk = country.id;
}
+ onResponse(response) {
+ this.client.postcode = response.code;
+ }
+
onSubmit() {
- this.$.watcher.submit().then(
+ return this.$.watcher.submit().then(
json => this.$state.go('client.card.basicData', {id: json.data.id})
);
}
}
-Controller.$inject = ['$scope', '$state', '$http'];
+Controller.$inject = ['$scope', '$state', '$http', '$translate', 'vnApp'];
ngModule.component('vnClientCreate', {
template: require('./index.html'),
diff --git a/modules/client/front/create/index.spec.js b/modules/client/front/create/index.spec.js
index fb8aa227e..b59dffe44 100644
--- a/modules/client/front/create/index.spec.js
+++ b/modules/client/front/create/index.spec.js
@@ -39,5 +39,30 @@ describe('Client', () => {
expect(controller.$state.go).toHaveBeenCalledWith('client.card.basicData', {id: '1234'});
});
});
+
+ describe('postcodeSelection() setter', () => {
+ it(`should set the town, province and contry properties`, () => {
+ controller.postcodeSelection = {
+ 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);
+ });
+ });
});
});
diff --git a/modules/client/front/index.js b/modules/client/front/index.js
index f7e4368db..04439b9ab 100644
--- a/modules/client/front/index.js
+++ b/modules/client/front/index.js
@@ -35,5 +35,6 @@ import './sample/create';
import './web-payment';
import './log';
import './sms';
+import './postcode';
import './dms/index';
import './dms/create';
diff --git a/modules/client/front/postcode/index.html b/modules/client/front/postcode/index.html
new file mode 100644
index 000000000..5ff80440e
--- /dev/null
+++ b/modules/client/front/postcode/index.html
@@ -0,0 +1,47 @@
+
+
+ New postcode
+ Please, ensure you put the correct data!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/client/front/postcode/index.js b/modules/client/front/postcode/index.js
new file mode 100644
index 000000000..08a419dab
--- /dev/null
+++ b/modules/client/front/postcode/index.js
@@ -0,0 +1,70 @@
+import ngModule from '../module';
+import Component from 'core/lib/component';
+import './style.scss';
+
+class Controller extends Component {
+ constructor($element, $scope, $http, $translate, vnApp) {
+ super($element, $scope);
+ this.$ = $scope;
+ this.$http = $http;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
+ }
+
+ get townSelection() {
+ return this._townSelection;
+ }
+
+ set townSelection(selection) {
+ this._townSelection = selection;
+
+ if (!selection) return;
+
+ const province = selection.province;
+ const country = province.country;
+
+ this.data.provinceFk = province.id;
+ this.data.countryFk = country.id;
+ }
+
+ open() {
+ this.$.postcodeDialog.show();
+ }
+
+ onOpen() {
+ this.$.postcode.focus();
+ }
+
+ onResponse(response) {
+ if (response == 'ACCEPT') {
+ try {
+ if (!this.data.code)
+ throw new Error(`The postcode can't be empty`);
+ if (!this.data.townFk)
+ throw new Error(`The town can't be empty`);
+
+ this.$http.patch(`/api/postcodes`, this.data).then(response => {
+ if (response.data) {
+ this.vnApp.showMessage(this.$translate.instant('The postcode has been saved'));
+
+ this.emit('response', {response: response.data});
+ }
+ });
+ } catch (e) {
+ this.vnApp.showError(this.$translate.instant(e.message));
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+Controller.$inject = ['$element', '$scope', '$http', '$translate', 'vnApp'];
+
+ngModule.component('vnClientPostcode', {
+ template: require('./index.html'),
+ controller: Controller,
+ bindings: {
+ data: '<',
+ }
+});
diff --git a/modules/client/front/postcode/index.spec.js b/modules/client/front/postcode/index.spec.js
new file mode 100644
index 000000000..ce5cd5f2e
--- /dev/null
+++ b/modules/client/front/postcode/index.spec.js
@@ -0,0 +1,34 @@
+import './index';
+
+describe('Client', () => {
+ describe('Component vnClientPostcode', () => {
+ let controller;
+ let $httpBackend;
+ let $element;
+
+ beforeEach(ngModule('client'));
+
+ beforeEach(angular.mock.inject(($componentController, _$httpBackend_) => {
+ $httpBackend = _$httpBackend_;
+ $element = angular.element('');
+ controller = $componentController('vnClientPostcode', {$element});
+ controller.client = {id: 101};
+ }));
+
+ describe('onResponse()', () => {
+ it('should perform a POST query and show a success snackbar', () => {
+ let params = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
+ controller.data = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
+
+ spyOn(controller.vnApp, 'showMessage');
+ $httpBackend.when('PATCH', `/api/postcodes`, params).respond(200, params);
+ $httpBackend.expect('PATCH', `/api/postcodes`, params).respond(params);
+
+ controller.onResponse('ACCEPT');
+ $httpBackend.flush();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The postcode has been saved');
+ });
+ });
+ });
+});
diff --git a/modules/client/front/postcode/locale/es.yml b/modules/client/front/postcode/locale/es.yml
new file mode 100644
index 000000000..ab8b0fc21
--- /dev/null
+++ b/modules/client/front/postcode/locale/es.yml
@@ -0,0 +1,5 @@
+New postcode: Nuevo código postal
+Please, ensure you put the correct data!: ¡Por favor, asegúrate de poner los datos correctos!
+The postcode can't be empty: El código postal no puede quedar vacío
+The town can't be empty: La población no puede quedar vacía
+The postcode has been saved: El código postal ha sido guardado
\ No newline at end of file
diff --git a/modules/client/front/postcode/style.scss b/modules/client/front/postcode/style.scss
new file mode 100644
index 000000000..b9ef984b7
--- /dev/null
+++ b/modules/client/front/postcode/style.scss
@@ -0,0 +1,9 @@
+@import "variables";
+
+vn-client-postcode {
+ vn-dialog {
+ p {
+ color: $color-alert
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/item/back/methods/item/clone.js b/modules/item/back/methods/item/clone.js
index c4e15aa01..f543164fc 100644
--- a/modules/item/back/methods/item/clone.js
+++ b/modules/item/back/methods/item/clone.js
@@ -65,14 +65,19 @@ module.exports = Self => {
fields: ['botanical', 'countryFk', 'taxClassFk']
}, options);
+ const promises = [];
for (tax of originalTaxes) {
tax.itemFk = newId;
- await models.ItemTaxCountry.upsertWithWhere({
+ const newTax = models.ItemTaxCountry.upsertWithWhere({
itemFk: newId,
countryFk: tax.countryFk,
}, tax, options);
+
+ promises.push(newTax);
}
+
+ await Promise.all(promises);
}
/**
@@ -110,10 +115,14 @@ module.exports = Self => {
fields: ['tagFk', 'value', 'priority']
}, options);
+ const promises = [];
for (tag of originalTags) {
tag.itemFk = newId;
+ const newItemTag = models.ItemTag.create(tag, options);
- await models.ItemTag.create(tag, options);
+ promises.push(newItemTag);
}
+
+ await Promise.all(promises);
}
};
diff --git a/modules/ticket/back/methods/ticket/addSale.js b/modules/ticket/back/methods/ticket/addSale.js
index 595d036c5..dd3bdd218 100644
--- a/modules/ticket/back/methods/ticket/addSale.js
+++ b/modules/ticket/back/methods/ticket/addSale.js
@@ -43,7 +43,7 @@ module.exports = Self => {
const ticket = await models.Ticket.findById(id);
const shouldRefresh = false;
- const [[stock]] = await Self.rawSql(`CALL vn.getItemVisibleAvailable(?, ?, ?, ?)`, [
+ const [[stock]] = await Self.rawSql(`CALL vn.itemGetVisibleAvailable(?, ?, ?, ?)`, [
itemId,
ticket.shipped,
ticket.warehouseFk,