diff --git a/client/core/src/components/date-picker/date-picker.html b/client/core/src/components/date-picker/date-picker.html index 299d9df4b..60ba189d8 100644 --- a/client/core/src/components/date-picker/date-picker.html +++ b/client/core/src/components/date-picker/date-picker.html @@ -1,28 +1,18 @@
+ ng-mouseleave="$ctrl.hasMouseIn = false"> -
- - query_builder - clear diff --git a/client/core/src/components/date-picker/date-picker.js b/client/core/src/components/date-picker/date-picker.js index db5e59d6f..99715d717 100644 --- a/client/core/src/components/date-picker/date-picker.js +++ b/client/core/src/components/date-picker/date-picker.js @@ -3,240 +3,93 @@ import Component from '../../lib/component'; import Flatpickr from 'vendor/src/flatpickr'; import './style.scss'; -// equivalences to format date between flatpicker and angularjs -export const formatEquivalence = { - d: 'dd', // Day of the month, 2 digits with leading zeros (01 to 31) - j: 'd', // Day of the month without leading zeros (1 to 31) - m: 'MM', // Month in year, padded (01-12) - n: 'M', // Month in year (1-12) - y: 'yy', // A two digit representation of a year (00-99) - Y: 'yyyy', // A full numeric representation of a year, 4 digits (1999 or 2003) - H: 'HH', // Hour in AM/PM, padded (01-12) - h: 'H', // Hour in AM/PM, (1-12) - i: 'mm', // Minutes (00 to 59) - s: 'ss' // Seconds (00 to 59) -}; - class DatePicker extends Component { - constructor($element, $translate, $filter, $timeout, $attrs) { - super($element); + constructor($element, $scope, $translate, $attrs) { + super($element, $scope); this.input = $element[0].querySelector('input'); this.$translate = $translate; - this.$filter = $filter; - this.$timeout = $timeout; this.$attrs = $attrs; - this.enabled = true; this._modelView = null; this._model = undefined; - this._optionsChecked = false; - this._waitingInit = 0; - this.hasFocus = false; + this.dateValue = undefined; this.hasMouseIn = false; + let locale = this.$translate.use(); + this.defaultOptions = { + locale: locale, + dateFormat: locale == 'es' ? 'd-m-Y' : 'Y-m-d', + enableTime: false, + onValueUpdate: () => this.onValueUpdate() + }; + this.userOptions = {}; + this._iniOptions = this.defaultOptions; + componentHandler.upgradeElement($element[0].firstChild); + this.vp = new Flatpickr(this.input, this._iniOptions); + } + + onValueUpdate() { + if (this.vp.selectedDates.length) + this.model = this.vp.selectedDates[0]; + else + this.model = null; + this.$.$apply(); + } + + set iniOptions(value) { + this.userOptions = value; + let options = Object.assign({}, this.defaultOptions, value); + this._iniOptions = options; + this.isTimePicker = options.enableTime && options.noCalendar; + + // TODO: When some properties change Flatpickr doesn't refresh the view + //for (let option in options) + // this.vp.set(option, options[option]); + + if (this.vp) this.vp.destroy(); + this.vp = new Flatpickr(this.input, this._iniOptions); + this.vp.setDate(this.dateValue); + this.mdlUpdate(); + } + + get iniOptions() { + return this.userOptions; } get model() { return this._model; } - set model(value) { - if (this._optionsChecked) { - this._waitingInit = 0; - this._model = value; - if (value && !this.modelView) { - let options = this._getOptions(); - let initialDateFormat; - if (options && options.dateFormat) { - initialDateFormat = options.dateFormat; - } else { - initialDateFormat = this.$translate.use() === 'es' ? 'd-m-Y' : 'Y-m-d'; - if (options.enableTime) { - initialDateFormat += ' H:i:s'; - } - } - let format = this._formatFlat2Angular(initialDateFormat); - this._modelView = this.$filter('date')(new Date(this._model), format); - this.mdlUpdate(); - } - } else if (this._waitingInit < 4) { - this._waitingInit++; - this.$timeout(() => { - this.model = value; - }, 250); - } else { - this.model = null; - this.modelView = ''; - this._waitingInit = 0; - } - } - get modelView() { - return this._modelView; - } - set modelView(value) { - this._modelView = value; - this.input.value = value; - this._setModel(value); + set model(value) { + this._model = value; + this.dateValue = value ? new Date(value) : null; + this.vp.setDate(this.dateValue); this.mdlUpdate(); } + get modelView() { + return this._modelView; + } + + set modelView(value) { + this._modelView = value; + } + onClear() { - this.modelView = null; - } - onClick() { - if (this.vp) { - this.vp.open(); - } + this.model = null; } + mdlUpdate() { - this.$timeout(() => { - let mdlField = this.element.firstChild.MaterialTextfield; - if (mdlField) - mdlField.updateClasses_(); - }, 500); - } - - _formatFlat2Angular(string) { // change string Flatpickr format to angular format (d-m-Y -> dd-MM-yyyy) - let aux = string.split(/[ZT.,/ :-]/); - let parts = []; - aux.forEach( - val => { - parts.push(formatEquivalence[val]); - } - ); - if (string.indexOf(' ') !== -1 || string.indexOf('T') !== -1) { // datetime format - let dates = parts.slice(0, 3).join('-'); - let hours = parts.slice(3, parts.length).join(':'); - return `${dates} ${hours}`.trim(); - } else if (string.indexOf(':') !== -1) { // only time format - return parts.join(':'); - } // only date format - return parts.join('-'); - } - - _string2BackFormat(value) { - let formats = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/); - let aux = value.split(/[ZT.,/ :-]/); - let date = {}; - formats.forEach( - (k, i) => { - if (k.toLowerCase() === 'y') { - date.year = aux[i]; - } else if (k === 'm' || k === 'n') { - date.month = aux[i]; - } else if (k === 'd' || k === 'j') { - date.day = aux[i]; - } else if (k.toLowerCase() === 'h') { - date.hour = aux[i]; - } else if (k === 'i') { - date.minutes = aux[i]; - } else if (k === 's') { - date.seccons = aux[i]; - } - } - ); - - let dateStr = ''; - let hourStr = ''; - - if (date.year && date.month && date.day) { - dateStr = `${date.year}-${date.month}-${date.day}`; - } - if (date.hour) { - hourStr = date.hour; - if (date.minutes) { - hourStr += ':' + date.minutes; - } else { - hourStr += ':00'; - } - if (date.seccons) { - hourStr += ':' + date.seccons; - } else { - hourStr += ':00'; - } - } - return `${dateStr} ${hourStr}`.trim(); - } - - _setModel(value) { - let model; - let options = this._getOptions(); - if (!value) { - model = undefined; - } else if (!options || (options.dateFormat && options.dateFormat.startsWith('Y-m-d'))) { - model = value; - } else { - model = this._string2BackFormat(value); - } - - if (this.model !== model) { - this.model = model; - } - } - - _getOptions() { - if (this.iniOptions && this._optionsChecked) { - return this.iniOptions; - } else if (!this.iniOptions) { - this.iniOptions = {}; - } - - if (!this.iniOptions.locale) - this.iniOptions.locale = this.$translate.use(); - - if (!this.iniOptions.dateFormat) - this.iniOptions.dateFormat = this.iniOptions.locale === 'es' ? 'd-m-Y' : 'Y-m-d'; - else if (this.iniOptions.dateFormat) { - let format = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/); - if (format.length <= 1) { - throw new Error(`Error: Invalid string format ${format}`); - } - format.forEach( - val => { - if (!formatEquivalence[val]) { - throw new Error(`Error in dateFormat ${this.iniOptions.dateFormat}: is not like Flatpickr Formatting Token https://chmln.github.io/flatpickr/formatting/`); - } - } - ); - } - - if (this.$attrs.hasOwnProperty('today')) { - this.iniOptions.defaultDate = new Date(); - } - - this._optionsChecked = true; - return this.iniOptions; - } - - initPicker() { - this.iniOptions = this._getOptions(); - this.isTimePicker = (this.iniOptions && this.iniOptions.enableTime && this.iniOptions.noCalendar); - this.vp = new Flatpickr(this.input, this.iniOptions); - if (this.iniOptions.defaultDate) { - this.modelView = this.vp.formatDate(this.iniOptions.defaultDate, this.iniOptions.dateFormat); - } - } - destroyPicker() { - if (this.vp) - this.vp.destroy(); - this.vp = undefined; - } - - $onChanges(objChange) { - if (objChange.iniOptions && objChange.iniOptions.currentValue) { - this.iniOptions = Object.assign(this.iniOptions, objChange.iniOptions.currentValue); - } - } - - $onInit() { - this.initPicker(); + let mdlField = this.element.firstChild.MaterialTextfield; + if (mdlField) + mdlField.updateClasses_(); } $onDestroy() { - this.destroyPicker(); + this.vp.destroy(); } } -DatePicker.$inject = ['$element', '$translate', '$filter', '$timeout', '$attrs']; +DatePicker.$inject = ['$element', '$scope', '$translate', '$attrs']; ngModule.component('vnDatePicker', { template: require('./date-picker.html'), diff --git a/client/core/src/components/date-picker/date-picker.spec.js b/client/core/src/components/date-picker/date-picker.spec.js deleted file mode 100644 index 2be0c1eb4..000000000 --- a/client/core/src/components/date-picker/date-picker.spec.js +++ /dev/null @@ -1,47 +0,0 @@ -import './date-picker.js'; - -describe('Component vnDatePicker', () => { - let $componentController; - let $filter; - let $timeout; - let $element; - let $attrs; - let $translate; - let controller; - - beforeEach(() => { - angular.mock.module('client'); - }); - - beforeEach(angular.mock.inject((_$componentController_, _$filter_, _$timeout_, _$translate_) => { - $componentController = _$componentController_; - $filter = _$filter_; - $timeout = _$timeout_; - $element = angular.element(`
`); - $translate = _$translate_; - $attrs = {}; - controller = $componentController('vnDatePicker', {$element, $translate, $filter, $timeout, $attrs}); - })); - - describe('_formatFlat2Angular()', () => { - it(`should format date from Y-m-d to yyyy-MM-dd`, () => { - let formatedDate = controller._formatFlat2Angular(`Y-m-d`); - - expect(formatedDate).toBe('yyyy-MM-dd'); - }); - - it(`should format date from d-m-Y to dd-MM-yyyy`, () => { - let formatedDate = controller._formatFlat2Angular(`d-m-Y`); - - expect(formatedDate).toBe('dd-MM-yyyy'); - }); - - it(`should split the given string into parts`, () => { - controller.iniOptions = {dateFormat: 'd/m/Y'}; - controller._optionsChecked = true; - controller.model = '2017-12-23'; - - expect(controller.modelView).toBe('23-12-2017'); - }); - }); -}); diff --git a/client/core/src/components/date-picker/style.scss b/client/core/src/components/date-picker/style.scss index 99f1cbc1b..1807e6949 100644 --- a/client/core/src/components/date-picker/style.scss +++ b/client/core/src/components/date-picker/style.scss @@ -1,3 +1,5 @@ +@import "colors"; + vn-date-picker { .mdl-chip__action { position: absolute; @@ -7,9 +9,18 @@ vn-date-picker { margin: 22px 0px; background-color: white; } + .mdl-textfield { + width: 100%; + } .material-icons { font-size: 18px; float: right; margin-right: 5px; } +} + +.flatpickr-months .flatpickr-month, +.flatpickr-weekdays, +span.flatpickr-weekday { + background-color: $main-01; } \ No newline at end of file diff --git a/client/core/src/components/drop-down/drop-down.js b/client/core/src/components/drop-down/drop-down.js index bfe372b7d..c8b6c2a52 100755 --- a/client/core/src/components/drop-down/drop-down.js +++ b/client/core/src/components/drop-down/drop-down.js @@ -196,7 +196,7 @@ export default class DropDown extends Component { } let where = {}; - where[this.showField] = {regexp: search}; + where[this.showField] = {like: `%${search}%`}; return where; } diff --git a/client/core/src/components/step-control/step-control.js b/client/core/src/components/step-control/step-control.js index b655411d0..0ca1f0c46 100644 --- a/client/core/src/components/step-control/step-control.js +++ b/client/core/src/components/step-control/step-control.js @@ -16,12 +16,19 @@ export default class StepControl { } set currentState(state) { - let isAllowed = true; + if (!this.onStepChange) + return this.$state.go(state); - if (this.onStepChange) - isAllowed = this.onStepChange({state}); + let change = this.onStepChange({state}); - if (isAllowed) + if (typeof change === 'object' && change.then) { + return change.then(isAllowed => { + if (isAllowed) + this.$state.go(state); + }); + } + + if (change) this.$state.go(state); } diff --git a/client/item/src/data/data.html b/client/item/src/data/data.html index 507fdc2b2..d37fc0af1 100644 --- a/client/item/src/data/data.html +++ b/client/item/src/data/data.html @@ -51,6 +51,7 @@ field="$ctrl.item.expenceFk" initial-data="$ctrl.item.expence"> + diff --git a/client/item/src/data/locale/es.yml b/client/item/src/data/locale/es.yml new file mode 100644 index 000000000..8efa03cd6 --- /dev/null +++ b/client/item/src/data/locale/es.yml @@ -0,0 +1 @@ +Reference: Referencia \ No newline at end of file diff --git a/client/locator/routes.json b/client/locator/routes.json index b508fcc5f..0ea240bda 100644 --- a/client/locator/routes.json +++ b/client/locator/routes.json @@ -1,4 +1,4 @@ -{ +/* { "module": "locator", "name": "Locator", "icon": "add_location", @@ -11,4 +11,4 @@ "acl": ["developer"] } ] -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/client/modules.yml b/client/modules.yml index cd51504b1..3ffb57dfc 100644 --- a/client/modules.yml +++ b/client/modules.yml @@ -2,9 +2,9 @@ auth: [] client: [] core: [] item: [] -locator: [] -production: [] +#locator: [] +#production: [] salix: [] -route: [] +#route: [] ticket: [item] order: [] diff --git a/client/production/routes.json b/client/production/routes.json index 159a80144..2df511b28 100644 --- a/client/production/routes.json +++ b/client/production/routes.json @@ -1,4 +1,4 @@ -{ +/* { "module": "production", "name": "Production", "icon": "local_florist", @@ -11,4 +11,4 @@ "acl": ["developer"] } ] -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/client/route/routes.json b/client/route/routes.json index 9e7c48833..907a65b75 100644 --- a/client/route/routes.json +++ b/client/route/routes.json @@ -1,4 +1,4 @@ -{ +/* { "module": "route", "name": "Routes", "icon" : "local_shipping", @@ -65,4 +65,4 @@ } } ] -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/client/ticket/routes.json b/client/ticket/routes.json index 577654d62..2d481ba72 100644 --- a/client/ticket/routes.json +++ b/client/ticket/routes.json @@ -71,6 +71,18 @@ "ticket": "$ctrl.data" } }, + { + "url" : "/sale", + "state": "ticket.card.sale", + "component": "vn-ticket-sale", + "params": { + "ticket": "$ctrl.ticket" + }, + "menu": { + "description": "Sale", + "icon": "icon-lines" + } + }, { "url": "/observation", "state": "ticket.card.observation", @@ -141,7 +153,8 @@ "menu": { "description": "Tracking", "icon": "remove_red_eye" - } + }, + "acl": ["production"] }, { "url": "/edit", @@ -159,18 +172,6 @@ "client": "$ctrl.client" } }, - { - "url" : "/sale", - "state": "ticket.card.sale", - "component": "vn-ticket-sale", - "params": { - "ticket": "$ctrl.ticket" - }, - "menu": { - "description": "Sale", - "icon": "icon-lines" - } - }, { "url" : "/sale-checked", "state": "ticket.card.saleChecked", diff --git a/client/ticket/src/data/data.js b/client/ticket/src/data/data.js index df67f2920..f2492fc6e 100644 --- a/client/ticket/src/data/data.js +++ b/client/ticket/src/data/data.js @@ -7,17 +7,21 @@ class Controller { } set ticket(data) { + if (!data) return; + this.data = Object.assign({}, data); } - onSubmit() { - //post data - alert('Data saved'); - console.log(this.data); + registerChild(child) { + this.child = child; } onStepChange(state) { - return true; + return this.child.onStepChange(state); + } + + onSubmit() { + this.child.onSubmit(); } } diff --git a/client/ticket/src/data/step-one/locale/es.yml b/client/ticket/src/data/step-one/locale/es.yml new file mode 100644 index 000000000..fadbc2f54 --- /dev/null +++ b/client/ticket/src/data/step-one/locale/es.yml @@ -0,0 +1 @@ +There's no available agency for this landing date: No hay ninguna agencia disponible para la fecha de envío seleccionada \ No newline at end of file diff --git a/client/ticket/src/data/step-one/step-one.html b/client/ticket/src/data/step-one/step-one.html index e5b8b2ce3..8db25398d 100644 --- a/client/ticket/src/data/step-one/step-one.html +++ b/client/ticket/src/data/step-one/step-one.html @@ -1,6 +1,6 @@
- Ticket configuration - Basic data + Basic data + ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i'}"> + label="Landed" + model="$ctrl.ticket.landed"> { + if (res.data); + this.ticket.sale = res.data; + + return true + }, res => { + if (res.data.error.message === 'NO_AGENCY_AVAILABLE') + this.vnApp.showError( + this.$translate.instant(`There's no available agency for this landing date`) + ); + }); + } + + isFormInvalid() { + return !this.ticket.clientFk || !this.ticket.addressFk || !this.ticket.agencyModeFk + || !this.ticket.companyFk || !this.ticket.shipped || !this.ticket.landed; } } -Controller.$inject = ['$scope']; +Controller.$inject = ['$scope', '$http', '$translate', 'vnApp']; ngModule.component('vnTicketDataStepOne', { template: require('./step-one.html'), controller: Controller, bindings: { ticket: '<' + }, + require: { + data: '^vnTicketData' } }); diff --git a/client/ticket/src/data/step-one/step-one.spec.js b/client/ticket/src/data/step-one/step-one.spec.js new file mode 100644 index 000000000..ad4a0a971 --- /dev/null +++ b/client/ticket/src/data/step-one/step-one.spec.js @@ -0,0 +1,63 @@ +import './step-one.js'; + +describe('ticket', () => { + describe('Component vnTicketDataStepOne', () => { + let $componentController; + let $state; + let controller; + let $httpBackend; + + beforeEach(() => { + angular.mock.module('ticket'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { + $componentController = _$componentController_; + $state = _$state_; + $httpBackend = _$httpBackend_; + controller = $componentController('vnTicketDataStepOne', {$state: $state}); + })); + + describe('isFormInvalid()', () => { + it('should check if all form fields are valid', () => { + controller.ticket = { + clientFk: 1, + addressFk: 121, + agencyModeFk: 1, + companyFk: 442, + shipped: Date.now(), + landed: Date.now() + }; + + let result = controller.isFormInvalid(); + expect(result).toBeFalsy(); + }); + }); + + describe('onStepChange()', () => { + it('should call onStepChange method and return a NO_AGENCY_AVAILABLE signal error', async () => { + controller.ticket = { + id: 1, + clientFk: 1, + addressFk: 121, + agencyModeFk: 1, + companyFk: 442, + shipped: Date.now(), + landed: Date.now() + }; + + let data = { + addressFk: 121, + agencyModeFk: 1, + landed: Date.now() + }; + let response = {error: {message: 'NO_AGENCY_AVAILABLE'}}; + + $httpBackend.whenPOST(`/ticket/api/sales/1/priceDifference`, data).respond(400, response); + $httpBackend.expectPOST(`/ticket/api/sales/1/priceDifference`, data); + controller.onStepChange(); + $httpBackend.flush(); + }); + }); + }); +}); \ No newline at end of file diff --git a/client/ticket/src/data/step-three/locale/es.yml b/client/ticket/src/data/step-three/locale/es.yml new file mode 100644 index 000000000..d2c21e5ef --- /dev/null +++ b/client/ticket/src/data/step-three/locale/es.yml @@ -0,0 +1,3 @@ +Charge: Cargo +Choose an option: Selecciona una opción +Charge difference to: Diferencia a cargo de \ No newline at end of file diff --git a/client/ticket/src/data/step-three/step-three.html b/client/ticket/src/data/step-three/step-three.html index 41e185929..e3d762ded 100644 --- a/client/ticket/src/data/step-three/step-three.html +++ b/client/ticket/src/data/step-three/step-three.html @@ -1,14 +1,14 @@ - Ticket configuration - Charge + Charge + field="$ctrl.ticket.option" + initial-data="$ctrl.ticket.option"> diff --git a/client/ticket/src/data/step-three/step-three.js b/client/ticket/src/data/step-three/step-three.js index 2dde82cfe..f09400bf3 100644 --- a/client/ticket/src/data/step-three/step-three.js +++ b/client/ticket/src/data/step-three/step-three.js @@ -1,15 +1,62 @@ import ngModule from '../../module'; class Controller { - constructor($scope) { + + constructor($http, $scope, $state, $translate, vnApp) { + this.$http = $http; this.$scope = $scope; + this.$state = $state; + this.$translate = $translate; + this.vnApp = vnApp; + } + + $onInit() { + this.data.registerChild(this); + } + + $onChanges() { + this.ticket.option = 1; + } + + onStepChange(state) { + return true; + } + + onSubmit() { + if (!this.ticket.option) + return this.vnApp.showError( + this.$translate.instant('Choose an option') + ); + + let query = `/ticket/api/tickets/${this.ticket.id}/componentUpdate`; + let data = { + agencyModeFk: this.ticket.agencyModeFk, + addressFk: this.ticket.addressFk, + warehouseFk: this.ticket.warehouseFk, + shipped: this.ticket.shipped, + landed: this.ticket.landed, + option: this.ticket.option + }; + + this.$http.post(query, data).then(res => { + if (res.data) { + this.$state.go('ticket.card.summary', {id: this.$state.params.id}); + this.card.reload(); + } + }); } } +Controller.$inject = ['$http', '$scope', '$state', '$translate', 'vnApp']; + ngModule.component('vnTicketDataStepThree', { template: require('./step-three.html'), controller: Controller, bindings: { ticket: '<' + }, + require: { + card: '^vnTicketCard', + data: '^vnTicketData' } }); diff --git a/client/ticket/src/data/step-three/step-three.spec.js b/client/ticket/src/data/step-three/step-three.spec.js new file mode 100644 index 000000000..76748de0e --- /dev/null +++ b/client/ticket/src/data/step-three/step-three.spec.js @@ -0,0 +1,51 @@ +/* import './step-three.js'; + +describe('ticket', () => { + describe('Component vnTicketDataStepThree', () => { + let $componentController; + let $state; + let controller; + let $httpBackend; + + beforeEach(() => { + angular.mock.module('ticket'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { + $componentController = _$componentController_; + $state = _$state_; + $httpBackend = _$httpBackend_; + controller = $componentController('vnTicketDataStepThree', {$state: $state}); + })); + + describe('onSubmit()', () => { + it('should call onSubmit()', () => { + controller.ticket = { + id: 1, + agencyModeFk: 1, + addressFk: 121, + warehouseFk: 1, + shipped: Date.now(), + landed: Date.now(), + option: 1 + }; + + let data = { + agencyModeFk: 1, + addressFk: 121, + warehouseFk: 1, + shipped: Date.now(), + landed: Date.now(), + option: 1 + }; + + let response = {data: {error: {message: 'NOTHING_HERE'}}}; + + $httpBackend.whenPOST(`/ticket/api/tickets/1/componentUpdate`, data).respond(400, response); + $httpBackend.expectPOST(`/ticket/api/tickets/1/componentUpdate`, data); + controller.onSubmit(); + $httpBackend.flush(); + }); + }); + }); +}); */ \ No newline at end of file diff --git a/client/ticket/src/data/step-two/locale/es.yml b/client/ticket/src/data/step-two/locale/es.yml new file mode 100644 index 000000000..2cb66b38b --- /dev/null +++ b/client/ticket/src/data/step-two/locale/es.yml @@ -0,0 +1,3 @@ +Price (PPU): Precio (Ud.) +New price (PPU): Nuevo precio (Ud.) +Price difference: Diferencia de precio \ No newline at end of file diff --git a/client/ticket/src/data/step-two/step-two.html b/client/ticket/src/data/step-two/step-two.html index 507d3729f..bbe5a56a9 100644 --- a/client/ticket/src/data/step-two/step-two.html +++ b/client/ticket/src/data/step-two/step-two.html @@ -1,6 +1,6 @@ - Ticket configuration - Price difference + Price difference @@ -8,21 +8,29 @@ - - - + + + - + - - - + + + + + + + + + + +
Item Description QuantityPriceNew pricePrice gapPrice (PPU)New price (PPU)Price difference
{{("000000"+sale.itemFk).slice(-6)}} {{::sale.quantity}}{{::sale.price | currency:'€':2}}--{{::sale.price | currency: '€': 2}}{{::sale.component.newPrice | currency: '€': 2}}{{::sale.component.difference | currency: '€': 2}}
{{$ctrl.ticket.sale.totalUnitPrice | currency: '€': 2}}{{$ctrl.ticket.sale.totalNewPrice | currency: '€': 2}}{{$ctrl.ticket.sale.totalDifference | currency: '€': 2}}
diff --git a/client/ticket/src/data/step-two/step-two.js b/client/ticket/src/data/step-two/step-two.js index d6688ae8c..b0ed76a00 100644 --- a/client/ticket/src/data/step-two/step-two.js +++ b/client/ticket/src/data/step-two/step-two.js @@ -1,28 +1,29 @@ import ngModule from '../../module'; class Controller { - constructor($http, $scope) { + + constructor($http) { this.$http = $http; - this.$scope = $scope; } - $onChanges(data) { - if (!this.ticket || !this.ticket.id) return; + $onInit() { + this.data.registerChild(this); + } - let query = `/ticket/api/sales/${this.ticket.id}/priceDifference`; - this.$http.get(query).then(res => { - if (res.data) - this.ticket.sales = res.data; - }); + onStepChange(state) { + return true; } } -Controller.$inject = ['$http', '$scope']; +Controller.$inject = ['$http']; ngModule.component('vnTicketDataStepTwo', { template: require('./step-two.html'), controller: Controller, bindings: { ticket: '<' + }, + require: { + data: '^vnTicketData' } }); diff --git a/client/ticket/src/locale/es.yml b/client/ticket/src/locale/es.yml index c98a9beb3..0f4df5c74 100644 --- a/client/ticket/src/locale/es.yml +++ b/client/ticket/src/locale/es.yml @@ -51,4 +51,5 @@ Volume: Volumen Warehouse: Almacén Worker: Trabajador Package size: Bultos -VAT: IVA \ No newline at end of file +VAT: IVA +PPU: Ud. \ No newline at end of file diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index dee236660..e36069078 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -234,7 +234,7 @@ export default { itemBarcodes: { barcodeButton: `${components.vnMenuItem}[ui-sref="item.card.itemBarcode"]`, addBarcodeButton: `${components.vnIcon}[icon="add_circle"]`, - thirdCodeInput: `vn-horizontal:nth-child(4) > ${components.vnTextfield}`, + thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(4) > ${components.vnTextfield}`, submitBarcodesButton: `${components.vnSubmit}`, firstCodeRemoveButton: `vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]` }, diff --git a/package-lock.json b/package-lock.json index d61c561fb..94775b281 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5940,9 +5940,9 @@ } }, "flatpickr": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-2.6.3.tgz", - "integrity": "sha1-RXNXUy3rE189pktCW/RDVzeWFWQ=" + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.4.6.tgz", + "integrity": "sha512-5b4aJtMBiyXyg5paf3lZ872t1Qjt7Qv4SNqChKh2AvP+OYaC1jrutty0goW6WvvkASoamzeFEFbPJIBdHqxNRA==" }, "for-in": { "version": "0.1.6", diff --git a/package.json b/package.json index 64f01d4ff..35ade2ee7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "angular-paging": "^2.2.2", "angular-translate": "^2.17.0", "angular-translate-loader-partial": "^2.17.0", - "flatpickr": "^2.6.3", + "flatpickr": "^4.4.6", "fs-extra": "^5.0.0", "material-design-lite": "^1.3.0", "mg-crud": "^1.1.2", diff --git a/services/db/install/changes/1.0.5/01-agencyHourOffer.sql b/services/db/install/changes/1.0.5/01-agencyHourOffer.sql new file mode 100644 index 000000000..df7c17696 --- /dev/null +++ b/services/db/install/changes/1.0.5/01-agencyHourOffer.sql @@ -0,0 +1,73 @@ +USE `vn`; +DROP procedure IF EXISTS `agencyHourOffer`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `agencyHourOffer`(vDate DATE, vAddressFk INT, vAgencyFk INT) +BEGIN +/** + * Devuelve las posibles fechas de envío de un ticket + * + * @param vDate La fecha + * @param vAddressFk Id del consignatario + * @param vAgencyFk Id de la agencia + * @return tmp.agencyHourOffer + */ + DECLARE vDone BOOL; + DECLARE vWarehouseFk SMALLINT; + + DECLARE vCur CURSOR FOR + SELECT w.id warehouseFk + FROM warehouse w + WHERE w.hasAvailable; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + + DROP TEMPORARY TABLE IF EXISTS tmp.agencyHourOffer; + CREATE TEMPORARY TABLE tmp.agencyHourOffer + ( + warehouseFk TINYINT NOT NULL PRIMARY KEY, + shipped DATE NOT NULL, + landed DATE NOT NULL + ) + ENGINE = MEMORY; + + OPEN vCur; + + l: LOOP + SET vDone = FALSE; + FETCH vCur INTO vWarehouseFk; + + IF vDone THEN + LEAVE l; + END IF; + + INSERT INTO tmp.agencyHourOffer (warehouseFk, shipped, landed) + SELECT vWarehouseFk, shipping, vDate FROM ( + SELECT TIMESTAMPADD(DAY, -ah.substractDay, vDate) shipping, ah.maxHour + FROM agencyHour ah + LEFT JOIN address a ON a.id = vAddressFk + WHERE ah.warehouseFk = vWarehouseFk + AND (weekDay = WEEKDAY(vDate) + OR weekDay IS NULL) + AND (ah.agencyFk = vAgencyFk + OR ah.agencyFk IS NULL) + AND (ah.provinceFk = a.provinceFk + OR ah.provinceFk IS NULL + OR vAddressFk IS NULL) + ORDER BY ( + (ah.weekDay IS NOT NULL) + + (ah.agencyFk IS NOT NULL) + + ((ah.provinceFk IS NOT NULL) * 3) + ) DESC + LIMIT 1 + ) t + WHERE t.shipping >= CURDATE() + AND IF(t.shipping = CURDATE(), t.maxHour > HOUR(NOW()), TRUE); + END LOOP; + + CLOSE vCur; +END$$ + +DELIMITER ; + diff --git a/services/db/install/changes/1.0.5/02-buyUltimateFromInterval.sql b/services/db/install/changes/1.0.5/02-buyUltimateFromInterval.sql new file mode 100644 index 000000000..667101d99 --- /dev/null +++ b/services/db/install/changes/1.0.5/02-buyUltimateFromInterval.sql @@ -0,0 +1,43 @@ +USE `vn`; +DROP procedure IF EXISTS `buyUltimateFromInterval`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `buyUltimateFromInterval`(vWarehouseFk SMALLINT, vStarted DATE, vEnded DATE) +BEGIN +/** + * Calcula las últimas compras realizadas + * desde un rango de fechas. + * + * @param vWarehouseFk Id del almacén + * @param vStarted Fecha inicial + * @param vEnded Fecha fin + * @return tmp.buyUltimateFromInterval + */ + IF vEnded IS NULL THEN + SET vEnded = vStarted; + END IF; + + IF vEnded < vStarted THEN + SET vStarted = TIMESTAMPADD(MONTH, -1, vEnded); + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp.buyUltimateFromInterval; + CREATE TEMPORARY TABLE tmp.buyUltimateFromInterval + ENGINE = MEMORY + SELECT + b.itemFk, + t.warehouseInFk warehouseFk, + MULTIMAX(t.landed, b.id) buyFk, + MAX(t.landed) landed + FROM buy b + JOIN entry e ON e.id = b.entryFk + JOIN travel t ON t.id = e.travelFk + WHERE t.landed BETWEEN vStarted AND vEnded + AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk) + AND b.price2 > 0 + AND NOT b.isIgnored + GROUP BY itemFk, warehouseInFk; +END$$ + +DELIMITER ; diff --git a/services/db/install/changes/1.0.5/03-buyUltimate.sql b/services/db/install/changes/1.0.5/03-buyUltimate.sql new file mode 100644 index 000000000..a25badf65 --- /dev/null +++ b/services/db/install/changes/1.0.5/03-buyUltimate.sql @@ -0,0 +1,35 @@ +USE `vn`; +DROP procedure IF EXISTS `buyUltimate`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `buyUltimate`(vWarehouseFk SMALLINT, vDate DATE) +BEGIN +/** + * Calcula las últimas compras realizadas hasta una fecha + * + * @param vWarehouseFk Id del almacén + * @param vDate Compras hasta fecha + * @return tmp.buyUltimate + */ + CALL cache.last_buy_refresh (FALSE); + + DROP TEMPORARY TABLE IF EXISTS tmp.buyUltimate; + CREATE TEMPORARY TABLE tmp.buyUltimate + (PRIMARY KEY (itemFk, warehouseFk)) + ENGINE = MEMORY + SELECT item_id itemFk, buy_id buyFk, warehouse_id warehouseFk + FROM cache.last_buy + WHERE warehouse_id = vWarehouseFk OR vWarehouseFk IS NULL; + + CALL vn.buyUltimateFromInterval(vWarehouseFk, CURDATE(), vDate); + + REPLACE INTO tmp.buyUltimate + SELECT itemFk, buyFk, warehouseFk + FROM tmp.buyUltimateFromInterval + WHERE warehouseFk = vWarehouseFk OR vWarehouseFk IS NULL; + + DROP TEMPORARY TABLE tmp.buyUltimateFromInterval; +END$$ + +DELIMITER ; \ No newline at end of file diff --git a/services/db/install/changes/1.0.5/04-ticketComponentCalculate.sql b/services/db/install/changes/1.0.5/04-ticketComponentCalculate.sql new file mode 100644 index 000000000..d9e047e80 --- /dev/null +++ b/services/db/install/changes/1.0.5/04-ticketComponentCalculate.sql @@ -0,0 +1,294 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketComponentCalculate`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentCalculate`( + vAddressFk INT, + vAgencyModeFk INT) +proc: BEGIN +/** + * Calcula los componentes de un ticket + * + * @param vAddressFk Id del consignatario + * @param vAgencyModeFk Id del modo de agencia + * @return tmp.ticketComponent, tmp.ticketComponentPrice + */ + DECLARE vClientFk INT; + DECLARE vGeneralInflationCoefficient INT DEFAULT 1.3; + DECLARE vMinimumDensityWeight INT DEFAULT 167; + DECLARE vBoxFreightItem INT DEFAULT 71; + DECLARE vBoxVolume BIGINT DEFAULT 138000; + DECLARE vSpecialPriceComponent INT DEFAULT 10; + DECLARE vExtraFreightComponent INT DEFAULT 14; + DECLARE vDeliveryComponent INT DEFAULT 15; + DECLARE vRecoveryComponent INT DEFAULT 17; + DECLARE vSellByPacketComponent INT DEFAULT 22; + DECLARE vBuyValueComponent INT DEFAULT 28; + DECLARE vMarginComponent INT DEFAULT 29; + DECLARE vDiscountLastItemComponent INT DEFAULT 32; + DECLARE vExtraBaggedComponent INT DEFAULT 38; + DECLARE vManaAutoComponent INT DEFAULT 39; + DECLARE vFreightBonusComponent INT DEFAULT 41; + + SELECT clientFk INTO vClientFK + FROM address + WHERE id = vAddressFk; + + SET @rate2 := 0; + SET @rate3 := 0; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentCalculate; + CREATE TEMPORARY TABLE tmp.ticketComponentCalculate + (PRIMARY KEY (itemFk, warehouseFk)) + ENGINE = MEMORY + SELECT + tl.itemFk, tl.warehouseFk, tl.available, + IF((@rate2 := IFNULL(pf.rate2, b.price2)) < i.minPrice AND i.hasMinPrice, i.minPrice, @rate2) * 1.0 rate2, + IF((@rate3 := IFNULL(pf.rate3, b.price3)) < i.minPrice AND i.hasMinPrice, i.minPrice, @rate3) * 1.0 rate3, + IFNULL(pf.rate3, 0) AS minPrice, + IFNULL(pf.packing, b.packing) packing, + IFNULL(pf.grouping, b.grouping) grouping, + ABS(IFNULL(pf.box, b.groupingMode)) groupingMode, + tl.buyFk, i.typeFk + FROM tmp.ticketLot tl + JOIN buy b ON b.id = tl.buyFk + JOIN item i ON i.id = tl.itemFk + JOIN itemType it ON it.id = i.typeFk + LEFT JOIN itemCategory ic ON ic.id = it.categoryFk + LEFT JOIN specialPrice sp ON sp.itemFk = i.id AND sp.clientFk = vClientFk + LEFT JOIN ( + SELECT * FROM ( + SELECT pf.itemFk, pf.grouping, pf.packing, pf.box, pf.rate2, pf.rate3, aho.warehouseFk + FROM priceFixed pf + JOIN tmp.agencyHourOffer aho ON pf.warehouseFk = aho.warehouseFk OR pf.warehouseFk = 0 + WHERE aho.shipped BETWEEN pf.started AND pf.ended ORDER BY pf.itemFk, pf.warehouseFk DESC + ) tpf + GROUP BY tpf.itemFk, tpf.warehouseFk + ) pf ON pf.itemFk = tl.itemFk AND pf.warehouseFk = tl.warehouseFk + WHERE b.buyingValue + b.freightValue + b.packageValue + b.comissionValue > 0.01 AND ic.display <> 0; + + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent; + CREATE TEMPORARY TABLE tmp.ticketComponent ( + `warehouseFk` INT UNSIGNED NOT NULL, + `itemFk` INT NOT NULL, + `componentFk` INT UNSIGNED NOT NULL, + `cost` DECIMAL(10,4) NOT NULL, + INDEX `itemWarehouse` USING BTREE (`itemFk` ASC, `warehouseFk` ASC), + UNIQUE INDEX `itemWarehouseComponent` (`itemFk` ASC, `warehouseFk` ASC, `componentFk` ASC)); + + + + INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost) + SELECT + tcc.warehouseFk, + tcc.itemFk, + vBuyValueComponent, + tcc.rate3 - b.buyingValue - b.freightValue - b.packageValue - b.comissionValue + FROM tmp.ticketComponentCalculate tcc + JOIN buy b ON b.id = tcc.buyFk; + + INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost) + SELECT + tcc.warehouseFk, + tcc.itemFk, + vMarginComponent, + tcc.rate3 - b.buyingValue - b.freightValue - b.packageValue - b.comissionValue + FROM tmp.ticketComponentCalculate tcc + JOIN buy b ON b.id = tcc.buyFk; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentBase; + CREATE TEMPORARY TABLE tmp.ticketComponentBase ENGINE = MEMORY + SELECT tc.itemFk, ROUND(SUM(tc.cost), 4) AS base, tc.warehouseFk + FROM tmp.ticketComponent tc + GROUP BY tc.itemFk, warehouseFk; + + INSERT INTO tmp.ticketComponent + SELECT tcb.warehouseFk, tcb.itemFk, vRecoveryComponent, ROUND(tcb.base * LEAST(cr.recobro, 0.25), 3) + FROM tmp.ticketComponentBase tcb + JOIN bi.claims_ratio cr ON cr.Id_Cliente = vClientFk + WHERE cr.recobro > 0.009; + + INSERT INTO tmp.ticketComponent + SELECT tcb.warehouseFk, tcb.itemFk, vManaAutoComponent, ROUND(base * (0.01 + prices_modifier_rate), 3) as manaAuto + FROM tmp.ticketComponentBase tcb + JOIN `client` c on c.id = vClientFk + JOIN bs.mana_spellers ms ON c.salesPersonFk = ms.Id_Trabajador + WHERE ms.prices_modifier_activated + HAVING manaAuto <> 0; + + INSERT INTO tmp.ticketComponent + SELECT + tcb.warehouseFk, + tcb.itemFk, + cr.id, + GREATEST(IFNULL(ROUND(tcb.base * cr.tax, 4), 0), tcc.minPrice - tcc.rate3) + FROM tmp.ticketComponentBase tcb + JOIN componentRate cr + JOIN tmp.ticketComponentCalculate tcc ON tcc.itemFk = tcb.itemFk AND tcc.warehouseFk = tcb.warehouseFk + LEFT JOIN specialPrice sp ON sp.clientFk = vClientFk AND sp.itemFk = tcc.itemFk + WHERE cr.id = vDiscountLastItemComponent AND cr.tax <> 0 AND tcc.minPrice < tcc.rate3 AND sp.value IS NULL; + + INSERT INTO tmp.ticketComponent + SELECT tcc.warehouseFk, tcc.itemFk, vSellByPacketComponent, tcc.rate2 - tcc.rate3 + FROM tmp.ticketComponentCalculate tcc + JOIN buy b ON b.id = tcc.buyFk + LEFT JOIN specialPrice sp ON sp.clientFk = vClientFk AND sp.itemFk = tcc.itemFk + WHERE sp.value IS NULL; + + INSERT INTO tmp.ticketComponent + SELECT + tcc.warehouseFK, + tcc.itemFk, + vDeliveryComponent, + vGeneralInflationCoefficient + * ROUND( + r.cm3 + * IF(am.deliveryMethodFk = 1, (GREATEST(i.density, vMinimumDensityWeight) / vMinimumDensityWeight), 1) + * IFNULL(amz.price + * amz.inflation, 50) / vBoxVolume, 4 + ) cost + FROM tmp.ticketComponentCalculate tcc + JOIN item i ON i.id = tcc.itemFk + JOIN agencyMode am ON am.id = vAgencyModeFk + JOIN `address` a ON a.id = vAddressFk + JOIN agencyProvince ap ON ap.agencyFk = a.id + AND ap.warehouseFk = tcc.warehouseFk AND ap.provinceFk = a.provinceFk + JOIN agencyModeZone amz ON amz.agencyModeFk = vAgencyModeFk + AND amz.zone = ap.zone AND amz.itemFk = 71 AND amz.warehouseFk = tcc.warehouseFk + LEFT JOIN bi.rotacion r ON r.warehouse_id = tcc.warehouseFk + AND r.Id_Article = tcc.itemFk + HAVING cost <> 0; + + INSERT INTO tmp.ticketComponent + SELECT + tcc.warehouseFk, + tcc.itemFk, + vFreightBonusComponent, + vGeneralInflationCoefficient + * ROUND( + r.cm3 + * IF(am.deliveryMethodFk = 1, (GREATEST(i.density, vMinimumDensityWeight) / vMinimumDensityWeight), 1) + * awb.bonus + * amz.inflation / vBoxVolume, 4 + ) cost + FROM tmp.ticketComponentCalculate tcc + JOIN item i ON i.id = tcc.itemFk + JOIN agencyMode am ON am.id = vAgencyModeFk + JOIN `address` a ON a.id = vAddressFk + JOIN agencyProvince ap ON ap.agencyFk = a.id + AND ap.warehouseFk = tcc.warehouseFk AND ap.provinceFk = a.provinceFk + JOIN agencyModeZone amz ON amz.agencyModeFk = vAgencyModeFk + AND amz.zone = ap.zone AND amz.itemFk = vBoxFreightItem AND amz.warehouseFk = tcc.warehouseFk + JOIN agencyWeekDayBonus awb ON awb.warehouseFk = amz.warehouseFk AND awb.zone = amz.zone AND am.id = awb.agencyFk + LEFT JOIN bi.rotacion r ON r.warehouse_id = tcc.warehouseFk + AND r.Id_Article = tcc.itemFk + JOIN tmp.agencyHourOffer aho ON aho.warehouseFk = awb.warehouseFk + AND WEEKDAY(aho.landed) = awb.weekDay + HAVING cost <> 0 + LIMIT 1; + + IF (SELECT COUNT(*) FROM vn.addressForPackaging WHERE addressFk = vAddressFk) THEN + INSERT INTO tmp.ticketComponent + SELECT tcc.warehouseFk, b.itemFk, vExtraBaggedComponent, ap.packagingValue cost + FROM tmp.ticketComponentCalculate tcc + JOIN vn.addressForPackaging ap + WHERE ap.addressFk = vAddressFk; + END IF; + + INSERT INTO tmp.ticketComponent + SELECT tcb.warehouseFk, tcb.itemFk, vExtraFreightComponent, tcb.base * (IFNULL(pe.percentage,pp.percentage)/100) + FROM tmp.ticketComponentBase tcb + JOIN tmp.agencyHourOffer aho ON aho.warehouseFk = tcb.warehouseFk + LEFT JOIN preparationPercentage pp ON pp.weekDay = WEEKDAY(aho.shipped) + AND tcb.warehouseFk = IFNULL(pp.warehouseFk, tcb.warehouseFk) + LEFT JOIN preparationException pe ON pe.exceptionDay = aho.shipped + AND tcb.warehouseFk = IFNULL(pe.warehouseFk, tcb.warehouseFk) + WHERE IFNULL(pe.percentage, pp.percentage); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentCopy; + CREATE TEMPORARY TABLE tmp.ticketComponentCopy ENGINE = MEMORY + SELECT * FROM tmp.ticketComponent; + + INSERT INTO tmp.ticketComponent + SELECT + tcc.warehouseFk, + tcc.itemFk, + vSpecialPriceComponent, + sp.value - SUM(tcc.cost) sumCost + FROM tmp.ticketComponentCopy tcc + JOIN componentRate cr ON cr.id = tcc.componentFk + JOIN specialPrice sp ON sp.clientFk = vClientFK AND sp.itemFk = tcc.itemFk + WHERE cr.classRate IS NULL + GROUP BY tcc.itemFk, tcc.warehouseFk + HAVING ABS(sumCost) > 0.001; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentSum; + CREATE TEMPORARY TABLE tmp.ticketComponentSum + (INDEX (itemFk, warehouseFk)) + ENGINE = MEMORY + SELECT SUM(cost) sumCost, tc.itemFk, tc.warehouseFk, cr.classRate + FROM tmp.ticketComponent tc + JOIN componentRate cr ON cr.id = tc.componentFk + GROUP BY tc.itemFk, tc.warehouseFk, cr.classRate; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentRate; + CREATE TEMPORARY TABLE tmp.ticketComponentRate ENGINE = MEMORY + SELECT + tcc.warehouseFk, + tcc.itemFk, + 1 rate, + IF(tcc.groupingMode = 1, tcc.grouping, 1) grouping, + SUM(tcs.sumCost) price + FROM tmp.ticketComponentCalculate tcc + JOIN tmp.ticketComponentSum tcs ON tcs.itemFk = tcc.itemFk + AND tcs.warehouseFk = tcc.warehouseFk + WHERE IFNULL(tcs.classRate, 1) = 1 + AND tcc.groupingMode < 2 AND (tcc.packing > tcc.grouping or tcc.groupingMode = 0) + GROUP BY tcs.warehouseFk, tcs.itemFk; + + INSERT INTO tmp.ticketComponentRate (warehouseFk, itemFk, rate, grouping, price) + SELECT + tcc.warehouseFk, + tcc.itemFk, + 2 rate, + tcc.packing grouping, + SUM(tcs.sumCost) price + FROM tmp.ticketComponentCalculate tcc + JOIN tmp.ticketComponentSum tcs ON tcs.itemFk = tcc.itemFk + AND tcs.warehouseFk = tcc.warehouseFk + WHERE tcc.available IS NULL OR (IFNULL(tcs.classRate, 2) = 2 + AND tcc.packing > 0 AND tcc.available >= tcc.packing) + GROUP BY tcs.warehouseFk, tcs.itemFk; + + INSERT INTO tmp.ticketComponentRate (warehouseFk, itemFk, rate, grouping, price) + SELECT + tcc.warehouseFk, + tcc.itemFk, + 3 rate, + tcc.available grouping, + SUM(tcs.sumCost) price + FROM tmp.ticketComponentCalculate tcc + JOIN tmp.ticketComponentSum tcs ON tcs.itemFk = tcc.itemFk + AND tcs.warehouseFk = tcc.warehouseFk + WHERE IFNULL(tcs.classRate, 3) = 3 + GROUP BY tcs.warehouseFk, tcs.itemFk; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentPrice; + CREATE TEMPORARY TABLE tmp.ticketComponentPrice ENGINE = MEMORY + SELECT * FROM ( + SELECT * FROM tmp.ticketComponentRate ORDER BY price + ) t + GROUP BY itemFk, warehouseFk, grouping; + + DROP TEMPORARY TABLE + tmp.ticketComponentCalculate, + tmp.ticketComponentSum, + tmp.ticketComponentBase, + tmp.ticketComponentRate, + tmp.ticketComponentCopy; +END$$ + +DELIMITER ; + diff --git a/services/db/install/changes/1.0.5/05-ticketComponentPreview.sql b/services/db/install/changes/1.0.5/05-ticketComponentPreview.sql new file mode 100644 index 000000000..c33fdf7c0 --- /dev/null +++ b/services/db/install/changes/1.0.5/05-ticketComponentPreview.sql @@ -0,0 +1,77 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketComponentPreview`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentPreview`( + vDate DATE, + vAddressFk INT, + vAgencyModeFk INT, + vTicketFk INT) +BEGIN +/** + * Devuelve un listado previo de + * componentes para un ticket + * + * @param vDate Fecha de envío + * @param vAddressFk Id del consignatario + * @param vAgencyModeFk Id del modo de agencia + * @param vTicketFk Id del ticket + */ + DECLARE vWarehouseFk SMALLINT; + DECLARE vAgencyFk INT; + DECLARE vShipped DATE; + DECLARE vBuyOrderItem INT DEFAULT 100; + + SELECT warehouseFk INTO vWarehouseFK + FROM ticket + WHERE id = vTicketFk; + + SELECT agencyFk INTO vAgencyFk + FROM agencyMode + WHERE id = vAgencyModeFk; + + CALL agencyHourOffer(vDate, vAddressFk, vAgencyFk); + + SELECT shipped INTO vShipped + FROM tmp.agencyHourOffer + WHERE warehouseFk = vWarehouseFK; + + CALL buyUltimate(vWarehouseFK, vShipped); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot; + CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY ( + SELECT + vWarehouseFK AS warehouseFk, + NULL AS available, + s.itemFk, + bu.buyFk + FROM sale s + LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk + WHERE s.ticketFk = vTicketFk + AND s.itemFk != vBuyOrderItem + GROUP BY bu.warehouseFk, bu.itemFk); + + CALL ticketComponentCalculate(vAddressFk, vAgencyModeFk); + + REPLACE INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost) + SELECT t.warehouseFk, s.itemFk, sc.componentFk, sc.value + FROM saleComponent sc + JOIN sale s ON s.id = sc.saleFk + JOIN ticket t ON t.id = s.ticketFk + JOIN componentRate cr ON cr.id = sc.componentFk + WHERE s.ticketFk = vTicketFk AND NOT cr.isRenewable; + + SET @shipped = vShipped; + + DROP TEMPORARY TABLE + tmp.agencyHourOffer, + tmp.buyUltimate, + tmp.ticketLot; + + IF IFNULL(vShipped, CURDATE() - 1) < CURDATE() THEN + CALL util.throw('NO_AGENCY_AVAILABLE'); + END IF; +END$$ + +DELIMITER ; \ No newline at end of file diff --git a/services/db/install/changes/1.0.5/06-ticketComponentPriceDifference.sql b/services/db/install/changes/1.0.5/06-ticketComponentPriceDifference.sql new file mode 100644 index 000000000..947a7c3a0 --- /dev/null +++ b/services/db/install/changes/1.0.5/06-ticketComponentPriceDifference.sql @@ -0,0 +1,50 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketComponentPriceDifference`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentPriceDifference`( + vDate DATE, + vAddressFk INT, + vAgencyModeFk INT, + vTicketFk INT) +BEGIN +/** + * Devuelve las diferencias de precio + * de los movimientos de un ticket. + * + * @param vTicketFk Id del ticket + */ + CALL vn.ticketComponentPreview(vDate, vAddressFk, vAgencyModeFk, vTicketFk); + + SELECT + s.itemFk, + i.name, + i.size, + i.category, + IFNULL(s.quantity, 0) AS quantity, + IFNULL(s.price, 0) AS price, + ROUND(SUM(tc.cost), 4) AS newPrice, + s.quantity * (s.price - ROUND(SUM(cost), 4)) difference, + s.id AS saleFk + FROM sale s + JOIN item i ON i.id = s.itemFk + JOIN ticket t ON t.id = s.ticketFk + LEFT JOIN tmp.ticketComponent tc ON tc.itemFk = s.itemFk + AND tc.warehouseFk = t.warehouseFk + LEFT JOIN saleComponent sc ON sc.saleFk = s.id + AND sc.componentFk = tc.componentFk + LEFT JOIN componentRate cr ON cr.id = tc.componentFk + WHERE + t.id = vTicketFk + AND IF(sc.componentFk IS NULL + AND cr.classRate IS NOT NULL, FALSE, TRUE) + GROUP BY s.id ORDER BY s.id; + + DROP TEMPORARY TABLE + tmp.ticketComponent, + tmp.ticketComponentPrice; +END$$ + +DELIMITER ; + diff --git a/services/db/install/changes/1.0.5/07-ticketComponentUpdate.sql b/services/db/install/changes/1.0.5/07-ticketComponentUpdate.sql new file mode 100644 index 000000000..d92a17a1d --- /dev/null +++ b/services/db/install/changes/1.0.5/07-ticketComponentUpdate.sql @@ -0,0 +1,50 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketComponentUpdate`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentUpdate`( + vTicketFk INT, + vAgencyModeFk INT, + vAddressFk INT, + vWarehouseFk INT, + vShipped DATETIME, + vLanded DATE, + vOption INT) +BEGIN + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + START TRANSACTION; + + UPDATE ticket t + SET + t.agencyModeFk = vAgencyModeFk, + t.addressFk = vAddressFk, + t.warehouseFk = vWarehouseFk, + t.landed = vLanded, + t.shipped = vShipped + WHERE + t.id = vTicketFk; + + IF vOption <> 8 THEN + DROP TEMPORARY TABLE IF EXISTS tmp.sale; + CREATE TEMPORARY TABLE tmp.sale + (PRIMARY KEY (saleFk)) + ENGINE = MEMORY + SELECT id AS saleFk, vWarehouseFk warehouseFk + FROM sale s WHERE s.ticketFk = vTicketFk; + + CALL ticketComponentUpdateSale (vOption); + + DROP TEMPORARY TABLE tmp.sale; + END IF; + + COMMIT; +END$$ + +DELIMITER ; + diff --git a/services/db/install/changes/1.0.5/08-ticketComponentUpdateSale.sql b/services/db/install/changes/1.0.5/08-ticketComponentUpdateSale.sql new file mode 100644 index 000000000..23aafe499 --- /dev/null +++ b/services/db/install/changes/1.0.5/08-ticketComponentUpdateSale.sql @@ -0,0 +1,153 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketComponentUpdateSale`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentUpdateSale`(vOption INT) +BEGIN +/** + * A partir de la tabla tmp.movement, crea los Movimientos_componentes + * y modifica el campo Preu de la tabla Movimientos + * + * @param i_option integer tipo de actualizacion + * @param table tmp.movement tabla memory con el campo Id_Movimiento, warehouse_id + **/ + DECLARE vComponentFk INT; + DECLARE vRenewComponents BOOLEAN; + DECLARE vKeepPrices BOOLEAN; + + CASE vOption + WHEN 1 THEN + SET vRenewComponents = TRUE; + SET vKeepPrices = FALSE; + WHEN 2 THEN + SET vComponentFk = 17; + SET vRenewComponents = TRUE; + SET vKeepPrices = TRUE; + WHEN 3 THEN + SET vComponentFk = 37; + SET vRenewComponents = TRUE; + SET vKeepPrices = TRUE; + WHEN 4 THEN + SET vComponentFk = 34; + SET vRenewComponents = TRUE; + SET vKeepPrices = TRUE; + WHEN 5 THEN + SET vComponentFk = 35; + SET vRenewComponents = TRUE; + SET vKeepPrices = TRUE; + WHEN 6 THEN + SET vComponentFk = 36; + SET vRenewComponents = TRUE; + SET vKeepPrices = TRUE; + WHEN 7 THEN + REPLACE INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, 28, ROUND(((s.price * (100 - s.discount) / 100) - SUM(IFNULL(sc.value, 0))) * 0.8, 3) + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id + LEFT JOIN saleComponent sc ON sc.saleFk = s.id + AND sc.componentFk NOT IN (28, 29) + GROUP BY s.id; + + REPLACE INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, 29, ROUND(((s.price * (100 - s.discount) / 100) - SUM(IFNULL(sc.value, 0))) * 0.2, 3) + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id + LEFT JOIN saleComponent sc ON sc.saleFk = s.id + AND sc.componentFk NOT IN (28, 29) + GROUP BY s.id; + + SET vRenewComponents = FALSE; + SET vKeepPrices = FALSE; + WHEN 8 THEN + DELETE sc.* + FROM tmp.sale tmps JOIN saleComponent sc ON sc.saleFk = tmps.saleFk; + + REPLACE INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, 28, ROUND(((s.price * (100 - s.discount) / 100)), 3) + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id; + + SET vRenewComponents = FALSE; + SET vKeepPrices = FALSE; + WHEN 9 THEN + SET vRenewComponents = TRUE; + SET vKeepPrices = TRUE; + END CASE; + + IF vRenewComponents THEN + DELETE sc.* + FROM tmp.sale tmps + JOIN saleComponent sc ON sc.saleFk = tmps.saleFk + JOIN componentRate cr ON cr.id = sc.componentFk + WHERE cr.isRenewable; + + REPLACE INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, tc.componentFk, tc.cost + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id + JOIN tmp.ticketComponent tc ON tc.itemFk = s.itemFk AND tc.warehouseFk = tmps.warehouseFk + LEFT JOIN saleComponent sc ON sc.saleFk = s.id + AND sc.componentFk = tc.componentFk + LEFT JOIN componentRate cr ON cr.id = tc.componentFk + WHERE IF(sc.componentFk IS NULL AND NOT cr.isRenewable, FALSE, TRUE); + END IF; + + IF vKeepPrices THEN + REPLACE INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, vComponentFk, ROUND((s.price * (100 - s.discount) / 100) - SUM(sc.value), 3) dif + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id + LEFT JOIN saleComponent sc ON sc.saleFk = s.id + WHERE sc.saleFk <> vComponentFk + GROUP BY s.id + HAVING dif <> 0; + ELSE + UPDATE sale s + JOIN item i on i.id = s.id + JOIN itemType it on it.id = i.typeFk + JOIN (SELECT SUM(sc.value) sumValue, sc.saleFk + FROM saleComponent sc + JOIN tmp.sale tmps ON tmps.saleFk = sc.saleFk + GROUP BY sc.saleFk) sc ON sc.saleFk = s.id + SET s.price = sumValue + WHERE it.code != 'PRT'; + + REPLACE INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, 21, s.price * (100 - s.discount) / 100 - sum(sc.value) saleValue + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id + LEFT JOIN saleComponent sc ON sc.saleFk = s.id + WHERE sc.saleFk != 21 + GROUP BY s.id + HAVING ROUND(saleValue, 4) <> 0; + END IF; + + UPDATE sale s + JOIN ( + SELECT SUM(sc.value) sumValue, sc.saleFk + FROM saleComponent sc + JOIN tmp.sale tmps ON tmps.saleFk = sc.saleFk + JOIN componentRate cr ON cr.id = sc.componentFk + JOIN componentTypeRate ctr on ctr.id = cr.componentTypeRate AND ctr.base + GROUP BY sc.saleFk) sc ON sc.saleFk = s.id + SET s.priceFixed = sumValue, s.isPriceFixed = 1; + + DELETE sc.* + FROM saleComponent sc + JOIN tmp.sale tmps ON tmps.saleFk = sc.saleFk + JOIN sale s on s.id = sc.saleFk + JOIN item i ON i.id = s.itemFk + JOIN itemType it ON it.id = i.typeFk + WHERE it.code = 'PRT'; + + INSERT INTO saleComponent(saleFk, componentFk, value) + SELECT s.id, 15, s.price + FROM sale s + JOIN tmp.sale tmps ON tmps.saleFk = s.id + JOIN item i ON i.id = s.itemFK + JOIN itemType it ON it.id = i.typeFk + WHERE it.code = 'PRT' AND s.price > 0; +END$$ + +DELIMITER ; diff --git a/services/db/install/changes/1.0.5/09-ticketComponentMakeUpdate.sql b/services/db/install/changes/1.0.5/09-ticketComponentMakeUpdate.sql new file mode 100644 index 000000000..b33588bea --- /dev/null +++ b/services/db/install/changes/1.0.5/09-ticketComponentMakeUpdate.sql @@ -0,0 +1,31 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketComponentMakeUpdate`; + +DELIMITER $$ +USE `vn`$$ +CREATE PROCEDURE `ticketComponentMakeUpdate` ( + vTicketFk INT, + vAgencyModeFk INT, + vAddressFk INT, + vWarehouseFk INT, + vShipped DATETIME, + vLanded DATE, + vOption INT) +BEGIN +/** + * Devuelve las diferencias de precio + * de los movimientos de un ticket. + * + * @param vTicketFk Id del ticket + */ + + CALL vn.ticketComponentPreview (vLanded, vAddressFk, vAgencyModeFk, vTicketFk); + CALL vn.ticketComponentUpdate (vTicketFk, vAgencyModeFk, vAddressFk, vWarehouseFk, vShipped, vLanded, vOption); + + DROP TEMPORARY TABLE + tmp.ticketComponent, + tmp.ticketComponentPrice; +END$$ + +DELIMITER ; + diff --git a/services/db/install/changes/1.0.5/10-Tickets.sql b/services/db/install/changes/1.0.5/10-Tickets.sql new file mode 100644 index 000000000..4ae295f66 --- /dev/null +++ b/services/db/install/changes/1.0.5/10-Tickets.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn2008`.`Tickets` +ADD COLUMN `isDeleted` TINYINT(2) NOT NULL DEFAULT '0' AFTER `boxed`; diff --git a/services/db/install/changes/1.0.5/11-ticket.sql b/services/db/install/changes/1.0.5/11-ticket.sql new file mode 100644 index 000000000..5f8b048b4 --- /dev/null +++ b/services/db/install/changes/1.0.5/11-ticket.sql @@ -0,0 +1,26 @@ +USE `vn`; +CREATE + OR REPLACE ALGORITHM = UNDEFINED + DEFINER = `root`@`%` + SQL SECURITY DEFINER +VIEW `ticket` AS + SELECT + `t`.`Id_Ticket` AS `id`, + `t`.`Id_Cliente` AS `clientFk`, + `t`.`warehouse_id` AS `warehouseFk`, + `t`.`Fecha` AS `shipped`, + `t`.`landing` AS `landed`, + `t`.`Alias` AS `nickname`, + `t`.`Factura` AS `refFk`, + `t`.`Id_Consigna` AS `addressFk`, + `t`.`Localizacion` AS `location`, + `t`.`Solucion` AS `solution`, + `t`.`Id_Ruta` AS `routeFk`, + `t`.`empresa_id` AS `companyFk`, + `t`.`Id_Agencia` AS `agencyModeFk`, + `t`.`Prioridad` AS `priority`, + `t`.`Bultos` AS `packages`, + `t`.`isDeleted`, + `t`.`odbc_date` AS `created` + FROM + `vn2008`.`Tickets` `t`; diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json index 50f3de9d1..caf866ca5 100644 --- a/services/loopback/common/locale/es.json +++ b/services/loopback/common/locale/es.json @@ -17,5 +17,7 @@ "The IBAN does not have the correct format": "El IBAN no tiene el formato correcto", "That payment method requires an IBAN": "El método de pago seleccionado requiere que se especifique el IBAN", "State cannot be blank": "El estado no puede estar en blanco", - "Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado" + "Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado", + "EXPIRED_DATE": "EXPIRED_DATE", + "NO_AGENCY_AVAILABLE": "NO_AGENCY_AVAILABLE" } \ No newline at end of file diff --git a/services/loopback/common/methods/item/clone.js b/services/loopback/common/methods/item/clone.js index b0021bb0b..4846a4825 100644 --- a/services/loopback/common/methods/item/clone.js +++ b/services/loopback/common/methods/item/clone.js @@ -37,6 +37,7 @@ module.exports = Self => { delete copy.id; delete copy.itemTag; + delete copy.description; let newItem = await Self.create(copy); let promises = []; diff --git a/services/loopback/common/methods/sale/priceDifference.js b/services/loopback/common/methods/sale/priceDifference.js index c40b11f1c..707bef883 100644 --- a/services/loopback/common/methods/sale/priceDifference.js +++ b/services/loopback/common/methods/sale/priceDifference.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethod('priceDifference', { - description: 'Returns a sale price difference', + description: 'Returns sales with price difference', accessType: 'READ', accepts: [{ arg: 'ticketFk', @@ -8,6 +8,12 @@ module.exports = Self => { required: true, description: 'ticket id', http: {source: 'path'} + }, { + arg: 'data', + type: 'Object', + required: true, + description: 'landed, addressFk, agencyModeFk', + http: {source: 'body'} }], returns: { type: ['Object'], @@ -15,11 +21,11 @@ module.exports = Self => { }, http: { path: `/:ticketFk/priceDifference`, - verb: 'GET' + verb: 'post' } }); - Self.priceDifference = async ticketFk => { + Self.priceDifference = async (ticketFk, data) => { let filter = { where: { ticketFk: ticketFk @@ -45,7 +51,26 @@ module.exports = Self => { } }] }; + let salesObj = {}; + salesObj.items = await Self.find(filter); + salesObj.totalUnitPrice = 0.00; + salesObj.totalNewPrice = 0.00; + salesObj.totalDifference = 0.00; - return await Self.find(filter); + let query = `CALL vn.ticketComponentPriceDifference(?, ?, ?, ?)`; + let [differences] = await Self.rawSql(query, [data.landed, data.addressFk, data.agencyModeFk, ticketFk]); + + salesObj.items.forEach(sale => { + differences.forEach(difference => { + if (sale.id == difference.saleFk) + sale.component = difference; + }); + + salesObj.totalUnitPrice += sale.price; + salesObj.totalNewPrice += sale.component.newPrice; + salesObj.totalDifference += sale.component.difference; + }); + + return salesObj; }; }; diff --git a/services/loopback/common/methods/sale/specs/priceDifference.spec.js b/services/loopback/common/methods/sale/specs/priceDifference.spec.js new file mode 100644 index 000000000..387a8da56 --- /dev/null +++ b/services/loopback/common/methods/sale/specs/priceDifference.spec.js @@ -0,0 +1,16 @@ +const app = require(`${servicesDir}/ticket/server/server`); + +describe('sale priceDifference()', () => { + it('should call the priceDifference method and return a NO_AGENCY_AVAILABLE signal error', done => { + let data = { + landed: Date.now(), + addressFk: 121, + agencyModeFk: 1 + }; + app.models.Sale.priceDifference(1, data) + .catch(response => { + expect(response).toEqual(new Error('ER_SIGNAL_EXCEPTION: NO_AGENCY_AVAILABLE')); + done(); + }); + }); +}); diff --git a/services/loopback/common/methods/ticket/componentUpdate.js b/services/loopback/common/methods/ticket/componentUpdate.js new file mode 100644 index 000000000..faa89dda7 --- /dev/null +++ b/services/loopback/common/methods/ticket/componentUpdate.js @@ -0,0 +1,41 @@ +module.exports = Self => { + Self.remoteMethod('componentUpdate', { + description: 'Save ticket sale components', + accessType: 'WRITE', + accepts: [{ + arg: 'ticketFk', + type: 'number', + required: true, + description: 'ticket id', + http: {source: 'path'} + }, { + arg: 'data', + type: 'Object', + required: true, + description: 'landed, addressFk, agencyModeFk', + http: {source: 'body'} + }], + returns: { + type: ['Object'], + root: true + }, + http: { + path: `/:ticketFk/componentUpdate`, + verb: 'post' + } + }); + + Self.componentUpdate = async (ticketFk, data) => { + let query = 'CALL vn.ticketComponentMakeUpdate(?, ?, ?, ?, ?, ?, ?)'; + let res = await Self.rawSql(query, [ + ticketFk, + data.agencyModeFk, + data.addressFk, + data.warehouseFk, + data.shipped, + data.landed, + data.option + ]); + return res; + }; +}; diff --git a/services/loopback/common/methods/ticket/specs/componentUpdate.spec.js b/services/loopback/common/methods/ticket/specs/componentUpdate.spec.js new file mode 100644 index 000000000..bcef7e79a --- /dev/null +++ b/services/loopback/common/methods/ticket/specs/componentUpdate.spec.js @@ -0,0 +1,19 @@ +const app = require(`${servicesDir}/ticket/server/server`); + +describe('ticket componentUpdate()', () => { + it('should call the componentUpdate method', done => { + let data = { + agencyModeFk: 1, + addressFk: 121, + warehouseFk: 1, + shipped: Date.now(), + landed: Date.now(), + option: 1 + }; + app.models.Ticket.componentUpdate(1, data) + .catch(response => { + expect(response).toEqual(new Error('ER_SIGNAL_EXCEPTION: NO_AGENCY_AVAILABLE')); + done(); + }); + }); +}); diff --git a/services/loopback/common/models/ticket.js b/services/loopback/common/models/ticket.js index 18b8dc62e..fb8188efe 100644 --- a/services/loopback/common/models/ticket.js +++ b/services/loopback/common/models/ticket.js @@ -6,4 +6,5 @@ module.exports = Self => { require('../methods/ticket/summary')(Self); require('../methods/ticket/getTotal')(Self); require('../methods/ticket/getTaxes')(Self); + require('../methods/ticket/componentUpdate')(Self); }; diff --git a/services/mailer/package.json b/services/mailer/package.json index 408ce541d..17bd23567 100644 --- a/services/mailer/package.json +++ b/services/mailer/package.json @@ -12,7 +12,8 @@ "nodemailer": "^4.0.1", "path": "^0.12.7", "request": "^2.83.0", - "require-yaml": "0.0.1" + "require-yaml": "0.0.1", + "fs-extra": "^5.0.0" }, "repository": { "type": "git", diff --git a/services/mailer/server/server.js b/services/mailer/server/server.js.bak similarity index 100% rename from services/mailer/server/server.js rename to services/mailer/server/server.js.bak diff --git a/services/print/package.json b/services/print/package.json index d63a8fe34..9d763c113 100644 --- a/services/print/package.json +++ b/services/print/package.json @@ -10,7 +10,9 @@ "inline-css": "^2.2.2", "mustache": "^2.3.0", "mysql": "^2.13.0", - "path": "^0.12.7" + "path": "^0.12.7", + "require-yaml": "0.0.1", + "fs-extra": "^5.0.0" }, "repository": { "type": "git", diff --git a/services/print/server/server.js b/services/print/server/server.js.bak similarity index 100% rename from services/print/server/server.js rename to services/print/server/server.js.bak diff --git a/services/production/server/server.js b/services/production/server/server.js.bak similarity index 100% rename from services/production/server/server.js rename to services/production/server/server.js.bak diff --git a/services/route/server/server.js b/services/route/server/server.js.bak similarity index 100% rename from services/route/server/server.js rename to services/route/server/server.js.bak diff --git a/services/ticket/common/models/ticket-tracking.js b/services/ticket/common/models/ticket-tracking.js index 464436daa..22db92406 100644 --- a/services/ticket/common/models/ticket-tracking.js +++ b/services/ticket/common/models/ticket-tracking.js @@ -8,14 +8,6 @@ module.exports = function(Self) { let token = ctx.options.accessToken; let userId = token && token.userId; - let isEmployee = await models.Account.hasRole(userId, 'employee'); - let isProduction = await models.Account.hasRole(userId, 'production'); - let isAlertLevelZero = await models.State.isAlertLevelZero(ctx.instance.stateFk); - let ticketAlertLevel = await models.TicketState.findOne({where: {id: ctx.instance.ticketFk}, fields: ["alertLevel"]}); - - if ((!isProduction && !isAlertLevelZero) || !isEmployee || (isEmployee && ticketAlertLevel != 0 && !isProduction)) - throw new Error("You don't have enough privileges to do that"); - let user = await models.Worker.findOne({where: {userFk: userId}}); ctx.instance.workerFk = user.id; });