Tarea #438 order.line
This commit is contained in:
parent
da9a783843
commit
65ffade0a3
|
@ -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>
|
|
@ -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: '<'
|
||||
}
|
||||
});
|
|
@ -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!');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
Remove item: Eliminar articulo
|
|
@ -0,0 +1,8 @@
|
|||
vn-order-line{
|
||||
vn-table {
|
||||
img {
|
||||
border-radius: 50%;
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ input[type=reset]::-moz-focus-inner
|
|||
|
||||
.totalBox {
|
||||
border: 1px solid #CCC;
|
||||
text-align: left;
|
||||
text-align: right!important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 18px;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -2,7 +2,7 @@ module.exports = Self => {
|
|||
require('../methods/order/new')(Self);
|
||||
require('../methods/order/getTotalVolume')(Self);
|
||||
require('../methods/order/getVolumes')(Self);
|
||||
//require('../methods/order/getTaxes')(Self);
|
||||
require('../methods/order/getTaxes')(Self);
|
||||
require('../methods/order/isEditable')(Self);
|
||||
require('../methods/order/getTotal')(Self);
|
||||
require('../methods/order/itemFilter')(Self);
|
||||
|
|
Loading…
Reference in New Issue