diff --git a/client/claim/src/detail/locale/es.yml b/client/claim/src/detail/locale/es.yml index 39f547ebf..072a699bc 100644 --- a/client/claim/src/detail/locale/es.yml +++ b/client/claim/src/detail/locale/es.yml @@ -1,7 +1,7 @@ Claimed: Reclamados Disc.: Dto. Attended by: Atendida por -Landed: Recibido +Landed: F. entrega Price: Precio Claimable sales from ticket: Lineas reclamables del ticket Detail: Detalles diff --git a/client/core/src/components/check/check.js b/client/core/src/components/check/check.js index 5b1a276d6..1f8aa7969 100644 --- a/client/core/src/components/check/check.js +++ b/client/core/src/components/check/check.js @@ -10,11 +10,12 @@ export default class Controller extends Input { this.input.addEventListener('change', () => this.onChange()); } set field(value) { + this._field = value; this.input.checked = value == true; this.mdlUpdate(); } get field() { - return this.input.checked == true; + return this._field; } $onInit() { if (this.model) { @@ -30,6 +31,7 @@ export default class Controller extends Input { } } onChange() { + this._field = this.input.checked == true; this.$.$applyAsync(); } } diff --git a/client/core/src/components/tooltip/tooltip.js b/client/core/src/components/tooltip/tooltip.js index 3f221c107..e0bc323eb 100644 --- a/client/core/src/components/tooltip/tooltip.js +++ b/client/core/src/components/tooltip/tooltip.js @@ -15,6 +15,7 @@ export default class Tooltip extends Component { this.$timeout = $timeout; $element.addClass('vn-tooltip mdl-shadow--4dp'); this.position = 'down'; + this.margin = 10; } /** @@ -64,8 +65,8 @@ export default class Tooltip extends Component { axis = 'y'; } - let arrowSize = 10; - let tipMargin = arrowSize; + let arrowSize = this.margin; + let tipMargin = this.margin; let rect = this.parent.getBoundingClientRect(); let tipRect = this.element.getBoundingClientRect(); @@ -73,8 +74,8 @@ export default class Tooltip extends Component { let bgColor = tipComputed.getPropertyValue('background-color'); let min = tipMargin; - let maxTop = window.innerHeight - tipRect.height - tipMargin; - let maxLeft = window.innerWidth - tipRect.width - tipMargin; + let maxTop = this.window.innerHeight - tipRect.height - tipMargin; + let maxLeft = this.window.innerWidth - tipRect.width - tipMargin; // Coordinates diff --git a/client/core/src/components/tooltip/tooltip.spec.js b/client/core/src/components/tooltip/tooltip.spec.js index b3d62a12e..2a7df9bc7 100644 --- a/client/core/src/components/tooltip/tooltip.spec.js +++ b/client/core/src/components/tooltip/tooltip.spec.js @@ -7,59 +7,112 @@ describe('Component vnTooltip', () => { let $httpBackend; let $timeout; let controller; + let $tooltip; + let $controller; + let parent; beforeEach(() => { angular.mock.module('client'); }); - beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => { + beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_, $compile, $document) => { $scope = $rootScope.$new(); $timeout = _$timeout_; $element = angular.element(`
${template}
`); + $tooltip = $compile(`test`)($rootScope); + $document.find('body').append($tooltip); $httpBackend = _$httpBackend_; $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); controller = _$componentController_('vnTooltip', {$element, $scope, $timeout, $transclude: null}); + $controller = $tooltip[0].$ctrl; + parent = angular.element('
')[0]; })); describe('show()', () => { - it(`should define parent property and add a class named 'show' to the element`, () => { - spyOn(controller, 'relocate'); - spyOn(controller, 'cancelTimeout'); + it(`should check that tooltip is visible into the screen`, () => { + $controller.show(parent); - controller.show({name: 'parentElement'}); + let clientRect = $controller.element.getBoundingClientRect(); + let style = window.getComputedStyle($controller.element); - expect(controller.parent).toEqual({name: 'parentElement'}); - expect($element[0].classList).toContain('show'); + expect(style.visibility).toEqual('visible'); + expect(style.display).not.toEqual('none'); + + expect(0).toBeLessThanOrEqual(clientRect.top); + expect(0).toBeLessThanOrEqual(clientRect.left); + expect($controller.window.innerHeight).toBeGreaterThan(clientRect.bottom); + expect($controller.window.innerWidth).toBeGreaterThan(clientRect.right); }); }); describe('hide()', () => { - it(`should remove a class named 'show' from the element`, () => { - spyOn(controller, 'cancelTimeout'); + it(`should check that tooltip is not visible`, () => { + $controller.show(parent); + $controller.hide(); + let style = window.getComputedStyle($controller.element); - controller.hide(); - - expect($element[0].classList).not.toContain('show'); + expect(style.display).toEqual('none'); }); }); - describe('cancelTimeout()', () => { - it(`should call $timeout cancel method and unset relocateTimeout property`, () => { - spyOn(controller.$timeout, 'cancel'); - controller.relocateTimeout = {name: 'MyTimeout'}; + describe('relocate()', () => { + it(`should reallocate tooltip on top-left`, () => { + let parent = {getBoundingClientRect() { + return {top: 0, left: 0, height: 10, width: 10}; + }}; + $controller.show(parent); + let clientRect = $controller.element.getBoundingClientRect(); - controller.cancelTimeout(); - - expect(controller.$timeout.cancel).toHaveBeenCalledWith({name: 'MyTimeout'}); - expect(controller.relocateTimeout).toBeNull(); + expect($controller.margin).toBeLessThan(clientRect.top); + expect($controller.margin).toEqual(clientRect.left); }); - it(`should not call $timeout cancel method`, () => { - spyOn(controller.$timeout, 'cancel'); - controller.relocateTimeout = {name: 'MyTimeout'}; + it(`should reallocate tooltip on bottom-left`, () => { + let parent = { + getBoundingClientRect() { + return {top: $controller.window.innerHeight, left: 0, height: 10, width: 10}; + }}; + $controller.show(parent); + let clientRect = $controller.element.getBoundingClientRect(); - expect(controller.$timeout.cancel).not.toHaveBeenCalledWith(); - expect(controller.relocateTimeout).toBeDefined(); + expect($controller.window.innerHeight).toBeGreaterThan(clientRect.top); + expect($controller.margin).toEqual(clientRect.left); + }); + + it(`should reallocate tooltip on bottom-right`, () => { + let parent = { + getBoundingClientRect() { + return {top: $controller.window.innerHeight, left: $controller.window.innerWidth, height: 10, width: 10}; + }}; + $controller.show(parent); + let clientRect = $controller.element.getBoundingClientRect(); + + expect($controller.window.innerWidth).toBeGreaterThan(clientRect.left); + expect($controller.window.innerWidth - $controller.margin).toEqual(clientRect.right); + }); + + it(`should reallocate tooltip on top-right`, () => { + let parent = { + getBoundingClientRect() { + return {top: 0, left: $controller.window.innerWidth, height: 10, width: 10}; + }}; + $controller.show(parent); + let clientRect = $controller.element.getBoundingClientRect(); + + expect($controller.margin).toBeLessThan(clientRect.top); + expect($controller.window.innerWidth - $controller.margin).toEqual(clientRect.right); + }); + + it(`should reallocate tooltip on center`, () => { + let parent = { + getBoundingClientRect() { + return {top: $controller.window.innerHeight / 2, left: $controller.window.innerWidth / 2, height: 10, width: 10}; + }}; + $controller.show(parent); + let clientRect = $controller.element.getBoundingClientRect(); + + expect($controller.window.innerHeight / 2).toBeLessThan(clientRect.top); + expect($controller.window.innerWidth / 2).toBeGreaterThan(clientRect.left); }); }); }); diff --git a/client/item/src/last-entries/locale/es.yml b/client/item/src/last-entries/locale/es.yml index bece49318..0eac6eaa6 100644 --- a/client/item/src/last-entries/locale/es.yml +++ b/client/item/src/last-entries/locale/es.yml @@ -1,5 +1,5 @@ Since: Desde -Landed: Llegada +Landed: F. entrega Stems: Tallos Quantity: Cantidad Cost: Coste diff --git a/client/order/src/catalog-search-panel/index.html b/client/order/src/catalog-search-panel/index.html new file mode 100644 index 000000000..bb745fde6 --- /dev/null +++ b/client/order/src/catalog-search-panel/index.html @@ -0,0 +1,25 @@ +
+
+ + + {{name}} + + + + + + + + + +
+
diff --git a/client/order/src/catalog-search-panel/index.js b/client/order/src/catalog-search-panel/index.js new file mode 100644 index 000000000..0399d7aeb --- /dev/null +++ b/client/order/src/catalog-search-panel/index.js @@ -0,0 +1,7 @@ +import ngModule from '../module'; +import SearchPanel from 'core/src/components/searchbar/search-panel'; + +ngModule.component('vnOrderCatalogSearchPanel', { + template: require('./index.html'), + controller: SearchPanel +}); diff --git a/client/order/src/filter/index.html b/client/order/src/filter/index.html index 56c130dee..f94a23564 100644 --- a/client/order/src/filter/index.html +++ b/client/order/src/filter/index.html @@ -69,7 +69,7 @@ - + diff --git a/client/order/src/index.js b/client/order/src/index.js index cb618a97e..6da1a918f 100644 --- a/client/order/src/index.js +++ b/client/order/src/index.js @@ -3,6 +3,7 @@ export * from './module'; import './card'; import './descriptor'; import './search-panel'; +import './catalog-search-panel'; import './filter'; import './index/'; import './summary'; diff --git a/client/order/src/index/index.html b/client/order/src/index/index.html index 9a02eb75f..4a2cf9624 100644 --- a/client/order/src/index/index.html +++ b/client/order/src/index/index.html @@ -6,6 +6,16 @@ data="orders">
+
+ + + + +
diff --git a/client/order/src/index/index.js b/client/order/src/index/index.js index e0571c4a4..d94f10df6 100644 --- a/client/order/src/index/index.js +++ b/client/order/src/index/index.js @@ -18,6 +18,24 @@ export default class Controller { }; } + exprBuilder(param, value) { + switch (param) { + case 'search': + return {id: value}; + case 'from': + return {landed: {gte: value}}; + case 'to': + return {landed: {lte: value}}; + case 'id': + case 'clientFk': + case 'workerFk': + case 'sourceApp': + case 'agencyModeFk': + case 'isConfirmed': + return {[param]: value}; + } + } + showDescriptor(event, clientFk) { this.$scope.descriptor.clientFk = clientFk; this.$scope.descriptor.parent = event.target; diff --git a/client/order/src/search-panel/index.html b/client/order/src/search-panel/index.html index bb745fde6..dc9c4d9a6 100644 --- a/client/order/src/search-panel/index.html +++ b/client/order/src/search-panel/index.html @@ -1,25 +1,61 @@ -
+
- - - {{name}} - - + label="Order id" + model="filter.id"> + + + + + + + + {{firstName}} {{name}} + + + + + + + + + + + + +
-
+
\ No newline at end of file diff --git a/client/order/src/search-panel/locale/es.yml b/client/order/src/search-panel/locale/es.yml new file mode 100644 index 000000000..d7ccd18cf --- /dev/null +++ b/client/order/src/search-panel/locale/es.yml @@ -0,0 +1,9 @@ +Order id: Id ticket +Client id: Id cliente +From landed: Desde f. entrega +To landed: Hasta f. entrega +To: Hasta +Agency: Agencia +Application: AplicaciĆ³n +SalesPerson: Comercial +Order confirmed: Pedido confirmado \ No newline at end of file diff --git a/services/claim/common/methods/claim/regularizeClaim.js b/services/claim/common/methods/claim/regularizeClaim.js index 59d8635a5..24295bc79 100644 --- a/services/claim/common/methods/claim/regularizeClaim.js +++ b/services/claim/common/methods/claim/regularizeClaim.js @@ -117,7 +117,7 @@ module.exports = Self => { async function getTicketId(params, transaction) { const currentDate = new Date(); - currentDate.setHours(0, 0, 0, 0); + currentDate.setHours(null, null, null); let ticket = await Self.app.models.Ticket.findOne({ where: { diff --git a/services/loopback/common/methods/vn-model/getSetValues.js b/services/loopback/common/methods/vn-model/getSetValues.js new file mode 100644 index 000000000..8afb51f1e --- /dev/null +++ b/services/loopback/common/methods/vn-model/getSetValues.js @@ -0,0 +1,50 @@ +module.exports = Self => { + /** + * Returns a set of allowed values defined on table scheme + * @param {String} column - Model or Table column name + * @return {Array} - Array of set values + */ + Self.getSetValues = async function(column) { + let model = this.app.models[this.modelName].definition; + let properties = model.properties; + let columnName; + let tableName; + + if (model.settings && model.settings.mysql) + tableName = model.settings.mysql.table; + + if (properties[column]) { + columnName = column; + + if (properties[column].mysql) + columnName = properties[column].mysql.columnName; + } + + let findColumn = Object.keys(properties).find(prop => { + return properties[prop].mysql && properties[prop].mysql.columnName === column; + }); + + if (findColumn) + columnName = properties[findColumn].mysql.columnName; + + let type = await this.rawSql(` + SELECT DISTINCT column_type FROM information_schema.columns + WHERE table_name = ? + AND column_name = ?`, [tableName, columnName]); + + if (!type) return; + + let setValues; + setValues = type[0].column_type; + setValues = setValues.replace(/set\((.*)\)/i, '$1'); + setValues = setValues.replace(/'/g, ''); + setValues = setValues.match(new RegExp(/(\w+)+/, 'ig')); + + let values = []; + setValues.forEach(setValue => { + values.push({value: setValue}); + }); + + return values; + }; +}; diff --git a/services/loopback/common/methods/vn-model/rewriteDbError.js b/services/loopback/common/methods/vn-model/rewriteDbError.js index 57f49202d..1a4045662 100644 --- a/services/loopback/common/methods/vn-model/rewriteDbError.js +++ b/services/loopback/common/methods/vn-model/rewriteDbError.js @@ -1,4 +1,9 @@ module.exports = Self => { + /** + * Catches database errors overriding + * model.create() and model.upsert() methods + * @param {Object} replaceErrFunc - Callback + */ Self.rewriteDbError = function(replaceErrFunc) { this.once('attached', () => { let realUpsert = this.upsert; diff --git a/services/loopback/common/methods/vn-model/specs/getSetValues.spec.js b/services/loopback/common/methods/vn-model/specs/getSetValues.spec.js new file mode 100644 index 000000000..1cdeb7a81 --- /dev/null +++ b/services/loopback/common/methods/vn-model/specs/getSetValues.spec.js @@ -0,0 +1,23 @@ +const app = require('../../../../../order/server/server'); + +describe('Model getSetValues()', () => { + it('should extend getSetValues properties to any model passed', () => { + let exampleModel = app.models.Order; + + expect(exampleModel.getSetValues).toBeDefined(); + }); + + it('should return an array of set values from model column sourceApp', async() => { + let result = await app.models.Order.getSetValues('sourceApp'); + + expect(result.length).toEqual(6); + expect(result[5].value).toEqual('TABLET_VN'); + }); + + it('should return an array of set values from table column source_app', async() => { + let result = await app.models.Order.getSetValues('source_app'); + + expect(result.length).toEqual(6); + expect(result[5].value).toEqual('TABLET_VN'); + }); +}); diff --git a/services/loopback/common/models/vn-model.js b/services/loopback/common/models/vn-model.js index ba27f8e6f..5831c2615 100644 --- a/services/loopback/common/models/vn-model.js +++ b/services/loopback/common/models/vn-model.js @@ -2,6 +2,8 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = function(Self) { + Self.ParameterizedSQL = ParameterizedSQL; + Self.setup = function() { Self.super_.setup.call(this); /* @@ -173,6 +175,14 @@ module.exports = function(Self) { }; }; + /** + * Executes an SQL query + * @param {String} query - SQL query + * @param {Object} params - Query data params + * @param {Object} options - Query options (Ex: {transaction}) + * @param {Object} cb - Callback + * @return {Object} Connector promise + */ Self.rawSql = function(query, params, options = {}, cb) { var connector = this.dataSource.connector; return new Promise(function(resolve, reject) { @@ -187,6 +197,12 @@ module.exports = function(Self) { }); }; + /** + * Executes an SQL query from an Stmt + * @param {ParameterizedSql} stmt - Stmt object + * @param {Object} options - Query options (Ex: {transaction}) + * @return {Object} Connector promise + */ Self.rawStmt = function(stmt, options = {}) { return this.rawSql(stmt.sql, stmt.params, options); }; @@ -195,6 +211,12 @@ module.exports = function(Self) { return this.dataSource.connector.escapeName(name); }; + /** + * Constructs SQL where clause from Loopback filter + * @param {Object} filter - filter + * @param {String} tableAlias - Query main table alias + * @return {String} Builded SQL where + */ Self.buildWhere = function(filter, tableAlias) { let connector = this.dataSource.connector; let wrappedConnector = Object.create(connector); @@ -208,12 +230,22 @@ module.exports = function(Self) { return wrappedConnector.makeWhere(this.modelName, filter.where); }; + /** + * Constructs SQL limit clause from Loopback filter + * @param {Object} filter - filter + * @return {String} Builded SQL limit + */ Self.buildLimit = function(filter) { let sql = new ParameterizedSQL(''); this.dataSource.connector.applyPagination(this.modelName, sql, filter); return sql; }; + /** + * Constructs SQL order clause from Loopback filter + * @param {Object} filter - filter + * @return {String} Builded SQL order + */ Self.buildOrderBy = function(filter) { let order = filter.order; @@ -242,6 +274,11 @@ module.exports = function(Self) { return `ORDER BY ${clauses.join(', ')}`; }; + /** + * Constructs SQL pagination from Loopback filter + * @param {Object} filter - filter + * @return {String} Builded SQL pagination + */ Self.buildPagination = function(filter) { return ParameterizedSQL.join([ this.buildOrderBy(filter), @@ -249,6 +286,13 @@ module.exports = function(Self) { ]); }; + /** + * Constructs SQL filter including where, order and limit + * clauses from Loopback filter + * @param {Object} filter - filter + * @param {String} tableAlias - Query main table alias + * @return {String} Builded SQL limit + */ Self.buildSuffix = function(filter, tableAlias) { return ParameterizedSQL.join([ this.buildWhere(filter, tableAlias), @@ -256,9 +300,10 @@ module.exports = function(Self) { ]); }; - Self.ParameterizedSQL = ParameterizedSQL; - - require('../methods/vn-model/installMethod')(Self); + // Action bindings require('../methods/vn-model/validateBinded')(Self); + // Handle MySql errors require('../methods/vn-model/rewriteDbError')(Self); + // Get table set of values + require('../methods/vn-model/getSetValues')(Self); }; diff --git a/services/order/common/methods/order/getSourceValues.js b/services/order/common/methods/order/getSourceValues.js new file mode 100644 index 000000000..da3685c62 --- /dev/null +++ b/services/order/common/methods/order/getSourceValues.js @@ -0,0 +1,18 @@ +module.exports = Self => { + Self.remoteMethod('getSourceValues', { + description: 'Gets the sourceApp type set', + accessType: 'READ', + returns: { + type: ['String'], + root: true + }, + http: { + path: `/getSourceValues`, + verb: 'GET' + } + }); + + Self.getSourceValues = async () => { + return Self.getSetValues('sourceApp'); + }; +}; diff --git a/services/order/common/models/order.js b/services/order/common/models/order.js index 4df8090e0..0e7ec2400 100644 --- a/services/order/common/models/order.js +++ b/services/order/common/models/order.js @@ -8,4 +8,5 @@ module.exports = Self => { require('../methods/order/catalogFilter')(Self); require('../methods/order/summary')(Self); require('../methods/order/getVAT')(Self); + require('../methods/order/getSourceValues')(Self); };