diff --git a/client/client/src/locale/es.yml b/client/client/src/locale/es.yml index 15f819c67..9fc7fbdb3 100644 --- a/client/client/src/locale/es.yml +++ b/client/client/src/locale/es.yml @@ -1,8 +1,12 @@ Active: Activo +Add contact: Añadir contacto +Amount: Importe Client: Cliente Clients: Clientes Comercial Name: Comercial +Contacts: Contactos Basic data: Datos básicos +Back: Volver Fiscal data: Datos Fiscales Addresses: Consignatarios Web access: Acceso web @@ -21,6 +25,4 @@ Credit : Crédito Credit contracts: Contratos de crédito Verified data: Datos comprobados Mandate: Mandato -Amount: Importe -Back: Volver -Contacts: Contactos \ No newline at end of file +Remove contact: Eliminar \ No newline at end of file diff --git a/client/core/src/directives/index.js b/client/core/src/directives/index.js index ed316a512..fc1171d03 100644 --- a/client/core/src/directives/index.js +++ b/client/core/src/directives/index.js @@ -8,3 +8,4 @@ import './on-error-src'; import './zoom-image'; import './visible-by'; import './bind'; +import './repeat-last'; diff --git a/client/core/src/directives/repeat-last.js b/client/core/src/directives/repeat-last.js new file mode 100644 index 000000000..894666cae --- /dev/null +++ b/client/core/src/directives/repeat-last.js @@ -0,0 +1,21 @@ +import ngModule from '../module'; + +/** + * Calls a passed function if is the last element from an ng-repeat. + * + * @attribute {String} onLast - Callback function + * @return {Object} The directive + */ +directive.$inject = ['$parse']; +export function directive($parse) { + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + if ($scope.$last && $attrs.onLast) { + let fn = $parse($attrs.onLast); + fn($scope); + } + } + }; +} +ngModule.directive('vnRepeatLast', directive); diff --git a/client/item/routes.json b/client/item/routes.json index 89f6b442e..018393b36 100644 --- a/client/item/routes.json +++ b/client/item/routes.json @@ -110,7 +110,7 @@ "item": "$ctrl.item" } }, { - "url" : "/diary", + "url" : "/diary?q", "state": "item.card.diary", "component": "vn-item-diary", "params": { diff --git a/client/item/src/card/card.spec.js b/client/item/src/card/card.spec.js index acb6d39df..20693836a 100644 --- a/client/item/src/card/card.spec.js +++ b/client/item/src/card/card.spec.js @@ -25,8 +25,8 @@ describe('Item', () => { describe('_getItem()', () => { it('should request to get the item', () => { - $httpBackend.whenGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}').respond({data: 'item'}); - $httpBackend.expectGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}'); + $httpBackend.whenGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk","warehouseFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}').respond({data: 'item'}); + $httpBackend.expectGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk","warehouseFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}'); controller._getItem(); $httpBackend.flush(); }); diff --git a/client/item/src/card/index.js b/client/item/src/card/index.js index b0b14e8a7..440c498b8 100644 --- a/client/item/src/card/index.js +++ b/client/item/src/card/index.js @@ -35,7 +35,7 @@ class Controller { include: [ {relation: "itemType", scope: { - fields: ['name', 'workerFk'], + fields: ['name', 'workerFk', 'warehouseFk'], include: { relation: 'worker', fields: ['firstName', 'name'] diff --git a/client/item/src/diary/index.html b/client/item/src/diary/index.html index 321082d40..3be516a52 100644 --- a/client/item/src/diary/index.html +++ b/client/item/src/diary/index.html @@ -1,3 +1,11 @@ + + + @@ -8,42 +16,42 @@ url="/item/api/Warehouses" show-field="name" value-field="id" - initial-data="$ctrl.warehouseFk" - field="$ctrl.warehouseFk" - label="Select warehouse"> + initial-data="$ctrl.filter.where.warehouseFk" + field="$ctrl.filter.where.warehouseFk" + label="Select warehouse" on-change="$ctrl.onChange(value)"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DateStateOriginReferenceNameInOutBalance
{{diary.date | date:'dd/MM/yyyy HH:mm' }}{{diary.alertLevel | dashIfEmpty}}{{diary.origin | dashIfEmpty}}{{diary.reference | dashIfEmpty}}{{diary.name | dashIfEmpty}}{{diary.in | dashIfEmpty}}{{diary.out | dashIfEmpty}}{{diary.balance | dashIfEmpty}}
No results
+ + + + Date + State + Origin + Reference + Worker + In + Out + Balance + + + + + {{::sale.date | date:'dd/MM/yyyy HH:mm' }} + {{::sale.alertLevel | dashIfEmpty}} + {{::sale.origin | dashIfEmpty}} + {{::sale.reference | dashIfEmpty}} + {{sale.name | dashIfEmpty}} + {{::sale.in | dashIfEmpty}} + {{::sale.out | dashIfEmpty}} + {{::sale.balance | dashIfEmpty}} + + + + No results + +
- - +
diff --git a/client/item/src/diary/index.js b/client/item/src/diary/index.js index 67c6bcd34..79af25b13 100644 --- a/client/item/src/diary/index.js +++ b/client/item/src/diary/index.js @@ -2,32 +2,96 @@ import ngModule from '../module'; import './style.scss'; class Controller { - constructor($scope, $http) { - this.$ = $scope; + constructor($scope, $http, $state, $window) { + this.$scope = $scope; this.$http = $http; - this.diary = []; + this.$state = $state; + this.$window = $window; } - set warehouseFk(value) { - this._getItemDiary(value); - this._warehouseFk = value; + $postLink() { + if (this.item) + this.filterBuilder(); } - get warehouseFk() { - return this._warehouseFk; + set item(value) { + this._item = value; + + if (value && this.$scope.model) + this.filterBuilder(); } - _getItemDiary(warehouse) { - if (warehouse == null) - return; - let params = {itemFk: this.item.id, warehouseFk: warehouse}; - this.$http.get(`/item/api/Items/getDiary?params=${JSON.stringify(params)}`).then(res => { - this.diary = res.data; - }); + get item() { + return this._item; + } + + get alertLevelIndex() { + let lines = this.$scope.model.data; + for (let i = 0; i < lines.length; i++) { + let isFutureDate = new Date(lines[i].date) > new Date(); + let isGenreOut = lines[i].alertLevel != 0; + + if (!isFutureDate && !isGenreOut) + return i; + } + } + + onChange(value) { + if (!value) return; + + this.filter.where.warehouseFk = value; + this.$scope.model.refresh(); + } + +/** + * Builds a filter with default values + * and aplies query params. + */ + filterBuilder() { + this.filter = { + where: { + itemFk: this.item.id, + warehouseFk: this.item.itemType.warehouseFk + } + + }; + let where = this.filter.where; + + if (this.$state.params.q) { + let queryFilter = JSON.parse(this.$state.params.q); + where.warehouseFk = queryFilter.warehouseFk; + } + } + + scrollToActive() { + let body = this.$window.document.body; + let lineIndex = this.alertLevelIndex; + let lines = body.querySelector('vn-tbody').children; + + if (!lineIndex || !lines.length) return; + + lines[lineIndex].scrollIntoView(); + lines[lineIndex - 1].querySelector('.balance').classList.add('counter'); + } + +/** + * Compares a date with the current one + * @param {Object} date - Date to compare + * @return {Boolean} - Returns true if the two dates equals + */ + isToday(date) { + let today = new Date(); + today.setHours(0, 0, 0, 0); + + let comparedDate = new Date(date); + comparedDate.setHours(0, 0, 0, 0); + + if (!(today - comparedDate)) + return true; } } -Controller.$inject = ['$scope', '$http']; +Controller.$inject = ['$scope', '$http', '$state', '$window']; ngModule.component('vnItemDiary', { template: require('./index.html'), diff --git a/client/item/src/diary/index.spec.js b/client/item/src/diary/index.spec.js index 6cad8fc81..303a36083 100644 --- a/client/item/src/diary/index.spec.js +++ b/client/item/src/diary/index.spec.js @@ -17,25 +17,47 @@ describe('Item', () => { $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); $scope = $rootScope.$new(); controller = $componentController('vnItemDiary', {$scope: $scope}); - controller.item = {id: 3}; + controller.$scope.model = {}; })); - describe('set warehouseFk()', () => { - it(`should call _getItemDiary() with 2 and set warehouseFk`, () => { - spyOn(controller, '_getItemDiary'); - controller.warehouseFk = 2; + describe('isToday()', () => { + it(`should call isToday() an return true if an specified date is the current date`, () => { + let date = new Date(); - expect(controller._getItemDiary).toHaveBeenCalledWith(2); - expect(controller.warehouseFk).toEqual(2); + let result = controller.isToday(date); + + expect(result).toBeTruthy(); + }); + + it(`should call isToday() an return false if an specified date is the current date`, () => { + let date = '2018-07-03'; + + let result = controller.isToday(date); + + expect(result).toBeFalsy(); }); }); - describe('_getItemDiary()', () => { - it(`should make a request to get the diary hwen is called with a number`, () => { - $httpBackend.whenGET('/item/api/Items/getDiary?params={"itemFk":3,"warehouseFk":2}').respond({data: 'item'}); - $httpBackend.expectGET('/item/api/Items/getDiary?params={"itemFk":3,"warehouseFk":2}'); - controller._getItemDiary(2); - $httpBackend.flush(); + describe('alertLevelIndex()', () => { + it(`should call alertLevelIndex() and return an index from line with alertLevel 0 and current date`, () => { + controller.$scope.model = {data: [ + {name: 'My item 1', alertLevel: 3, date: '2018-05-02'}, + {name: 'My item 2', alertLevel: 1, date: '2018-05-03'}, + {name: 'My item 3', alertLevel: 0, date: new Date()}] + }; + let result = controller.alertLevelIndex; + + expect(result).toEqual(2); + }); + }); + + describe('set item()', () => { + it(`should call filterBuilder()`, () => { + spyOn(controller, 'filterBuilder'); + controller.item = {id: 1}; + + expect(controller.filterBuilder).toHaveBeenCalledWith(); + expect(controller.item).toEqual({id: 1}); }); }); }); diff --git a/client/salix/src/styles/misc.scss b/client/salix/src/styles/misc.scss index 4e311df21..f94ddb8bd 100644 --- a/client/salix/src/styles/misc.scss +++ b/client/salix/src/styles/misc.scss @@ -242,4 +242,15 @@ fieldset[disabled] .mdl-textfield .mdl-textfield__label, text-overflow: ellipsis; white-space: nowrap; overflow: hidden; +} + +.counter { + background-color: $main-header; + color: $color-white; + border-radius: 3px; + padding: 5px +} + +.counter.small { + font-size: 0.7em } \ No newline at end of file diff --git a/services/loopback/common/methods/item/getDiary.js b/services/loopback/common/methods/item/getDiary.js index df4176713..5d8259867 100644 --- a/services/loopback/common/methods/item/getDiary.js +++ b/services/loopback/common/methods/item/getDiary.js @@ -3,12 +3,14 @@ module.exports = Self => { description: 'Returns the ', accessType: 'READ', accepts: [{ - arg: 'params', - type: 'object', - description: 'itemFk, warehouseFk' + arg: 'filter', + type: 'Object', + required: true, + description: 'Filter defining where and paginated data', + http: {source: 'query'} }], returns: { - arg: 'diary', + type: ['Object'], root: true }, http: { @@ -17,8 +19,9 @@ module.exports = Self => { } }); - Self.getDiary = async params => { - let [diary] = await Self.rawSql(`CALL vn.itemDiary(?, ?)`, [params.itemFk, params.warehouseFk]); + Self.getDiary = async filter => { + let where = filter.where; + let [diary] = await Self.rawSql(`CALL vn.itemDiary(?, ?)`, [where.itemFk, where.warehouseFk]); return diary; }; }; diff --git a/services/loopback/common/models/item-type.json b/services/loopback/common/models/item-type.json index 8619a35be..c4753e531 100644 --- a/services/loopback/common/models/item-type.json +++ b/services/loopback/common/models/item-type.json @@ -24,10 +24,15 @@ }, "relations": { "worker": { - "type": "belongsTo", - "model": "Worker", - "foreignKey": "workerFk" - } + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" + }, + "warehouse": { + "type": "belongsTo", + "model": "Warehouse", + "foreignKey": "warehouseFk" + } }, "acls": [ {