diff --git a/client/core/src/components/index.js b/client/core/src/components/index.js
index 315f449ed..2da08fd15 100644
--- a/client/core/src/components/index.js
+++ b/client/core/src/components/index.js
@@ -29,4 +29,5 @@ import './combo/combo';
import './card/card';
import './switch/switch';
import './float-button/float-button';
+import './step-control/step-control';
import './label-value/label-value';
diff --git a/client/core/src/components/step-control/step-control.html b/client/core/src/components/step-control/step-control.html
new file mode 100644
index 000000000..fffdfe04d
--- /dev/null
+++ b/client/core/src/components/step-control/step-control.html
@@ -0,0 +1,33 @@
+
\ No newline at end of file
diff --git a/client/core/src/components/step-control/step-control.js b/client/core/src/components/step-control/step-control.js
new file mode 100644
index 000000000..5510a7815
--- /dev/null
+++ b/client/core/src/components/step-control/step-control.js
@@ -0,0 +1,71 @@
+import ngModule from '../../module';
+import './style.scss';
+
+export default class StepControl {
+ constructor($state) {
+ this.$state = $state;
+ }
+
+ set currentState(state) {
+ let isAllowed = true;
+
+ if (this.onStepChange)
+ isAllowed = this.onStepChange({state});
+
+ if (isAllowed)
+ this.$state.go(state);
+ }
+
+ get totalSteps() {
+ return this.steps.length;
+ }
+
+ get currentState() {
+ return this.$state.current.name;
+ }
+
+ get currentStepIndex() {
+ for (let i = 0; i < this.steps.length; i++) {
+ if (this.steps[i].state == this.$state.current.name)
+ return i;
+ }
+ }
+
+ onPreviousClick() {
+ let state = this.steps[this.currentStepIndex - 1].state;
+
+ this.currentState = state;
+ }
+
+ onNextClick() {
+ let state = this.steps[this.currentStepIndex + 1].state;
+
+ this.currentState = state;
+ }
+
+ canMovePrevious() {
+ return this.steps[0].state != this.currentState;
+ }
+
+ canFinalize() {
+ let lastStep = this.steps[this.totalSteps - 1];
+ return lastStep.state == this.currentState;
+ }
+
+ canMoveNext() {
+ let lastStep = this.steps[this.totalSteps - 1];
+ return lastStep.state != this.currentState;
+ }
+}
+
+StepControl.$inject = ['$state'];
+
+ngModule.component('vnStepControl', {
+ template: require('./step-control.html'),
+ controller: StepControl,
+ bindings: {
+ steps: '<',
+ onStepChange: '&?',
+ onStepEnd: '&?'
+ }
+});
diff --git a/client/core/src/components/step-control/step-control.spec.js b/client/core/src/components/step-control/step-control.spec.js
new file mode 100644
index 000000000..63a4354db
--- /dev/null
+++ b/client/core/src/components/step-control/step-control.spec.js
@@ -0,0 +1,49 @@
+import './step-control.js';
+
+describe('Component vnStepControl', () => {
+ let $componentController;
+ let controller;
+ let $state;
+
+ beforeEach(() => {
+ angular.mock.module('ticket');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_) => {
+ $componentController = _$componentController_;
+ $state = _$state_;
+ controller = $componentController('vnStepControl', {$state: $state});
+ }));
+
+ describe('currentState()', () => {
+ it(`should call the onStepChange method then return false and never call the go method`, () => {
+ controller.onStepChange = jasmine.createSpy(controller, 'onStepChange').and.returnValue(false);
+ spyOn(controller.$state, 'go');
+
+ controller.currentState = "something";
+
+ expect(controller.onStepChange).toHaveBeenCalledWith({state: 'something'});
+ expect(controller.$state.go).not.toHaveBeenCalledWith("something");
+ });
+
+ it(`should call the onStepChange method then return true and finally call the go method`, () => {
+ controller.onStepChange = jasmine.createSpy(controller, 'onStepChange').and.returnValue(true);
+ spyOn(controller.$state, 'go');
+
+ controller.currentState = "something";
+
+ expect(controller.onStepChange).toHaveBeenCalledWith({state: 'something'});
+ expect(controller.$state.go).toHaveBeenCalledWith("something");
+ });
+ });
+
+ describe('currentStepIndex()', () => {
+ it('should get the current state index from an Array of states', () => {
+ controller.$state.current.name = 'iam_a_current_state';
+ controller.steps = [{state: 'iam_not_current_state'}, {state: 'iam_a_current_state'}];
+
+ let result = controller.currentStepIndex;
+ expect(result).toEqual(1);
+ });
+ });
+});
diff --git a/client/core/src/components/step-control/style.scss b/client/core/src/components/step-control/style.scss
new file mode 100644
index 000000000..085801634
--- /dev/null
+++ b/client/core/src/components/step-control/style.scss
@@ -0,0 +1,58 @@
+vn-step-control {
+ display: flex;
+ justify-content: center;
+
+ .step-control {
+ border-top: 2px solid rgb(255,152,0);
+ margin-bottom: 15px;
+
+ & > .steps {
+ display: flex;
+ flex-direction: row
+ }
+
+ & > .steps > .step {
+ justify-content: center;
+ min-width: 125px;
+ display: flex;
+ flex: auto
+ }
+
+ & > .steps > .step .circle {
+ border: 2px solid rgb(255,152,0);
+ background-color: #FFF;
+ align-content: center;
+ margin-top: -9.5px;
+ -moz-border-radius: 50%;
+ -webkit-border-radius: 50%;
+ border-radius: 50%;
+ cursor: pointer;
+ height: 15px;
+ width: 15px
+ }
+
+ & > .steps > .step .circle.active {
+ background-color: rgb(255,152,0);
+ }
+
+ & > .buttons {
+ display: flex;
+ flex: auto;
+ flex-direction: row;
+ justify-content: space-between;
+ margin-top: 10px
+ }
+
+ & > .buttons > .step {
+ display: flex
+ }
+
+ & > .buttons > .step > .mdl-button {
+ line-height: 32px;
+ font-size: 12px;
+ padding: 0 12px;
+ height: 32px
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/client/core/src/locale/en.yml b/client/core/src/locale/en.yml
index a89a8ca8d..1c72342dd 100644
--- a/client/core/src/locale/en.yml
+++ b/client/core/src/locale/en.yml
@@ -7,4 +7,7 @@ Add: Add
Search: Search
Show More: Show More
No more results: No more results
-Hide: Hide
\ No newline at end of file
+Hide: Hide
+Next: Next
+Finalize: Finalize
+Previous: Back
\ No newline at end of file
diff --git a/client/core/src/locale/es.yml b/client/core/src/locale/es.yml
index 2b6386570..0f6d87d9f 100644
--- a/client/core/src/locale/es.yml
+++ b/client/core/src/locale/es.yml
@@ -7,4 +7,7 @@ Add: Añadir
Search: Buscar
Show More: Ver más
No more results: No hay más resultados
-Hide: Ocultar
\ No newline at end of file
+Hide: Ocultar
+Next: Siguiente
+Finalize: Finalizar
+Previous: Anterior
\ No newline at end of file
diff --git a/client/ticket/src/data/step-one/step-one.html b/client/ticket/src/data/step-one/step-one.html
index 9972c660b..9b07d94a5 100644
--- a/client/ticket/src/data/step-one/step-one.html
+++ b/client/ticket/src/data/step-one/step-one.html
@@ -1,4 +1,4 @@
-
diff --git a/client/ticket/src/data/step-one/step-one.js b/client/ticket/src/data/step-one/step-one.js
index 3db7aa4b0..87776169e 100644
--- a/client/ticket/src/data/step-one/step-one.js
+++ b/client/ticket/src/data/step-one/step-one.js
@@ -1,22 +1,17 @@
import ngModule from '../../module';
class Controller {
- constructor($scope, $timeout, $state) {
+ constructor($scope) {
this.$scope = $scope;
- this.$timeout = $timeout;
- this.$state = $state;
- }
- onSubmit() {
- this.$state.go('ticket.card.data.stepTwo');
}
}
-Controller.$inject = ['$scope', '$timeout', '$state'];
+Controller.$inject = ['$scope'];
ngModule.component('vnTicketDataStepOne', {
template: require('./step-one.html'),
+ controller: Controller,
bindings: {
ticket: '<'
- },
- controller: Controller
+ }
});
diff --git a/client/ticket/src/data/step-three/step-three.html b/client/ticket/src/data/step-three/step-three.html
index e69de29bb..472bf468d 100644
--- a/client/ticket/src/data/step-three/step-three.html
+++ b/client/ticket/src/data/step-three/step-three.html
@@ -0,0 +1,8 @@
+
diff --git a/client/ticket/src/data/step-three/step-three.js b/client/ticket/src/data/step-three/step-three.js
index e69de29bb..2dde82cfe 100644
--- a/client/ticket/src/data/step-three/step-three.js
+++ b/client/ticket/src/data/step-three/step-three.js
@@ -0,0 +1,15 @@
+import ngModule from '../../module';
+
+class Controller {
+ constructor($scope) {
+ this.$scope = $scope;
+ }
+}
+
+ngModule.component('vnTicketDataStepThree', {
+ template: require('./step-three.html'),
+ controller: Controller,
+ bindings: {
+ ticket: '<'
+ }
+});
diff --git a/client/ticket/src/data/step-two/step-two.html b/client/ticket/src/data/step-two/step-two.html
index e69de29bb..a1c5d3c0d 100644
--- a/client/ticket/src/data/step-two/step-two.html
+++ b/client/ticket/src/data/step-two/step-two.html
@@ -0,0 +1,29 @@
+
diff --git a/client/ticket/src/data/step-two/step-two.js b/client/ticket/src/data/step-two/step-two.js
index e69de29bb..244828304 100644
--- a/client/ticket/src/data/step-two/step-two.js
+++ b/client/ticket/src/data/step-two/step-two.js
@@ -0,0 +1,28 @@
+import ngModule from '../../module';
+
+class Controller {
+ constructor($http, $scope) {
+ this.$http = $http;
+ this.$scope = $scope;
+ }
+
+ $onChanges(data) {
+ if (!this.ticket || !this.ticket.id) return;
+
+ let query = `/ticket/api/sales/${this.ticket.id}/priceGap`;
+ this.$http.get(query).then(res => {
+ if (res.data)
+ this.ticket.sales = res.data;
+ });
+ }
+}
+
+Controller.$inject = ['$http', '$scope'];
+
+ngModule.component('vnTicketDataStepTwo', {
+ template: require('./step-two.html'),
+ controller: Controller,
+ bindings: {
+ ticket: '<'
+ }
+});
diff --git a/services/db/04-fixtures.sql b/services/db/04-fixtures.sql
index 039b879bb..83662e7d0 100644
--- a/services/db/04-fixtures.sql
+++ b/services/db/04-fixtures.sql
@@ -151,6 +151,13 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
(109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 0, 1, NULL, 0, 0, 19, 0, 1),
(110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 0, 1, NULL, 0, 0, NULL, 0, 1);
+INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
+ VALUES
+ ( 101, 50, CURDATE()),
+ ( 102, 100, CURDATE()),
+ ( 103, 0, CURDATE()),
+ ( 104, -30, CURDATE());
+
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `isDefaultAddress`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`)
VALUES
(101, '01', 'Somewhere in Thailand', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0),
@@ -537,7 +544,7 @@ INSERT INTO `bi`.`rotacion`(`Id_Article`, `warehouse_id`, `total`, `rotacion`, `
INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`)
VALUES
- ( 101, 0),
+ ( 101, 1500),
( 102, 100),
( 103, 1000),
( 104, 500),
diff --git a/services/db/changes/1.0.3/01-ticketVolume.sql b/services/db/changes/1.0.3/01-ticketVolume.sql
new file mode 100644
index 000000000..89cebb67e
--- /dev/null
+++ b/services/db/changes/1.0.3/01-ticketVolume.sql
@@ -0,0 +1,29 @@
+USE `vn`;
+DROP procedure IF EXISTS `ticketVolume`;
+
+DELIMITER $$
+USE `vn`$$
+CREATE DEFINER=`root`@`%` PROCEDURE `ticketVolume`(IN vTicketId INT)
+BEGIN
+ DECLARE vWarehouseId INTEGER;
+ DECLARE vShippedDate DATE;
+
+ DROP TEMPORARY TABLE IF EXISTS ticketVolume;
+ SELECT warehouseFk, shipped INTO vWarehouseId,vShippedDate FROM vn.ticket WHERE id = vTicketId;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS ticketVolume ENGINE MEMORY
+
+ SELECT itemFk, saleFk, quantity, concept, VolUd as m3_uni, volume as m3, volume * quantity as volumeTimesQuantity, @m3:= @m3 + ifnull(volume,0) as m3_total
+ FROM
+ (
+ SELECT round(r.cm3 / 1000000,3) as VolUd ,s.quantity, round(r.cm3 * s.quantity / 1000000,3) as volume,
+ s.itemFk, s.id AS saleFk, s.concept, @m3:= 0, @vol:=0, t.agencyModeFk
+ FROM sale s
+ JOIN vn.ticket t on t.id = s.ticketFk
+ JOIN bi.rotacion r ON r.Id_Article = s.itemFk AND r.warehouse_id = t.warehouseFk
+ WHERE s.ticketFk = vTicketId
+ ) sub;
+END$$
+
+DELIMITER ;
+
diff --git a/services/loopback/common/methods/client/specs/getAverageInvoiced.spec.js b/services/loopback/common/methods/client/specs/getAverageInvoiced.spec.js
index 0775423e0..a27e9a848 100644
--- a/services/loopback/common/methods/client/specs/getAverageInvoiced.spec.js
+++ b/services/loopback/common/methods/client/specs/getAverageInvoiced.spec.js
@@ -11,7 +11,7 @@ describe('client getAverageInvoiced()', () => {
it('should call the getAverageInvoiced method', done => {
model.getAverageInvoiced(101)
.then(response => {
- expect(response.invoiced).toEqual(0);
+ expect(response.invoiced).toEqual(1500);
done();
});
});
diff --git a/services/loopback/common/methods/client/specs/getMana.spec.js b/services/loopback/common/methods/client/specs/getMana.spec.js
index 942eaaca0..731c7a021 100644
--- a/services/loopback/common/methods/client/specs/getMana.spec.js
+++ b/services/loopback/common/methods/client/specs/getMana.spec.js
@@ -11,7 +11,7 @@ describe('client getMana()', () => {
it('should call the getMana method', done => {
model.getMana(101)
.then(response => {
- expect(response.mana).toEqual(0);
+ expect(response.mana).toEqual(30.02);
done();
});
});
diff --git a/services/loopback/common/methods/sale/priceGap.js b/services/loopback/common/methods/sale/price-gap.js
similarity index 100%
rename from services/loopback/common/methods/sale/priceGap.js
rename to services/loopback/common/methods/sale/price-gap.js
diff --git a/services/ticket/common/methods/sale/saleComponentFilter.js b/services/loopback/common/methods/sale/saleComponentFilter.js
similarity index 100%
rename from services/ticket/common/methods/sale/saleComponentFilter.js
rename to services/loopback/common/methods/sale/saleComponentFilter.js
diff --git a/services/loopback/common/models/sale.js b/services/loopback/common/models/sale.js
index a5189ea26..5d452295d 100644
--- a/services/loopback/common/models/sale.js
+++ b/services/loopback/common/models/sale.js
@@ -1,4 +1,5 @@
module.exports = function(Self) {
require('../methods/sale/filter')(Self);
- require('../methods/sale/priceGap')(Self);
+ require('../methods/sale/saleComponentFilter.js')(Self);
+ require('../methods/sale/price-gap')(Self);
};
diff --git a/services/loopback/common/models/sale.json b/services/loopback/common/models/sale.json
index fec1f2dd9..9466549da 100644
--- a/services/loopback/common/models/sale.json
+++ b/services/loopback/common/models/sale.json
@@ -1,38 +1,38 @@
{
- "name": "Sale",
- "base": "VnModel",
- "options": {
- "mysql": {
- "table": "sale"
- }
+ "name": "Sale",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "sale"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "Number",
+ "description": "Identifier"
},
- "properties": {
- "id": {
- "id": true,
- "type": "Number",
- "description": "Identifier"
- },
- "concept": {
- "type": "String"
- },
- "quantity": {
- "type": "Number"
- },
- "price": {
- "type": "Number"
- },
- "discount": {
- "type": "Number"
- },
- "reserved": {
- "type": "Number"
- },
- "isPicked": {
- "type": "Number"
- },
- "created": {
- "type": "date"
- }
+ "concept": {
+ "type": "String"
+ },
+ "quantity": {
+ "type": "Number"
+ },
+ "price": {
+ "type": "Number"
+ },
+ "discount": {
+ "type": "Number"
+ },
+ "reserved": {
+ "type": "Number"
+ },
+ "isPicked": {
+ "type": "Number"
+ },
+ "created": {
+ "type": "date"
+ }
},
"relations": {
"item": {
@@ -51,6 +51,11 @@
"type": "hasOne",
"model": "SaleChecked",
"foreignKey": "saleFk"
- }
+ },
+ "components": {
+ "type": "hasMany",
+ "model": "SaleComponent",
+ "foreignKey": "saleFk"
+ }
}
}
diff --git a/services/ticket/common/methods/sale/filter.js b/services/ticket/common/methods/sale/filter.js
deleted file mode 100644
index f9b6304f6..000000000
--- a/services/ticket/common/methods/sale/filter.js
+++ /dev/null
@@ -1,39 +0,0 @@
-module.exports = Self => {
- Self.installMethod('filter', filterParams);
-
- function filterParams(params) {
- return {
- where: {
- ticketFk: params.ticketFk
- },
- skip: (params.page - 1) * params.size,
- limit: params.size,
- order: params.order || 'concept ASC',
- include: [{
- relation: "item",
- scope: {
- include: {
- relation: "itemTag",
- scope: {
- fields: ["tagFk", "value"],
- include: {
- relation: "tag",
- scope: {
- fields: ["name"]
- }
- },
- limit: 6
- }
- },
- fields: ["itemFk", "name"]
- }
- },
- {
- relation: "isChecked",
- scope: {
- fields: ["isChecked"]
- }
- }]
- };
- }
-};
diff --git a/services/ticket/common/models/sale.js b/services/ticket/common/models/sale.js
deleted file mode 100644
index c8afd2123..000000000
--- a/services/ticket/common/models/sale.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = function(Self) {
- require('../methods/sale/filter.js')(Self);
- require('../methods/sale/saleComponentFilter.js')(Self);
-};
diff --git a/services/ticket/common/models/sale.json b/services/ticket/common/models/sale.json
deleted file mode 100644
index 529329613..000000000
--- a/services/ticket/common/models/sale.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "name": "Sale",
- "base": "VnModel",
- "options": {
- "mysql": {
- "table": "sale"
- }
- },
- "properties": {
- "id": {
- "id": true,
- "type": "Number",
- "description": "Identifier"
- },
- "concept": {
- "type": "String"
- },
- "quantity": {
- "type": "Number"
- },
- "price": {
- "type": "Number"
- },
- "discount": {
- "type": "Number"
- },
- "reserved": {
- "type": "Number"
- },
- "isPicked": {
- "type": "Number"
- },
- "created": {
- "type": "date"
- }
- },
- "relations": {
- "item": {
- "type": "belongsTo",
- "model": "Item",
- "foreignKey": "itemFk",
- "required": true
- },
- "ticket": {
- "type": "belongsTo",
- "model": "Ticket",
- "foreignKey": "ticketFk",
- "required": true
- },
- "isChecked": {
- "type": "hasOne",
- "model": "SaleChecked",
- "foreignKey": "saleFk"
- },
- "components": {
- "type": "hasMany",
- "model": "SaleComponent",
- "foreignKey": "saleFk"
- }
- }
-}
diff --git a/services/ticket/server/model-config.json b/services/ticket/server/model-config.json
index bb5715e73..eccd5dae5 100644
--- a/services/ticket/server/model-config.json
+++ b/services/ticket/server/model-config.json
@@ -5,9 +5,6 @@
"ObservationType": {
"dataSource": "vn"
},
- "Sale": {
- "dataSource": "vn"
- },
"TicketTracking": {
"dataSource": "vn"
},