From e698d84a4f8be7c2c06258dd1d67c8f0224806f5 Mon Sep 17 00:00:00 2001 From: Joan Date: Thu, 30 Aug 2018 08:50:03 +0200 Subject: [PATCH] crud-model refactor. crud-model fixes #409 --- client/client/src/contact/index.html | 12 +- client/client/src/contact/index.js | 26 +-- client/client/src/contact/index.spec.js | 80 --------- client/client/src/helpers/watcherHelper.js | 14 -- .../src/components/rest-model/crud-model.js | 2 +- client/core/src/components/watcher/watcher.js | 58 +++---- client/core/src/lib/module-loader.js | 6 +- client/helpers/crudModelHelper.js | 19 ++ client/helpers/watcherHelper.js | 11 ++ client/item/src/barcode/index.html | 22 ++- client/item/src/barcode/index.js | 124 +------------ client/item/src/barcode/index.spec.js | 146 ---------------- client/item/src/diary/index.html | 6 +- client/item/src/diary/index.js | 14 ++ client/item/src/item.js | 5 +- client/item/src/niche/index.html | 56 +++--- client/item/src/niche/index.js | 143 +-------------- client/item/src/niche/niche.spec.js | 159 ----------------- client/item/src/tags/index.html | 23 ++- client/item/src/tags/index.js | 93 ++-------- client/item/src/tags/index.spec.js | 152 ++-------------- .../src/ticket-descriptor-popover/index.html | 6 + .../src/ticket-descriptor-popover/index.js | 79 +++++++++ .../ticket-descriptor-popover/index.spec.js | 64 +++++++ .../src/ticket-descriptor-popover/style.scss | 15 ++ .../src/ticket-descriptor}/index.html | 12 +- client/item/src/ticket-descriptor/index.js | 30 ++++ client/modules.yml | 5 +- client/ticket/routes.json | 2 +- client/ticket/src/descriptor/index.js | 42 ----- client/ticket/src/descriptor/index.spec.js | 36 ---- client/ticket/src/locale/es.yml | 1 - client/ticket/src/note/index.html | 46 +++-- client/ticket/src/note/index.js | 131 +------------- client/ticket/src/note/index.spec.js | 164 ------------------ client/ticket/src/package/index.html | 11 +- client/ticket/src/package/index.js | 72 ++------ client/ticket/src/package/index.spec.js | 88 ---------- client/ticket/src/ticket.js | 1 - client/ticket/src/tracking/index/index.html | 2 +- e2e/helpers/selectors.js | 17 +- .../item-module/04_create_item_tags.spec.js | 22 +-- .../item-module/05_create_item_niche.spec.js | 10 +- services/item/common/models/item-barcode.js | 4 + services/item/common/models/item-niche.js | 22 ++- services/item/common/models/item-niche.json | 57 +++--- services/loopback/common/locale/en.json | 3 +- services/loopback/common/locale/es.json | 6 +- services/loopback/common/models/item-tag.js | 18 ++ services/loopback/common/models/vn-model.js | 28 +-- .../common/models/ticket-observation.js | 18 ++ 51 files changed, 592 insertions(+), 1591 deletions(-) delete mode 100644 client/client/src/contact/index.spec.js delete mode 100644 client/client/src/helpers/watcherHelper.js create mode 100644 client/helpers/crudModelHelper.js create mode 100644 client/helpers/watcherHelper.js delete mode 100644 client/item/src/barcode/index.spec.js delete mode 100644 client/item/src/niche/niche.spec.js create mode 100644 client/item/src/ticket-descriptor-popover/index.html create mode 100644 client/item/src/ticket-descriptor-popover/index.js create mode 100644 client/item/src/ticket-descriptor-popover/index.spec.js create mode 100644 client/item/src/ticket-descriptor-popover/style.scss rename client/{ticket/src/descriptor => item/src/ticket-descriptor}/index.html (84%) create mode 100644 client/item/src/ticket-descriptor/index.js delete mode 100644 client/ticket/src/descriptor/index.js delete mode 100644 client/ticket/src/descriptor/index.spec.js delete mode 100644 client/ticket/src/note/index.spec.js delete mode 100644 client/ticket/src/package/index.spec.js diff --git a/client/client/src/contact/index.html b/client/client/src/contact/index.html index e4eff340a..56c501690 100644 --- a/client/client/src/contact/index.html +++ b/client/client/src/contact/index.html @@ -1,11 +1,10 @@ + data="contacts"> - - + + ng-click="model.remove($index)"> - + this.$scope.model.save(true)) - .then(() => this.$scope.watcher.notifySaved()); + this.$scope.model.save().then(() => { + this.$scope.watcher.notifySaved(); + this.$scope.model.refresh(); + }); } } -Controller.$inject = ['$http', '$scope', '$stateParams', '$translate', 'vnApp']; +Controller.$inject = ['$scope', '$stateParams', '$translate']; ngModule.component('vnClientContact', { template: require('./index.html'), diff --git a/client/client/src/contact/index.spec.js b/client/client/src/contact/index.spec.js deleted file mode 100644 index c19e4e13a..000000000 --- a/client/client/src/contact/index.spec.js +++ /dev/null @@ -1,80 +0,0 @@ -import './index.js'; -import {watcher} from '../helpers/watcherHelper.js'; - -describe('Client', () => { - describe('Component vnClientContact', () => { - let $componentController; - let $scope; - let $state; - let controller; - let $httpBackend; - - beforeEach(() => { - angular.mock.module('client'); - }); - - beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$httpBackend_) => { - $componentController = _$componentController_; - $state = _$state_; - $httpBackend = _$httpBackend_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - $scope = $rootScope.$new(); - $scope.form = {$invalid: false}; - $scope.model = { - refresh: () => {}, - data: [ - {id: 1, name: 'My contact 1', phone: '123456789'}, - {id: 2, name: 'My contact 2', phone: '123456789'}, - {id: 3, name: 'My contact 3', phone: '123456789'} - ] - }; - $scope.watcher = watcher; - controller = $componentController('vnClientContact', {$scope: $scope}, {$state: $state}); - controller.client = { - id: 101 - }; - })); - - describe('onDataChange()', () => { - it('should define contacts and oldInstances properties into controller', () => { - controller.onDataChange(); - - expect(controller.contacts).toBeDefined(); - expect(controller.contacts.length).toEqual(3); - }); - }); - - describe('add / remove tags', () => { - it('should add one empty contact into controller contacts collection', () => { - controller.contacts = []; - controller.add(); - - expect(controller.contacts.length).toEqual(1); - expect(controller.contacts[0].id).toBe(undefined); - }); - - it('should remove a contact that occupies the position in the index', () => { - let index = 2; - controller.onDataChange(); - controller.remove(index); - - expect(controller.contacts.length).toEqual(2); - expect(controller.contacts[index]).toBe(undefined); - }); - }); - - xdescribe('onSubmit()', () => { - it("should perfom a query to delete contacts", () => { - controller.$scope.model.data = [ - {id: 1, name: 'My contact 1', phone: '123456789'}, - {id: 2, name: 'My contact 2', phone: '123456789'} - ]; - spyOn(controller.$scope.watcher, 'notifySaved'); - - controller.onSubmit(); - - expect(controller.$scope.watcher.notifySaved).toHaveBeenCalledWith(); - }); - }); - }); -}); diff --git a/client/client/src/helpers/watcherHelper.js b/client/client/src/helpers/watcherHelper.js deleted file mode 100644 index f0a62af78..000000000 --- a/client/client/src/helpers/watcherHelper.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports.watcher = { - realSubmit: () => { - return { - then: () => {} - }; - }, - check: () => {}, - save: () => { - return { - then: () => {} - }; - }, - notifySaved: () => {} -}; diff --git a/client/core/src/components/rest-model/crud-model.js b/client/core/src/components/rest-model/crud-model.js index 1d71dfd61..55db63c89 100644 --- a/client/core/src/components/rest-model/crud-model.js +++ b/client/core/src/components/rest-model/crud-model.js @@ -132,7 +132,7 @@ export default class CrudModel extends ModelProxy { let url = this.saveUrl ? this.saveUrl : `${this.url}/crud`; return this.$http.post(url, changes) - .then(() => this.resetChanges); + .then(() => this.resetChanges()); } } CrudModel.$inject = ['$http', '$q']; diff --git a/client/core/src/components/watcher/watcher.js b/client/core/src/components/watcher/watcher.js index f890a1977..5d2f4b096 100644 --- a/client/core/src/components/watcher/watcher.js +++ b/client/core/src/components/watcher/watcher.js @@ -180,17 +180,6 @@ export default class Watcher extends Component { this.vnApp.showSuccess(this._.instant('Data saved!')); } - writeData(json, resolve) { - Object.assign(this.data, json.data); - this.updateOriginalData(); - resolve(json); - } - - updateOriginalData() { - this.orgData = this.copyInNewObject(this.data); - this.setPristine(); - } - setPristine() { if (this.form) this.form.$setPristine(); } @@ -199,24 +188,6 @@ export default class Watcher extends Component { if (this.form) this.form.$setDirty(); } - copyInNewObject(data) { - let newCopy = {}; - if (data && typeof data === 'object') { - Object.keys(data).forEach( - val => { - if (!isFullEmpty(data[val])) { - if (typeof data[val] === 'object') { - newCopy[val] = this.copyInNewObject(data[val]); - } else { - newCopy[val] = data[val]; - } - } - } - ); - } - return newCopy; - } - callback(transition) { if (!this.state && this.dirty) { this.state = transition.to().name; @@ -236,6 +207,35 @@ export default class Watcher extends Component { this.state = null; } } + + writeData(json, resolve) { + Object.assign(this.data, json.data); + this.updateOriginalData(); + resolve(json); + } + + updateOriginalData() { + this.orgData = this.copyInNewObject(this.data); + this.setPristine(); + } + + copyInNewObject(data) { + let newCopy = {}; + if (data && typeof data === 'object') { + Object.keys(data).forEach( + val => { + if (!isFullEmpty(data[val])) { + if (typeof data[val] === 'object') { + newCopy[val] = this.copyInNewObject(data[val]); + } else { + newCopy[val] = data[val]; + } + } + } + ); + } + return newCopy; + } } Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate', '$attrs', '$q']; diff --git a/client/core/src/lib/module-loader.js b/client/core/src/lib/module-loader.js index 57cca1753..4ffada30c 100644 --- a/client/core/src/lib/module-loader.js +++ b/client/core/src/lib/module-loader.js @@ -1,8 +1,8 @@ import ngModule from '../module'; import splitingRegister from './spliting-register'; -factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate']; -export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate) { +factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate', '$q']; +export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate, $q) { class ModuleLoader { constructor() { this._loaded = {}; @@ -15,7 +15,7 @@ export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $t if (loaded[moduleName] instanceof Promise) return loaded[moduleName]; if (loaded[moduleName] === false) - return Promise.reject( + return $q.reject( new Error(`Module dependency loop detected: ${moduleName}`)); loaded[moduleName] = false; diff --git a/client/helpers/crudModelHelper.js b/client/helpers/crudModelHelper.js new file mode 100644 index 000000000..53fe8320c --- /dev/null +++ b/client/helpers/crudModelHelper.js @@ -0,0 +1,19 @@ +module.exports.crudModel = { + data: [], + insert: () => { + return new Promise(accept => { + accept(); + }); + }, + remove: () => { + return new Promise(accept => { + accept(); + }); + }, + save: () => { + return new Promise(accept => { + accept(); + }); + }, + refresh: () => {} +}; diff --git a/client/helpers/watcherHelper.js b/client/helpers/watcherHelper.js new file mode 100644 index 000000000..92c4084b4 --- /dev/null +++ b/client/helpers/watcherHelper.js @@ -0,0 +1,11 @@ +module.exports.watcher = { + realSubmit: () => { + return new Promise(accept => { + accept(); + }); + }, + check: () => {}, + notifySaved: () => {}, + setDirty: () => {}, + setPristine: () => {} +}; diff --git a/client/item/src/barcode/index.html b/client/item/src/barcode/index.html index 95a059a0e..4bffdd0ff 100644 --- a/client/item/src/barcode/index.html +++ b/client/item/src/barcode/index.html @@ -1,11 +1,19 @@ + + -
+ Barcodes - + + + ng-click="model.remove($index)"> + + ng-click="model.insert()"> diff --git a/client/item/src/barcode/index.js b/client/item/src/barcode/index.js index b1bbab3f4..4096ab7eb 100644 --- a/client/item/src/barcode/index.js +++ b/client/item/src/barcode/index.js @@ -1,129 +1,21 @@ import ngModule from '../module'; export default class Controller { - constructor($state, $scope, $http, $q, $translate, vnApp) { - this.$state = $state; + constructor($stateParams, $scope) { + this.$stateParams = $stateParams; this.$scope = $scope; - this.$http = $http; - this.$q = $q; - this.$translate = $translate; - this.vnApp = vnApp; - - this.barcodes = []; - this.removedBarcodes = []; - this.oldBarcodes = {}; } - _setIconAdd() { - if (this.barcodes.length) { - this.barcodes.map(element => { - element.showAddIcon = false; - return true; - }); - this.barcodes[this.barcodes.length - 1].showAddIcon = true; - } else { - this.addBarcode(); - } - } - - _setDirtyForm() { - if (this.$scope.form) { - 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; - } - - addBarcode() { - this.barcodes.push({code: null, itemFk: this.$state.params.id, showAddIcon: true}); - this._setIconAdd(); - } - - removeBarcode(index) { - let item = this.barcodes[index]; - if (item) { - this.barcodes.splice(index, 1); - this._setIconAdd(); - if (item.id) { - this.removedBarcodes.push(item.id); - this._setDirtyForm(); - } - } - } - - submit() { - let codes = []; - let repeatedBarcodes = false; - let canSubmit; - let barcodesObj = { - delete: this.removedBarcodes, - create: [], - update: [] - }; - for (let i = 0; i < this.barcodes.length; i++) { - let barcode = this.barcodes[i]; - let isNewBarcode = barcode.id === undefined; - - if (barcode.code && codes.indexOf(barcode.code) !== -1) { - repeatedBarcodes = true; - break; - } - if (barcode.code) codes.push(barcode.code); - - if (isNewBarcode && barcode.code) { - barcodesObj.create.push(barcode); - } else if (!isNewBarcode && !this._equalBarcodes(this.oldBarcodes[barcode.id], barcode)) { - barcodesObj.update.push(barcode); - } - } - - if (repeatedBarcodes) { - return this.vnApp.showError(this.$translate.instant('The barcode must be unique')); - } - - canSubmit = barcodesObj.update.length > 0 || barcodesObj.create.length > 0 || barcodesObj.delete.length > 0; - - if (canSubmit) { - return this.$http.post(`/item/api/ItemBarcodes/crudItemBarcodes`, barcodesObj).then(() => { - this.getBarcodes(); - this._unsetDirtyForm(); - this.$scope.watcher.notifySaved(); - }); - } - this.vnApp.showError(this.$translate.instant('No changes to save')); - } - - setOldBarcodes(response) { - this._setIconAdd(); - response.data.forEach(barcode => { - this.oldBarcodes[barcode.id] = Object.assign({}, barcode); + onSubmit() { + this.$scope.watcher.check(); + this.$scope.model.save().then(() => { + this.$scope.watcher.notifySaved(); + this.$scope.model.refresh(); }); } - - getBarcodes() { - let filter = { - where: {itemFk: this.$state.params.id} - }; - this.$http.get(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).then(response => { - this.barcodes = response.data; - this.setOldBarcodes(response); - }); - } - - $onInit() { - this.getBarcodes(); - } } -Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp']; +Controller.$inject = ['$stateParams', '$scope']; ngModule.component('vnItemBarcode', { template: require('./index.html'), diff --git a/client/item/src/barcode/index.spec.js b/client/item/src/barcode/index.spec.js deleted file mode 100644 index 06adc75da..000000000 --- a/client/item/src/barcode/index.spec.js +++ /dev/null @@ -1,146 +0,0 @@ -import './index.js'; - -describe('Item', () => { - describe('Component vnItemBarcode', () => { - let $componentController; - let $state; - let controller; - let $httpBackend; - - beforeEach(() => { - angular.mock.module('item'); - }); - - beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { - $componentController = _$componentController_; - $state = _$state_; - $httpBackend = _$httpBackend_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - $state.params.id = '1'; - controller = $componentController('vnItemBarcode', {$state: $state}); - controller.$scope.watcher = { - notifySaved: () => {} - }; - })); - - describe('add / remove barcode()', () => { - it('should add one empty barcode into controller barcodes collection and call _setIconAdd()', () => { - controller.barcodes = []; - spyOn(controller, '_setIconAdd').and.callThrough(); - controller.addBarcode(); - - expect(controller._setIconAdd).toHaveBeenCalledWith(); - expect(controller.barcodes.length).toEqual(1); - expect(controller.barcodes[0].id).toBe(undefined); - expect(controller.barcodes[0].showAddIcon).toBeTruthy(); - }); - - it('should remove a barcode that occupies the position in the index given and call _setIconAdd()', () => { - let index = 2; - controller.barcodes = [ - {id: 1, code: '1111', showAddIcon: false}, - {id: 2, code: '2222', showAddIcon: false}, - {id: 3, code: '3333', showAddIcon: true} - ]; - - spyOn(controller, '_setIconAdd').and.callThrough(); - - controller.removeBarcode(index); - - expect(controller._setIconAdd).toHaveBeenCalledWith(); - expect(controller.barcodes.length).toEqual(2); - expect(controller.barcodes[0].showAddIcon).toBeFalsy(); - expect(controller.barcodes[1].showAddIcon).toBeTruthy(); - expect(controller.barcodes[index]).toBe(undefined); - }); - }); - - describe('_equalBarcodes()', () => { - it('should return true if two barcodes are equals independent of control attributes', () => { - let code1 = {id: 1, code: '1111', showAddIcon: true}; - let code2 = {id: 1, code: '1111', showAddIcon: false}; - let equals = controller._equalBarcodes(code2, code1); - - expect(equals).toBeTruthy(); - }); - - it('should return false if two barcodes aint equals independent of control attributes', () => { - let code1 = {id: 1, code: '1111', showAddIcon: true}; - let code2 = {id: 1, code: '2222', showAddIcon: true}; - let equals = controller._equalBarcodes(code2, code1); - - expect(equals).toBeFalsy(); - }); - }); - - describe('getBarcodes()', () => { - it('should perform a GET query to receive the item barcodes', () => { - let filter = { - where: {itemFk: '1'} - }; - let res = [{id: 1, code: '1111'}]; - $httpBackend.when('GET', `/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).respond(res); - $httpBackend.expectGET(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`); - controller.getBarcodes(); - $httpBackend.flush(); - }); - }); - - describe('submit()', () => { - it("should return an error message 'The barcode must be unique' when the code isnt unique", () => { - spyOn(controller.vnApp, 'showError').and.callThrough(); - controller.barcodes = [ - {code: 123454, itemFk: 1, id: 1}, - {code: 123454, itemFk: 1} - ]; - controller.oldBarcodes = {1: {id: 1, code: 123454, itemFk: 1}}; - controller.submit(); - - expect(controller.vnApp.showError).toHaveBeenCalledWith('The barcode must be unique'); - }); - - it("should perfom a query to delete barcodes", () => { - controller.removedBarcodes = [1, 2, 3]; - - $httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{code: 123454, itemFk: 1, id: 1}]); - $httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!'); - $httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`); - controller.submit(); - $httpBackend.flush(); - }); - - it("should perfom a query to update barcodes", () => { - controller.barcodes = [{code: 2222, itemFk: 1, id: 1}]; - controller.oldBarcodes = {1: {id: 1, code: 1111, itemFk: 1}}; - - $httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]); - $httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!'); - $httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`); - controller.submit(); - $httpBackend.flush(); - }); - - it("should perfom a query to create new barcode", () => { - controller.barcodes = [{code: 1111, itemFk: 1}]; - - $httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]); - $httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!'); - $httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`); - controller.submit(); - $httpBackend.flush(); - }); - - it("should return a message 'No changes to save' when there are no changes to apply", () => { - spyOn(controller.vnApp, 'showError').and.callThrough(); - controller.oldBarcodes = [ - {code: 1, itemFk: 1, id: 1}, - {code: 2, itemFk: 1, id: 2} - ]; - controller.barcodes = []; - controller.submit(); - - expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save'); - }); - }); - }); -}); diff --git a/client/item/src/diary/index.html b/client/item/src/diary/index.html index ecc4170ac..f4221d978 100644 --- a/client/item/src/diary/index.html +++ b/client/item/src/diary/index.html @@ -37,10 +37,11 @@ {{::sale.date | date:'dd/MM/yyyy HH:mm' }} - {{::sale.origin | dashIfEmpty}} + + {{::sale.origin | dashIfEmpty}} {{::sale.stateName | dashIfEmpty}} {{::sale.reference | dashIfEmpty}} - {{sale.name | dashIfEmpty}} + {{sale.name | dashIfEmpty}} {{::sale.in | dashIfEmpty}} {{::sale.out | dashIfEmpty}} {{::sale.balance | dashIfEmpty}} @@ -53,3 +54,4 @@ + diff --git a/client/item/src/diary/index.js b/client/item/src/diary/index.js index 15a012291..675b35c5f 100644 --- a/client/item/src/diary/index.js +++ b/client/item/src/diary/index.js @@ -110,6 +110,20 @@ class Controller { if (!(today - comparedDate)) return true; } + + showDescriptor(event, sale) { + if (!sale.isTicket) return; + + this.$scope.descriptor.ticketFk = sale.origin; + this.$scope.descriptor.parent = event.target; + this.$scope.descriptor.show(); + event.preventDefault(); + event.stopImmediatePropagation(); + } + + onDescriptorLoad() { + this.$scope.popover.relocate(); + } } Controller.$inject = ['$scope', '$http', '$state', '$window']; diff --git a/client/item/src/item.js b/client/item/src/item.js index 7b364c3a5..e04eef06f 100644 --- a/client/item/src/item.js +++ b/client/item/src/item.js @@ -7,6 +7,9 @@ import './diary'; import './create'; import './card'; import './descriptor'; +import './descriptor-popover'; +import './ticket-descriptor'; +import './ticket-descriptor-popover'; import './data'; import './tags'; import './tax'; @@ -16,4 +19,4 @@ import './niche'; import './botanical'; import './barcode'; import './summary'; -import './descriptor-popover'; + diff --git a/client/item/src/niche/index.html b/client/item/src/niche/index.html index db573091a..5cba83f51 100644 --- a/client/item/src/niche/index.html +++ b/client/item/src/niche/index.html @@ -1,48 +1,46 @@ + + - + Niches - + + vn-acl="buyer,replenisher" vn-one vn-focus> - - - - + + + + + ng-click="model.insert()"> diff --git a/client/item/src/niche/index.js b/client/item/src/niche/index.js index f483fb1f9..5d2442c58 100644 --- a/client/item/src/niche/index.js +++ b/client/item/src/niche/index.js @@ -1,148 +1,21 @@ import ngModule from '../module'; export default class Controller { - constructor($stateParams, $scope, $http, $translate, vnApp) { - this.params = $stateParams; + constructor($stateParams, $scope) { + this.$stateParams = $stateParams; this.$scope = $scope; - this.$http = $http; - this.$translate = $translate; - this.vnApp = vnApp; - - this.warehouses = []; - this.niches = []; - this.removedNiches = []; - this.oldNiches = {}; } - $onInit() { - this.getNiches(); - this.getWarehouses(); - } - - _setIconAdd() { - if (this.niches.length) { - this.niches.map(element => { - element.showAddIcon = false; - return true; - }); - this.niches[this.niches.length - 1].showAddIcon = true; - } else { - this.addNiche(); - } - } - - _setDirtyForm() { - if (this.$scope.form) { - this.$scope.form.$setDirty(); - } - } - - _unsetDirtyForm() { - if (this.$scope.form) { - this.$scope.form.$setPristine(); - } - } - - addNiche() { - this.niches.push({code: null, itemFk: this.params.id, showAddIcon: true}); - this._setIconAdd(); - } - - removeNiche(index) { - let item = this.niches[index]; - if (item) { - this.niches.splice(index, 1); - this._setIconAdd(); - if (item.id) { - this.removedNiches.push(item.id); - this._setDirtyForm(); - } - } - } - - _equalNiches(oldNiche, newNiche) { - return oldNiche.id === newNiche.id && oldNiche.code === newNiche.code && oldNiche.warehouseFk === newNiche.warehouseFk; - } - - setOldNiches(response) { - this._setIconAdd(); - response.data.forEach(niche => { - this.oldNiches[niche.id] = Object.assign({}, niche); + onSubmit() { + this.$scope.watcher.check(); + this.$scope.model.save().then(() => { + this.$scope.watcher.notifySaved(); + this.$scope.model.refresh(); }); } - - getNiches() { - let filter = { - where: {itemFk: this.params.id}, - include: {relation: 'warehouse'} - }; - - this.$http.get(`/item/api/ItemNiches?filter=${JSON.stringify(filter)}`).then(response => { - this.niches = response.data; - this.setOldNiches(response); - }); - } - - getWarehouse(id, warehouses) { - return warehouses.find(warehouse => warehouse.id === id); - } - - getWarehouses() { - this.$http.get(`/item/api/Warehouses`).then(response => { - this.warehouses = response.data; - }); - } - - submit() { - let warehousesDefined = []; - let repeatedWarehouse = false; - let canSubmit; - let nichesObj = { - delete: this.removedNiches, - create: [], - update: [] - }; - - this.niches.forEach(niche => { - let isNewNiche = !niche.id; - - if (warehousesDefined.indexOf(niche.warehouseFk) !== -1) { - repeatedWarehouse = true; - return; - } - warehousesDefined.push(niche.warehouseFk); - - if (isNewNiche) { - nichesObj.create.push(niche); - } - - if (!isNewNiche && !this._equalNiches(this.oldNiches[niche.id], niche)) { - nichesObj.update.push(niche); - } - }); - - if (this.$scope.form.$invalid) { - return this.vnApp.showError(this.$translate.instant('Some fields are invalid')); - } - - if (repeatedWarehouse) { - return this.vnApp.showError(this.$translate.instant('The niche must be unique')); - } - - canSubmit = nichesObj.update.length > 0 || nichesObj.create.length > 0 || nichesObj.delete.length > 0; - - if (canSubmit) { - return this.$http.post(`/item/api/ItemNiches/crudItemNiches`, nichesObj).then(() => { - this.getNiches(); - this._unsetDirtyForm(); - this.$scope.watcher.notifySaved(); - }); - } - this.vnApp.showError(this.$translate.instant('No changes to save')); - } } -Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp']; +Controller.$inject = ['$stateParams', '$scope']; ngModule.component('vnItemNiche', { template: require('./index.html'), diff --git a/client/item/src/niche/niche.spec.js b/client/item/src/niche/niche.spec.js deleted file mode 100644 index 0309d2535..000000000 --- a/client/item/src/niche/niche.spec.js +++ /dev/null @@ -1,159 +0,0 @@ -import './index.js'; - -describe('Item', () => { - describe('Component vnItemNiche', () => { - let $componentController; - let $state; - let controller; - let $httpBackend; - - beforeEach(() => { - angular.mock.module('item'); - }); - - beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { - $componentController = _$componentController_; - $state = _$state_; - $httpBackend = _$httpBackend_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - controller = $componentController('vnItemNiche', {$state: $state}); - controller.$scope.watcher = { - notifySaved: () => {} - }; - })); - - describe('add / remove niche', () => { - it('should add one empty niche into controller niches collection and call _setIconAdd()', () => { - controller.niches = []; - spyOn(controller, '_setIconAdd').and.callThrough(); - controller.addNiche(); - - expect(controller._setIconAdd).toHaveBeenCalledWith(); - expect(controller.niches.length).toEqual(1); - expect(controller.niches[0].id).toBe(undefined); - expect(controller.niches[0].showAddIcon).toBeTruthy(); - }); - - it('should remove a niche that occupies the position in the index given and call _setIconAdd()', () => { - let index = 2; - controller.niches = [ - {id: 1, warehouseFk: 1, code: '1111', showAddIcon: false}, - {id: 2, warehouseFk: 2, code: '2222', showAddIcon: false}, - {id: 3, warehouseFk: 3, code: '3333', showAddIcon: true} - ]; - - spyOn(controller, '_setIconAdd').and.callThrough(); - - controller.removeNiche(index); - - expect(controller._setIconAdd).toHaveBeenCalledWith(); - expect(controller.niches.length).toEqual(2); - expect(controller.niches[0].showAddIcon).toBeFalsy(); - expect(controller.niches[1].showAddIcon).toBeTruthy(); - expect(controller.niches[index]).toBe(undefined); - }); - }); - - describe('_equalNiches()', () => { - it('should return true if two niches are equals independent of control attributes', () => { - let niche1 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: true}; - let niche2 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: false}; - let equals = controller._equalNiches(niche2, niche1); - - expect(equals).toBeTruthy(); - }); - - it('should return false if two niches aint equals independent of control attributes', () => { - let niche1 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: true}; - let niche2 = {id: 1, warehouseFk: 1, code: '2222', showAddIcon: true}; - let equals = controller._equalNiches(niche2, niche1); - - expect(equals).toBeFalsy(); - }); - }); - - describe('get Niches / Warehouses', () => { - it('should perform a GET query to receive the item niches', () => { - let res = [{id: 1, warehouseFk: 1, code: '1111'}]; - - $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond(res); - $httpBackend.expectGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`); - controller.getNiches(); - $httpBackend.flush(); - }); - - it('should perform a GET query to receive the all warehouses', () => { - let res = [ - {id: 1, warehouseFk: 1, name: 'warehouse one'}, - {id: 2, warehouseFk: 2, name: 'warehouse two'} - ]; - - $httpBackend.whenGET(`/item/api/Warehouses`).respond(res); - $httpBackend.expectGET(`/item/api/Warehouses`); - controller.getWarehouses(); - $httpBackend.flush(); - }); - }); - - describe('submit()', () => { - it("should return an error message 'The niche must be unique' when the niche warehouse isnt unique", () => { - controller.$scope.form = {}; - spyOn(controller.vnApp, 'showError').and.callThrough(); - controller.niches = [ - {warehouseFk: 1, code: 123454, itemFk: 1, id: 1}, - {warehouseFk: 1, code: 123454, itemFk: 1} - ]; - controller.oldNiches = {1: {warehouseFk: 1, id: 1, code: 123454, itemFk: 1}}; - controller.submit(); - - expect(controller.vnApp.showError).toHaveBeenCalledWith('The niche must be unique'); - }); - - it("should perfom a query to delete niches", () => { - controller.$scope.form = {$setPristine: () => {}}; - controller.oldNiches = {1: {id: 1, warehouseFk: 1, code: '1111'}}; - controller.niches = []; - controller.removedNiches = [1]; - - $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]); - $httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!'); - controller.submit(); - $httpBackend.flush(); - }); - - it("should perfom a query to update niches", () => { - controller.$scope.form = {$setPristine: () => {}}; - controller.niches = [{id: 1, warehouseFk: 1, code: '2222'}]; - controller.oldNiches = {1: {id: 1, warehouseFk: 1, code: '1111'}}; - - $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]); - $httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!'); - controller.submit(); - $httpBackend.flush(); - }); - - it("should perfom a query to create new niche", () => { - controller.$scope.form = {$setPristine: () => {}}; - controller.niches = [{warehouseFk: 1, code: 1111, itemFk: 1}]; - - $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]); - $httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).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, 'showError').and.callThrough(); - controller.oldNiches = [ - {warehouseFk: 1, code: 1, itemFk: 1, id: 1}, - {warehouseFk: 2, code: 2, itemFk: 1, id: 2} - ]; - controller.niches = []; - controller.submit(); - - expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save'); - }); - }); - }); -}); diff --git a/client/item/src/tags/index.html b/client/item/src/tags/index.html index c4514b804..05a98203e 100644 --- a/client/item/src/tags/index.html +++ b/client/item/src/tags/index.html @@ -1,18 +1,27 @@ - + + - + Tags - + @@ -64,7 +73,7 @@ vn-bind="+" vn-tooltip="Add tag" icon="add_circle" - ng-click="$ctrl.addTag()"> + ng-click="$ctrl.add()"> diff --git a/client/item/src/tags/index.js b/client/item/src/tags/index.js index 20430516e..90d3d6e27 100644 --- a/client/item/src/tags/index.js +++ b/client/item/src/tags/index.js @@ -1,63 +1,27 @@ import ngModule from '../module'; class Controller { - constructor($stateParams, $scope, $http) { - this.params = $stateParams; - this.$ = $scope; - this.$http = $http; - this.tags = []; - this.removedTags = []; + constructor($stateParams, $scope) { + this.$stateParams = $stateParams; + this.$scope = $scope; } - $onInit() { - this.getTags(); - } - - getTags() { - let filter = { - where: {itemFk: this.params.id}, - order: 'priority ASC', - include: {relation: 'tag'} - }; - this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => { - this.removedTags = []; - - this.tags = response.data; - this.itemTags = JSON.parse(JSON.stringify(this.tags)); - this.orgTags = {}; - this.tags.forEach(tag => { - this.orgTags[tag.id] = Object.assign({}, tag); - }); - - this.$.form.$setPristine(); + add() { + this.$scope.model.insert({ + itemFk: this.$stateParams.id, + priority: this.getHighestPriority() }); } - addTag() { - this.tags.push({ - itemFk: this.params.id, - priority: this.getHighestPriority(this.tags) - }); - } - - getHighestPriority(tags) { + getHighestPriority() { let max = 0; - tags.forEach(tag => { + this.$scope.model.data.forEach(tag => { if (tag.priority > max) max = tag.priority; }); return max + 1; } - removeTag(index) { - let item = this.tags[index]; - this.tags.splice(index, 1); - if (item.id) { - this.removedTags.push(item.id); - this.$.form.$setDirty(); - } - } - getSourceTable(selection) { if (!selection || selection.isFree === true) return null; @@ -70,43 +34,18 @@ class Controller { } } - tagIsEqual(oldTag, newTag) { - return oldTag.tagFk === newTag.tagFk && - oldTag.value === newTag.value && - oldTag.priority === newTag.priority; - } - - submit() { - this.$.watcher.check(); - - let changes = { - delete: this.removedTags, - create: [], - update: [] - }; - this.tags.forEach(tag => { - if (!tag.id) - changes.create.push(tag); - else if (!this.tagIsEqual(this.orgTags[tag.id], tag)) { - let tagToUpdate = Object.assign({}, tag); - delete tagToUpdate.tag; - changes.update.push(tagToUpdate); - } - }); - - this.$http.post(`/item/api/ItemTags/crud`, changes).then(() => { - this.getTags(); - this.$.watcher.notifySaved(); + onSubmit() { + this.$scope.watcher.check(); + this.$scope.model.save().then(() => { + this.$scope.watcher.notifySaved(); + this.$scope.model.refresh(); }); } } -Controller.$inject = ['$stateParams', '$scope', '$http']; +Controller.$inject = ['$stateParams', '$scope']; ngModule.component('vnItemTags', { template: require('./index.html'), - controller: Controller, - bindings: { - itemTags: '=' - } + controller: Controller }); diff --git a/client/item/src/tags/index.spec.js b/client/item/src/tags/index.spec.js index 5b3049809..21b6879c0 100644 --- a/client/item/src/tags/index.spec.js +++ b/client/item/src/tags/index.spec.js @@ -1,71 +1,34 @@ import './index.js'; +import {crudModel} from '../../../helpers/crudModelHelper'; describe('Item', () => { describe('Component vnItemTags', () => { let $componentController; - let $state; + let $scope; let controller; - let $httpBackend; beforeEach(() => { angular.mock.module('item'); }); - beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { + beforeEach(angular.mock.inject((_$componentController_, $rootScope) => { $componentController = _$componentController_; - $state = _$state_; - $httpBackend = _$httpBackend_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - controller = $componentController('vnItemTags', {$state: $state}); - controller.$.form = { - $setPristine: () => {}, - $dirty: true - }; - controller.$.watcher = { - notifySaved: () => {}, - check: () => {} - }; + $scope = $rootScope.$new(); + $scope.model = crudModel; + $scope.model.data = [{priority: 1}, {priority: 2}, {priority: 1}]; + controller = $componentController('vnItemTags', {$scope}); })); - describe('add / remove tags', () => { - it('should add one empty tag into controller tags collection', () => { - controller.tags = []; - controller.addTag(); - - expect(controller.tags.length).toEqual(1); - expect(controller.tags[0].id).toBe(undefined); - }); - - it('should remove a tag that occupies the position in the index', () => { - controller.$.form = {$setDirty: () => {}}; - spyOn(controller.$.form, '$setDirty'); - - let index = 2; - controller.tags = [ - {id: 1, typeFk: 1, value: '1111', showAddIcon: false}, - {id: 2, typeFk: 2, value: '2222', showAddIcon: false}, - {id: 3, typeFk: 3, value: '3333', showAddIcon: true} - ]; - - controller.removeTag(index); - - expect(controller.tags.length).toEqual(2); - expect(controller.tags[index]).toBe(undefined); - expect(controller.$.form.$setDirty).toHaveBeenCalledWith(); - }); - }); - describe('getHighestPriority', () => { it('should return the highest priority value + 1 from the array', () => { - let tags = [{priority: 1}, {priority: 2}, {priority: 1}]; - let result = controller.getHighestPriority(tags); + let result = controller.getHighestPriority(); expect(result).toEqual(3); }); it('should return 1 when there is no priority defined', () => { - let tags = []; - let result = controller.getHighestPriority(tags); + $scope.model.data = []; + let result = controller.getHighestPriority(); expect(result).toEqual(1); }); @@ -93,100 +56,5 @@ describe('Item', () => { expect(result).toBe("/api/ItemTags/filterItemTags/3"); }); }); - - describe('tagIsEqual()', () => { - it('should return true if two tags are equals independent of control attributes', () => { - let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true}; - let tag2 = {id: 1, typeFk: 1, value: '1111', showAddIcon: false}; - let equals = controller.tagIsEqual(tag2, tag1); - - expect(equals).toBeTruthy(); - }); - - it('should return false if two tags aint equal independent of control attributes', () => { - let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true}; - let tag2 = {id: 1, typeFk: 1, value: '2222', showAddIcon: true}; - let equals = controller.tagIsEqual(tag2, tag1); - - expect(equals).toBeFalsy(); - }); - }); - - describe('get itemTags', () => { - it('should perform a GET query to receive the item tags', () => { - controller.$.form = {$setPristine: () => {}}; - spyOn(controller.$.form, '$setPristine'); - - let res = [{id: 1, typeFk: 1, value: '1111'}]; - - $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond(res); - $httpBackend.expectGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`); - controller.getTags(); - $httpBackend.flush(); - - expect(controller.$.form.$setPristine).toHaveBeenCalledWith(); - }); - }); - - describe('submit()', () => { - // TODO: Server validation should be implemented - xit("should return an error message 'The tag must be unique' when the tag value isnt unique", () => { - controller.$.form = []; - spyOn(controller.vnApp, 'showError').and.callThrough(); - controller.tags = [ - {typeFk: 1, value: 123454, itemFk: 1, id: 1}, - {typeFk: 1, value: 123454, itemFk: 1} - ]; - controller.orgTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}}; - controller.submit(); - - expect(controller.vnApp.showError).toHaveBeenCalledWith('The tag must be unique'); - }); - - it("should perfom a query to delete tags", () => { - controller.orgTags = {1: {id: 1, typeFk: 1, value: '1111'}}; - controller.tags = []; - controller.removedTags = [1]; - - $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]); - $httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!'); - controller.submit(); - $httpBackend.flush(); - }); - - it("should perfom a query to update tags", () => { - controller.tags = [{id: 1, typeFk: 1, value: '2222'}]; - controller.orgTags = {1: {id: 1, typeFk: 1, value: '1111'}}; - - $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]); - $httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!'); - controller.submit(); - $httpBackend.flush(); - }); - - it("should perfom a query to create new tag", () => { - controller.tags = [{typeFk: 1, value: 1111, itemFk: 1}]; - - $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]); - $httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!'); - controller.submit(); - $httpBackend.flush(); - }); - - it("should throw 'No changes to save' error when there are no changes to apply", () => { - controller.$.watcher = { - check: () => { - throw new Error('No changes to save'); - } - }; - - controller.orgTags = []; - controller.tags = []; - - expect(function() { - controller.submit(); - }).toThrowError(); - }); - }); }); }); diff --git a/client/item/src/ticket-descriptor-popover/index.html b/client/item/src/ticket-descriptor-popover/index.html new file mode 100644 index 000000000..a00767c81 --- /dev/null +++ b/client/item/src/ticket-descriptor-popover/index.html @@ -0,0 +1,6 @@ + + + + diff --git a/client/item/src/ticket-descriptor-popover/index.js b/client/item/src/ticket-descriptor-popover/index.js new file mode 100644 index 000000000..f210e2d1d --- /dev/null +++ b/client/item/src/ticket-descriptor-popover/index.js @@ -0,0 +1,79 @@ +import ngModule from '../module'; +import Component from 'core/src/lib/component'; +import './style.scss'; + +class Controller extends Component { + constructor($element, $scope, $http) { + super($element, $scope); + this.$http = $http; + this._quicklinks = {}; + this.isTooltip = true; + this.clear(); + } + + set ticketFk(value) { + if (value) { + let filter = { + include: [ + {relation: 'warehouse', scope: {fields: ['name']}}, + {relation: 'agencyMode', scope: {fields: ['name']}}, + { + relation: 'client', + scope: { + fields: ['salesPersonFk', 'name', 'isActive', 'isFreezed', 'isTaxDataChecked'], + include: { + relation: 'salesPerson', + fields: ['firstName', 'name'] + } + } + }, + { + relation: 'tracking', + scope: { + fields: ['stateFk'], + include: { + relation: 'state', + fields: ['name'] + } + } + } + ] + }; + + let json = encodeURIComponent(JSON.stringify(filter)); + let query = `/ticket/api/Tickets/${value}?filter=${json}`; + this.$http.get(query).then(res => { + if (res.data) + this.ticket = res.data; + }); + } else + this.clear(); + } + + get quicklinks() { + return this._quicklinks; + } + + set quicklinks(value = {}) { + this._quicklinks = Object.assign(value, this._quicklinks); + } + + clear() { + this.ticket = null; + } + + show() { + this.$.popover.parent = this.parent; + this.$.popover.show(); + } +} +Controller.$inject = ['$element', '$scope', '$http']; + +ngModule.component('vnTicketDescriptorPopover', { + template: require('./index.html'), + bindings: { + ticketFk: '<', + quicklinks: '<' + }, + controller: Controller +}); diff --git a/client/item/src/ticket-descriptor-popover/index.spec.js b/client/item/src/ticket-descriptor-popover/index.spec.js new file mode 100644 index 000000000..45d5eaf19 --- /dev/null +++ b/client/item/src/ticket-descriptor-popover/index.spec.js @@ -0,0 +1,64 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnTicketDescriptorPopover', () => { + let $componentController; + let $scope; + let controller; + let $httpBackend; + let $element; + + beforeEach(() => { + angular.mock.module('item'); + }); + + beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => { + $componentController = _$componentController_; + $element = angular.element(''); + $httpBackend = _$httpBackend_; + $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); + $scope = $rootScope.$new(); + controller = $componentController('vnTicketDescriptorPopover', {$scope, $element, $httpBackend}); + controller.parent = 'mariano'; + controller.$.popover = {show: () => {}}; + })); + + describe('ticketFk setter', () => { + it(`shoud call clear if the given values is null`, () => { + spyOn(controller, 'clear'); + controller.ticketFk = null; + + expect(controller.clear).toHaveBeenCalledWith(); + expect(controller.ticket).toEqual(null); + }); + }); + + describe('quicklinks setter', () => { + it(`shoud set _quicklinks to a given value`, () => { + controller.quicklinks = 3; + + expect(controller._quicklinks).toEqual(3); + }); + }); + + describe('clear()', () => { + it(`should set ticket to null`, () => { + controller.ticket = '1'; + + controller.clear(); + + expect(controller.ticket).toEqual(null); + }); + }); + + describe('show()', () => { + it(`should set $.popover.parent and call $.popover.show`, () => { + spyOn(controller.$.popover, 'show'); + controller.show(); + + expect(controller.$.popover.show).toHaveBeenCalledWith(); + expect(controller.$.popover.parent).toEqual('mariano'); + }); + }); + }); +}); diff --git a/client/item/src/ticket-descriptor-popover/style.scss b/client/item/src/ticket-descriptor-popover/style.scss new file mode 100644 index 000000000..d41d28a87 --- /dev/null +++ b/client/item/src/ticket-descriptor-popover/style.scss @@ -0,0 +1,15 @@ +vn-ticket-descriptor-popover { + vn-ticket-descriptor { + display: block; + width: 16em; + max-height: 28em; + + &>vn-card { + margin: 0!important; + } + + .header > a:first-child { + display: none + } + } +} \ No newline at end of file diff --git a/client/ticket/src/descriptor/index.html b/client/item/src/ticket-descriptor/index.html similarity index 84% rename from client/ticket/src/descriptor/index.html rename to client/item/src/ticket-descriptor/index.html index c7339c346..7d96845e6 100644 --- a/client/ticket/src/descriptor/index.html +++ b/client/item/src/ticket-descriptor/index.html @@ -11,30 +11,30 @@
{{::$ctrl.client.name}}
+ value="{{$ctrl.ticket.id}}"> + value="{{$ctrl.ticket.client.name}}"> + value="{{$ctrl.ticket.client.salesPerson.firstName}} {{$ctrl.ticket.client.salesPerson.name}}"> + value="{{$ctrl.ticket.agencyMode.name}}"> + value="{{$ctrl.ticket.warehouse.name}}"> + value="{{$ctrl.ticket.nickname}}">
diff --git a/client/item/src/ticket-descriptor/index.js b/client/item/src/ticket-descriptor/index.js new file mode 100644 index 000000000..2f3b776e6 --- /dev/null +++ b/client/item/src/ticket-descriptor/index.js @@ -0,0 +1,30 @@ +import ngModule from '../module'; + +class Controller { + constructor($http, $scope) { + this.$scope = $scope; + this.$http = $http; + } + + showDescriptor(event, clientFk) { + this.$scope.descriptor.clientFk = clientFk; + this.$scope.descriptor.parent = event.target; + this.$scope.descriptor.show(); + event.preventDefault(); + event.stopImmediatePropagation(); + } + + onDescriptorLoad() { + this.$scope.popover.relocate(); + } +} + +Controller.$inject = ['$http', '$scope']; + +ngModule.component('vnTicketDescriptor', { + template: require('./index.html'), + bindings: { + ticket: '<' + }, + controller: Controller +}); diff --git a/client/modules.yml b/client/modules.yml index 617a08969..0b8e1d16b 100644 --- a/client/modules.yml +++ b/client/modules.yml @@ -1,11 +1,8 @@ auth: [] client: [] core: [] -item: [] -#locator: [] -#production: [] +item: [client] salix: [] -#route: [] ticket: [item, client] order: [item, ticket] claim: [item, client] diff --git a/client/ticket/routes.json b/client/ticket/routes.json index e583bcb7e..312e28c4d 100644 --- a/client/ticket/routes.json +++ b/client/ticket/routes.json @@ -163,7 +163,7 @@ "params": { "ticket": "$ctrl.ticket" }, - "acl": ["production"] + "acl": ["production", "administrative"] }, { "url" : "/sale-checked", diff --git a/client/ticket/src/descriptor/index.js b/client/ticket/src/descriptor/index.js deleted file mode 100644 index 0023c144c..000000000 --- a/client/ticket/src/descriptor/index.js +++ /dev/null @@ -1,42 +0,0 @@ -import ngModule from '../module'; - -class Controller { - - constructor($http, $scope) { - this.$ = $scope; - this.$http = $http; - } - - getClientDebt(clientFk) { - this.$http.get(`/client/api/Clients/${clientFk}/getDebt`).then(response => { - this.clientDebt = response.data.debt; - }); - } - - showDescriptor(event, clientFk) { - this.$.descriptor.clientFk = clientFk; - this.$.descriptor.parent = event.target; - this.$.descriptor.show(); - event.preventDefault(); - event.stopImmediatePropagation(); - } - - onDescriptorLoad() { - this.$.popover.relocate(); - } - - $onChanges() { - if (this.ticket) - this.getClientDebt(this.ticket.clientFk); - } -} - -Controller.$inject = ['$http', '$scope']; - -ngModule.component('vnTicketDescriptor', { - template: require('./index.html'), - bindings: { - ticket: '<' - }, - controller: Controller -}); diff --git a/client/ticket/src/descriptor/index.spec.js b/client/ticket/src/descriptor/index.spec.js deleted file mode 100644 index acea5bab9..000000000 --- a/client/ticket/src/descriptor/index.spec.js +++ /dev/null @@ -1,36 +0,0 @@ -import './index'; - -describe('Ticket', () => { - describe('Component vnTicketDescriptor', () => { - let $componentController; - let controller; - let $scope; - let $httpBackend; - - beforeEach(() => { - angular.mock.module('ticket'); - }); - - beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => { - $componentController = _$componentController_; - $httpBackend = _$httpBackend_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - $scope = $rootScope.$new(); - controller = $componentController('vnTicketDescriptor', {$scope: $scope}); - })); - - describe('getClientDebt()', () => { - it('should store the client debt into the controller', () => { - let clientFk = 101; - let response = {debt: 10}; - - $httpBackend.when('GET', `/client/api/Clients/${clientFk}/getDebt`).respond(response); - $httpBackend.expect('GET', `/client/api/Clients/${clientFk}/getDebt`); - controller.getClientDebt(clientFk); - $httpBackend.flush(); - - expect(controller.clientDebt).toEqual(response.debt); - }); - }); - }); -}); diff --git a/client/ticket/src/locale/es.yml b/client/ticket/src/locale/es.yml index fcaf25447..233928399 100644 --- a/client/ticket/src/locale/es.yml +++ b/client/ticket/src/locale/es.yml @@ -44,7 +44,6 @@ Shipment: Salida Shipped: F. envio Some fields are invalid: Algunos campos no son válidos State: Estado -The observation type must be unique: El tipo de observación debe ser único Tickets: Tickets Total import: Importe total Warehouse: Almacén diff --git a/client/ticket/src/note/index.html b/client/ticket/src/note/index.html index d42a46e17..e8b5b6175 100644 --- a/client/ticket/src/note/index.html +++ b/client/ticket/src/note/index.html @@ -1,38 +1,36 @@ + + + + - + Notes - - + + label="Observation type" vn-one vn-focus> - - @@ -41,7 +39,7 @@ medium-grey vn-tooltip="Remove note" icon="remove_circle_outline" - ng-click="$ctrl.removeObservation($index)"> + ng-click="model.remove($index)"> @@ -51,8 +49,8 @@ pointer vn-tooltip="Add note" icon="add_circle" vn-bind="+" - ng-if="observationTypes.model.length > $ctrl.ticketObservations.length" - ng-click="$ctrl.addObservation()"> + ng-if="observationTypes.length > observations.length" + ng-click="model.insert()"> diff --git a/client/ticket/src/note/index.js b/client/ticket/src/note/index.js index ff9eef7b3..4a74b3b98 100644 --- a/client/ticket/src/note/index.js +++ b/client/ticket/src/note/index.js @@ -1,136 +1,21 @@ import ngModule from '../module'; class Controller { - constructor($stateParams, $scope, $http, $translate, vnApp) { - this.params = $stateParams; + constructor($stateParams, $scope) { + this.$stateParams = $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); + onSubmit() { + this.$scope.watcher.check(); + this.$scope.model.save().then(() => { + this.$scope.watcher.notifySaved(); + this.$scope.model.refresh(); }); } - - 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.showError(this.$translate.instant('Some fields are invalid')); - } - - if (repeatedType) { - return this.vnApp.showError(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/crudTicketObservation`, observationsObj).then(() => { - this.getObservations(); - this._unsetDirtyForm(); - this.$scope.watcher.notifySaved(); - }); - } - this.vnApp.showError(this.$translate.instant('No changes to save')); - } - - $onInit() { - this.getObservations(); - } } -Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp']; +Controller.$inject = ['$stateParams', '$scope']; ngModule.component('vnTicketObservation', { template: require('./index.html'), diff --git a/client/ticket/src/note/index.spec.js b/client/ticket/src/note/index.spec.js deleted file mode 100644 index fc2681375..000000000 --- a/client/ticket/src/note/index.spec.js +++ /dev/null @@ -1,164 +0,0 @@ -import './index.js'; - -describe('ticket', () => { - describe('Component vnTicketObservation', () => { - 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_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - controller = $componentController('vnTicketObservation', {$state: $state}); - controller.$scope.watcher = { - notifySaved: () => {} - }; - })); - - 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.ticketObservations.length).toEqual(1); - expect(controller.ticketObservations[0].id).toBe(undefined); - expect(controller.ticketObservations[0].showAddIcon).toBeTruthy(); - expect(controller._setIconAdd).toHaveBeenCalledWith(); - }); - - 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.ticketObservations.length).toEqual(2); - expect(controller.ticketObservations[0].showAddIcon).toBeFalsy(); - expect(controller.ticketObservations[1].showAddIcon).toBeTruthy(); - expect(controller.ticketObservations[index]).toBe(undefined); - expect(controller._setIconAdd).toHaveBeenCalledWith(); - }); - }); - - 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 response = [{id: 1, observationTypeFk: 1, description: 'one'}]; - spyOn(controller, 'setOldObservations'); - - $httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond(response); - $httpBackend.expectGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`); - controller.getObservations(); - $httpBackend.flush(); - - expect(controller.setOldObservations).toHaveBeenCalledWith(jasmine.any(Object)); - }); - }); - - describe('submit()', () => { - it("should return an error message 'Some fields are invalid'", () => { - controller.$scope.form = {}; - controller.$scope.form.$invalid = true; - spyOn(controller.vnApp, 'showError').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.showError).toHaveBeenCalledWith('Some fields are invalid'); - }); - - it("should return an error message 'The observation type must be unique'", () => { - controller.$scope.form = {}; - spyOn(controller.vnApp, 'showError').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.showError).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/crudTicketObservation`).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/crudTicketObservation`).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/crudTicketObservation`).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, 'showError').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.showError).toHaveBeenCalledWith('No changes to save'); - }); - }); - }); -}); diff --git a/client/ticket/src/package/index.html b/client/ticket/src/package/index.html index 8d3230832..c815e42b8 100644 --- a/client/ticket/src/package/index.html +++ b/client/ticket/src/package/index.html @@ -1,17 +1,16 @@ + data="packages" on-data-change="$ctrl.onDataChange()"> - - - + Packages @@ -45,7 +44,7 @@ medium-grey vn-tooltip="Remove package" icon="remove_circle_outline" - ng-click="$ctrl.removePackage($index)"> + ng-click="model.remove($index)"> @@ -56,7 +55,7 @@ vn-tooltip="Add package" vn-bind="+" icon="add_circle" - ng-click="$ctrl.addPackage()"> + ng-click="$ctrl.add()"> diff --git a/client/ticket/src/package/index.js b/client/ticket/src/package/index.js index 10a3eec29..a225c4349 100644 --- a/client/ticket/src/package/index.js +++ b/client/ticket/src/package/index.js @@ -1,80 +1,32 @@ import ngModule from '../module'; class Controller { - constructor($http, $scope, $stateParams, $translate, vnApp) { - this.$http = $http; + constructor($scope, $stateParams) { this.$scope = $scope; this.$stateParams = $stateParams; - this.$translate = $translate; - this.vnApp = vnApp; - this.removedPackages = []; } - submit() { - let query = `/ticket/api/TicketPackagings/crud`; - let packagesObj = { - delete: this.removedPackages, - create: [], - update: [] - }; - - this.packages.forEach(item => { - if (typeof item.id === 'undefined') - packagesObj.create.push(item); - - if (typeof item.id !== 'undefined' && !this.packageEquals(item, this.oldPackages[item.id])) - packagesObj.update.push(item); + add() { + this.$scope.model.insert({ + packagingFk: null, + quantity: null, + created: new Date(), + ticketFk: this.$stateParams.id }); + } + onSubmit() { this.$scope.watcher.check(); - - this.$http.post(query, packagesObj).then(res => { + this.$scope.model.save().then(() => { this.$scope.watcher.notifySaved(); this.$scope.model.refresh(); }); } - - removePackage(index) { - if (this.packages[index] && this.packages[index].id) - this.removedPackages.push(this.packages[index].id); - - this.packages.splice(index, 1); - } - - addPackage() { - let data = { - packagingFk: null, - quantity: null, - created: Date.now(), - ticketFk: this.ticket.id - }; - this.packages.push(data); - } - - getPackages() { - this.packages = this.$scope.model.data; - this.setOldPackages(); - } - - setOldPackages() { - this.oldPackages = []; - this.removedPackages = []; - this.packages.forEach(item => { - this.oldPackages[item.id] = Object.assign({}, item); - }); - } - - packageEquals(newPackage, oldPackage) { - return newPackage.packagingFk === oldPackage.packagingFk && newPackage.quantity == oldPackage.quantity; - } } -Controller.$inject = ['$http', '$scope', '$stateParams', '$translate', 'vnApp']; +Controller.$inject = ['$scope', '$stateParams']; ngModule.component('vnTicketPackageIndex', { template: require('./index.html'), - controller: Controller, - bindings: { - ticket: '<' - } + controller: Controller }); diff --git a/client/ticket/src/package/index.spec.js b/client/ticket/src/package/index.spec.js deleted file mode 100644 index 3222c58c8..000000000 --- a/client/ticket/src/package/index.spec.js +++ /dev/null @@ -1,88 +0,0 @@ -import './index.js'; - -describe('Ticket', () => { - describe('Component vnTicketPackageIndex', () => { - let $componentController; - let controller; - let $httpBackend; - let $scope; - - beforeEach(() => { - angular.mock.module('ticket'); - }); - - beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_, $rootScope) => { - $componentController = _$componentController_; - $httpBackend = _$httpBackend_; - $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - $scope = { - model: { - refresh: () => {} - }, - watcher: { - check: () => {}, - notifySaved: () => {} - } - }; - controller = $componentController('vnTicketPackageIndex', {$scope: $scope}); - })); - - describe('removePackage()', () => { - it('should push a package to removedPackages in the controller', () => { - controller.packages = [{id: 1}, {id: 2}]; - controller.removePackage(0); - - expect(controller.removedPackages).toEqual([1]); - }); - }); - - describe('submit()', () => { - it('should perform a post', () => { - spyOn(controller.$scope.watcher, 'notifySaved'); - spyOn(controller.$scope.model, 'refresh'); - - controller.removedPackages = []; - controller.oldPackages = []; - controller.oldPackages[1] = {id: 1, packagingFk: 1, quantity: 5, ticketFk: 1}; - controller.packages = [ - {quantity: 5, packagingFk: 2, ticketFk: 1}, - {id: 1, packagingFk: 1, quantity: 25, ticketFk: 1} - ]; - - let data = { - delete: [], - create: [{quantity: 5, packagingFk: 2, ticketFk: 1}], - update: [{id: 1, packagingFk: 1, quantity: 25, ticketFk: 1}] - }; - - $httpBackend.when('POST', '/ticket/api/TicketPackagings/crud', data).respond(200); - $httpBackend.expect('POST', '/ticket/api/TicketPackagings/crud', data).respond('ok'); - controller.submit(); - $httpBackend.flush(); - - expect(controller.$scope.model.refresh).toHaveBeenCalledWith(); - expect(controller.$scope.watcher.notifySaved).toHaveBeenCalledWith(); - }); - }); - - describe('packageEquals()', () => { - it('should return true if the old package and the new one matches', () => { - let oldPackage = {quantity: 5, packagingFk: 2}; - let newPackage = {quantity: 5, packagingFk: 2}; - - let result = controller.packageEquals(oldPackage, newPackage); - - expect(result).toBeTruthy(); - }); - - it(`should return false if the old package and the new one doesn't match`, () => { - let oldPackage = {quantity: 5, packagingFk: 2}; - let newPackage = {quantity: 6, packagingFk: 2}; - - let result = controller.packageEquals(oldPackage, newPackage); - - expect(result).toBeFalsy(); - }); - }); - }); -}); diff --git a/client/ticket/src/ticket.js b/client/ticket/src/ticket.js index 357451f3f..0fc02a400 100644 --- a/client/ticket/src/ticket.js +++ b/client/ticket/src/ticket.js @@ -3,7 +3,6 @@ export * from './module'; import './search-panel'; import './index'; import './card'; -import './descriptor'; import './summary'; import './data'; import './data/step-one'; diff --git a/client/ticket/src/tracking/index/index.html b/client/ticket/src/tracking/index/index.html index 53c76c356..cbbf2b74c 100644 --- a/client/ticket/src/tracking/index/index.html +++ b/client/ticket/src/tracking/index/index.html @@ -37,6 +37,6 @@ - + \ No newline at end of file diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 95236a1a7..79767fe5b 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -240,22 +240,19 @@ export default { addBarcodeButton: `vn-icon[icon="add_circle"]`, thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(4) > ${components.vnTextfield}`, submitBarcodesButton: `${components.vnSubmit}`, - firstCodeRemoveButton: `vn-horizontal:nth-child(2) > vn-icon[icon="remove_circle_outline"]` + firstCodeRemoveButton: `vn-item-barcode vn-horizontal vn-none vn-icon[icon="remove_circle_outline"]` }, itemNiches: { nicheButton: `vn-menu-item a[ui-sref="item.card.niche"]`, addNicheButton: `vn-icon[icon="add_circle"]`, - firstWarehouseSelect: `vn-autocomplete[field="itemNiche.warehouseFk"] input`, - firstWarehouseDisabled: `vn-horizontal:nth-child(2) > vn-textfield[label="Warehouse"] input`, - firstWarehouseSelectSecondOption: `vn-autocomplete[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`, + firstWarehouseSelect: `vn-autocomplete[field="niche.warehouseFk"] input`, + firstWarehouseSelectSecondOption: `vn-autocomplete[field="niche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`, firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Code"] input`, - secondWarehouseSelect: `vn-horizontal:nth-child(3) > vn-autocomplete[field="itemNiche.warehouseFk"] input`, - secondWarehouseDisabled: `vn-horizontal:nth-child(3) > vn-textfield[label="Warehouse"] input`, + secondWarehouseSelect: `vn-horizontal:nth-child(3) > vn-autocomplete[field="niche.warehouseFk"] input`, secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Code"] input`, - secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-icon[icon="remove_circle_outline"]`, - thirdWarehouseSelect: `vn-horizontal:nth-child(4) > vn-autocomplete[field="itemNiche.warehouseFk"] input`, - thirdWarehouseDisabled: `vn-horizontal:nth-child(4) > vn-textfield[label="Warehouse"] input`, - thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > vn-autocomplete[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`, + secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-none > vn-icon[icon="remove_circle_outline"]`, + thirdWarehouseSelect: `vn-horizontal:nth-child(4) > vn-autocomplete[field="niche.warehouseFk"] input`, + thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > vn-autocomplete[field="niche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`, thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Code"] input`, submitNichesButton: `${components.vnSubmit}` }, 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 fe3725b35..2d03af0c7 100644 --- a/e2e/paths/item-module/04_create_item_tags.spec.js +++ b/e2e/paths/item-module/04_create_item_tags.spec.js @@ -65,10 +65,10 @@ describe('Item', () => { .click(selectors.itemBasicData.basicDataButton) .wait(selectors.itemBasicData.nameInput) .click(selectors.itemTags.tagsButton) - .waitForTextInInput(selectors.itemTags.firstTagDisabled, 'Diámetro') - .getInputValue(selectors.itemTags.firstTagDisabled) + .waitForTextInInput(selectors.itemTags.firstTagSelect, 'Ancho de la base') + .getInputValue(selectors.itemTags.firstTagSelect) .then(result => { - expect(result).toEqual('Diámetro'); + expect(result).toEqual('Ancho de la base'); }); }); @@ -92,8 +92,8 @@ describe('Item', () => { it(`should confirm the second select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.secondTagDisabled, 'Variedad') - .getInputValue(selectors.itemTags.secondTagDisabled) + .waitForTextInInput(selectors.itemTags.secondTagSelect, 'Variedad') + .getInputValue(selectors.itemTags.secondTagSelect) .then(result => { expect(result).toEqual('Variedad'); }); @@ -119,8 +119,8 @@ describe('Item', () => { it(`should confirm the third select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.thirdTagDisabled, 'Longitud(cm)') - .getInputValue(selectors.itemTags.thirdTagDisabled) + .waitForTextInInput(selectors.itemTags.thirdTagSelect, 'Longitud(cm)') + .getInputValue(selectors.itemTags.thirdTagSelect) .then(result => { expect(result).toEqual('Longitud(cm)'); }); @@ -146,8 +146,8 @@ describe('Item', () => { it(`should confirm the fourth select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.fourthTagDisabled, 'Proveedor') - .getInputValue(selectors.itemTags.fourthTagDisabled) + .waitForTextInInput(selectors.itemTags.fourthTagSelect, 'Proveedor') + .getInputValue(selectors.itemTags.fourthTagSelect) .then(result => { expect(result).toEqual('Proveedor'); }); @@ -173,8 +173,8 @@ describe('Item', () => { it(`should confirm the fifth select is the expected one`, () => { return nightmare - .waitForTextInInput(selectors.itemTags.fifthTagDisabled, 'Color') - .getInputValue(selectors.itemTags.fifthTagDisabled) + .waitForTextInInput(selectors.itemTags.fifthTagSelect, 'Color') + .getInputValue(selectors.itemTags.fifthTagSelect) .then(result => { expect(result).toEqual('Color'); }); 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 a81348120..c3a1c04e0 100644 --- a/e2e/paths/item-module/05_create_item_niche.spec.js +++ b/e2e/paths/item-module/05_create_item_niche.spec.js @@ -63,8 +63,8 @@ describe('Item', () => { .click(selectors.itemBasicData.basicDataButton) .wait(selectors.itemBasicData.nameInput) .click(selectors.itemNiches.nicheButton) - .waitForTextInInput(selectors.itemNiches.firstWarehouseDisabled, 'Warehouse One') - .getInputValue(selectors.itemNiches.firstWarehouseDisabled) + .waitForTextInInput(selectors.itemNiches.firstWarehouseSelect, 'Warehouse One') + .getInputValue(selectors.itemNiches.firstWarehouseSelect) .then(result => { expect(result).toEqual('Warehouse One'); return nightmare @@ -77,7 +77,7 @@ describe('Item', () => { it(`should confirm the second niche is the expected one`, () => { return nightmare - .getInputValue(selectors.itemNiches.secondWarehouseDisabled) + .getInputValue(selectors.itemNiches.secondWarehouseSelect) .then(result => { expect(result).toEqual('Warehouse Three'); return nightmare @@ -90,9 +90,9 @@ describe('Item', () => { it(`should confirm the third niche is the expected one`, () => { return nightmare - .getInputValue(selectors.itemNiches.thirdWarehouseDisabled) + .getInputValue(selectors.itemNiches.thirdWarehouseSelect) .then(result => { - expect(result).toEqual('Warehouse Four'); + expect(result).toEqual('Warehouse Two'); return nightmare .getInputValue(selectors.itemNiches.thirdCodeInput); }) diff --git a/services/item/common/models/item-barcode.js b/services/item/common/models/item-barcode.js index dc4838c92..be7898e66 100644 --- a/services/item/common/models/item-barcode.js +++ b/services/item/common/models/item-barcode.js @@ -1,3 +1,7 @@ module.exports = Self => { require('../methods/item-barcode/crudItemBarcodes')(Self); + + Self.validatesUniquenessOf('code', { + message: `Barcode must be unique` + }); }; diff --git a/services/item/common/models/item-niche.js b/services/item/common/models/item-niche.js index cfceabec0..b9b52c180 100644 --- a/services/item/common/models/item-niche.js +++ b/services/item/common/models/item-niche.js @@ -1,3 +1,23 @@ module.exports = Self => { - require('../methods/item-niche/crudItemNiches')(Self); +/* Self.validateAsync('warehouseFk', validateWarehouseUniqueness, { + message: `The warehouse can't be repeated` + }); + + async function validateWarehouseUniqueness(err, done) { + let where = { + itemFk: this.itemFk, + warehouseFk: this.warehouseFk + }; + + if (this.id != null) + where.id = {neq: this.id}; + + let warehouseExists = await Self.findOne({where: where}); + console.log(warehouseExists); + + if (warehouseExists) + err(); + + done(); + } */ }; diff --git a/services/item/common/models/item-niche.json b/services/item/common/models/item-niche.json index 1317987c6..61ae42ec2 100644 --- a/services/item/common/models/item-niche.json +++ b/services/item/common/models/item-niche.json @@ -1,29 +1,38 @@ { - "name": "ItemNiche", - "base": "VnModel", - "options": { - "mysql": { + "name": "ItemNiche", + "base": "VnModel", + "options": { + "mysql": { "table": "itemPlacement", "database": "vn" - } - }, - "properties": { - "code": { - "type": "String", - "required": true - } - }, - "relations": { - "item": { - "type": "belongsTo", - "model": "Item", - "foreignKey": "itemFk" + } }, - "warehouse": { - "type": "belongsTo", - "model": "Warehouse", - "foreignKey": "warehouseFk", - "required": true - } - } + "properties": { + "id": { + "type": "Number", + "id": 1, + "description": "Identifier" + }, + "warehouseFk": { + "type": "Number", + "description": "Identifier" + }, + "code": { + "type": "String", + "required": true + } + }, + "relations": { + "item": { + "type": "belongsTo", + "model": "Item", + "foreignKey": "itemFk" + }, + "warehouse": { + "type": "belongsTo", + "model": "Warehouse", + "foreignKey": "warehouseFk", + "required": true + } + } } diff --git a/services/loopback/common/locale/en.json b/services/loopback/common/locale/en.json index 8a250665d..9bfbace75 100644 --- a/services/loopback/common/locale/en.json +++ b/services/loopback/common/locale/en.json @@ -30,5 +30,6 @@ "The grade must be an integer greater than or equal to zero": "The grade must be an integer greater than or equal to zero", "Sample type cannot be blank": "Sample type cannot be blank", "The new quantity should be smaller than the old one": "La nueva cantidad debe ser menor que la anterior", - "The package cannot be blank": "The package cannot be blank" + "The package cannot be blank": "The package cannot be blank", + "The warehouse can't be repeated": "The warehouse can't be repeated" } \ No newline at end of file diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json index f68d6861e..57ddd4465 100644 --- a/services/loopback/common/locale/es.json +++ b/services/loopback/common/locale/es.json @@ -42,5 +42,9 @@ "This order is not editable": "Esta orden no se puede modificar", "You can't create an order for a frozen client": "No puedes crear una orden para un cliente congelado", "You can't create an order for a client that has a debt": "No puedes crear una orden para un cliente con deuda", - "is not a valid date": "No es una fecha valida" + "is not a valid date": "No es una fecha valida", + "Barcode must be unique": "El código de barras debe ser único", + "The warehouse can't be repeated": "El almacén no puede repetirse", + "The tag can't be repeated": "El tag no puede repetirse", + "The observation type can't be repeated": "El tipo de observación no puede repetirse" } \ No newline at end of file diff --git a/services/loopback/common/models/item-tag.js b/services/loopback/common/models/item-tag.js index 61bd7af6b..837c656d1 100644 --- a/services/loopback/common/models/item-tag.js +++ b/services/loopback/common/models/item-tag.js @@ -1,3 +1,21 @@ module.exports = Self => { require('../methods/item-tag/filterItemTags')(Self); + +/* Self.validateAsync('tagFk', validateTagUniqueness, { + message: `The tag can't be repeated` + }); + + async function validateTagUniqueness(err, done) { + let tagExists = await Self.findOne({ + where: { + itemFk: this.itemFk, + tagFk: this.tagFk + } + }); + + if (tagExists) + err(); + + done(); + } */ }; diff --git a/services/loopback/common/models/vn-model.js b/services/loopback/common/models/vn-model.js index 85b5e1650..b9d18d912 100644 --- a/services/loopback/common/models/vn-model.js +++ b/services/loopback/common/models/vn-model.js @@ -140,27 +140,35 @@ module.exports = function(Self) { } }); this[methodName] = async actions => { - let promises = []; let transaction = await this.beginTransaction({}); let options = {transaction: transaction}; try { if (actions.delete && actions.delete.length) { - promises.push(this.destroyAll({id: {inq: actions.delete}}, options)); - } - if (actions.create && actions.create.length) { - promises.push(this.create(actions.create, options)); + await this.destroyAll({id: {inq: actions.delete}}, options); } if (actions.update) { - actions.update.forEach(toUpdate => { - promises.push(this.upsert(toUpdate, options)); - }); + try { + let promises = []; + actions.update.forEach(toUpdate => { + promises.push(this.upsert(toUpdate, options)); + }); + await Promise.all(promises); + } catch (error) { + throw error[0]; + } + } + if (actions.create && actions.create.length) { + try { + await this.create(actions.create, options); + } catch (error) { + throw error[error.length - 1]; + } } - await Promise.all(promises); await transaction.commit(); } catch (error) { await transaction.rollback(); - throw Array.isArray(error) ? error[0] : error; + throw error; } }; }; diff --git a/services/ticket/common/models/ticket-observation.js b/services/ticket/common/models/ticket-observation.js index 87e6f8748..d6b200aa2 100644 --- a/services/ticket/common/models/ticket-observation.js +++ b/services/ticket/common/models/ticket-observation.js @@ -1,3 +1,21 @@ module.exports = function(Self) { require('../methods/notes/crudTicketObservation.js')(Self); + + /* Self.validateAsync('observationTypeFk', validateObservationUniqueness, { + message: `The observation type can't be repeated` + }); + + async function validateObservationUniqueness(err, done) { + let observationExists = await Self.findOne({ + where: { + ticketFk: this.ticketFk, + observationTypeFk: this.observationTypeFk + } + }); + + if (observationExists) + err(); + + done(); + } */ };