Merge branch 'dev' of https://git.verdnatura.es/salix into dev
This commit is contained in:
commit
518a82bf26
|
@ -56,13 +56,12 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
returnDialog(response) {
|
returnDialog(response) {
|
||||||
if (response === 'CANCEL')
|
if (response === 'ACCEPT') {
|
||||||
return;
|
let params = {finished: Date.now()};
|
||||||
|
this.$http.patch(`/client/api/CreditClassifications/${this.classificationId}`, params).then(() => {
|
||||||
let params = {finished: Date.now()};
|
this._getClassifications(this.client.id);
|
||||||
this.$http.patch(`/client/api/CreditClassifications/${this.classificationId}`, params).then(() => {
|
});
|
||||||
this._getClassifications(this.client.id);
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,8 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
returnDialog(response) {
|
returnDialog(response) {
|
||||||
if (response === 'CANCEL')
|
if (response === 'ACCEPT')
|
||||||
return;
|
this.addCredit();
|
||||||
|
|
||||||
this.addCredit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addCredit() {
|
addCredit() {
|
||||||
|
|
|
@ -65,9 +65,9 @@ describe('Client', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('returnDialog()', () => {
|
describe('returnDialog()', () => {
|
||||||
it('should call addCredit() when is called with a param disctint from CANCEL', () => {
|
it('should call addCredit() when is called with ACCEPT', () => {
|
||||||
spyOn(controller, 'addCredit');
|
spyOn(controller, 'addCredit');
|
||||||
controller.returnDialog('Manzano');
|
controller.returnDialog('ACCEPT');
|
||||||
|
|
||||||
expect(controller.addCredit).toHaveBeenCalledWith();
|
expect(controller.addCredit).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<vn-icon
|
<vn-icon
|
||||||
vn-tooltip="Client has debt"
|
vn-tooltip="Client has debt"
|
||||||
icon="icon-risk"
|
icon="icon-risk"
|
||||||
ng-class="{bright: $ctrl.clientDebt < 0}">
|
ng-class="{bright: $ctrl.clientDebt > 0}">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
vn-tooltip="Client not checked"
|
vn-tooltip="Client not checked"
|
||||||
|
|
|
@ -2,13 +2,14 @@ import ngModule from '../../module';
|
||||||
import getWatchers from '../../lib/get-watchers';
|
import getWatchers from '../../lib/get-watchers';
|
||||||
|
|
||||||
class AutoPaging {
|
class AutoPaging {
|
||||||
constructor($http, $window, $element, $timeout, vnApp, $translate) {
|
constructor($http, $window, $element, $timeout, vnApp, $translate, $scope) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$window = $window;
|
this.$window = $window;
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.vnApp = vnApp;
|
this.vnApp = vnApp;
|
||||||
this.$translate = $translate;
|
this.$translate = $translate;
|
||||||
|
this.$scope = $scope;
|
||||||
|
|
||||||
this.numPerPage = null;
|
this.numPerPage = null;
|
||||||
this.maxItems = 0;
|
this.maxItems = 0;
|
||||||
|
@ -31,6 +32,7 @@ class AutoPaging {
|
||||||
res.instances.forEach(item => {
|
res.instances.forEach(item => {
|
||||||
this.items.push(item);
|
this.items.push(item);
|
||||||
});
|
});
|
||||||
|
this.$scope.$apply();
|
||||||
this.checkWatchers();
|
this.checkWatchers();
|
||||||
});
|
});
|
||||||
if (this.index.filter.page == this.numPages) {
|
if (this.index.filter.page == this.numPages) {
|
||||||
|
@ -108,7 +110,7 @@ class AutoPaging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoPaging.$inject = ['$http', '$window', '$element', '$timeout', 'vnApp', '$translate'];
|
AutoPaging.$inject = ['$http', '$window', '$element', '$timeout', 'vnApp', '$translate', '$scope'];
|
||||||
|
|
||||||
ngModule.component('vnAutoPaging', {
|
ngModule.component('vnAutoPaging', {
|
||||||
template: require('./auto-paging.html'),
|
template: require('./auto-paging.html'),
|
||||||
|
|
|
@ -1,28 +1,18 @@
|
||||||
<div
|
<div
|
||||||
class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label"
|
class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label"
|
||||||
tabindex="1"
|
|
||||||
ng-focus="$ctrl.hasFocus = true"
|
ng-focus="$ctrl.hasFocus = true"
|
||||||
ng-blur="$ctrl.hasFocus = false"
|
ng-blur="$ctrl.hasFocus = false"
|
||||||
ng-mouseenter="$ctrl.hasMouseIn = true"
|
ng-mouseenter="$ctrl.hasMouseIn = true"
|
||||||
ng-mouseleave="$ctrl.hasMouseIn = false"
|
ng-mouseleave="$ctrl.hasMouseIn = false">
|
||||||
ng-click="$ctrl.onClick()">
|
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="mdl-textfield__input"
|
class="mdl-textfield__input"
|
||||||
name="{{::$ctrl.name}}"
|
name="{{::$ctrl.name}}"
|
||||||
ng-model="$ctrl.modelView"
|
|
||||||
ng-disabled="{{!$ctrl.enabled}}"
|
ng-disabled="{{!$ctrl.enabled}}"
|
||||||
rule="{{::$ctrl.rule}}"/>
|
rule="{{::$ctrl.rule}}"/>
|
||||||
|
|
||||||
<div class="mdl-chip__action">
|
<div class="mdl-chip__action">
|
||||||
<i
|
|
||||||
class="material-icons"
|
|
||||||
ng-if="$ctrl.isTimePicker"
|
|
||||||
ng-click="$ctrl.vp.open()">
|
|
||||||
query_builder
|
|
||||||
</i>
|
|
||||||
<i
|
<i
|
||||||
class="material-icons pointer"
|
class="material-icons pointer"
|
||||||
ng-show="$ctrl.modelView&&($ctrl.hasFocus||$ctrl.hasMouseIn)"
|
ng-show="$ctrl.model && ($ctrl.hasFocus || $ctrl.hasMouseIn)"
|
||||||
ng-click="$ctrl.onClear()">
|
ng-click="$ctrl.onClear()">
|
||||||
clear
|
clear
|
||||||
</i>
|
</i>
|
||||||
|
|
|
@ -3,240 +3,93 @@ import Component from '../../lib/component';
|
||||||
import Flatpickr from 'vendor/src/flatpickr';
|
import Flatpickr from 'vendor/src/flatpickr';
|
||||||
import './style.scss';
|
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 {
|
class DatePicker extends Component {
|
||||||
constructor($element, $translate, $filter, $timeout, $attrs) {
|
constructor($element, $scope, $translate, $attrs) {
|
||||||
super($element);
|
super($element, $scope);
|
||||||
this.input = $element[0].querySelector('input');
|
this.input = $element[0].querySelector('input');
|
||||||
this.$translate = $translate;
|
this.$translate = $translate;
|
||||||
this.$filter = $filter;
|
|
||||||
this.$timeout = $timeout;
|
|
||||||
this.$attrs = $attrs;
|
this.$attrs = $attrs;
|
||||||
|
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
this._modelView = null;
|
this._modelView = null;
|
||||||
this._model = undefined;
|
this._model = undefined;
|
||||||
this._optionsChecked = false;
|
this.dateValue = undefined;
|
||||||
this._waitingInit = 0;
|
|
||||||
this.hasFocus = false;
|
|
||||||
this.hasMouseIn = false;
|
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);
|
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() {
|
get model() {
|
||||||
return this._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);
|
set model(value) {
|
||||||
this._modelView = this.$filter('date')(new Date(this._model), format);
|
this._model = value;
|
||||||
this.mdlUpdate();
|
this.dateValue = value ? new Date(value) : null;
|
||||||
}
|
this.vp.setDate(this.dateValue);
|
||||||
} 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);
|
|
||||||
this.mdlUpdate();
|
this.mdlUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get modelView() {
|
||||||
|
return this._modelView;
|
||||||
|
}
|
||||||
|
|
||||||
|
set modelView(value) {
|
||||||
|
this._modelView = value;
|
||||||
|
}
|
||||||
|
|
||||||
onClear() {
|
onClear() {
|
||||||
this.modelView = null;
|
this.model = null;
|
||||||
}
|
|
||||||
onClick() {
|
|
||||||
if (this.vp) {
|
|
||||||
this.vp.open();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mdlUpdate() {
|
mdlUpdate() {
|
||||||
this.$timeout(() => {
|
let mdlField = this.element.firstChild.MaterialTextfield;
|
||||||
let mdlField = this.element.firstChild.MaterialTextfield;
|
if (mdlField)
|
||||||
if (mdlField)
|
mdlField.updateClasses_();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onDestroy() {
|
$onDestroy() {
|
||||||
this.destroyPicker();
|
this.vp.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DatePicker.$inject = ['$element', '$translate', '$filter', '$timeout', '$attrs'];
|
DatePicker.$inject = ['$element', '$scope', '$translate', '$attrs'];
|
||||||
|
|
||||||
ngModule.component('vnDatePicker', {
|
ngModule.component('vnDatePicker', {
|
||||||
template: require('./date-picker.html'),
|
template: require('./date-picker.html'),
|
||||||
|
|
|
@ -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(`<div><input></div>`);
|
|
||||||
$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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@import "colors";
|
||||||
|
|
||||||
vn-date-picker {
|
vn-date-picker {
|
||||||
.mdl-chip__action {
|
.mdl-chip__action {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -7,9 +9,18 @@ vn-date-picker {
|
||||||
margin: 22px 0px;
|
margin: 22px 0px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
.mdl-textfield {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
.material-icons {
|
.material-icons {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flatpickr-months .flatpickr-month,
|
||||||
|
.flatpickr-weekdays,
|
||||||
|
span.flatpickr-weekday {
|
||||||
|
background-color: $main-01;
|
||||||
|
}
|
|
@ -196,7 +196,7 @@ export default class DropDown extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
let where = {};
|
let where = {};
|
||||||
where[this.showField] = {regexp: search};
|
where[this.showField] = {like: `%${search}%`};
|
||||||
return where;
|
return where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
import './multi-check.scss';
|
import Input from '../../lib/input';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw checkbox with a drop-down and multi options
|
* Draw checkbox with a drop-down and multi options
|
||||||
|
@ -7,8 +7,9 @@ import './multi-check.scss';
|
||||||
* @param {Array} data List of options shown in drop-down
|
* @param {Array} data List of options shown in drop-down
|
||||||
* @param {Array} models Elements to check / unCheck
|
* @param {Array} models Elements to check / unCheck
|
||||||
*/
|
*/
|
||||||
export default class MultiCheck {
|
export default class MultiCheck extends Input {
|
||||||
constructor() {
|
constructor($element, $scope) {
|
||||||
|
super($element, $scope);
|
||||||
this._checkAll = false;
|
this._checkAll = false;
|
||||||
this.checkField = 'checked';
|
this.checkField = 'checked';
|
||||||
}
|
}
|
||||||
|
@ -36,7 +37,8 @@ ngModule.component('vnMultiCheck', {
|
||||||
bindings: {
|
bindings: {
|
||||||
data: '=',
|
data: '=',
|
||||||
checkField: '<?',
|
checkField: '<?',
|
||||||
checkAll: '=?'
|
checkAll: '=?',
|
||||||
|
disabled: '<?'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
.multi-check {
|
|
||||||
vn-icon{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.primaryCheckbox {
|
|
||||||
vn-icon{
|
|
||||||
font-size: 22px;
|
|
||||||
margin-left: -4px;
|
|
||||||
i{
|
|
||||||
color: rgba(0,0,0,.54);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.color {
|
|
||||||
i{
|
|
||||||
color: rgb(255,152,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.arrow_down{
|
|
||||||
i{
|
|
||||||
padding-top: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,12 +16,19 @@ export default class StepControl {
|
||||||
}
|
}
|
||||||
|
|
||||||
set currentState(state) {
|
set currentState(state) {
|
||||||
let isAllowed = true;
|
if (!this.onStepChange)
|
||||||
|
return this.$state.go(state);
|
||||||
|
|
||||||
if (this.onStepChange)
|
let change = this.onStepChange({state});
|
||||||
isAllowed = 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);
|
this.$state.go(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
"description": "Tax",
|
"description": "Tax",
|
||||||
"icon": "icon-tax"
|
"icon": "icon-tax"
|
||||||
},
|
},
|
||||||
"acl": ["administrative","salesAssistant"]
|
"acl": ["administrative","buyer"]
|
||||||
}, {
|
}, {
|
||||||
"url" : "/history",
|
"url" : "/history",
|
||||||
"state": "item.card.history",
|
"state": "item.card.history",
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
field="$ctrl.item.expenceFk"
|
field="$ctrl.item.expenceFk"
|
||||||
initial-data="$ctrl.item.expence">
|
initial-data="$ctrl.item.expence">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
|
<vn-textfield vn-one label="Reference" field="$ctrl.item.description"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Reference: Referencia
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
/* {
|
||||||
"module": "locator",
|
"module": "locator",
|
||||||
"name": "Locator",
|
"name": "Locator",
|
||||||
"icon": "add_location",
|
"icon": "add_location",
|
||||||
|
@ -11,4 +11,4 @@
|
||||||
"acl": ["developer"]
|
"acl": ["developer"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
} */
|
|
@ -2,9 +2,9 @@ auth: []
|
||||||
client: []
|
client: []
|
||||||
core: []
|
core: []
|
||||||
item: []
|
item: []
|
||||||
locator: []
|
#locator: []
|
||||||
production: []
|
#production: []
|
||||||
salix: []
|
salix: []
|
||||||
route: []
|
#route: []
|
||||||
ticket: [item]
|
ticket: [item]
|
||||||
order: []
|
order: []
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Orders: Orders
|
|
|
@ -1 +0,0 @@
|
||||||
Orders: Catálogo
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
/* {
|
||||||
"module": "production",
|
"module": "production",
|
||||||
"name": "Production",
|
"name": "Production",
|
||||||
"icon": "local_florist",
|
"icon": "local_florist",
|
||||||
|
@ -11,4 +11,4 @@
|
||||||
"acl": ["developer"]
|
"acl": ["developer"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
} */
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
/* {
|
||||||
"module": "route",
|
"module": "route",
|
||||||
"name": "Routes",
|
"name": "Routes",
|
||||||
"icon" : "local_shipping",
|
"icon" : "local_shipping",
|
||||||
|
@ -65,4 +65,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
} */
|
|
@ -16,6 +16,7 @@ Logout: Cerrar sesión
|
||||||
Modules access : Acceso a módulos
|
Modules access : Acceso a módulos
|
||||||
Notifications: Notificaciones
|
Notifications: Notificaciones
|
||||||
name: Nombre
|
name: Nombre
|
||||||
|
Orders: Catálogo
|
||||||
phone: Teléfono
|
phone: Teléfono
|
||||||
Preview: Vista previa
|
Preview: Vista previa
|
||||||
Production : Producción
|
Production : Producción
|
||||||
|
|
|
@ -71,6 +71,18 @@
|
||||||
"ticket": "$ctrl.data"
|
"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",
|
"url": "/observation",
|
||||||
"state": "ticket.card.observation",
|
"state": "ticket.card.observation",
|
||||||
|
@ -141,7 +153,8 @@
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Tracking",
|
"description": "Tracking",
|
||||||
"icon": "remove_red_eye"
|
"icon": "remove_red_eye"
|
||||||
}
|
},
|
||||||
|
"acl": ["production"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "/edit",
|
"url": "/edit",
|
||||||
|
@ -159,18 +172,6 @@
|
||||||
"client": "$ctrl.client"
|
"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",
|
"url" : "/sale-checked",
|
||||||
"state": "ticket.card.saleChecked",
|
"state": "ticket.card.saleChecked",
|
||||||
|
|
|
@ -7,17 +7,21 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
set ticket(data) {
|
set ticket(data) {
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
this.data = Object.assign({}, data);
|
this.data = Object.assign({}, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
registerChild(child) {
|
||||||
//post data
|
this.child = child;
|
||||||
alert('Data saved');
|
|
||||||
console.log(this.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onStepChange(state) {
|
onStepChange(state) {
|
||||||
return true;
|
return this.child.onStepChange(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.child.onSubmit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
There's no available agency for this landing date: No hay ninguna agencia disponible para la fecha de envío seleccionada
|
|
@ -1,22 +1,23 @@
|
||||||
<form name="form">
|
<form name="form">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Ticket configuration - Basic data</vn-title>
|
<vn-title>Basic data</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
|
vn-id="client"
|
||||||
url="/api/Clients"
|
url="/api/Clients"
|
||||||
label="Client"
|
label="Client"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
field="$ctrl.ticket.clientFk"
|
field="$ctrl.ticket.clientFk"
|
||||||
initial-data="$ctrl.ticket.clientFk">
|
initial-data="$ctrl.ticket.clientFk"
|
||||||
|
on-change="$ctrl.onChange()">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="/api/Addresses"
|
url="{{$ctrl.getAddresses()}}"
|
||||||
label="Address"
|
label="Address"
|
||||||
show-field="nickname"
|
show-field="nickname"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
field="$ctrl.ticket.addressFk"
|
field="$ctrl.ticket.addressFk">
|
||||||
initial-data="$ctrl.ticket.addressFk">
|
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="/api/AgencyModes"
|
url="/api/AgencyModes"
|
||||||
|
@ -29,14 +30,13 @@
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-date-picker vn-one
|
<vn-date-picker vn-one
|
||||||
label="Shipment"
|
label="Shipped"
|
||||||
model="$ctrl.ticket.shipped"
|
model="$ctrl.ticket.shipped"
|
||||||
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i', time_24hr: true}">
|
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i'}">
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
<vn-date-picker vn-one
|
<vn-date-picker vn-one
|
||||||
label="Landing"
|
label="Landed"
|
||||||
model="$ctrl.ticket.landed"
|
model="$ctrl.ticket.landed">
|
||||||
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i', time_24hr: true}">
|
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="/api/Companies"
|
url="/api/Companies"
|
||||||
|
|
|
@ -1,17 +1,68 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($scope) {
|
constructor($scope, $http, $translate, vnApp) {
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
|
this.$http = $http;
|
||||||
|
this.$translate = $translate;
|
||||||
|
this.vnApp = vnApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.data.registerChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange() {
|
||||||
|
if (this.ticket)
|
||||||
|
this.ticket.addressFk = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAddresses() {
|
||||||
|
if (this.ticket)
|
||||||
|
return `/api/Clients/${this.ticket.clientFk}/addresses`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onStepChange(state) {
|
||||||
|
if (this.isFormInvalid())
|
||||||
|
return this.vnApp.showError(
|
||||||
|
this.$translate.instant('Some fields are invalid')
|
||||||
|
);
|
||||||
|
|
||||||
|
let query = `/ticket/api/sales/${this.ticket.id}/priceDifference`;
|
||||||
|
let data = {
|
||||||
|
landed: this.ticket.landed,
|
||||||
|
addressFk: this.ticket.addressFk,
|
||||||
|
agencyModeFk: this.ticket.agencyModeFk
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.$http.post(query, data).then(res => {
|
||||||
|
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', {
|
ngModule.component('vnTicketDataStepOne', {
|
||||||
template: require('./step-one.html'),
|
template: require('./step-one.html'),
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
ticket: '<'
|
ticket: '<'
|
||||||
|
},
|
||||||
|
require: {
|
||||||
|
data: '^vnTicketData'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
Charge: Cargo
|
||||||
|
Choose an option: Selecciona una opción
|
||||||
|
Charge difference to: Diferencia a cargo de
|
|
@ -1,14 +1,14 @@
|
||||||
<form name="form">
|
<form name="form">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Ticket configuration - Charge</vn-title>
|
<vn-title>Charge</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="/api/Clients"
|
url="/ticket/api/TicketUpdateActions"
|
||||||
label="Charge difference to"
|
label="Charge difference to"
|
||||||
show-field="name"
|
show-field="description"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
field="$ctrl.ticket.clientFk"
|
field="$ctrl.ticket.option"
|
||||||
initial-data="$ctrl.ticket.clientFk">
|
initial-data="$ctrl.ticket.option">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,15 +1,62 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($scope) {
|
|
||||||
|
constructor($http, $scope, $state, $translate, vnApp) {
|
||||||
|
this.$http = $http;
|
||||||
this.$scope = $scope;
|
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', {
|
ngModule.component('vnTicketDataStepThree', {
|
||||||
template: require('./step-three.html'),
|
template: require('./step-three.html'),
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
ticket: '<'
|
ticket: '<'
|
||||||
|
},
|
||||||
|
require: {
|
||||||
|
card: '^vnTicketCard',
|
||||||
|
data: '^vnTicketData'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}); */
|
|
@ -0,0 +1,3 @@
|
||||||
|
Price (PPU): Precio (Ud.)
|
||||||
|
New price (PPU): Nuevo precio (Ud.)
|
||||||
|
Price difference: Diferencia de precio
|
|
@ -1,6 +1,6 @@
|
||||||
<form name="form">
|
<form name="form">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Ticket configuration - Price difference</vn-title>
|
<vn-title>Price difference</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<table class="vn-grid">
|
<table class="vn-grid">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -8,21 +8,29 @@
|
||||||
<th number translate>Item</th>
|
<th number translate>Item</th>
|
||||||
<th translate style="text-align:center">Description</th>
|
<th translate style="text-align:center">Description</th>
|
||||||
<th number translate>Quantity</th>
|
<th number translate>Quantity</th>
|
||||||
<th number translate>Price</th>
|
<th number translate>Price (PPU)</th>
|
||||||
<th number translate>New price</th>
|
<th number translate>New price (PPU)</th>
|
||||||
<th number translate>Price gap</th>
|
<th number translate>Price difference</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="sale in $ctrl.ticket.sales track by sale.id">
|
<tr ng-repeat="sale in $ctrl.ticket.sale.items track by sale.id">
|
||||||
<td number>{{("000000"+sale.itemFk).slice(-6)}}</td>
|
<td number>{{("000000"+sale.itemFk).slice(-6)}}</td>
|
||||||
<td><vn-fetched-tags sale="sale"/></td>
|
<td><vn-fetched-tags sale="sale"/></td>
|
||||||
<td number>{{::sale.quantity}}</td>
|
<td number>{{::sale.quantity}}</td>
|
||||||
<td number>{{::sale.price | currency:'€':2}}</td>
|
<td number>{{::sale.price | currency: '€': 2}}</td>
|
||||||
<td number>-</td>
|
<td number>{{::sale.component.newPrice | currency: '€': 2}}</td>
|
||||||
<td number>-</td>
|
<td number>{{::sale.component.difference | currency: '€': 2}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3"></td>
|
||||||
|
<td number><strong>{{$ctrl.ticket.sale.totalUnitPrice | currency: '€': 2}}</strong></td>
|
||||||
|
<td number><strong>{{$ctrl.ticket.sale.totalNewPrice | currency: '€': 2}}</strong></td>
|
||||||
|
<td number><strong>{{$ctrl.ticket.sale.totalDifference | currency: '€': 2}}</strong></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,28 +1,29 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($http, $scope) {
|
|
||||||
|
constructor($http) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$scope = $scope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onChanges(data) {
|
$onInit() {
|
||||||
if (!this.ticket || !this.ticket.id) return;
|
this.data.registerChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
let query = `/ticket/api/sales/${this.ticket.id}/priceDifference`;
|
onStepChange(state) {
|
||||||
this.$http.get(query).then(res => {
|
return true;
|
||||||
if (res.data)
|
|
||||||
this.ticket.sales = res.data;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$http', '$scope'];
|
Controller.$inject = ['$http'];
|
||||||
|
|
||||||
ngModule.component('vnTicketDataStepTwo', {
|
ngModule.component('vnTicketDataStepTwo', {
|
||||||
template: require('./step-two.html'),
|
template: require('./step-two.html'),
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
ticket: '<'
|
ticket: '<'
|
||||||
|
},
|
||||||
|
require: {
|
||||||
|
data: '^vnTicketData'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,3 +52,4 @@ Warehouse: Almacén
|
||||||
Worker: Trabajador
|
Worker: Trabajador
|
||||||
Package size: Bultos
|
Package size: Bultos
|
||||||
VAT: IVA
|
VAT: IVA
|
||||||
|
PPU: Ud.
|
|
@ -234,7 +234,7 @@ export default {
|
||||||
itemBarcodes: {
|
itemBarcodes: {
|
||||||
barcodeButton: `${components.vnMenuItem}[ui-sref="item.card.itemBarcode"]`,
|
barcodeButton: `${components.vnMenuItem}[ui-sref="item.card.itemBarcode"]`,
|
||||||
addBarcodeButton: `${components.vnIcon}[icon="add_circle"]`,
|
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}`,
|
submitBarcodesButton: `${components.vnSubmit}`,
|
||||||
firstCodeRemoveButton: `vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]`
|
firstCodeRemoveButton: `vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]`
|
||||||
},
|
},
|
||||||
|
|
|
@ -5940,9 +5940,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flatpickr": {
|
"flatpickr": {
|
||||||
"version": "2.6.3",
|
"version": "4.4.6",
|
||||||
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.4.6.tgz",
|
||||||
"integrity": "sha1-RXNXUy3rE189pktCW/RDVzeWFWQ="
|
"integrity": "sha512-5b4aJtMBiyXyg5paf3lZ872t1Qjt7Qv4SNqChKh2AvP+OYaC1jrutty0goW6WvvkASoamzeFEFbPJIBdHqxNRA=="
|
||||||
},
|
},
|
||||||
"for-in": {
|
"for-in": {
|
||||||
"version": "0.1.6",
|
"version": "0.1.6",
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"angular-paging": "^2.2.2",
|
"angular-paging": "^2.2.2",
|
||||||
"angular-translate": "^2.17.0",
|
"angular-translate": "^2.17.0",
|
||||||
"angular-translate-loader-partial": "^2.17.0",
|
"angular-translate-loader-partial": "^2.17.0",
|
||||||
"flatpickr": "^2.6.3",
|
"flatpickr": "^4.4.6",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
"material-design-lite": "^1.3.0",
|
"material-design-lite": "^1.3.0",
|
||||||
"mg-crud": "^1.1.2",
|
"mg-crud": "^1.1.2",
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
|
@ -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 ;
|
|
@ -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 ;
|
|
@ -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 ;
|
||||||
|
|
|
@ -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 ;
|
|
@ -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 ;
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
|
@ -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 ;
|
|
@ -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 ;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE `vn2008`.`Tickets`
|
||||||
|
ADD COLUMN `isDeleted` TINYINT(2) NOT NULL DEFAULT '0' AFTER `boxed`;
|
|
@ -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`;
|
|
@ -0,0 +1,14 @@
|
||||||
|
UPDATE `salix`.`ACL` SET `accessType`='READ' WHERE `id`='20';
|
||||||
|
UPDATE `salix`.`ACL` SET `principalId`='production' WHERE `id`='67';
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('78', 'TicketTracking', '*', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `permission`, `principalType`, `principalId`) VALUES ('79', 'TicketTracking', 'changeState', 'ALLOW', 'ROLE', 'employe');
|
||||||
|
|
||||||
|
UPDATE `salix`.`ACL` SET `accessType`='READ' WHERE `id`='65';
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('80', 'Sale', 'removes', '*', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('81', 'Sale', 'moveToTicket', '*', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
UPDATE `salix`.`ACL` SET `principalId`='employee' WHERE `id`='79';
|
||||||
|
UPDATE `salix`.`ACL` SET `accessType`='*' WHERE `id`='79';
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('82', 'Sale', 'updateQuantity', '*', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('83', 'Sale', 'updatePrice', '*', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('84', 'Sale', 'updateDiscount', '*', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,27 @@
|
||||||
|
DROP VIEW `salix`.`Accounting`;
|
||||||
|
DROP VIEW `salix`.`Address`;
|
||||||
|
DROP VIEW `salix`.`Agency`;
|
||||||
|
DROP VIEW `salix`.`AgencyMode`;
|
||||||
|
DROP VIEW `salix`.`Bank`;
|
||||||
|
DROP VIEW `salix`.`City`;
|
||||||
|
DROP VIEW `salix`.`Client`;
|
||||||
|
DROP VIEW `salix`.`ClientCredit`;
|
||||||
|
DROP VIEW `salix`.`ClientCreditLimit`;
|
||||||
|
DROP VIEW `salix`.`ClientObservation`;
|
||||||
|
DROP VIEW `salix`.`ClientType`;
|
||||||
|
DROP VIEW `salix`.`ContactChannel`;
|
||||||
|
DROP VIEW `salix`.`Country`;
|
||||||
|
DROP VIEW `salix`.`CreditClassification`;
|
||||||
|
DROP VIEW `salix`.`Delivery`;
|
||||||
|
DROP VIEW `salix`.`Employee`;
|
||||||
|
DROP VIEW `salix`.`PayMethod`;
|
||||||
|
DROP VIEW `salix`.`Province`;
|
||||||
|
DROP VIEW `salix`.`Route`;
|
||||||
|
DROP VIEW `salix`.`State`;
|
||||||
|
DROP VIEW `salix`.`Ticket`;
|
||||||
|
DROP VIEW `salix`.`TicketState`;
|
||||||
|
DROP VIEW `salix`.`Vehicle`;
|
||||||
|
DROP VIEW `salix`.`Warehouse`;
|
||||||
|
DROP VIEW `salix`.`WarehouseAlias`;
|
||||||
|
DROP VIEW `salix`.`Worker`;
|
||||||
|
DROP VIEW `salix`.`Zone`;
|
|
@ -0,0 +1,26 @@
|
||||||
|
DROP TRIGGER IF EXISTS `vn2008`.`Articles_AFTER_INSERT`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn2008`$$
|
||||||
|
CREATE DEFINER=`root`@`%` TRIGGER `vn2008`.`Articles_AFTER_INSERT` AFTER INSERT ON `Articles` FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
CALL itemTagArrangedUpdate(NEW.Id_Article);
|
||||||
|
|
||||||
|
INSERT INTO vn.itemTaxCountry(itemFk, countryFk, taxClassFk)
|
||||||
|
SELECT NEW.Id_Article, 1, NEW.iva_group_id;
|
||||||
|
|
||||||
|
INSERT INTO vn.itemTaxCountry(itemFk, countryFk, taxClassFk)
|
||||||
|
SELECT NEW.Id_Article, 5, NEW.iva_group_id;
|
||||||
|
|
||||||
|
INSERT INTO vn.itemTaxCountry(itemFk, countryFk, taxClassFk)
|
||||||
|
SELECT NEW.Id_Article, 30, NEW.iva_group_id;
|
||||||
|
|
||||||
|
IF NEW.tipo_id IS NOT NULL THEN
|
||||||
|
INSERT INTO vn.itemTag (itemFk, tagFk, priority)
|
||||||
|
SELECT NEW.Id_Article, tagFk, priority FROM vn.itemTypeTag
|
||||||
|
WHERE itemTypeFk = NEW.tipo_id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,23 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `ticketListCreate`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `ticketListCreate`(
|
||||||
|
vClientId INT
|
||||||
|
,vShipped DATE
|
||||||
|
,vWarehouseId INT
|
||||||
|
,vCompanyFk INT
|
||||||
|
,vAddressFk INT
|
||||||
|
,vAgencyType INT
|
||||||
|
,vRouteFk INT
|
||||||
|
,vlanded DATE)
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
DECLARE vNewTicket INT;
|
||||||
|
CALL vn.ticketCreate(vClientId, vShipped, vWarehouseId, vCompanyFk, vAddressFk, vAgencyType, vRouteFk, vlanded,vNewTicket);
|
||||||
|
SELECT vNewTicket;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
|
@ -568,6 +568,14 @@ INSERT INTO `vn`.`itemTag`(`id`,`itemFk`,`tagFk`,`value`,`priority`)
|
||||||
(19, 4, 4, 'Manhattan', 2),
|
(19, 4, 4, 'Manhattan', 2),
|
||||||
(20, 4, 5, 'Tony Stark', 1);
|
(20, 4, 5, 'Tony Stark', 1);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`itemTypeTag`(`id`, `itemTypeFk`, `tagFk`, `priority`)
|
||||||
|
VALUES
|
||||||
|
( 1, 1, 1, 0),
|
||||||
|
( 2, 2, 2, 0),
|
||||||
|
( 3, 3, 3, 1),
|
||||||
|
( 4, 1, 4, 1),
|
||||||
|
( 5, 1, 5, 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`itemLog` (`id`, `originFk`, `userFk`, `action`, `description`)
|
INSERT INTO `vn`.`itemLog` (`id`, `originFk`, `userFk`, `action`, `description`)
|
||||||
VALUES
|
VALUES
|
||||||
('1', '1', '1', 'insert', 'We made a change!');
|
('1', '1', '1', 'insert', 'We made a change!');
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "ItemTypeTag",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "itemTypeTag",
|
||||||
|
"database": "vn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"priority": {
|
||||||
|
"type": "Number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"type": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "ItemType",
|
||||||
|
"foreignKey": "itemTypeFk"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Tag",
|
||||||
|
"foreignKey": "tagFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,5 +34,8 @@
|
||||||
},
|
},
|
||||||
"Genus": {
|
"Genus": {
|
||||||
"dataSource": "edi"
|
"dataSource": "edi"
|
||||||
|
},
|
||||||
|
"ItemTypeTag": {
|
||||||
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,5 +17,7 @@
|
||||||
"The IBAN does not have the correct format": "El IBAN no tiene el formato correcto",
|
"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",
|
"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",
|
"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"
|
||||||
}
|
}
|
|
@ -37,6 +37,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
delete copy.id;
|
delete copy.id;
|
||||||
delete copy.itemTag;
|
delete copy.itemTag;
|
||||||
|
delete copy.description;
|
||||||
|
|
||||||
let newItem = await Self.create(copy);
|
let newItem = await Self.create(copy);
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('priceDifference', {
|
Self.remoteMethod('priceDifference', {
|
||||||
description: 'Returns a sale price difference',
|
description: 'Returns sales with price difference',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'ticketFk',
|
arg: 'ticketFk',
|
||||||
|
@ -8,6 +8,12 @@ module.exports = Self => {
|
||||||
required: true,
|
required: true,
|
||||||
description: 'ticket id',
|
description: 'ticket id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'data',
|
||||||
|
type: 'Object',
|
||||||
|
required: true,
|
||||||
|
description: 'landed, addressFk, agencyModeFk',
|
||||||
|
http: {source: 'body'}
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['Object'],
|
||||||
|
@ -15,11 +21,11 @@ module.exports = Self => {
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
path: `/:ticketFk/priceDifference`,
|
path: `/:ticketFk/priceDifference`,
|
||||||
verb: 'GET'
|
verb: 'post'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.priceDifference = async ticketFk => {
|
Self.priceDifference = async (ticketFk, data) => {
|
||||||
let filter = {
|
let filter = {
|
||||||
where: {
|
where: {
|
||||||
ticketFk: ticketFk
|
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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('isEditable', {
|
||||||
|
description: 'Check if a ticket is editable',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'ticketFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'ticketFk',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'boolean',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:ticketFk/isEditable`,
|
||||||
|
verb: 'get'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.isEditable = async ticketFk => {
|
||||||
|
let state = await Self.app.models.TicketState.findOne({where: {ticketFk: ticketFk}, fields: 'alertLevel'});
|
||||||
|
|
||||||
|
return state != null && state.alertLevel == 0;
|
||||||
|
};
|
||||||
|
};
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -129,6 +129,11 @@ module.exports = Self => {
|
||||||
async function validateCreditChange(ctx, finalState) {
|
async function validateCreditChange(ctx, finalState) {
|
||||||
let models = Self.app.models;
|
let models = Self.app.models;
|
||||||
let userId = ctx.options.accessToken.userId;
|
let userId = ctx.options.accessToken.userId;
|
||||||
|
|
||||||
|
let currentUserIsManager = await models.Account.hasRole(userId, 'manager');
|
||||||
|
if (currentUserIsManager)
|
||||||
|
return;
|
||||||
|
|
||||||
let filter = {
|
let filter = {
|
||||||
fields: ['roleFk'],
|
fields: ['roleFk'],
|
||||||
where: {
|
where: {
|
||||||
|
@ -162,22 +167,22 @@ module.exports = Self => {
|
||||||
let query = 'SELECT * FROM clientCredit WHERE clientFk = ? ORDER BY created DESC LIMIT 1';
|
let query = 'SELECT * FROM clientCredit WHERE clientFk = ? ORDER BY created DESC LIMIT 1';
|
||||||
let instances = await Self.rawSql(query, [finalState.id]);
|
let instances = await Self.rawSql(query, [finalState.id]);
|
||||||
|
|
||||||
if (instances.length !== 1 || instances[0].workerFk == userId || instances[0].amount > 0)
|
if (instances.length !== 1 || instances[0].amount > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
query = `SELECT COUNT(distinct r.id) > 0 as hasManagerRole
|
query = `
|
||||||
FROM clientCredit cc
|
SELECT COUNT(*) AS hasRoleManager
|
||||||
JOIN worker em ON em.id = cc.workerFk
|
FROM worker em
|
||||||
JOIN account.user ac ON ac.id = em.userFk
|
JOIN account.user ac ON ac.id = em.userFk
|
||||||
JOIN salix.RoleMapping rm ON rm.principalId = ac.id
|
JOIN salix.RoleMapping rm ON rm.principalId = ac.id
|
||||||
JOIN account.role r on r.id = rm.roleId
|
JOIN account.role r on r.id = rm.roleId
|
||||||
WHERE rm.principalType = 'USER'
|
WHERE em.id = ?
|
||||||
AND cc.workerFk = ?
|
AND rm.principalType = 'USER'
|
||||||
AND r.name = 'manager'`;
|
AND r.name = 'manager'`;
|
||||||
|
|
||||||
let instance = await Self.rawSql(query, [instances[0].workerFk]);
|
let instance = await Self.rawSql(query, [instances[0].workerFk]);
|
||||||
|
|
||||||
if (instance[0].hasManagerRole > 0)
|
if (instance[0].hasRoleManager)
|
||||||
throw new Error('Only manager can change the credit');
|
throw new Error('Only manager can change the credit');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,8 +13,10 @@
|
||||||
"forceId": false
|
"forceId": false
|
||||||
},
|
},
|
||||||
"updated": {
|
"updated": {
|
||||||
"type": "Date",
|
"type": "Date"
|
||||||
"required": false
|
},
|
||||||
|
"alertLevel": {
|
||||||
|
"type": "Number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -32,11 +34,6 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Worker",
|
"model": "Worker",
|
||||||
"foreignKey": "workerFk"
|
"foreignKey": "workerFk"
|
||||||
},
|
|
||||||
"alertLevel": {
|
|
||||||
"type": "belongsTo",
|
|
||||||
"model": "State",
|
|
||||||
"foreignKey": "alertLevel"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,5 @@ module.exports = Self => {
|
||||||
require('../methods/ticket/summary')(Self);
|
require('../methods/ticket/summary')(Self);
|
||||||
require('../methods/ticket/getTotal')(Self);
|
require('../methods/ticket/getTotal')(Self);
|
||||||
require('../methods/ticket/getTaxes')(Self);
|
require('../methods/ticket/getTaxes')(Self);
|
||||||
|
require('../methods/ticket/componentUpdate')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -86,6 +86,11 @@
|
||||||
"type": "hasMany",
|
"type": "hasMany",
|
||||||
"model": "TicketObservation",
|
"model": "TicketObservation",
|
||||||
"foreignKey": "ticketFk"
|
"foreignKey": "ticketFk"
|
||||||
|
},
|
||||||
|
"alertLevel": {
|
||||||
|
"type": "hasOne",
|
||||||
|
"model": "TicketState",
|
||||||
|
"foreignKey": "ticketFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,8 @@
|
||||||
"nodemailer": "^4.0.1",
|
"nodemailer": "^4.0.1",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"request": "^2.83.0",
|
"request": "^2.83.0",
|
||||||
"require-yaml": "0.0.1"
|
"require-yaml": "0.0.1",
|
||||||
|
"fs-extra": "^5.0.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
"inline-css": "^2.2.2",
|
"inline-css": "^2.2.2",
|
||||||
"mustache": "^2.3.0",
|
"mustache": "^2.3.0",
|
||||||
"mysql": "^2.13.0",
|
"mysql": "^2.13.0",
|
||||||
"path": "^0.12.7"
|
"path": "^0.12.7",
|
||||||
|
"require-yaml": "0.0.1",
|
||||||
|
"fs-extra": "^5.0.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"You don't have enough privileges to change the state of this ticket": "You don't have enough privileges to change the state of this ticket"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"You don't have enough privileges to change the state of this ticket": "No tienes permisos para cambiar el estado de este ticket"
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('changeState', {
|
||||||
|
description: 'Change the state of a ticket',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'params',
|
||||||
|
type: 'object',
|
||||||
|
required: true,
|
||||||
|
description: 'ticketFk',
|
||||||
|
http: {source: 'body'}
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'string',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/changeState`,
|
||||||
|
verb: 'post'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.changeState = async (params, ctx) => {
|
||||||
|
let isEditable = await Self.app.models.Ticket.isEditable(params.ticketFk);
|
||||||
|
if (isEditable)
|
||||||
|
return await Self.app.models.TicketTracking.create(params);
|
||||||
|
|
||||||
|
throw new Error(`You don't have enough privileges to change the state of this ticket`);
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
require('../methods/ticket-tracking/filter')(Self);
|
require('../methods/ticket-tracking/filter')(Self);
|
||||||
|
require('../methods/ticket-tracking/changeState')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
|
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
|
||||||
|
|
||||||
|
@ -8,14 +9,6 @@ module.exports = function(Self) {
|
||||||
let token = ctx.options.accessToken;
|
let token = ctx.options.accessToken;
|
||||||
let userId = token && token.userId;
|
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}});
|
let user = await models.Worker.findOne({where: {userFk: userId}});
|
||||||
ctx.instance.workerFk = user.id;
|
ctx.instance.workerFk = user.id;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue