diff --git a/client/client/routes.json b/client/client/routes.json index c466ad7f9..73eb28fd3 100644 --- a/client/client/routes.json +++ b/client/client/routes.json @@ -220,6 +220,57 @@ "params": { "client": "$ctrl.client" } + }, + { + "url": "/credit-classification", + "abstract": true, + "state": "clientCard.creditClassification", + "component": "ui-view", + "acl": ["creditInsurance"] + }, + { + "url": "/list", + "state": "clientCard.creditClassification.list", + "component": "vn-client-credit-classification-list", + "params": { + "client": "$ctrl.client" + }, + "menu": { + "description": "Credit contracts", + "icon": "security" + }, + "acl": ["creditInsurance"] + }, + { + "url": "/create", + "state": "clientCard.creditClassification.create", + "component": "vn-client-credit-classification-create", + "params": { + "client": "$ctrl.client" + } + }, + { + "url": "/credit-insurance", + "abstract": true, + "state": "clientCard.creditInsurance", + "component": "ui-view", + "acl": ["creditInsurance"] + }, + { + "url": "/:classificationId/list", + "state": "clientCard.creditInsurance.list", + "component": "vn-client-credit-insurance-list", + "params": { + "client": "$ctrl.client" + } + }, + { + "url": "/:classificationId/create", + "state": "clientCard.creditInsurance.create", + "component": "vn-client-credit-insurance-create", + "params": { + "client": "$ctrl.client" + } } ] } diff --git a/client/client/src/address-edit/address-edit.html b/client/client/src/address-edit/address-edit.html index ba83368eb..cc50c1060 100644 --- a/client/client/src/address-edit/address-edit.html +++ b/client/client/src/address-edit/address-edit.html @@ -54,6 +54,7 @@ + + 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0; + canSubmitObservations = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0; if (repeatedTypes) { this.vnApp.showMessage( this.$translate.instant('The observation type must be unique') ); - } else if (canWatcherSubmit && !canObservationsSubmit) { + } else if (canSubmitWatcher && !canSubmitObservations) { this.$scope.watcher.submit().then(() => { this.$state.go('clientCard.addresses.list', {id: this.$state.params.id}); }); - } else if (!canWatcherSubmit && canObservationsSubmit) { + } else if (!canSubmitWatcher && canSubmitObservations) { this._submitObservations(observationsObj).then(() => { this.$state.go('clientCard.addresses.list', {id: this.$state.params.id}); }); - } else if (canWatcherSubmit && canObservationsSubmit) { + } else if (canSubmitWatcher && canSubmitObservations) { this.$q.all([this.$scope.watcher.submit(), this._submitObservations(observationsObj)]).then(() => { this.$state.go('clientCard.addresses.list', {id: this.$state.params.id}); }); @@ -113,7 +115,7 @@ export default class Controller { this._unsetDirtyForm(); } - $onInit() { + _getAddressNotes() { let filter = { where: {addressFk: this.address.id}, include: {relation: 'observationType'} @@ -121,10 +123,14 @@ export default class Controller { this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => { this.observations = res.data; res.data.forEach(item => { - this.observationsOld[item.id] = Object.assign({}, item); + this.oldObservations[item.id] = Object.assign({}, item); }); }); } + + $onInit() { + this._getAddressNotes(); + } } Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp']; diff --git a/client/client/src/client.js b/client/client/src/client.js index 935a33b43..f583127a2 100644 --- a/client/client/src/client.js +++ b/client/client/src/client.js @@ -23,3 +23,7 @@ import './invoices/invoices'; import './summary/client-summary'; import './recovery-list/recovery-list'; import './recovery-create/recovery-create'; +import './credit-classification-list/credit-classification-list'; +import './credit-classification-create/credit-classification-create'; +import './credit-insurance-list/credit-insurance-list'; +import './credit-insurance-create/credit-insurance-create'; diff --git a/client/client/src/credit-classification-create/credit-classification-create.html b/client/client/src/credit-classification-create/credit-classification-create.html new file mode 100644 index 000000000..a8aa58ada --- /dev/null +++ b/client/client/src/credit-classification-create/credit-classification-create.html @@ -0,0 +1,24 @@ + + + +
+ + New contract + + + + + + + + +
diff --git a/client/client/src/credit-classification-create/credit-classification-create.js b/client/client/src/credit-classification-create/credit-classification-create.js new file mode 100644 index 000000000..9e5c5de1d --- /dev/null +++ b/client/client/src/credit-classification-create/credit-classification-create.js @@ -0,0 +1,20 @@ +import ngModule from '../module'; + +class Controller { + constructor($filter, $state) { + this.creditClassification = { + started: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm') + }; + this.$state = $state; + } +} + +Controller.$inject = ['$filter', '$state']; + +ngModule.component('vnClientCreditClassificationCreate', { + template: require('./credit-classification-create.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-classification-list/credit-classification-list.html b/client/client/src/credit-classification-list/credit-classification-list.html new file mode 100644 index 000000000..827e73453 --- /dev/null +++ b/client/client/src/credit-classification-list/credit-classification-list.html @@ -0,0 +1,43 @@ + + + Contract credit insurance + + + + + lock_outline + + +
Since {{::classification.started | date:'dd/MM/yyyy'}}
+
To {{classification.finished | date:'dd/MM/yyyy'}}
+
+ + + Credit {{insurance.credit}} + Grade + - + {{insurance.grade}} + Date {{insurance.created | date:'dd/MM/yyyy' }} + + + + + +
+
+
+
+ + +
\ No newline at end of file diff --git a/client/client/src/credit-classification-list/credit-classification-list.js b/client/client/src/credit-classification-list/credit-classification-list.js new file mode 100644 index 000000000..6b8d479e9 --- /dev/null +++ b/client/client/src/credit-classification-list/credit-classification-list.js @@ -0,0 +1,68 @@ +import ngModule from '../module'; + +class Controller { + + constructor($http, $scope) { + this.$http = $http; + this.$scope = $scope; + } + + $onChanges() { + if (this.client && this.client.id) + this._getClassifications(this.client.id); + } + + _getClassifications(clientId) { + let filter = { + include: [ + { + relation: 'creditInsurances', + scope: { + fields: ['id', 'credit', 'created', 'grade'], + order: 'created DESC', + limit: 2 + } + } + + ], + where: {client: clientId} + }; + filter = encodeURIComponent(JSON.stringify(filter)); + + let query = `/client/api/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) { + let params = {finished: Date.now()}; + this.$http.patch(`/client/api/CreditClassifications/${classification.id}`, params).then(() => { + this._getClassifications(this.client.id); + }); + } +} + +Controller.$inject = ['$http', '$scope']; + +ngModule.component('vnClientCreditClassificationList', { + template: require('./credit-classification-list.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-classification-list/credit-classification-list.spec.js b/client/client/src/credit-classification-list/credit-classification-list.spec.js new file mode 100644 index 000000000..c233b6dc8 --- /dev/null +++ b/client/client/src/credit-classification-list/credit-classification-list.spec.js @@ -0,0 +1,80 @@ +import './credit-classification-list.js'; + +describe('Client', () => { + describe('Component vnClientCreditClassificationList', () => { + let $componentController; + let controller; + let $httpBackend; + + beforeEach(() => { + angular.mock.module('client'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => { + $componentController = _$componentController_; + $httpBackend = _$httpBackend_; + controller = $componentController('vnClientCreditClassificationList'); + })); + + describe('_getClassifications()', () => { + it('should perform a GET query to define the classifications property in the controller', () => { + let res = ['some classifications']; + let query = '/client/api/CreditClassifications?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22creditInsurances%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.now()}, + {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.now()}, + {finished: Date.now()} + ]; + + let result = controller.canCreateNew(); + + expect(result).toBeTruthy(); + }); + }); + + describe('closeContract()', () => { + it('should perform a GET query to set a due date to a contract', () => { + let res = ['pepinillos']; + controller.client = {id: 101}; + let classification = {id: 1}; + let query = '/client/api/CreditClassifications/1'; + spyOn(controller, '_getClassifications'); + + $httpBackend.whenPATCH(query).respond(res); + $httpBackend.expectPATCH(query); + controller.closeContract(classification); + $httpBackend.flush(); + + expect(controller._getClassifications).toHaveBeenCalledWith(101); + }); + }); + }); +}); diff --git a/client/client/src/credit-classification-list/locale/es.yml b/client/client/src/credit-classification-list/locale/es.yml new file mode 100644 index 000000000..aec6b185a --- /dev/null +++ b/client/client/src/credit-classification-list/locale/es.yml @@ -0,0 +1,4 @@ +Contract credit insurance: Contratos de seguro de crédito +New contract: Nuevo contrato +Close contract: Cerrar contrato +Edit contract: Modificar contrato \ No newline at end of file diff --git a/client/client/src/credit-insurance-create/credit-insurance-create.html b/client/client/src/credit-insurance-create/credit-insurance-create.html new file mode 100644 index 000000000..8d8005187 --- /dev/null +++ b/client/client/src/credit-insurance-create/credit-insurance-create.html @@ -0,0 +1,42 @@ + + + +
+ + New credit + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/client/client/src/credit-insurance-create/credit-insurance-create.js b/client/client/src/credit-insurance-create/credit-insurance-create.js new file mode 100644 index 000000000..f9d22189f --- /dev/null +++ b/client/client/src/credit-insurance-create/credit-insurance-create.js @@ -0,0 +1,20 @@ +import ngModule from '../module'; + +class Controller { + constructor($state, $filter) { + this.insurance = { + created: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm') + }; + this.classificationId = $state.params.classificationId; + } +} + +Controller.$inject = ['$state', '$filter']; + +ngModule.component('vnClientCreditInsuranceCreate', { + template: require('./credit-insurance-create.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-insurance-create/locale/es.yml b/client/client/src/credit-insurance-create/locale/es.yml new file mode 100644 index 000000000..deb27ae21 --- /dev/null +++ b/client/client/src/credit-insurance-create/locale/es.yml @@ -0,0 +1 @@ +New credit: Añadir crédito \ No newline at end of file diff --git a/client/client/src/credit-insurance-list/credit-insurance-list.html b/client/client/src/credit-insurance-list/credit-insurance-list.html new file mode 100644 index 000000000..ba3931013 --- /dev/null +++ b/client/client/src/credit-insurance-list/credit-insurance-list.html @@ -0,0 +1,28 @@ + + + + + Requested credits + + + + + + + + {{insurance.credit}} + {{insurance.grade}} + {{insurance.created | date: 'dd/MM/yyyy'}} + + + + + + + + + \ No newline at end of file diff --git a/client/client/src/credit-insurance-list/credit-insurance-list.js b/client/client/src/credit-insurance-list/credit-insurance-list.js new file mode 100644 index 000000000..73403f375 --- /dev/null +++ b/client/client/src/credit-insurance-list/credit-insurance-list.js @@ -0,0 +1,17 @@ +import ngModule from '../module'; + +class Controller { + constructor($state) { + this.classificationId = $state.params.classificationId; + } +} + +Controller.$inject = ['$state']; + +ngModule.component('vnClientCreditInsuranceList', { + template: require('./credit-insurance-list.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-insurance-list/locale/es.yml b/client/client/src/credit-insurance-list/locale/es.yml new file mode 100644 index 000000000..b21b6b030 --- /dev/null +++ b/client/client/src/credit-insurance-list/locale/es.yml @@ -0,0 +1 @@ +Requested credits: Créditos solicitados \ No newline at end of file diff --git a/client/client/src/descriptor/descriptor.html b/client/client/src/descriptor/descriptor.html index 950baf89c..8d2c825df 100644 --- a/client/client/src/descriptor/descriptor.html +++ b/client/client/src/descriptor/descriptor.html @@ -25,30 +25,36 @@ - - + + +
\ No newline at end of file diff --git a/client/client/src/fiscal-data/fiscal-data.html b/client/client/src/fiscal-data/fiscal-data.html index b70dd319f..b0493cd25 100644 --- a/client/client/src/fiscal-data/fiscal-data.html +++ b/client/client/src/fiscal-data/fiscal-data.html @@ -89,13 +89,20 @@ + + diff --git a/client/client/src/locale/es.yml b/client/client/src/locale/es.yml index bb2984d9b..c46f0430a 100644 --- a/client/client/src/locale/es.yml +++ b/client/client/src/locale/es.yml @@ -17,7 +17,7 @@ Save: Guardar Pay method : Forma de pago Address: Consignatario Credit : Crédito -Secured credit: Crédito asegurado +Credit contracts: Contratos de crédito Verified data: Datos comprobados Mandate: Mandato Amount: Importe \ No newline at end of file diff --git a/client/client/src/summary/client-summary.html b/client/client/src/summary/client-summary.html index e506ae23e..a720f9c41 100644 --- a/client/client/src/summary/client-summary.html +++ b/client/client/src/summary/client-summary.html @@ -123,8 +123,8 @@
Recovery
-

Since {{$ctrl.recovery.started}}

-

To {{$ctrl.recovery.finished}}

+

Since {{$ctrl.recovery.started | date:'dd/MM/yyyy'}}

+

To {{$ctrl.recovery.finished | date:'dd/MM/yyyy'}}

Amount {{$ctrl.recovery.amount | currency:'€':2}}

Period {{$ctrl.recovery.period}}

@@ -145,8 +145,8 @@

Secured credit - - - {{$ctrl.summary.creditInsurance | currency:'€':2}} + - + {{$ctrl.summary.creditInsurance | currency:'€':2}}

diff --git a/client/client/src/summary/client-summary.js b/client/client/src/summary/client-summary.js index a3e7c7bae..2a6b9e3f3 100644 --- a/client/client/src/summary/client-summary.js +++ b/client/client/src/summary/client-summary.js @@ -1,53 +1,29 @@ import ngModule from '../module'; -class ClientSummary { +class Controller { constructor($http) { this.$http = $http; } - set client(value) { - if (!value) + $onChanges() { + if (!this.client || !this.client.id) return; + this.getSummary(); + this.getGreuse(); + this.getRecoveries(); + } + + getSummary() { let filter = { include: [ - { - relation: 'account', - scope: { - fields: ['name', 'active'] - } - }, - { - relation: 'salesPerson', - scope: { - fields: ['name'] - } - }, - { - relation: 'country', - scope: { - fields: ['country'] - } - }, - { - relation: 'province', - scope: { - fields: ['name'] - } - }, - { - relation: 'contactChannel', - scope: { - fields: ['name'] - } - }, - { - relation: 'payMethod', - scope: { - fields: ['name'] - } - }, + {relation: 'account', scope: {fields: ['name', 'active']}}, + {relation: 'salesPerson', scope: {fields: ['name']}}, + {relation: 'country', scope: {fields: ['country']}}, + {relation: 'province', scope: {fields: ['name']}}, + {relation: 'contactChannel', scope: {fields: ['name']}}, + {relation: 'payMethod', scope: {fields: ['name']}}, { relation: 'addresses', scope: { @@ -57,43 +33,46 @@ class ClientSummary { } ] }; + filter = encodeURIComponent(JSON.stringify(filter)); - let clientSummary = `/client/api/Clients/${value.id}?filter=${JSON.stringify(filter)}`; - - this.$http.get(encodeURIComponent(clientSummary)).then(res => { + let query = `/client/api/Clients/${this.client.id}?filter=${filter}`; + this.$http.get(query).then(res => { if (res.data) { this.summary = res.data; this.address = res.data.addresses[0]; } }); + } - let greugeSum = `/client/api/Greuges/${value.id}/sumAmount`; - - this.$http.get(encodeURIComponent(greugeSum)).then(res => { + getGreuse() { + let query = `/client/api/Greuges/${this.client.id}/sumAmount`; + this.$http.get(query).then(res => { if (res.data) this.greuge = res.data; }); + } - let recoveryFilter = { + getRecoveries() { + let filter = { where: { - and: [{clientFk: value.id}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}] + and: [{clientFk: this.client.id}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}] }, limit: 1 }; + filter = encodeURIComponent(JSON.stringify(filter)); - let recovery = `/client/api/Recoveries?filter=${JSON.stringify(recoveryFilter)}`; - - this.$http.get(encodeURIComponent(recovery)).then(res => { + let query = `/client/api/Recoveries?filter=${filter}`; + this.$http.get(query).then(res => { if (res.data) this.recovery = res.data[0]; }); } } -ClientSummary.$inject = ['$http']; +Controller.$inject = ['$http']; ngModule.component('vnClientSummary', { template: require('./client-summary.html'), - controller: ClientSummary, + controller: Controller, bindings: { client: '<' } diff --git a/client/client/src/web-access/locale/es.yml b/client/client/src/web-access/locale/es.yml index 2d1905c16..9d95dcc24 100644 --- a/client/client/src/web-access/locale/es.yml +++ b/client/client/src/web-access/locale/es.yml @@ -2,4 +2,5 @@ User: Usuario Enable web access: Habilitar acceso web New password: Nueva contraseña Repeat password: Repetir contraseña -Change password: Cambiar contraseña \ No newline at end of file +Change password: Cambiar contraseña +Client must be checked to activate: No se puede activar un cliente si no esta verificado (036) \ No newline at end of file diff --git a/client/client/src/web-access/web-access.html b/client/client/src/web-access/web-access.html index 47e05759a..7c9b87df9 100644 --- a/client/client/src/web-access/web-access.html +++ b/client/client/src/web-access/web-access.html @@ -23,6 +23,7 @@ vn-one margin-medium-top label="User" + info="Client must be checked to activate" field="$ctrl.account.name"> diff --git a/client/core/src/components/autocomplete/autocomplete.html b/client/core/src/components/autocomplete/autocomplete.html index 0ee10c5ae..4d04f884f 100755 --- a/client/core/src/components/autocomplete/autocomplete.html +++ b/client/core/src/components/autocomplete/autocomplete.html @@ -16,8 +16,8 @@ - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/client/core/src/components/drop-down/drop-down.js b/client/core/src/components/drop-down/drop-down.js index 482297618..07a856273 100755 --- a/client/core/src/components/drop-down/drop-down.js +++ b/client/core/src/components/drop-down/drop-down.js @@ -45,6 +45,9 @@ export default class DropDown extends Component { this._search = value; this.$.model.clear(); + if (value != null) + this._activeOption = 0; + this.$timeout.cancel(this.searchTimeout); this.searchTimeout = this.$timeout(() => { this.refreshModel(); @@ -86,8 +89,8 @@ export default class DropDown extends Component { * @param {String} search The initial search term or %null */ show(search) { - this.search = search; this._activeOption = -1; + this.search = search; this.buildList(); this.$.popover.parent = this.parent; this.$.popover.show(); @@ -101,7 +104,7 @@ export default class DropDown extends Component { } /** - * Activates a option and scrolls the drop-down to that option. + * Activates an option and scrolls the drop-down to that option. * * @param {Number} option The option index */ @@ -122,7 +125,7 @@ export default class DropDown extends Component { } /** - * Activates a option. + * Activates an option. * * @param {Number} option The option index */ @@ -146,10 +149,11 @@ export default class DropDown extends Component { * @param {Number} option The option index */ selectOption(option) { - if (option != -1) { - let data = this.$.model.data; - let item = data ? data[option] : null; - let value = item ? item[this.valueField] : null; + let data = this.$.model.data; + let item = option != -1 && data ? data[option] : null; + + if (item) { + let value = item[this.valueField]; if (this.multiple) { if (!Array.isArray(this.selection)) { @@ -252,6 +256,9 @@ export default class DropDown extends Component { let nOpts = data ? data.length - 1 : 0; switch (event.keyCode) { + case 9: // Tab + this.selectOption(option); + return; case 13: // Enter this.selectOption(option); break; diff --git a/client/core/src/components/popover/popover.js b/client/core/src/components/popover/popover.js index 4e2326c77..4df7cc115 100644 --- a/client/core/src/components/popover/popover.js +++ b/client/core/src/components/popover/popover.js @@ -88,6 +88,9 @@ export default class Popover extends Component { this.showTimeout = this.$timeout(() => { this.element.style.display = 'none'; this.showTimeout = null; + + if (this.onClose) + this.onClose(); }, 250); this.document.removeEventListener('keydown', this.docKeyDownHandler); @@ -95,12 +98,6 @@ export default class Popover extends Component { if (this.deregisterCallback) this.deregisterCallback(); - - if (this.parent) - this.parent.focus(); - - if (this.onClose) - this.onClose(); } /** @@ -189,35 +186,3 @@ ngModule.component('vnPopover', { onClose: '&?' } }); - -class PopoverService { - constructor($document, $compile, $transitions, $rootScope) { - this.$compile = $compile; - this.$rootScope = $rootScope; - this.$document = $document; - this.stack = []; - } - show(child, parent, $scope) { - let element = this.$compile('')($scope || this.$rootScope)[0]; - let popover = element.$ctrl; - popover.parent = parent; - popover.child = child; - popover.show(); - popover.onClose = () => { - this.$document[0].body.removeChild(element); - if ($scope) $scope.$destroy(); - }; - this.$document[0].body.appendChild(element); - return popover; - } - - showComponent(componentTag, $scope, parent) { - let $newScope = $scope.$new(); - let childElement = this.$compile(`<${componentTag}/>`)($newScope)[0]; - this.show(childElement, parent, $newScope); - return childElement; - } -} -PopoverService.$inject = ['$document', '$compile', '$transitions', '$rootScope']; - -ngModule.service('vnPopover', PopoverService); diff --git a/client/core/src/components/textfield/textfield.html b/client/core/src/components/textfield/textfield.html index 43599186b..7f39ccf64 100644 --- a/client/core/src/components/textfield/textfield.html +++ b/client/core/src/components/textfield/textfield.html @@ -1,8 +1,8 @@ -
- + ng-blur="$ctrl.hasFocus = false"/>
{ @@ -30,11 +31,13 @@ export default class Controller { this.$scope.form.$setDirty(); } } + _unsetDirtyForm() { if (this.$scope.form) { this.$scope.form.$setPristine(); } } + _equalBarcodes(oldBarcode, newBarcode) { return oldBarcode.id === newBarcode.id && oldBarcode.code === newBarcode.code; } diff --git a/client/item/src/niche/item-niche.html b/client/item/src/niche/item-niche.html index ae30034db..068eedb41 100644 --- a/client/item/src/niche/item-niche.html +++ b/client/item/src/niche/item-niche.html @@ -8,7 +8,8 @@ Item Niches + + { this.niches = response.data; this.setOldNiches(response); @@ -95,6 +97,7 @@ export default class Controller { create: [], update: [] }; + this.niches.forEach(niche => { let isNewNiche = !niche.id; diff --git a/client/item/src/niche/item-niche.spec.js b/client/item/src/niche/item-niche.spec.js index 3218f262e..e223133d9 100644 --- a/client/item/src/niche/item-niche.spec.js +++ b/client/item/src/niche/item-niche.spec.js @@ -92,7 +92,7 @@ describe('Item', () => { }); describe('submit()', () => { - it("should return an error message 'The niche must be unique' when the niche code isnt unique", () => { + it("should return an error message 'The niche must be unique' when the niche warehouse isnt unique", () => { controller.$scope.form = {}; spyOn(controller.vnApp, 'showMessage').and.callThrough(); controller.niches = [ diff --git a/client/item/src/tags/item-tags.html b/client/item/src/tags/item-tags.html index 318a5dec7..c92a13292 100644 --- a/client/item/src/tags/item-tags.html +++ b/client/item/src/tags/item-tags.html @@ -8,6 +8,7 @@ Item tags + + - - - - - - - - \ No newline at end of file + + + + + + + + + + diff --git a/client/salix/src/components/searchbar/searchbar.js b/client/salix/src/components/searchbar/searchbar.js index 324ddf5a4..81e71198c 100644 --- a/client/salix/src/components/searchbar/searchbar.js +++ b/client/salix/src/components/searchbar/searchbar.js @@ -1,12 +1,10 @@ import ngModule from '../../module'; export default class Controller { - constructor($element, $scope, $document, $compile, vnPopover, $timeout, $state, $transitions) { + constructor($element, $scope, $compile, $timeout, $state, $transitions) { this.element = $element[0]; - this.$scope = $scope; - this.$document = $document; + this.$ = $scope; this.$compile = $compile; - this.vnPopover = vnPopover; this.$timeout = $timeout; this.stringSearch = ''; this.$state = $state; @@ -91,23 +89,32 @@ export default class Controller { filter = this.getFiltersFromString(this.stringSearch); } - this.child = this.vnPopover.showComponent(this.popover, this.$scope, this.element); + this.$child = this.$compile(`<${this.popover}/>`)(this.$.$new()); - // XXX: ¿Existe una forma más adecuada de acceder al controlador de un componente? - var childCtrl = angular.element(this.child).isolateScope().$ctrl; + var childCtrl = this.$child.isolateScope().$ctrl; childCtrl.filter = Object.assign({}, filter); childCtrl.onSubmit = filter => this.onChildSubmit(filter); if (this.data) childCtrl.data = Object.assign({}, this.data); + event.preventDefault(); + + this.$.popover.parent = this.element; + this.$.popover.child = this.$child[0]; + this.$.popover.show(); + } + + onPopoverClose() { + this.$child.scope().$destroy(); + this.$child.remove(); + this.$child = null; } onChildSubmit(filter) { + this.$.popover.hide(); this.stringSearch = this.createStringFromObject(filter); this.clearFilter(); - this.$timeout(() => { - this.onSubmit(); - }); + this.$timeout(() => this.onSubmit()); } onSubmit() { @@ -120,12 +127,6 @@ export default class Controller { if (this.onSearch) this.onSearch(); - if (angular.element(this.child)) { - if (angular.element(this.child).scope()) - angular.element(this.child).scope().$destroy(); - angular.element(this.child).remove(); - } - delete this.child; this.pushFiltersToState(filter); } @@ -139,12 +140,10 @@ export default class Controller { let filter = JSON.parse(decodeURIComponent(this.$state.params.q)); this.stringSearch = this.createStringFromObject(filter); } - this.$timeout(() => { - this.onSubmit(); - }); + this.$timeout(() => this.onSubmit()); } } -Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$timeout', '$state', '$transitions']; +Controller.$inject = ['$element', '$scope', '$compile', '$timeout', '$state', '$transitions']; ngModule.component('vnSearchbar', { template: require('./searchbar.html'), diff --git a/client/salix/src/locale/es.yml b/client/salix/src/locale/es.yml index fe3cdf228..e1ba19aa9 100644 --- a/client/salix/src/locale/es.yml +++ b/client/salix/src/locale/es.yml @@ -18,4 +18,9 @@ credit: Crédito phone: Teléfono creditInsurance: Crédito Asegurado Return to module index: Volver a la página principal del módulo -Preview: Vista previa \ No newline at end of file +Preview: Vista previa +Client has debt: Cliente con riesgo +Web Account inactive: Sin acceso Web +Client Frozen: Cliente congelado +Client inactive: Cliente inactivo +Client not checked: Cliente no comprobado \ No newline at end of file diff --git a/client/salix/src/styles/misc.scss b/client/salix/src/styles/misc.scss index e20bda7ed..b90297764 100644 --- a/client/salix/src/styles/misc.scss +++ b/client/salix/src/styles/misc.scss @@ -215,7 +215,7 @@ vn-main-block { color: #ffa410; margin-left: .5em; transition: opacity 250ms ease-out; - + font-size: 2em; &:hover { opacity: 1; } diff --git a/client/ticket/routes.json b/client/ticket/routes.json index 8fd9b65f5..e0c476028 100644 --- a/client/ticket/routes.json +++ b/client/ticket/routes.json @@ -1,14 +1,92 @@ { "module": "ticket", "name": "Tickets", - "icon": "receipt", + "icon": "icon-ticket", "validations": false, "routes": [ { - "url": "/tickets", - "state": "tickets", - "component": "vn-ticket-index", - "acl": ["developer"] + "url": "/ticket", + "state": "ticket", + "abstract": true, + "component": "ui-view" + }, + { + "url": "/list?q", + "state": "ticket.list", + "component": "vn-ticket-list" + }, + { + "url": "/create", + "state": "ticket.create", + "component": "vn-ticket-create" + }, + { + "url": "/:id", + "state": "ticket.card", + "abstract": true, + "component": "vn-ticket-card" + }, + { + "url": "/summary", + "state": "ticket.card.summary", + "component": "vn-ticket-summary", + "params": { + "ticket": "$ctrl.ticket" + } + }, + { + "url" : "/data", + "state": "ticket.card.data", + "component": "vn-ticket-data", + "params": { + "ticket": "$ctrl.ticket" + }, + "menu": { + "description": "Basic data", + "icon": "settings" + } + }, + { + "url": "/observations", + "state": "ticket.card.observations", + "component": "vn-ticket-observations", + "params": { + "ticket": "$ctrl.ticket" + }, + "menu": { + "description": "Notes", + "icon": "insert_drive_file" + } + }, + { + "url" : "/package", + "abstract": true, + "state": "ticket.card.package", + "component": "ui-view" + }, + { + "url": "/list", + "state": "ticket.card.package.list", + "component": "vn-ticket-package-list", + "params": { + "ticket": "$ctrl.ticket" + }, + "menu": { + "description": "Packages", + "icon": "icon-bucket" + } + }, + { + "url" : "/review", + "state": "ticket.card.review", + "component": "vn-ticket-review", + "params": { + "ticket": "$ctrl.ticket" + }, + "menu": { + "description": "Review", + "icon": "remove_red_eye" + } } ] } \ No newline at end of file diff --git a/client/ticket/src/card/ticket-card.html b/client/ticket/src/card/ticket-card.html new file mode 100644 index 000000000..266252ee5 --- /dev/null +++ b/client/ticket/src/card/ticket-card.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/client/ticket/src/card/ticket-card.js b/client/ticket/src/card/ticket-card.js new file mode 100644 index 000000000..8f3ea3462 --- /dev/null +++ b/client/ticket/src/card/ticket-card.js @@ -0,0 +1,35 @@ +import ngModule from '../module'; + +class TicketCard { + constructor($http, $state, $timeout) { + this.$http = $http; + this.$state = $state; + this.$timeout = $timeout; + + this.ticket = null; + } + + _getTicket() { + let filter = { + }; + this.$http.get(`/ticket/api/Tickets/${this.$state.params.id}?filter=${JSON.stringify(filter)}`) + .then(res => { + if (res.data && res.data.id) { + this.$timeout(() => { + this.ticket = res.data; + }); + } + } + ); + } + + $onInit() { + this._getTicket(); + } +} +TicketCard.$inject = ['$http', '$state', '$timeout']; + +ngModule.component('vnTicketCard', { + template: require('./ticket-card.html'), + controller: TicketCard +}); diff --git a/client/ticket/src/create/ticket-create.html b/client/ticket/src/create/ticket-create.html new file mode 100644 index 000000000..1542ffbc4 --- /dev/null +++ b/client/ticket/src/create/ticket-create.html @@ -0,0 +1,18 @@ + + + +
+
+ + New ticket + + + + + +
+
diff --git a/client/ticket/src/create/ticket-create.js b/client/ticket/src/create/ticket-create.js new file mode 100644 index 000000000..f9b33c16d --- /dev/null +++ b/client/ticket/src/create/ticket-create.js @@ -0,0 +1,21 @@ +import ngModule from '../module'; + +class TicketCreate { + constructor($scope, $state) { + this.$ = $scope; + this.$state = $state; + this.Ticket = {}; + } + + onSubmit() { + this.$.watcher.submit().then( + json => this.$state.go('ticket.card.data', {id: json.data.id}) + ); + } +} +TicketCreate.$inject = ['$scope', '$state']; + +ngModule.component('vnTicketCreate', { + template: require('./ticket-create.html'), + controller: TicketCreate +}); diff --git a/client/ticket/src/data/ticket-data.html b/client/ticket/src/data/ticket-data.html new file mode 100644 index 000000000..e69de29bb diff --git a/client/ticket/src/data/ticket-data.js b/client/ticket/src/data/ticket-data.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/ticket/src/index/style.scss b/client/ticket/src/list/style.scss similarity index 100% rename from client/ticket/src/index/style.scss rename to client/ticket/src/list/style.scss diff --git a/client/ticket/src/index/item.html b/client/ticket/src/list/ticket-item.html similarity index 79% rename from client/ticket/src/index/item.html rename to client/ticket/src/list/ticket-item.html index eed354bff..c46590caf 100644 --- a/client/ticket/src/index/item.html +++ b/client/ticket/src/list/ticket-item.html @@ -1,10 +1,10 @@ -
{{::$ctrl.ticket.name}}
+
{{::$ctrl.ticket.nickname}}
Id {{::$ctrl.ticket.id}}
diff --git a/client/ticket/src/index/item.js b/client/ticket/src/list/ticket-item.js similarity index 88% rename from client/ticket/src/index/item.js rename to client/ticket/src/list/ticket-item.js index c48d773f1..da58c89cd 100644 --- a/client/ticket/src/index/item.js +++ b/client/ticket/src/list/ticket-item.js @@ -13,7 +13,7 @@ class Controller { ngModule.component('vnTicketItem', { controller: Controller, - template: require('./item.html'), + template: require('./ticket-item.html'), bindings: { ticket: '<' } diff --git a/client/ticket/src/index/index.html b/client/ticket/src/list/ticket-list.html similarity index 79% rename from client/ticket/src/index/index.html rename to client/ticket/src/list/ticket-list.html index 51a50474c..51750d20a 100644 --- a/client/ticket/src/index/index.html +++ b/client/ticket/src/list/ticket-list.html @@ -1,4 +1,4 @@ - +
@@ -19,6 +19,6 @@
-
- + + diff --git a/client/ticket/src/index/index.js b/client/ticket/src/list/ticket-list.js similarity index 57% rename from client/ticket/src/index/index.js rename to client/ticket/src/list/ticket-list.js index bc514194c..f1538f300 100644 --- a/client/ticket/src/index/index.js +++ b/client/ticket/src/list/ticket-list.js @@ -1,5 +1,6 @@ import ngModule from '../module'; -import './item'; +import './ticket-item'; +import './style.scss'; export default class Controller { search(index) { @@ -8,7 +9,7 @@ export default class Controller { } Controller.$inject = []; -ngModule.component('vnTicketIndex', { - template: require('./index.html'), +ngModule.component('vnTicketList', { + template: require('./ticket-list.html'), controller: Controller }); diff --git a/client/ticket/src/locale/es.yml b/client/ticket/src/locale/es.yml index 1f272d420..e65b6ab54 100644 --- a/client/ticket/src/locale/es.yml +++ b/client/ticket/src/locale/es.yml @@ -1 +1,6 @@ -Tickets: Tickets \ No newline at end of file +Tickets: Tickets +Notes: Notas +Observation type: Tipo de observación +Description: Descripción +The observation type must be unique: El tipo de observación debe ser único +Some fields are invalid: Algunos campos no son válidos \ No newline at end of file diff --git a/client/ticket/src/notes/ticket-observations.html b/client/ticket/src/notes/ticket-observations.html new file mode 100644 index 000000000..b48ec5a72 --- /dev/null +++ b/client/ticket/src/notes/ticket-observations.html @@ -0,0 +1,60 @@ + + +
+ + + Notes + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/client/ticket/src/notes/ticket-observations.js b/client/ticket/src/notes/ticket-observations.js new file mode 100644 index 000000000..793865fde --- /dev/null +++ b/client/ticket/src/notes/ticket-observations.js @@ -0,0 +1,140 @@ +import ngModule from '../module'; + +class TicketObservations { + constructor($stateParams, $scope, $http, $translate, vnApp) { + this.params = $stateParams; + this.$scope = $scope; + this.$http = $http; + this.$translate = $translate; + this.vnApp = vnApp; + + this.ticketObservations = []; + this.oldObservations = {}; + this.removedObservations = []; + } + + _setIconAdd() { + if (this.ticketObservations.length) { + this.ticketObservations.map(element => { + element.showAddIcon = false; + return true; + }); + this.ticketObservations[this.ticketObservations.length - 1].showAddIcon = true; + } + } + + _setDirtyForm() { + if (this.$scope.form) { + this.$scope.form.$setDirty(); + } + } + + _unsetDirtyForm() { + if (this.$scope.form) { + this.$scope.form.$setPristine(); + } + } + + addObservation() { + this.ticketObservations.push({description: null, ticketFk: this.params.id, showAddIcon: true}); + this._setIconAdd(); + } + + removeObservation(index) { + let item = this.ticketObservations[index]; + if (item) { + this.ticketObservations.splice(index, 1); + this._setIconAdd(); + if (item.id) { + this.removedObservations.push(item.id); + this._setDirtyForm(); + } + } + } + + _equalObservations(oldObservation, newObservation) { + return oldObservation.id === newObservation.id && oldObservation.observationTypeFk === newObservation.observationTypeFk && oldObservation.description === newObservation.description; + } + + setOldObservations(response) { + this._setIconAdd(); + response.data.forEach(observation => { + this.oldObservations[observation.id] = Object.assign({}, observation); + }); + } + + getObservations() { + let filter = { + where: {ticketFk: this.params.id}, + include: ['observationType'] + }; + + this.$http.get(`/ticket/api/TicketObservations?filter=${JSON.stringify(filter)}`).then(response => { + this.ticketObservations = response.data; + this.setOldObservations(response); + }); + } + + submit() { + let typesDefined = []; + let repeatedType = false; + let canSubmit; + let observationsObj = { + delete: this.removedObservations, + create: [], + update: [] + }; + + this.ticketObservations.forEach(observation => { + let isNewObservation = !observation.id; + + delete observation.showAddIcon; + + if (typesDefined.indexOf(observation.observationTypeFk) !== -1) { + repeatedType = true; + return; + } + typesDefined.push(observation.observationTypeFk); + + if (isNewObservation && observation.description && observation.observationTypeFk) { + observationsObj.create.push(observation); + } + + if (!isNewObservation && !this._equalObservations(this.oldObservations[observation.id], observation)) { + observationsObj.update.push(observation); + } + }); + + if (this.$scope.form.$invalid) { + return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid')); + } + + if (repeatedType) { + return this.vnApp.showMessage(this.$translate.instant('The observation type must be unique')); + } + + canSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0; + + if (canSubmit) { + return this.$http.post(`/ticket/api/TicketObservations/crudTicketObservations`, observationsObj).then(() => { + this.getObservations(); + this._unsetDirtyForm(); + }); + } + this.vnApp.showMessage(this.$translate.instant('No changes to save')); + } + + $onInit() { + this.getObservations(); + } +} + +TicketObservations.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp']; + +ngModule.component('vnTicketObservations', { + template: require('./ticket-observations.html'), + controller: TicketObservations, + bindings: { + ticket: '<' + } +}); diff --git a/client/ticket/src/notes/ticket-observations.spec.js b/client/ticket/src/notes/ticket-observations.spec.js new file mode 100644 index 000000000..982cfb61b --- /dev/null +++ b/client/ticket/src/notes/ticket-observations.spec.js @@ -0,0 +1,143 @@ +import './ticket-observations.js'; + +describe('ticket', () => { + describe('Component vnTicketObservations', () => { + let $componentController; + let $state; + let controller; + let $httpBackend; + + beforeEach(() => { + angular.mock.module('ticket'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { + $componentController = _$componentController_; + $state = _$state_; + $httpBackend = _$httpBackend_; + controller = $componentController('vnTicketObservations', {$state: $state}); + })); + + describe('add / remove observation', () => { + it('should add one empty observation into controller observations collection and call _setIconAdd()', () => { + controller.ticketObservations = []; + spyOn(controller, '_setIconAdd').and.callThrough(); + controller.addObservation(); + + expect(controller._setIconAdd).toHaveBeenCalledWith(); + expect(controller.ticketObservations.length).toEqual(1); + expect(controller.ticketObservations[0].id).toBe(undefined); + expect(controller.ticketObservations[0].showAddIcon).toBeTruthy(); + }); + + it('should remove an observation that occupies the position in the index given and call _setIconAdd()', () => { + let index = 2; + controller.ticketObservations = [ + {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false}, + {id: 2, observationTypeFk: 2, description: 'two', showAddIcon: false}, + {id: 3, observationTypeFk: 3, description: 'three', showAddIcon: true} + ]; + + spyOn(controller, '_setIconAdd').and.callThrough(); + + controller.removeObservation(index); + + expect(controller._setIconAdd).toHaveBeenCalledWith(); + expect(controller.ticketObservations.length).toEqual(2); + expect(controller.ticketObservations[0].showAddIcon).toBeFalsy(); + expect(controller.ticketObservations[1].showAddIcon).toBeTruthy(); + expect(controller.ticketObservations[index]).toBe(undefined); + }); + }); + + describe('_equalObservations()', () => { + it('should return true if two observations are equals independent of control attributes', () => { + let observationOne = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: true}; + let observationTwo = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false}; + let equals = controller._equalObservations(observationOne, observationTwo); + + expect(equals).toBeTruthy(); + }); + + it('should return false if two observations aint equals independent of control attributes', () => { + let observationOne = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: true}; + let observationTwo = {id: 1, observationTypeFk: 1, description: 'two', showAddIcon: true}; + let equals = controller._equalObservations(observationOne, observationTwo); + + expect(equals).toBeFalsy(); + }); + }); + + describe('get Observations()', () => { + it('should perform a GET query to receive the ticket observations', () => { + let res = [{id: 1, observationTypeFk: 1, description: 'one'}]; + + $httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond(res); + $httpBackend.expectGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`); + controller.getObservations(); + $httpBackend.flush(); + }); + }); + + describe('submit()', () => { + it("should return an error message 'The observation type must be unique'", () => { + controller.$scope.form = {}; + spyOn(controller.vnApp, 'showMessage').and.callThrough(); + controller.ticketObservations = [ + {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}, + {observationTypeFk: 1, description: 'one', itemFk: 1} + ]; + controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}}; + controller.submit(); + + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The observation type must be unique'); + }); + + it("should perfom a query to delete observations", () => { + controller.$scope.form = {$setPristine: () => {}}; + controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one'}}; + controller.ticketObservations = []; + controller.removedObservations = [1]; + + $httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]); + $httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!'); + controller.submit(); + $httpBackend.flush(); + }); + + it("should perfom a query to update observations", () => { + controller.$scope.form = {$setPristine: () => {}}; + controller.ticketObservations = [{id: 1, observationTypeFk: 1, description: 'number one!'}]; + controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one'}}; + + $httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]); + $httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!'); + controller.submit(); + $httpBackend.flush(); + }); + + it("should perfom a query to create new observation", () => { + controller.$scope.form = {$setPristine: () => {}}; + controller.ticketObservations = [{observationTypeFk: 2, description: 'two'}]; + + $httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]); + $httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!'); + controller.submit(); + $httpBackend.flush(); + }); + + it("should return a message 'No changes to save' when there are no changes to apply", () => { + controller.$scope.form = {$setPristine: () => {}}; + spyOn(controller.vnApp, 'showMessage').and.callThrough(); + controller.oldObservations = [ + {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false}, + {id: 2, observationTypeFk: 2, description: 'two', showAddIcon: true} + ]; + controller.ticketObservations = []; + controller.submit(); + + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save'); + }); + }); + }); +}); diff --git a/client/ticket/src/package/list/package-list.html b/client/ticket/src/package/list/package-list.html new file mode 100644 index 000000000..6a895361e --- /dev/null +++ b/client/ticket/src/package/list/package-list.html @@ -0,0 +1,56 @@ + + + + + Packages + + + + {{id}} : {{name}} + + + + + + + + + +
+ + + + + + diff --git a/client/ticket/src/package/list/package-list.js b/client/ticket/src/package/list/package-list.js new file mode 100644 index 000000000..f77a77418 --- /dev/null +++ b/client/ticket/src/package/list/package-list.js @@ -0,0 +1,19 @@ +import ngModule from '../../module'; + +class Controller { + + construct($http, $scope) { + this.$http = $http; + this.$ = $scope; + } +} + +Controller.$inject = ['$http', '$scope']; + +ngModule.component('vnTicketPackageList', { + template: require('./package-list.html'), + controller: Controller, + bindings: { + ticket: '<' + } +}); diff --git a/client/ticket/src/package/locale/es.yml b/client/ticket/src/package/locale/es.yml new file mode 100644 index 000000000..93ef2231d --- /dev/null +++ b/client/ticket/src/package/locale/es.yml @@ -0,0 +1,6 @@ +Packages: Embalajes +Package: Embalaje +Quantity: Cantidad +Added: Añadido +Add package: Añadir embalaje +Remove package: Quitar embalaje \ No newline at end of file diff --git a/client/ticket/src/review/locale/es.yml b/client/ticket/src/review/locale/es.yml new file mode 100644 index 000000000..ae3a7e678 --- /dev/null +++ b/client/ticket/src/review/locale/es.yml @@ -0,0 +1,4 @@ +date : Fecha +Employee : Empleado +State: Estado +Review: Revision \ No newline at end of file diff --git a/client/ticket/src/review/review.html b/client/ticket/src/review/review.html new file mode 100644 index 000000000..d38b231e5 --- /dev/null +++ b/client/ticket/src/review/review.html @@ -0,0 +1,23 @@ + + + + + Review + + + + + + + +
+ + No results + + + + + + + + \ No newline at end of file diff --git a/client/ticket/src/review/review.js b/client/ticket/src/review/review.js new file mode 100644 index 000000000..7b4cc5678 --- /dev/null +++ b/client/ticket/src/review/review.js @@ -0,0 +1,18 @@ +import ngModule from '../module'; + +class ticketReview { + construct($http, $scope) { + this.$http = $http; + this.$ = $scope; + } +} + +ticketReview.$inject = ['$http', '$scope']; + +ngModule.component('vnTicketReview', { + template: require('./review.html'), + controller: ticketReview, + bindings: { + ticket: '<' + } +}); diff --git a/client/ticket/src/summary/ticket-summary.html b/client/ticket/src/summary/ticket-summary.html new file mode 100644 index 000000000..020e275ec --- /dev/null +++ b/client/ticket/src/summary/ticket-summary.html @@ -0,0 +1,9 @@ + + + +
Ticket Summary
+
+ + +
+
\ No newline at end of file diff --git a/client/ticket/src/summary/ticket-summary.js b/client/ticket/src/summary/ticket-summary.js new file mode 100644 index 000000000..ac62d499e --- /dev/null +++ b/client/ticket/src/summary/ticket-summary.js @@ -0,0 +1,12 @@ +import ngModule from '../module'; + +class TicketSummary {} +TicketSummary.$inject = []; + +ngModule.component('vnTicketSummary', { + template: require('./ticket-summary.html'), + controller: TicketSummary, + bindings: { + ticket: '<' + } +}); diff --git a/client/ticket/src/ticket.js b/client/ticket/src/ticket.js index c7b861d2c..4a7af6e58 100644 --- a/client/ticket/src/ticket.js +++ b/client/ticket/src/ticket.js @@ -1,4 +1,10 @@ export * from './module'; -import './index/index'; - +import './list/ticket-list'; +import './create/ticket-create'; +import './card/ticket-card'; +import './summary/ticket-summary'; +import './data/ticket-data'; +import './notes/ticket-observations'; +import './package/list/package-list'; +import './review/review'; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index ab30e2db7..0158b6e27 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -11,7 +11,8 @@ export default { }, moduleAccessView: { clientsSectionButton: `${components.vnModuleContainer}[ui-sref="clients"]`, - itemsSectionButton: `${components.vnModuleContainer}[ui-sref="item.index"]` + itemsSectionButton: `${components.vnModuleContainer}[ui-sref="item.index"]`, + ticketsSectionButton: `${components.vnModuleContainer}[ui-sref="ticket.list"]` }, clientsIndex: { searchClientInput: `${components.vnTextfield}`, @@ -188,24 +189,29 @@ export default { itemTags: { goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]', tagsButton: `${components.vnMenuItem}[ui-sref="item.card.tags"]`, + firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]`, firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`, + firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Tag"] > div > input`, firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`, firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`, firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`, secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`, + secondTagDisabled: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Tag"] > div > input`, secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`, secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`, secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`, thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`, + thirdTagDisabled: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Tag"] > div > input`, thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`, thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`, thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`, fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`, + fourthTagDisabled: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Tag"] > div > input`, fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`, fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`, fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`, - fifthRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnIcon}[icon="remove_circle_outline"]`, fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`, + fifthTagDisabled: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Tag"] > div > input`, fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`, fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`, fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`, @@ -233,14 +239,17 @@ export default { nicheButton: `${components.vnMenuItem}[ui-sref="item.card.niche"]`, addNicheButton: `${components.vnIcon}[icon="add_circle"]`, firstWarehouseSelect: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`, + firstWarehouseDisabled: `vn-horizontal:nth-child(2) > vn-textfield[label="Warehouse"] > div > input`, firstWarehouseSelectSecondOption: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`, + firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="code"] > div > input`, secondWarehouseSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`, - thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`, - thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`, + secondWarehouseDisabled: `vn-horizontal:nth-child(3) > vn-textfield[label="Warehouse"] > div > input`, + secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="code"] > div > input`, secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-one > ${components.vnIcon}[icon="remove_circle_outline"]`, - firstCodeInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`, - secondCodeInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`, - thirdCodeInput: `vn-horizontal:nth-child(4) > ${components.vnTextfield}`, + thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`, + thirdWarehouseDisabled: `vn-horizontal:nth-child(4) > vn-textfield[label="Warehouse"] > div > input`, + thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`, + thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="code"] > div > input`, submitNichesButton: `${components.vnSubmit}` }, itemBotanical: { @@ -261,5 +270,25 @@ export default { niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`, botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p`, barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(4) > vn-vertical > p` + }, + ticketsIndex: { + createTicketButton: `${components.vnFloatButton}`, + searchResult: `vn-ticket-item a`, + searchTicketInput: `${components.vnTextfield}`, + searchButton: `${components.vnSearchBar} > vn-icon-button > button` + }, + ticketNotes: { + notesButton: `${components.vnMenuItem}[ui-sref="ticket.card.observations"]`, + firstNoteRemoveButton: `${components.vnIcon}[icon="remove_circle_outline"]`, + addNoteButton: `${components.vnIcon}[icon="add_circle"]`, + firstNoteSelect: `${components.vnAutocomplete}[field="ticketObservation.observationTypeFk"] input`, + firstNoteSelectSecondOption: `${components.vnAutocomplete}[field="ticketObservation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`, + firstNoteDisabled: `vn-textfield[label="Observation type"] > div > input`, + firstDescriptionInput: `vn-textfield[label="Description"] > div > input`, + submitNotesButton: `${components.vnSubmit}` + }, + ticketPackages: { + packagesButton: `${components.vnMenuItem}[ui-sref="ticket.card.package.list"]`, + firstPackageSelect: `${components.vnAutocomplete}[label="Package"] input` } }; diff --git a/e2e/paths/client-module/12_lock_of_verified_data.spec.js b/e2e/paths/client-module/12_lock_of_verified_data.spec.js index 764476e62..775e588b1 100644 --- a/e2e/paths/client-module/12_lock_of_verified_data.spec.js +++ b/e2e/paths/client-module/12_lock_of_verified_data.spec.js @@ -61,7 +61,7 @@ describe('lock verified data path', () => { .wait(selectors.clientFiscalData.verifiedDataCheckboxInput) .evaluate(selector => { return document.querySelector(selector).className; - }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label') + }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(4) > label') .then(result => { expect(result).toContain('is-disabled'); }); @@ -452,7 +452,7 @@ describe('lock verified data path', () => { .wait(selectors.clientFiscalData.verifiedDataCheckboxInput) .evaluate(selector => { return document.querySelector(selector).className; - }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label') + }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(4) > label') .then(result => { expect(result).toContain('is-disabled'); }); diff --git a/e2e/paths/item-module/02_edit_item_basic_data.spec.js b/e2e/paths/item-module/02_edit_item_basic_data.spec.js index c2de03c06..36b7fb81e 100644 --- a/e2e/paths/item-module/02_edit_item_basic_data.spec.js +++ b/e2e/paths/item-module/02_edit_item_basic_data.spec.js @@ -66,9 +66,10 @@ describe('edit item basic data path', () => { it(`should confirm the item name was edited`, () => { return nightmare - .click(selectors.itemNiches.firstCodeInput) - .wait(selectors.itemNiches.firstCodeInput) + .click(selectors.itemNiches.nicheButton) + .wait(selectors.itemNiches.firstWarehouseDisabled) .waitToClick(selectors.itemBasicData.basicDataButton) + .waitForTextInInput(selectors.itemBasicData.nameInput, 'Rose of Purity') .getInputValue(selectors.itemBasicData.nameInput) .then(result => { expect(result).toEqual('Rose of Purity'); diff --git a/e2e/paths/item-module/03_edit_item_tax.spec.js b/e2e/paths/item-module/03_edit_item_tax.spec.js index 07bb75414..4347d1752 100644 --- a/e2e/paths/item-module/03_edit_item_tax.spec.js +++ b/e2e/paths/item-module/03_edit_item_tax.spec.js @@ -61,7 +61,7 @@ describe('add item tax path', () => { it(`should confirm the item tax class was edited`, () => { return nightmare .click(selectors.itemTags.tagsButton) - .wait(selectors.itemTags.firstTagSelect) + .wait(selectors.itemTags.firstTagDisabled) .waitToClick(selectors.itemTax.taxButton) .waitForTextInInput(selectors.itemTax.firstClassSelect, 'general') .getInputValue(selectors.itemTax.firstClassSelect) diff --git a/e2e/paths/item-module/04_create_item_tags.spec.js b/e2e/paths/item-module/04_create_item_tags.spec.js index 19d9ef26a..e83725bfa 100644 --- a/e2e/paths/item-module/04_create_item_tags.spec.js +++ b/e2e/paths/item-module/04_create_item_tags.spec.js @@ -43,22 +43,14 @@ describe('create item tags path', () => { }); }); - it(`should create a new tag, edit another and delete a former one`, () => { + it(`should create a new tag and delete a former one`, () => { return nightmare - .waitToClick(selectors.itemTags.firstTagSelect) - .waitToClick(selectors.itemTags.firstTagSelectOptionOne) - .clearInput(selectors.itemTags.firstValueInput) - .type(selectors.itemTags.firstValueInput, 'Dark Blue') - .clearInput(selectors.itemTags.firstRelevancyInput) - .type(selectors.itemTags.firstRelevancyInput, '2') - .waitToClick(selectors.itemTags.fifthRemoveTagButton) + .waitToClick(selectors.itemTags.firstRemoveTagButton) .waitToClick(selectors.itemTags.addItemTagButton) .waitToClick(selectors.itemTags.fifthTagSelect) .waitToClick(selectors.itemTags.fifthTagSelectOptionFive) .type(selectors.itemTags.fifthValueInput, 'Thanos') .type(selectors.itemTags.fifthRelevancyInput, '1') - .clearInput(selectors.itemTags.secondRelevancyInput) - .type(selectors.itemTags.secondRelevancyInput, '5') .click(selectors.itemTags.submitItemTagsButton) .waitForSnackbar() .then(result => { @@ -71,8 +63,8 @@ describe('create item tags path', () => { .click(selectors.itemBasicData.basicDataButton) .wait(selectors.itemBasicData.nameInput) .click(selectors.itemTags.tagsButton) - .waitForTextInInput(selectors.itemTags.firstTagSelect, 'Owner') - .getInputValue(selectors.itemTags.firstTagSelect) + .waitForTextInInput(selectors.itemTags.firstTagDisabled, 'Owner') + .getInputValue(selectors.itemTags.firstTagDisabled) .then(result => { expect(result).toEqual('Owner'); }); @@ -98,19 +90,19 @@ describe('create item tags path', () => { it(`should confirm the second select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.secondTagSelect, 'Color') - .getInputValue(selectors.itemTags.secondTagSelect) + .waitForTextInInput(selectors.itemTags.secondTagDisabled, 'Location') + .getInputValue(selectors.itemTags.secondTagDisabled) .then(result => { - expect(result).toEqual('Color'); + expect(result).toEqual('Location'); }); }); it(`should confirm the second value is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.secondValueInput, 'Dark Blue') + .waitForTextInInput(selectors.itemTags.secondValueInput, 'Gamoras hideout') .getInputValue(selectors.itemTags.secondValueInput) .then(result => { - expect(result).toEqual('Dark Blue'); + expect(result).toEqual('Gamoras hideout'); }); }); @@ -125,8 +117,8 @@ describe('create item tags path', () => { it(`should confirm the third select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.thirdTagSelect, 'Shape') - .getInputValue(selectors.itemTags.thirdTagSelect) + .waitForTextInInput(selectors.itemTags.thirdTagDisabled, 'Shape') + .getInputValue(selectors.itemTags.thirdTagDisabled) .then(result => { expect(result).toEqual('Shape'); }); @@ -152,8 +144,8 @@ describe('create item tags path', () => { it(`should confirm the fourth select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.fourthTagSelect, 'Power') - .getInputValue(selectors.itemTags.fourthTagSelect) + .waitForTextInInput(selectors.itemTags.fourthTagDisabled, 'Power') + .getInputValue(selectors.itemTags.fourthTagDisabled) .then(result => { expect(result).toEqual('Power'); }); @@ -179,19 +171,19 @@ describe('create item tags path', () => { it(`should confirm the fifth select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.fifthTagSelect, 'Location') - .getInputValue(selectors.itemTags.fifthTagSelect) + .waitForTextInInput(selectors.itemTags.fifthTagDisabled, 'Color') + .getInputValue(selectors.itemTags.fifthTagDisabled) .then(result => { - expect(result).toEqual('Location'); + expect(result).toEqual('Color'); }); }); it(`should confirm the fifth value is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.fifthValueInput, 'Gamoras hideout') + .waitForTextInInput(selectors.itemTags.fifthValueInput, 'Yellow') .getInputValue(selectors.itemTags.fifthValueInput) .then(result => { - expect(result).toEqual('Gamoras hideout'); + expect(result).toEqual('Yellow'); }); }); diff --git a/e2e/paths/item-module/05_create_item_niche.spec.js b/e2e/paths/item-module/05_create_item_niche.spec.js index 588dad678..cdadc7e0f 100644 --- a/e2e/paths/item-module/05_create_item_niche.spec.js +++ b/e2e/paths/item-module/05_create_item_niche.spec.js @@ -43,13 +43,9 @@ describe('create item niche path', () => { }); }); - it(`should click create a new niche, edit another and delete a former one`, () => { + it(`should click create a new niche and delete a former one`, () => { return nightmare .waitToClick(selectors.itemNiches.addNicheButton) - .waitToClick(selectors.itemNiches.firstWarehouseSelect) - .waitToClick(selectors.itemNiches.firstWarehouseSelectSecondOption) - .clearInput(selectors.itemNiches.firstCodeInput) - .type(selectors.itemNiches.firstCodeInput, 'A2') .waitToClick(selectors.itemNiches.secondNicheRemoveButton) .waitToClick(selectors.itemNiches.thirdWarehouseSelect) .waitToClick(selectors.itemNiches.thirdWarehouseSelectFourthOption) @@ -66,21 +62,21 @@ describe('create item niche path', () => { .click(selectors.itemBasicData.basicDataButton) .wait(selectors.itemBasicData.nameInput) .click(selectors.itemNiches.nicheButton) - .waitForTextInInput(selectors.itemNiches.firstWarehouseSelect, 'Warehouse Two') - .getInputValue(selectors.itemNiches.firstWarehouseSelect) + .waitForTextInInput(selectors.itemNiches.firstWarehouseDisabled, 'Warehouse One') + .getInputValue(selectors.itemNiches.firstWarehouseDisabled) .then(result => { - expect(result).toEqual('Warehouse Two'); + expect(result).toEqual('Warehouse One'); return nightmare .getInputValue(selectors.itemNiches.firstCodeInput); }) .then(result => { - expect(result).toEqual('A2'); + expect(result).toEqual('A1'); }); }); it(`should confirm the second niche is the expected one`, () => { return nightmare - .getInputValue(selectors.itemNiches.secondWarehouseSelect) + .getInputValue(selectors.itemNiches.secondWarehouseDisabled) .then(result => { expect(result).toEqual('Warehouse Three'); return nightmare @@ -93,7 +89,7 @@ describe('create item niche path', () => { it(`should confirm the third niche is the expected one`, () => { return nightmare - .getInputValue(selectors.itemNiches.thirdWarehouseSelect) + .getInputValue(selectors.itemNiches.thirdWarehouseDisabled) .then(result => { expect(result).toEqual('Warehouse Four'); return nightmare diff --git a/e2e/paths/ticket-module/01_create_ticket_observations.spec.js b/e2e/paths/ticket-module/01_create_ticket_observations.spec.js new file mode 100644 index 000000000..dfc7053b2 --- /dev/null +++ b/e2e/paths/ticket-module/01_create_ticket_observations.spec.js @@ -0,0 +1,77 @@ +import selectors from '../../helpers/selectors.js'; +import createNightmare from '../../helpers/helpers'; + +describe('create item niche path', () => { + const nightmare = createNightmare(); + + beforeAll(() => { + return nightmare + .waitForLogin('developer'); + }); + + it('should access to the tickets index by clicking the tickets button', () => { + return nightmare + .click(selectors.moduleAccessView.ticketsSectionButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/list'); + }); + }); + + it('should search for the ticket with id 1', () => { + return nightmare + .wait(selectors.ticketsIndex.searchTicketInput) + .type(selectors.ticketsIndex.searchTicketInput, '1') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countSearchResults(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should click on the search result to access to the ticket notes`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, '1') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketNotes.notesButton) + .waitForURL('observations') + .url() + .then(url => { + expect(url).toContain('observations'); + }); + }); + + it(`should click create a new note and delete a former one`, () => { + return nightmare + .waitToClick(selectors.ticketNotes.firstNoteRemoveButton) + .waitToClick(selectors.ticketNotes.addNoteButton) + .waitToClick(selectors.ticketNotes.firstNoteSelect) + .waitForTextInElement(selectors.ticketNotes.firstNoteSelectSecondOption, 'observation two') + .waitToClick(selectors.ticketNotes.firstNoteSelectSecondOption) + .type(selectors.ticketNotes.firstDescriptionInput, 'description') + .click(selectors.ticketNotes.submitNotesButton) + .waitForSnackbar() + .then(result => { + expect(result).toContain('Data saved!'); + }); + }); + + it(`should confirm the note is the expected one`, () => { + return nightmare + .click(selectors.ticketPackages.packagesButton) + .wait(selectors.ticketPackages.firstPackageSelect) + .click(selectors.ticketNotes.notesButton) + .waitForTextInInput(selectors.ticketNotes.firstNoteDisabled, 'observation two') + .getInputValue(selectors.ticketNotes.firstNoteDisabled) + .then(result => { + expect(result).toEqual('observation two'); + return nightmare + .getInputValue(selectors.ticketNotes.firstDescriptionInput); + }) + .then(result => { + expect(result).toEqual('description'); + }); + }); +}); diff --git a/package-lock.json b/package-lock.json index dfba5ada1..352d1587b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -105,7 +105,7 @@ "angular": { "version": "1.6.8", "resolved": "https://registry.npmjs.org/angular/-/angular-1.6.8.tgz", - "integrity": "sha1-W+N4pYvpGlSJ54tZxFGM2f0nP/s=" + "integrity": "sha512-9WErZIOw1Cu1V5Yxdvxz/6YpND8ntdP71fdPpufPFJvZodZXqCjQBYrHqEoMZreO5i84O3D/Jw/vepoFt68Azw==" }, "angular-cookies": { "version": "1.6.4", @@ -8375,6 +8375,16 @@ } } }, + "gulp-env": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/gulp-env/-/gulp-env-0.4.0.tgz", + "integrity": "sha1-g3BkaUmjJJPcBtrZSgZDKW+q2+g=", + "dev": true, + "requires": { + "ini": "1.3.4", + "through2": "2.0.1" + } + }, "gulp-extend": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/gulp-extend/-/gulp-extend-0.2.0.tgz", @@ -10985,7 +10995,7 @@ "karma-firefox-launcher": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=", + "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", "dev": true }, "karma-jasmine": { @@ -11006,7 +11016,7 @@ "karma-webpack": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz", - "integrity": "sha1-YciAkffdkQY1E0wDKyZqRlr/tX8=", + "integrity": "sha512-F1j3IG/XhiMzcunAXbWXH95uizjzr3WdTzmVWlta8xqxcCtAu9FByCb4sccIMxaVFAefpgnUW9KlCo0oLvIX6A==", "dev": true, "requires": { "async": "0.9.2", diff --git a/services/client/common/methods/creditInsurance/filter.js b/services/client/common/methods/creditInsurance/filter.js new file mode 100644 index 000000000..121c3a407 --- /dev/null +++ b/services/client/common/methods/creditInsurance/filter.js @@ -0,0 +1,14 @@ +module.exports = Self => { + Self.installMethod('filter', filterParams); + + function filterParams(params) { + return { + where: { + creditClassification: params.creditClassification + }, + skip: (params.page - 1) * params.size, + limit: params.size, + order: params.order + }; + } +}; diff --git a/services/client/common/models/credit-classification.json b/services/client/common/models/credit-classification.json index 01087314a..74edb6640 100644 --- a/services/client/common/models/credit-classification.json +++ b/services/client/common/models/credit-classification.json @@ -33,7 +33,7 @@ "model": "Client", "foreignKey": "client" }, - "creditInsurance": { + "creditInsurances": { "type": "hasMany", "model": "CreditInsurance", "foreignKey": "creditClassification" diff --git a/services/client/common/models/credit-insurance.js b/services/client/common/models/credit-insurance.js new file mode 100644 index 000000000..95902ab9c --- /dev/null +++ b/services/client/common/models/credit-insurance.js @@ -0,0 +1,22 @@ +module.exports = function(Self) { + require('../methods/creditInsurance/filter.js')(Self); + + Self.validateBinded('credit', Self.validateCredit, { + message: 'The credit must be an integer greater than or equal to zero', + allowNull: false, // FIXME: Ignored by loopback when it's false + allowBlank: false + }); + + Self.validateCredit = function(credit) { + return (credit >= 0 && credit % 1 == 0); + }; + + Self.validateBinded('grade', Self.validateGrade, { + message: 'The grade must be an integer greater than or equal to zero', + allowNull: true + }); + + Self.validateGrade = function(grade) { + return (typeof grade === 'undefined' || (grade >= 0 && grade % 1 == 0)); + }; +}; diff --git a/services/client/common/models/credit-insurance.json b/services/client/common/models/credit-insurance.json index a6d280bc6..58dd53ccc 100644 --- a/services/client/common/models/credit-insurance.json +++ b/services/client/common/models/credit-insurance.json @@ -27,7 +27,7 @@ } }, "relations": { - "creditClassification": { + "classification": { "type": "belongsTo", "model": "CreditClassification", "foreignKey": "creditClassification" diff --git a/services/db/04-fixtures.sql b/services/db/04-fixtures.sql index 9a8a36e6f..6ce558cc5 100644 --- a/services/db/04-fixtures.sql +++ b/services/db/04-fixtures.sql @@ -397,6 +397,12 @@ INSERT INTO `vn`.`item`(`id`, `name`,`typeFk`,`size`,`inkFk`,`category`,`stems`, (4, 'Mark I', 1, 60, 'AMR', 'EXT', 1, 1, 'Iron Mans first armor', 1, 05080000, 1, 2, 0, NULL, 0, 66090, 2), (5, 'Mjolnir', 3, 30, 'AZR', 'EXT', 1, 2, 'Thors hammer!', 2, 06021010, 1, 2, 0, NULL, 0, 67350, 2); +INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`) + VALUES + ( 1, 1, 1, 0, CURDATE(), 1, 0, 2, 1), + ( 2, 1, 1, 1, CURDATE(), 2, 1, 0, 2), + ( 3, 2, 2, 2, CURDATE(), 3, 2, 0, NULL); + INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPackageReturnable`, `created`, `itemFk`, `price`) VALUES (1, 0.00, 10, 10, 0, 0, CURDATE(), 1, 1.50), @@ -415,6 +421,29 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric ( 2, 1, 1, 'Gem of Time', 2 , 1.5, 0, 0, 0, CURDATE()), ( 3, 2, 2, 'Mjolnir' , 10, 4 , 0, 0, 0, CURDATE()); +INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`) + VALUES + ( 1, 0), + ( 2, 1); + +INSERT INTO `vn`.`componentTypeRate`(`id`, `type`) + VALUES + ( 1, 'agency'), + ( 2, 'client'), + ( 3, 'company'); + +INSERT INTO `vn`.`componentRate`(`id`, `name`, `componentTypeRate`, `classRate`, `tax`, `isRenewable`) + VALUES + ( 1, 'Special price', 1, NULL, NULL, 1), + ( 2, 'Delivery', 2, NULL, NULL, 1), + ( 3, 'Mana', 3, 1, NULL, 0 ); + +INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`) + VALUES + ( 1, 1, 0.5), + ( 2, 2, 1.2 ); + + INSERT INTO `vn`.`itemBarcode`(`id`, `itemFk`, `code`) VALUES (1, 1 ,1 ), diff --git a/services/db/changes/1.0.2/01-ACLinserts.sql b/services/db/changes/1.0.2/01-ACLinserts.sql index ec1bc0282..2136703fc 100644 --- a/services/db/changes/1.0.2/01-ACLinserts.sql +++ b/services/db/changes/1.0.2/01-ACLinserts.sql @@ -7,3 +7,8 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('TicketPackaging', '*', '*', 'ALLOW', 'ROLE', 'employee'); INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Packaging', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Packaging', '*', 'WRITE', 'ALLOW', 'ROLE', 'logistic'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SaleChecked', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SaleComponent', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Expedition', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Expedition', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Expedition', '*', 'WRITE', 'ALLOW', 'ROLE', 'production'); diff --git a/services/db/changes/1.0.2/03-saleChecked.sql b/services/db/changes/1.0.2/03-saleChecked.sql new file mode 100644 index 000000000..ba79c0565 --- /dev/null +++ b/services/db/changes/1.0.2/03-saleChecked.sql @@ -0,0 +1,11 @@ +USE `vn`; +CREATE + OR REPLACE ALGORITHM = UNDEFINED + DEFINER = `root`@`%` + SQL SECURITY DEFINER +VIEW `vn`.`saleChecked` AS + SELECT + `m`.`Id_Movimiento` AS `saleFk`, + `m`.`checked` AS `isChecked` + FROM + `vn2008`.`Movimientos_checked` `m`; diff --git a/services/db/changes/1.0.2/04-ticketVolume.sql b/services/db/changes/1.0.2/04-ticketVolume.sql new file mode 100644 index 000000000..5b6860700 --- /dev/null +++ b/services/db/changes/1.0.2/04-ticketVolume.sql @@ -0,0 +1,30 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketVolume`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ticketVolume`(IN vTicketId INT) +BEGIN + DECLARE vWarehouseId INTEGER; + DECLARE vShippedDate DATE; + + DROP TEMPORARY TABLE IF EXISTS ticketVolume; + SELECT warehouseFk, shipped INTO vWarehouseId,vShippedDate FROM vn.ticket WHERE id = vTicketId; + + CREATE TEMPORARY TABLE IF NOT EXISTS ticketVolume ENGINE MEMORY + + SELECT itemFk,quantity, concept, VolUd as m3_uni, volume as m3, @m3:= @m3 + ifnull(volume,0) as m3_total + FROM + ( + SELECT round(r.cm3 / 1000000,3) as VolUd ,s.quantity, round(r.cm3 * s.quantity / 1000000,3) as volume, + s.itemFk, s.concept, @m3:= 0, @vol:=0, t.agencyModeFk + FROM sale s + JOIN vn.ticket t on t.id = s.ticketFk + JOIN bi.rotacion r ON r.Id_Article = s.itemFk AND r.warehouse_id = t.warehouseFk + WHERE s.ticketFk = vTicketId + ) sub; + +END$$ + +DELIMITER ; + diff --git a/services/db/changes/1.0.2/05-expedition.sql b/services/db/changes/1.0.2/05-expedition.sql new file mode 100644 index 000000000..1baeeb480 --- /dev/null +++ b/services/db/changes/1.0.2/05-expedition.sql @@ -0,0 +1,19 @@ +USE `vn`; +CREATE + OR REPLACE ALGORITHM = UNDEFINED + DEFINER = `root`@`%` + SQL SECURITY DEFINER +VIEW `vn`.`expedition` AS + SELECT + `e`.`expeditions_id` AS `id`, + `e`.`agency_id` AS `agencyModeFk`, + `e`.`ticket_id` AS `ticketFk`, + `e`.`EsBulto` AS `isBox`, + `e`.`odbc_date` AS `created`, + `e`.`Id_Article` AS `itemFk`, + `e`.`counter` AS `counter`, + `e`.`checked` AS `checked`, + `e`.`workerFk` AS `workerFk` + FROM + `vn2008`.`expeditions` `e` + diff --git a/services/item/common/methods/item/crudItemBarcodes.js b/services/item/common/methods/item-barcode/crudItemBarcodes.js similarity index 100% rename from services/item/common/methods/item/crudItemBarcodes.js rename to services/item/common/methods/item-barcode/crudItemBarcodes.js diff --git a/services/item/common/methods/item/specs/crudItemBarcodes.spec.js b/services/item/common/methods/item-barcode/spec/crudItemBarcodes.spec.js similarity index 100% rename from services/item/common/methods/item/specs/crudItemBarcodes.spec.js rename to services/item/common/methods/item-barcode/spec/crudItemBarcodes.spec.js diff --git a/services/item/common/methods/item/getLog.js b/services/item/common/methods/item-log/getLog.js similarity index 100% rename from services/item/common/methods/item/getLog.js rename to services/item/common/methods/item-log/getLog.js diff --git a/services/item/common/methods/item/crudItemNiches.js b/services/item/common/methods/item-niche/crudItemNiches.js similarity index 100% rename from services/item/common/methods/item/crudItemNiches.js rename to services/item/common/methods/item-niche/crudItemNiches.js diff --git a/services/item/common/methods/item/specs/crudItemNiches.spec.js b/services/item/common/methods/item-niche/spec/crudItemNiches.spec.js similarity index 100% rename from services/item/common/methods/item/specs/crudItemNiches.spec.js rename to services/item/common/methods/item-niche/spec/crudItemNiches.spec.js diff --git a/services/item/common/methods/item/crudItemTags.js b/services/item/common/methods/item-tag/crudItemTags.js similarity index 100% rename from services/item/common/methods/item/crudItemTags.js rename to services/item/common/methods/item-tag/crudItemTags.js diff --git a/services/item/common/models/item-barcode.js b/services/item/common/models/item-barcode.js index be746ecb3..df121dcc3 100644 --- a/services/item/common/models/item-barcode.js +++ b/services/item/common/models/item-barcode.js @@ -1,3 +1,3 @@ module.exports = function(Self) { - require('../methods/item/crudItemBarcodes.js')(Self); + require('../methods/item-barcode/crudItemBarcodes.js')(Self); }; diff --git a/services/item/common/models/item-log.js b/services/item/common/models/item-log.js index 248cc6abd..a5ec25778 100644 --- a/services/item/common/models/item-log.js +++ b/services/item/common/models/item-log.js @@ -1,3 +1,3 @@ module.exports = function(Self) { - require('../methods/item/getLog.js')(Self); + require('../methods/item-log/getLog.js')(Self); }; diff --git a/services/item/common/models/item-niche.js b/services/item/common/models/item-niche.js index 8f9d85da7..edec4182e 100644 --- a/services/item/common/models/item-niche.js +++ b/services/item/common/models/item-niche.js @@ -1,3 +1,3 @@ module.exports = function(Self) { - require('../methods/item/crudItemNiches.js')(Self); + require('../methods/item-niche/crudItemNiches.js')(Self); }; diff --git a/services/item/common/models/item-tag.js b/services/item/common/models/item-tag.js index d4e768bdb..411528836 100644 --- a/services/item/common/models/item-tag.js +++ b/services/item/common/models/item-tag.js @@ -1,3 +1,3 @@ module.exports = function(Self) { - require('../methods/item/crudItemTags.js')(Self); + require('../methods/item-tag/crudItemTags.js')(Self); }; diff --git a/services/item/server/model-config.json b/services/item/server/model-config.json index 229054dd6..779816c19 100644 --- a/services/item/server/model-config.json +++ b/services/item/server/model-config.json @@ -1,22 +1,4 @@ { - "Item": { - "dataSource": "vn" - }, - "ItemType": { - "dataSource": "vn" - }, - "Ink": { - "dataSource": "vn" - }, - "Origin": { - "dataSource": "vn" - }, - "Producer": { - "dataSource": "vn" - }, - "Intrastat": { - "dataSource": "vn" - }, "TaxClass": { "dataSource": "vn" }, @@ -26,9 +8,6 @@ "TaxType": { "dataSource": "vn" }, - "Expence": { - "dataSource": "vn" - }, "ItemTag": { "dataSource": "vn" }, diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json index 7e09dd22c..edf12882c 100644 --- a/services/loopback/common/locale/es.json +++ b/services/loopback/common/locale/es.json @@ -5,5 +5,10 @@ "The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado", "Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado", "El método de pago seleccionado requiere que se especifique el IBAN": "El método de pago seleccionado requiere que se especifique el IBAN", - "can't be blank": "can't be blank" + "can't be blank": "can't be blank", + "DNI Incorrecto": "DNI Incorrecto", + "Ya existe un usuario con ese nombre": "Ya existe un usuario con ese nombre", + "ValidationError: The `Item` instance is not valid. Details: `originFk` Cannot be blank (value: undefined).": "ValidationError: The `Item` instance is not valid. Details: `originFk` Cannot be blank (value: undefined).", + "Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `Articles_ibfk_5` FOREIGN KEY (`tipo_id`) REFERENCES `Tipos` (`tipo_id`) ON UPDATE CASCADE)": "Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `Articles_ibfk_5` FOREIGN KEY (`tipo_id`) REFERENCES `Tipos` (`tipo_id`) ON UPDATE CASCADE)", + "Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `expenceFk` FOREIGN KEY (`expenceFk`) REFERENCES `Gastos` (`Id_Gasto`) ON UPDATE CASCADE)": "Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `expenceFk` FOREIGN KEY (`expenceFk`) REFERENCES `Gastos` (`Id_Gasto`) ON UPDATE CASCADE)" } \ No newline at end of file diff --git a/services/item/common/methods/item/clone.js b/services/loopback/common/methods/item/clone.js similarity index 90% rename from services/item/common/methods/item/clone.js rename to services/loopback/common/methods/item/clone.js index f6f846751..a3e9e38fc 100644 --- a/services/item/common/methods/item/clone.js +++ b/services/loopback/common/methods/item/clone.js @@ -1,4 +1,4 @@ -var UserError = require('../../../../loopback/common/helpers').UserError; +var UserError = require('../../helpers').UserError; module.exports = Self => { Self.remoteMethod('clone', { @@ -27,7 +27,7 @@ module.exports = Self => { id: itemId }, include: [ - {relation: "itemTag", scope: {order: "priority ASC", include: {relation: "tag"}}} + {relation: 'itemTag', scope: {order: 'priority ASC', include: {relation: 'tag'}}} ] }; diff --git a/services/item/common/methods/item/filter.js b/services/loopback/common/methods/item/filter.js similarity index 100% rename from services/item/common/methods/item/filter.js rename to services/loopback/common/methods/item/filter.js diff --git a/services/item/common/methods/item/updateTaxes.js b/services/loopback/common/methods/item/updateTaxes.js similarity index 100% rename from services/item/common/methods/item/updateTaxes.js rename to services/loopback/common/methods/item/updateTaxes.js diff --git a/services/loopback/common/methods/ticket/filter.js b/services/loopback/common/methods/ticket/filter.js new file mode 100644 index 000000000..aaf46ec97 --- /dev/null +++ b/services/loopback/common/methods/ticket/filter.js @@ -0,0 +1,42 @@ +module.exports = Self => { + Self.installMethod('filter', filterParams); + + function filterParams(params) { + let filters = { + where: {}, + skip: (params.page - 1) * params.size, + limit: params.size, + order: params.order || 'created DESC' + }; + + delete params.page; + delete params.size; + delete params.order; + + if (params.search) { + filters.where.and = [ + { + or: [ + {id: params.search}, + {name: {regexp: params.search}} + ] + } + ]; + delete params.search; + } + + Object.keys(params).forEach( + key => { + if (filters.where.and) { + let filter = {}; + filter[key] = (key === 'nickname') ? {regexp: params[key]} : params[key]; + filters.where.and.push(filter); + } else { + filters.where[key] = (key === 'nickname') ? {regexp: params[key]} : params[key]; + } + } + ); + + return filters; + } +}; diff --git a/services/loopback/common/models/agency-mode.json b/services/loopback/common/models/agency-mode.json index ebac22a77..d29695ae3 100644 --- a/services/loopback/common/models/agency-mode.json +++ b/services/loopback/common/models/agency-mode.json @@ -41,5 +41,13 @@ "model": "AgencyType", "foreignKey": "agencyTypeFk" } - } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] } diff --git a/services/loopback/common/models/client.json b/services/loopback/common/models/client.json index c7120e67a..c47e3e8a3 100644 --- a/services/loopback/common/models/client.json +++ b/services/loopback/common/models/client.json @@ -156,6 +156,11 @@ "type": "hasMany", "model": "Greuge", "foreignKey": "clientFk" + }, + "creditClassifications": { + "type": "hasMany", + "model": "CreditClassification", + "foreignKey": "client" } } } \ No newline at end of file diff --git a/services/item/common/models/expence.json b/services/loopback/common/models/expence.json similarity index 100% rename from services/item/common/models/expence.json rename to services/loopback/common/models/expence.json diff --git a/services/item/common/models/ink.json b/services/loopback/common/models/ink.json similarity index 100% rename from services/item/common/models/ink.json rename to services/loopback/common/models/ink.json diff --git a/services/item/common/models/intrastat.json b/services/loopback/common/models/intrastat.json similarity index 100% rename from services/item/common/models/intrastat.json rename to services/loopback/common/models/intrastat.json diff --git a/services/item/common/models/item-type.json b/services/loopback/common/models/item-type.json similarity index 100% rename from services/item/common/models/item-type.json rename to services/loopback/common/models/item-type.json diff --git a/services/item/common/models/item.js b/services/loopback/common/models/item.js similarity index 92% rename from services/item/common/models/item.js rename to services/loopback/common/models/item.js index 35cff55d4..8eb0c16a1 100644 --- a/services/item/common/models/item.js +++ b/services/loopback/common/models/item.js @@ -1,4 +1,4 @@ -let UserError = require('../../../loopback/common/helpers').UserError; +let UserError = require('../helpers').UserError; module.exports = function(Self) { require('../methods/item/filter.js')(Self); diff --git a/services/item/common/models/item.json b/services/loopback/common/models/item.json similarity index 100% rename from services/item/common/models/item.json rename to services/loopback/common/models/item.json diff --git a/services/item/common/models/origin.json b/services/loopback/common/models/origin.json similarity index 100% rename from services/item/common/models/origin.json rename to services/loopback/common/models/origin.json diff --git a/services/item/common/models/producer.json b/services/loopback/common/models/producer.json similarity index 100% rename from services/item/common/models/producer.json rename to services/loopback/common/models/producer.json diff --git a/services/loopback/common/models/specie.json b/services/loopback/common/models/specie.json new file mode 100644 index 000000000..afa669af3 --- /dev/null +++ b/services/loopback/common/models/specie.json @@ -0,0 +1,43 @@ +{ + "name": "Specie", + "base": "VnModel", + "options": { + "mysql": { + "table": "specie" + } + }, + "properties": { + "specie_id": { + "type": "Number", + "id": true, + "description": "Identifier" + }, + "latin_species_name": { + "type": "String" + }, + "entry_date": { + "type": "date" + }, + "expiry_date": { + "type": "date" + }, + "change_date_time": { + "type": "date" + } + }, + "relations": { + "genus": { + "type": "belongsTo", + "model": "Genus", + "foreignKey": "genus_id" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} \ No newline at end of file diff --git a/services/loopback/common/models/ticket.js b/services/loopback/common/models/ticket.js index f390c559f..108ebc872 100644 --- a/services/loopback/common/models/ticket.js +++ b/services/loopback/common/models/ticket.js @@ -2,4 +2,5 @@ module.exports = function(Self) { require('../methods/ticket/change-time.js')(Self); require('../methods/ticket/change-worker.js')(Self); + require('../methods/ticket/filter.js')(Self); }; diff --git a/services/loopback/common/models/ticket.json b/services/loopback/common/models/ticket.json index 493c18a78..cd50e1482 100644 --- a/services/loopback/common/models/ticket.json +++ b/services/loopback/common/models/ticket.json @@ -71,6 +71,11 @@ "model": "AgencyMode", "foreignKey": "agencyModeFk", "required": true + }, + "packages": { + "type": "hasMany", + "model": "TicketPackaging", + "foreignKey": "ticketFk" } } } \ No newline at end of file diff --git a/services/loopback/server/model-config.json b/services/loopback/server/model-config.json index b0d9eda0a..d04d34070 100644 --- a/services/loopback/server/model-config.json +++ b/services/loopback/server/model-config.json @@ -68,5 +68,26 @@ }, "TicketState":{ "dataSource": "vn" - } + }, + "Item": { + "dataSource": "vn" + }, + "Origin": { + "dataSource": "vn" + }, + "ItemType": { + "dataSource": "vn" + }, + "Expence": { + "dataSource": "vn" + }, + "Ink": { + "dataSource": "vn" + }, + "Intrastat": { + "dataSource": "vn" + }, + "Producer": { + "dataSource": "vn" + } } diff --git a/services/ticket/common/methods/packaging/listPackaging.js b/services/ticket/common/methods/packaging/listPackaging.js new file mode 100644 index 000000000..9aa1ad678 --- /dev/null +++ b/services/ticket/common/methods/packaging/listPackaging.js @@ -0,0 +1,49 @@ +module.exports = Self => { + Self.remoteMethod('listPackaging', { + description: 'Returns all packages including item', + accessType: 'READ', + accepts: [{ + arg: 'filter', + type: 'Object', + required: false, + description: 'Filter defining where and paginated data', + http: {source: 'query'} + }], + returns: { + type: ["Object"], + root: true + }, + http: { + path: `/listPackaging`, + verb: 'get' + } + }); + + Self.listPackaging = async filter => { + let where = ''; + let limit = ''; + let order = ''; + let params; + + if (filter) { + let connector = Self.dataSource.connector; + if (filter.where) { + if (filter.where.packagingFk) { + where = 'WHERE p.id = ?'; + params = [filter.where.packagingFk]; + } else { + let search = filter.where.name.regexp; + where = 'WHERE i.id REGEXP ? OR i.name REGEXP ?'; + params = [search, search]; + } + } + + limit = connector._buildLimit(null, filter.limit, filter.offset); + order = connector.buildOrderBy('Item', filter.order); + } + + let query = `SELECT i.name, i.id, p.id packagingFk FROM + item i JOIN packaging p ON i.id = p.itemFk ${where} ${order} ${limit}`; + return await Self.rawSql(query, params); + }; +}; diff --git a/services/ticket/common/methods/ticket/crudTicketObservations.js b/services/ticket/common/methods/ticket/crudTicketObservations.js new file mode 100644 index 000000000..33949e1f4 --- /dev/null +++ b/services/ticket/common/methods/ticket/crudTicketObservations.js @@ -0,0 +1,3 @@ +module.exports = Self => { + Self.installCrudModel('crudTicketObservations'); +}; diff --git a/services/ticket/common/models/componentRate.json b/services/ticket/common/models/componentRate.json new file mode 100644 index 000000000..41e987880 --- /dev/null +++ b/services/ticket/common/models/componentRate.json @@ -0,0 +1,39 @@ +{ + "name": "ComponentRate", + "base": "VnModel", + "options": { + "mysql": { + "table": "componentRate" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "description": "Identifier" + }, + "name": { + "type": "String" + }, + "classRate": { + "type": "Number" + }, + "tax": { + "type": "Number" + }, + "isRenewable": { + "type": "Number" + }, + "componentTypeRate": { + "type": "Number" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} \ No newline at end of file diff --git a/services/ticket/common/models/expedition.json b/services/ticket/common/models/expedition.json new file mode 100644 index 000000000..da070e04b --- /dev/null +++ b/services/ticket/common/models/expedition.json @@ -0,0 +1,51 @@ +{ + "name": "Expedition", + "base": "VnModel", + "options": { + "mysql": { + "table": "expedition" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "description": "Identifier" + }, + "isBox": { + "type": "Number" + }, + "created": { + "type": "Date" + }, + "counter": { + "type": "Number" + }, + "checked": { + "type": "Number" + } + }, + "relations": { + "ticket": { + "type": "belongsTo", + "model": "Ticket", + "foreignKey": "ticketFk" + }, + "agencyMode": { + "type": "belongsTo", + "model": "agency-mode", + "foreignKey": "agencyModeFk" + }, + "item": { + "type": "belongsTo", + "model": "Item", + "foreignKey": "itemFk" + }, + "worker": { + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" + } + } + } + \ No newline at end of file diff --git a/services/ticket/common/models/packaging.js b/services/ticket/common/models/packaging.js new file mode 100644 index 000000000..c252d02ce --- /dev/null +++ b/services/ticket/common/models/packaging.js @@ -0,0 +1,3 @@ +module.exports = function(Self) { + require('../methods/packaging/listPackaging')(Self); +}; diff --git a/services/ticket/common/models/packaging.json b/services/ticket/common/models/packaging.json index e05de2c93..9d5c098df 100644 --- a/services/ticket/common/models/packaging.json +++ b/services/ticket/common/models/packaging.json @@ -9,19 +9,19 @@ "properties": { "id": { "id": true, - "type": "Number", + "type": "String", "description": "Identifier" }, "volume": { "type": "Number" }, - "X": { + "width": { "type": "Date" }, - "Y": { + "height": { "type": "Number" }, - "Z": { + "depth": { "type": "Number" }, "isPackageReturnable": { @@ -37,7 +37,7 @@ "relations": { "item": { "type": "belongsTo", - "model": "Iicket", + "model": "Item", "foreignKey": "itemFk" } } diff --git a/services/ticket/common/models/saleChecked.json b/services/ticket/common/models/saleChecked.json new file mode 100644 index 000000000..8ac52d598 --- /dev/null +++ b/services/ticket/common/models/saleChecked.json @@ -0,0 +1,24 @@ +{ + "name": "SaleChecked", + "base": "VnModel", + "options": { + "mysql": { + "table": "saleChecked" + } + }, + "properties": { + "isChecked": { + "type": "Number" + }, + "saleFk": { + "id": true + } + }, + "relations": { + "sale": { + "type": "belongsTo", + "model": "Sale", + "foreignKey": "saleFk" + } + } +} \ No newline at end of file diff --git a/services/ticket/common/models/saleComponent.json b/services/ticket/common/models/saleComponent.json new file mode 100644 index 000000000..b990b1ed8 --- /dev/null +++ b/services/ticket/common/models/saleComponent.json @@ -0,0 +1,29 @@ +{ + "name": "SaleComponent", + "base": "VnModel", + "options": { + "mysql": { + "table": "saleComponent" + } + }, + "properties": { + "value": { + "type": "Number" + }, + "saleFk": { + "id": true + } + }, + "relations": { + "sale": { + "type": "belongsTo", + "model": "Sale", + "foreignKey": "saleFk" + }, + "componentRate": { + "type": "belongsTo", + "model": "componentRate", + "foreignKey": "componentFk" + } + } +} \ No newline at end of file diff --git a/services/ticket/common/models/ticketObservation.js b/services/ticket/common/models/ticketObservation.js new file mode 100644 index 000000000..bed837bd3 --- /dev/null +++ b/services/ticket/common/models/ticketObservation.js @@ -0,0 +1,3 @@ +module.exports = function(Self) { + require('../methods/ticket/crudTicketObservations.js')(Self); +}; diff --git a/services/ticket/common/models/ticketObservation.json b/services/ticket/common/models/ticketObservation.json index a6e5e3029..73fb71139 100644 --- a/services/ticket/common/models/ticketObservation.json +++ b/services/ticket/common/models/ticketObservation.json @@ -2,33 +2,34 @@ "name": "TicketObservation", "base": "VnModel", "options": { - "mysql": { - "table": "ticketObservation" - } + "mysql": { + "table": "ticketObservation", + "database": "vn" + } }, "properties": { - "id": { - "id": true, - "type": "Number", - "description": "Identifier" - }, - "description": { - "type": "String", - "required": true - } + "id": { + "id": true, + "type": "Number", + "description": "Identifier" + }, + "description": { + "type": "String", + "required": true + } }, "relations": { - "ticket": { - "type": "belongsTo", - "model": "Ticket", - "foreignKey": "ticketFk", - "required": true - }, - "observationType": { - "type": "belongsTo", - "model": "ObservationType", - "foreignKey": "observationTypeFk", - "required": true - } + "ticket": { + "type": "belongsTo", + "model": "Ticket", + "foreignKey": "ticketFk", + "required": true + }, + "observationType": { + "type": "belongsTo", + "model": "ObservationType", + "foreignKey": "observationTypeFk", + "required": true + } } - } \ No newline at end of file +} diff --git a/services/ticket/server/model-config.json b/services/ticket/server/model-config.json index 55ec2a2a5..2bcc701ef 100644 --- a/services/ticket/server/model-config.json +++ b/services/ticket/server/model-config.json @@ -16,5 +16,20 @@ }, "Packaging": { "dataSource": "vn" + }, + "SaleChecked": { + "dataSource": "vn" + }, + "ComponentRate": { + "dataSource": "vn" + }, + "SaleComponent": { + "dataSource": "vn" + }, + "Expedition": { + "dataSource": "vn" } -} +} + + +