Merge branch 'dev' of http://git.verdnatura.es/salix into dev

This commit is contained in:
Carlos Jimenez 2018-08-08 09:07:39 +02:00
commit 68a3a47894
26 changed files with 651 additions and 64 deletions

View File

@ -66,7 +66,7 @@ export default class Controller extends Component {
let shape = this.createShape(data); let shape = this.createShape(data);
setTimeout(() => setTimeout(() =>
this.hide(shape), data.timeout || 6000); this.hide(shape), data.timeout || 3000);
setTimeout(() => setTimeout(() =>
shape.classList.add('shown'), 30); shape.classList.add('shown'), 30);

View File

@ -1,31 +1,32 @@
@import "colors"; @import "colors";
vn-snackbar #shapes { vn-snackbar #shapes {
position: fixed;
bottom: 0;
right: 15px;
width: 20em;
max-height: 20.625em; max-height: 20.625em;
margin-left: -12.5em;
position: fixed;
z-index: 100; z-index: 100;
width: 25em;
left: 50%;
bottom: 0
} }
vn-snackbar .shape { vn-snackbar .shape {
box-sizing: border-box;
background-color: rgba(1, 1, 1, 0.8); background-color: rgba(1, 1, 1, 0.8);
box-shadow: 0 0 .4em rgba(1,1,1,.4);
transition: transform 300ms ease-in-out;
transform: translateY(20em);
box-sizing: border-box;
border-radius: .2em;
margin-bottom: 15px;
color: white; color: white;
padding: 1em; padding: 1em;
border-radius: .2em;
box-shadow: 0 0 .4em rgba(1,1,1,.4);
margin-bottom: 15px;
transform: translateX(20em);
transition: transform 300ms ease-in-out;
&.text { &.text {
text-align: center text-align: center
} }
&.shown { &.shown {
transform: translateX(0); transform: translateY(0);
} }
&.success { &.success {
@ -46,15 +47,15 @@ vn-snackbar .shape {
} }
& > button { & > button {
cursor: pointer;
float: right;
text-transform: uppercase;
border: none;
background-color: transparent; background-color: transparent;
font-weight: bold; text-transform: uppercase;
color: $main-01;
padding: .5em;
margin: -.5em;
margin-left: .5em; margin-left: .5em;
font-weight: bold;
cursor: pointer;
color: $main-01;
float: right;
border: none;
padding: .5em;
margin: -.5em
} }
} }

View File

@ -57,6 +57,18 @@
"icon": "icon-volume" "icon": "icon-volume"
} }
}, },
{
"url": "/line",
"state": "order.card.line",
"component": "vn-order-line",
"description": "Lines",
"params": {
"order": "$ctrl.order"
},
"menu": {
"icon": "icon-lines"
}
},
{ {
"url": "/create", "url": "/create",
"state": "order.create", "state": "order.create",

View File

@ -7,6 +7,8 @@ import './index/';
import './summary'; import './summary';
import './catalogue'; import './catalogue';
import './catalogue/product'; import './catalogue/product';
import './line';
//import './prices-popover';
import './volume'; import './volume';
import './create'; import './create';
import './create/card'; import './create/card';

View File

@ -0,0 +1,82 @@
<vn-watcher
vn-id="watcher"
data="$ctrl.rows">
</vn-watcher>
<vn-vertical>
<vn-card pad-large>
<vn-vertical>
<vn-horizontal>
<vn-title vn-two>Sale</vn-title>
<div class="totalBox">
<vn-label translate>Subtotal</vn-label>
<span>{{$ctrl.order.total - $ctrl.VAT | currency:'€':2}}</span>
<p>
<vn-label translate>VAT</vn-label>
<span>{{$ctrl.VAT | currency:'€':2}}</span>
</p>
<vn-label><strong>Total</strong></vn-label>
<strong>{{$ctrl.order.total | currency:'€':2}}</strong>
</div>
</vn-horizontal>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th style="text-align: center">Item</vn-th>
<vn-th style="text-align: center">ID</vn-th>
<vn-th>Description</vn-th>
<vn-th>Warehouse</vn-th>
<vn-th>Shipped</vn-th>
<vn-th number>Quantity</vn-th>
<vn-th number>Price</vn-th>
<vn-th ng-if="!$ctrl.order.isConfirmed"></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="row in $ctrl.rows">
<vn-td style="text-align: center">
<img
ng-src="//verdnatura.es/vn-image-data/catalog/50x50/{{::row.item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{::row.item.image}}"
on-error-src/>
</vn-td>
<vn-td ng-click="$ctrl.showDescriptor($event, row.itemFk)"
pointer number class="link">
{{("000000"+row.itemFk).slice(-6)}}
</vn-td>
<vn-td><vn-fetched-tags concept="row.item.name" tags="row.item.tags"/></vn-td>
<vn-td>{{row.warehouse.name}}</vn-td>
<vn-td>{{row.shipped | dashIfEmpty}}</vn-td>
<vn-td number>{{row.quantity}}</vn-td>
<vn-td number>
{{row.price | currency:'€':2}}
</vn-td>
<vn-td ng-if="!$ctrl.order.isConfirmed">
<vn-icon-button
medium-grey
vn-tooltip="Remove item"
icon="remove_circle_outline"
ng-click="$ctrl.removeRow($index)"
tabindex="-1">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="$ctrl.rows.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-vertical>
</vn-card>
<vn-button-bar ng-if="!$ctrl.order.isConfirmed">
<vn-button
label="Save"
ng-click="$ctrl.save()">
</vn-button>
</vn-button-bar>
</vn-vertical>
<vn-item-descriptor-popover
vn-id="descriptor">
</vn-item-descriptor-popover>

View File

@ -0,0 +1,95 @@
import ngModule from '../module';
import './style.scss';
class Controller {
constructor($scope, $state, $http, vnApp, $translate) {
this.$scope = $scope;
this.vnApp = vnApp;
this.$translate = $translate;
this.$state = $state;
this.$http = $http;
this.idsToRemove = [];
}
$onInit() {
this.getRows();
this.getVAT();
}
getRows() {
let filter = {
where: {orderFk: this.$state.params.id},
include: [{
relation: 'item',
scope: {
include: {
relation: 'tags',
scope: {
fields: ['tagFk', 'value'],
include: {
relation: 'tag',
scope: {
fields: ['name']
}
}
}
},
fields: ['itemFk', 'name', 'image']
}
},
{relation: 'warehouse'}]
};
filter = encodeURIComponent(JSON.stringify(filter));
let query = `/order/api/OrderRows?filter=${filter}`;
this.$http.get(query).then(res => {
this.rows = res.data;
});
}
getVAT() {
let query = `/order/api/Orders/${this.$state.params.id}/getTaxes`;
this.$http.get(query).then(res => {
this.VAT = res.data.tax;
});
}
removeRow(index) {
let [lineRemoved] = this.rows.splice(index, 1);
this.idsToRemove.push(lineRemoved.id);
}
// Item Descriptor
showDescriptor(event, itemFk) {
this.$scope.descriptor.itemFk = itemFk;
this.$scope.descriptor.parent = event.target;
this.$scope.descriptor.show();
}
onDescriptorLoad() {
this.$scope.popover.relocate();
}
save() {
let params = {
rows: this.idsToRemove,
actualOrderId: this.$state.params.id
};
let query = `/order/api/OrderRows/removes`;
this.$http.post(query, params).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
}
}
Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate'];
ngModule.component('vnOrderLine', {
template: require('./index.html'),
controller: Controller,
bindings: {
order: '<'
}
});

View File

@ -0,0 +1,109 @@
import './index.js';
describe('Order', () => {
describe('Component vnOrderLine', () => {
let $componentController;
let $state;
let controller;
let $httpBackend;
beforeEach(() => {
angular.mock.module('order');
});
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
$componentController = _$componentController_;
$state = _$state_;
$state = {params: {id: 1}};
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
controller = $componentController('vnOrderLine', {$state: $state});
controller.rows = [{id: 1}];
controller.$scope.popover = {relocate: () => {}};
controller.$scope.descriptor = {show: () => {}};
controller.vnApp = {showSuccess: () => {}};
}));
describe('getRows()', () => {
it('should make a query to get the rows of a given order', () => {
let filter = {
where: {orderFk: controller.$state.params.id},
include: [{
relation: 'item',
scope: {
include: {
relation: 'tags',
scope: {
fields: ['tagFk', 'value'],
include: {
relation: 'tag',
scope: {
fields: ['name']
}
}
}
},
fields: ['itemFk', 'name', 'image']
}
},
{relation: 'warehouse'}]
};
filter = encodeURIComponent(JSON.stringify(filter));
$httpBackend.expectGET(`/order/api/OrderRows?filter=${filter}`).respond({data: [{id: 1}]});
controller.getRows();
$httpBackend.flush();
});
});
describe('getTaxes()', () => {
it('should make a query to get the taxes of a given order', () => {
$httpBackend.expectGET(`/order/api/Orders/1/getTaxes`).respond({data: {tax: 3}});
controller.getVAT();
$httpBackend.flush();
});
});
describe('removeRow()', () => {
it('should remove a row from rows and add his id to idsRemoved', () => {
controller.removeRow(0);
expect(controller.rows.length).toBe(0);
expect(controller.idsToRemove[0]).toBe(1);
});
});
describe('showDescriptor()', () => {
it('should set $scope.descriptor.itemFk, $scope.descriptor.parent and call $scope.descriptor.show()', () => {
let event = {target: 1};
let itemFk = 1;
spyOn(controller.$scope.descriptor, 'show');
controller.showDescriptor(event, itemFk);
expect(controller.$scope.descriptor.itemFk).toBe(1);
expect(controller.$scope.descriptor.parent).toBe(1);
expect(controller.$scope.descriptor.show).toHaveBeenCalledWith();
});
});
describe('onDescriptorLoad()', () => {
it('should call $scope.popover.relocate()', () => {
spyOn(controller.$scope.popover, 'relocate');
controller.onDescriptorLoad();
expect(controller.$scope.popover.relocate).toHaveBeenCalledWith();
});
});
describe('save()', () => {
it('should make a query to remove the selected rows and call vnApp.showSuccess', () => {
spyOn(controller.vnApp, 'showSuccess');
$httpBackend.expectPOST(`/order/api/OrderRows/removes`).respond();
controller.save();
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
});
});

View File

@ -0,0 +1 @@
Remove item: Eliminar articulo

View File

@ -0,0 +1,8 @@
vn-order-line{
vn-table {
img {
border-radius: 50%;
max-width: 50px;
}
}
}

View File

@ -0,0 +1,64 @@
import './index';
describe('Order', () => {
describe('Component vnOrderVolume', () => {
let $componentController;
let controller;
let $httpBackend;
let $state;
let $scope;
beforeEach(() => {
angular.mock.module('order');
});
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
$scope = $rootScope.$new();
$scope.model = {data: [{itemFk: 1}, {itemFk: 2}], accept: () => {
return {
then: () => {}
};
}};
$scope.descriptor = {show: () => {}};
$scope.popover = {relocate: () => {}};
$state = _$state_;
$state.params.id = 1;
controller = $componentController('vnOrderVolume', {$scope: $scope}, {$httpBackend: $httpBackend}, {$state: $state});
}));
it('should join the sale volumes to its respective sale', () => {
let response = {volumes: [{itemFk: 1, volume: 0.008}, {itemFk: 2, volume: 0.003}]};
$httpBackend.whenGET(`/order/api/Orders/1/getVolumes`).respond(response);
$httpBackend.expectGET(`/order/api/Orders/1/getVolumes`);
controller.onDataChange();
$httpBackend.flush();
expect(controller.$scope.model.data[0].volume).toBe(0.008);
expect(controller.$scope.model.data[1].volume).toBe(0.003);
});
describe('showDescriptor()', () => {
it('should set $scope.descriptor.itemFk, $scope.descriptor.parent and call $scope.descriptor.show()', () => {
let event = {target: 1};
let itemFk = 1;
spyOn(controller.$scope.descriptor, 'show');
controller.showDescriptor(event, itemFk);
expect(controller.$scope.descriptor.itemFk).toBe(1);
expect(controller.$scope.descriptor.parent).toBe(1);
expect(controller.$scope.descriptor.show).toHaveBeenCalledWith();
});
});
describe('onDescriptorLoad()', () => {
it('should call $scope.popover.relocate()', () => {
spyOn(controller.$scope.popover, 'relocate');
controller.onDescriptorLoad();
expect(controller.$scope.popover.relocate).toHaveBeenCalledWith();
});
});
});
});

View File

@ -27,7 +27,7 @@ input[type=reset]::-moz-focus-inner
.totalBox { .totalBox {
border: 1px solid #CCC; border: 1px solid #CCC;
text-align: left; text-align: right!important;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 18px; padding: 18px;

View File

@ -228,7 +228,7 @@
label="Price" label="Price"
model="$ctrl.editedPrice" model="$ctrl.editedPrice"
type="text" type="text"
accept="$ctrl.updatePrice()"> on-change="$ctrl.updatePrice()">
<t-right-icons> <t-right-icons>
<span class="filter"></span> <span class="filter"></span>
</t-right-icons> </t-right-icons>

View File

@ -309,6 +309,9 @@ class Controller {
this.$http.post(`/ticket/api/Sales/${id}/updateQuantity`, {quantity: parseInt(quantity)}).then(() => { this.$http.post(`/ticket/api/Sales/${id}/updateQuantity`, {quantity: parseInt(quantity)}).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$scope.model.refresh(); this.$scope.model.refresh();
}).catch(e => {
this.vnApp.showError(e.data.error.message);
this.$scope.model.refresh();
}); });
} }

View File

@ -326,29 +326,29 @@ INSERT INTO `vn`.`invoiceOut`(`id`, `ref`, `serial`, `amount`, `issued`,`clientF
( 4, 'E4444444' , 'E', 290.30 , DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 8, 1), ( 4, 'E4444444' , 'E', 290.30 , DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 8, 1),
( 5, 'E5555555' , 'E', 190.30 , DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 8, 1); ( 5, 'E5555555' , 'E', 190.30 , DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 8, 1);
INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`) INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`)
VALUES VALUES
(1 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -15 DAY) , DATE_ADD(CURDATE(), INTERVAL -15 DAY) , 101, 'Batman', 121, NULL), (1 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -15 DAY) , DATE_ADD(CURDATE(), INTERVAL -15 DAY) , 101, 'Batman', 121, NULL, 0),
(2 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -10 DAY) , DATE_ADD(CURDATE(), INTERVAL -10 DAY) , 101, 'Spider-Man', 121, NULL), (2 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -10 DAY) , DATE_ADD(CURDATE(), INTERVAL -10 DAY) , 101, 'Spider-Man', 121, NULL, 0),
(3 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -5 DAY) , DATE_ADD(CURDATE(), INTERVAL -5 DAY) , 102, 'Super-Man', 122, NULL), (3 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -5 DAY) , DATE_ADD(CURDATE(), INTERVAL -5 DAY) , 102, 'Super-Man', 122, NULL, 0),
(4 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -4 DAY) , DATE_ADD(CURDATE(), INTERVAL -4 DAY) , 102, 'Iron-Man', 122, NULL), (4 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -4 DAY) , DATE_ADD(CURDATE(), INTERVAL -4 DAY) , 102, 'Iron-Man', 122, NULL, 0),
(5 , 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -3 DAY) , DATE_ADD(CURDATE(), INTERVAL -3 DAY) , 103, 'Magneto', 123, NULL), (5 , 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -3 DAY) , DATE_ADD(CURDATE(), INTERVAL -3 DAY) , 103, 'Magneto', 123, NULL, 0),
(6 , 3, 3, 4, DATE_ADD(CURDATE(), INTERVAL -2 DAY) , DATE_ADD(CURDATE(), INTERVAL -2 DAY) , 103, 'Legion', 123, NULL), (6 , 3, 3, 4, DATE_ADD(CURDATE(), INTERVAL -2 DAY) , DATE_ADD(CURDATE(), INTERVAL -2 DAY) , 103, 'Legion', 123, NULL, 0),
(7 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 DAY) , DATE_ADD(CURDATE(), INTERVAL -1 DAY) , 104, 'Ant-Man', 124, NULL), (7 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 DAY) , DATE_ADD(CURDATE(), INTERVAL -1 DAY) , 104, 'Ant-Man', 124, NULL, 0),
(8 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 104, 'Professor X', 124, NULL), (8 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 104, 'Professor X', 124, NULL, 0),
(9 , 5, 5, 4, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 105, 'Hulk', 125, NULL), (9 , 5, 5, 4, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 105, 'Hulk', 125, NULL, 0),
(10, 6, 5, 5, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 105, 'Jessica Jones', 125, NULL), (10, 6, 5, 5, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 105, 'Jessica Jones', 125, NULL, 0),
(11, 7, 1, 1, CURDATE() , CURDATE() , 101, 'ticket 1', 121, NULL), (11, 7, 1, 1, CURDATE() , CURDATE() , 101, 'ticket 1', 121, NULL, 0),
(12, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 101, 'ticket 2', 121, NULL), (12, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 101, 'ticket 2', 121, NULL, 0),
(13, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +2 MONTH), DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 101, 'ticket 3', 121, NULL), (13, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +2 MONTH), DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 101, 'ticket 3', 121, NULL, 0),
(14, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +3 MONTH), DATE_ADD(CURDATE(), INTERVAL +3 MONTH), 101, 'ticket 4', 121, NULL), (14, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +3 MONTH), DATE_ADD(CURDATE(), INTERVAL +3 MONTH), 101, 'ticket 4', 121, NULL, 0),
(15, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL +4 MONTH), DATE_ADD(CURDATE(), INTERVAL +4 MONTH), 101, 'ticket 5', 121, NULL), (15, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL +4 MONTH), DATE_ADD(CURDATE(), INTERVAL +4 MONTH), 101, 'ticket 5', 121, NULL, 0),
(16, 3, 3, 4, CURDATE() , CURDATE() , 101, 'ticket 6', 121, NULL), (16, 3, 3, 4, CURDATE() , CURDATE() , 101, 'ticket 6', 121, NULL, 0),
(17, 4, 4, 4, CURDATE() , CURDATE() , 106, 'ticket 7', 126, NULL), (17, 4, 4, 4, CURDATE() , CURDATE() , 106, 'ticket 7', 126, NULL, 0),
(18, 4, 4, 4, CURDATE() , CURDATE() , 107, 'ticket 8', 127, NULL), (18, 4, 4, 4, CURDATE() , CURDATE() , 107, 'ticket 8', 127, NULL, 0),
(19, 5, 5, 4, CURDATE() , CURDATE() , 108, 'ticket 9', 128, NULL), (19, 5, 5, 4, CURDATE() , CURDATE() , 108, 'ticket 9', 128, NULL, 0),
(20, 5, 5, 4, CURDATE() , CURDATE() , 109, 'ticket 10', 119, NULL), (20, 5, 5, 4, CURDATE() , CURDATE() , 109, 'ticket 10', 119, NULL, 0),
(21, 5, 5, 4, CURDATE() , CURDATE() , 110, 'ticket 11', 129, NULL); (21, 5, 5, 4, CURDATE() , CURDATE() , 110, 'ticket 11', 129, NULL, 1);
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES VALUES
@ -378,7 +378,7 @@ INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `crea
(18, 18, 1 , 19, CURDATE()), (18, 18, 1 , 19, CURDATE()),
(19, 19, 13, 19, CURDATE()), (19, 19, 13, 19, CURDATE()),
(20, 20, 15, 19, CURDATE()), (20, 20, 15, 19, CURDATE()),
(21, 21, 16, 19, CURDATE()); (21, 21, 3 , 19, CURDATE());
INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`) INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`)
VALUES VALUES

View File

@ -38,5 +38,6 @@
"You don't have enough privileges to change the state of this ticket": "No tienes permisos para cambiar el estado de este ticket", "You don't have enough privileges to change the state of this ticket": "No tienes permisos para cambiar el estado de este ticket",
"The new quantity should be smaller than the old one": "La nueva cantidad debe de ser menor que la anterior", "The new quantity should be smaller than the old one": "La nueva cantidad debe de ser menor que la anterior",
"The value should not be greater than 100%": "El valor no debe de ser mayor de 100%", "The value should not be greater than 100%": "El valor no debe de ser mayor de 100%",
"The value should be a number": "El valor debe ser un numero" "The value should be a number": "El valor debe ser un numero",
"This order is not editable": "Esta orden no se puede modificar"
} }

View File

@ -0,0 +1,27 @@
const app = require(`${servicesDir}/ticket/server/server`);
describe('ticket isEditable()', () => {
it('should return false if the ticket given is not editable', async() => {
let result = await app.models.Ticket.isEditable(2);
expect(result).toEqual(false);
});
it('should return false if the ticket given does not exists', async() => {
let result = await app.models.Ticket.isEditable(99999);
expect(result).toEqual(false);
});
it('should return false if the ticket given isDeleted', async() => {
let result = await app.models.Ticket.isEditable(21);
expect(result).toEqual(false);
});
it('should return true if the ticket given is editable', async() => {
let result = await app.models.Ticket.isEditable(1);
expect(result).toEqual(true);
});
});

View File

@ -0,0 +1,3 @@
{
"This order is not editable": "Esta orden no se puede editar"
}

View File

@ -0,0 +1,36 @@
const UserError = require('vn-loopback/common/helpers').UserError;
module.exports = Self => {
Self.remoteMethod('removes', {
description: 'Delete an Order Row',
accessType: '',
accepts: [{
arg: 'params',
type: 'object',
required: true,
description: '[Row IDs], actualOrderId',
http: {source: 'body'}
}],
returns: {
type: 'string',
root: true
},
http: {
path: `/removes`,
verb: 'post'
}
});
Self.removes = async params => {
if (!params.rows || !params.rows.length)
throw new Error('There is nothing delete');
await Self.app.models.Order.isEditable(params.actualOrderId);
let promises = [];
for (let i = 0; i < params.rows.length; i++) {
promises.push(Self.app.models.OrderRow.destroyById(params.rows[i]));
}
return await Promise.all(promises);
};
};

View File

@ -0,0 +1,25 @@
const app = require(`../../../../server/server`);
describe('order removes()', () => {
it('should throw an error if rows property is empty', async() => {
let error;
try {
await app.models.OrderRow.removes({rows: []});
} catch (e) {
error = e;
}
expect(error).toEqual(new Error('There is nothing delete'));
});
it('should throw an error if the row selected is not editable', async() => {
let error;
try {
await app.models.OrderRow.removes({rows: [2]});
} catch (e) {
error = e;
}
expect(error).toEqual(new Error('This order is not editable'));
});
});

View File

@ -0,0 +1,30 @@
module.exports = Self => {
Self.remoteMethod('getTaxes', {
description: 'Gets the taxes of a given order',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'order id',
http: {source: 'path'}
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/:id/getTaxes`,
verb: 'GET'
}
});
Self.getTaxes = async orderFk => {
let query = `CALL hedera.orderGetTax(?);
SELECT * FROM tmp.orderTax;`;
let res = await Self.rawSql(query, [orderFk]);
let [taxes] = res[1];
return taxes;
};
};

View File

@ -0,0 +1,30 @@
const UserError = require('vn-loopback/common/helpers').UserError;
module.exports = Self => {
Self.remoteMethod('isEditable', {
description: 'Check if an order is editable',
accessType: 'READ',
accepts: [{
arg: 'orderId',
type: 'number',
required: true,
description: 'orderId',
http: {source: 'path'}
}],
returns: {
type: 'boolean',
root: true
},
http: {
path: `/:orderId/isEditable`,
verb: 'get'
}
});
Self.isEditable = async orderId => {
let exists = await Self.app.models.Order.findOne({where: {id: orderId}, fields: ['isConfirmed']});
if (!exists || exists.isConfirmed === 1)
throw new UserError('This order is not editable');
};
};

View File

@ -0,0 +1,21 @@
const app = require(`../../../../server/server`);
describe('order getTaxes()', () => {
it('should call the getTaxes method and return undefined if its called with a string', async() => {
let result = await app.models.Order.getTaxes('pepinillos');
expect(result).toEqual(undefined);
});
it('should call the getTaxes method and return undefined if its called with unknown id', async() => {
let result = await app.models.Order.getTaxes(99999999999999999999999);
expect(result).toEqual(undefined);
});
it('should call the getTaxes method and return the taxes if its called with a known id', async() => {
let result = await app.models.Order.getTaxes(1);
expect(result.tax).toEqual(0.95);
});
});

View File

@ -0,0 +1,26 @@
const app = require(`../../../../server/server`);
const UserError = require('vn-loopback/common/helpers').UserError;
describe('order isEditable()', () => {
it('should throw an error if the order given is not editable', async() => {
let error;
try {
await app.models.Order.isEditable(2);
} catch (e) {
error = e;
}
expect(error).toEqual(new UserError('This order is not editable'));
});
it('should throw an error if the order given does not exists', async() => {
let error;
try {
await app.models.Order.isEditable(99999);
} catch (e) {
error = e;
}
expect(error).toEqual(new UserError('This order is not editable'));
});
});

View File

@ -0,0 +1,4 @@
module.exports = Self => {
//require('../methods/order-row/new')(Self);
require('../methods/order-row/removes')(Self);
};

View File

@ -50,6 +50,11 @@
"type": "belongsTo", "type": "belongsTo",
"model": "Order", "model": "Order",
"foreignKey": "orderFk" "foreignKey": "orderFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
} }
} }
} }

View File

@ -2,6 +2,8 @@ module.exports = Self => {
require('../methods/order/new')(Self); require('../methods/order/new')(Self);
require('../methods/order/getTotalVolume')(Self); require('../methods/order/getTotalVolume')(Self);
require('../methods/order/getVolumes')(Self); require('../methods/order/getVolumes')(Self);
require('../methods/order/getTaxes')(Self);
require('../methods/order/isEditable')(Self);
require('../methods/order/getTotal')(Self); require('../methods/order/getTotal')(Self);
require('../methods/order/itemFilter')(Self); require('../methods/order/itemFilter')(Self);
}; };