Added waste section
This commit is contained in:
parent
8807f64e09
commit
3a4c379033
|
@ -0,0 +1,30 @@
|
|||
USE `bs`;
|
||||
DROP procedure IF EXISTS `waste_getDetail`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `bs`$$
|
||||
CREATE DEFINER=`root`@`%`PROCEDURE `waste_getDetail` ()
|
||||
BEGIN
|
||||
DECLARE vWeek INT;
|
||||
DECLARE vYear INT;
|
||||
|
||||
SELECT week, year
|
||||
INTO vWeek, vYear
|
||||
FROM vn.time
|
||||
WHERE dated = CURDATE();
|
||||
|
||||
SELECT *, 100 * dwindle / total AS percentage
|
||||
FROM (
|
||||
SELECT buyer,
|
||||
ws.family,
|
||||
sum(ws.saleTotal) AS total,
|
||||
sum(ws.saleWaste) AS dwindle
|
||||
FROM bs.waste ws
|
||||
WHERE `year` = vYear AND `week` = vWeek
|
||||
GROUP BY buyer, family
|
||||
) sub
|
||||
ORDER BY percentage DESC;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
|
@ -20,4 +20,5 @@ import './niche';
|
|||
import './botanical';
|
||||
import './barcode';
|
||||
import './summary';
|
||||
import './waste';
|
||||
|
||||
|
|
|
@ -137,6 +137,15 @@
|
|||
"item": "$ctrl.item"
|
||||
},
|
||||
"acl": ["employee"]
|
||||
}, {
|
||||
"url" : "/waste",
|
||||
"state": "item.waste",
|
||||
"component": "vn-item-waste",
|
||||
"description": "Waste",
|
||||
"params": {
|
||||
"item": "$ctrl.item"
|
||||
},
|
||||
"acl": ["employee"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<vn-crud-model auto-load="true"
|
||||
vn-id="model"
|
||||
url="Items/filter"
|
||||
limit="20"
|
||||
data="requests"
|
||||
order="shipped DESC, isOk ASC">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer model="model">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="buer" number>Buyer</vn-th>
|
||||
<vn-th field="family">Family</vn-th>
|
||||
<vn-th field="percentage">Percentage</vn-th>
|
||||
<vn-th field="salesPersonNickname">Mermas</vn-th>
|
||||
<vn-th field="total">Total</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="request in requests">
|
||||
<vn-td number>
|
||||
<span class="link"
|
||||
ng-click="$ctrl.showTicketDescriptor($event, request.ticketFk)">
|
||||
{{request.ticketFk}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span title="{{::request.shipped | date: 'dd/MM/yyyy'}}"
|
||||
class="chip {{$ctrl.compareDate(request.shipped)}}">
|
||||
{{::request.shipped | date: 'dd/MM/yyyy'}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{::request.warehouse}}</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, request.salesPersonFk)">
|
||||
{{::request.salesPersonNickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td title="{{::request.description}}">{{::request.description}}</vn-td>
|
||||
<vn-td number>{{::request.quantity}}</vn-td>
|
||||
<vn-td number>{{::request.price | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, request.attenderFk)">
|
||||
{{::request.atenderNickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td-editable disabled="request.isOk != null" number>
|
||||
<text>{{request.itemFk}}</text>
|
||||
<field>
|
||||
<vn-input-number class="dense" vn-focus
|
||||
ng-model="request.itemFk">
|
||||
</vn-input-number>
|
||||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td-editable disabled="!request.itemFk || request.isOk != null" number>
|
||||
<text number>{{request.saleQuantity}}</text>
|
||||
<field>
|
||||
<vn-input-number class="dense" vn-focus
|
||||
ng-model="request.saleQuantity"
|
||||
on-change="$ctrl.changeQuantity(request)">
|
||||
</vn-input-number>
|
||||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showItemDescriptor($event, request.itemFk)"
|
||||
title="{{request.itemDescription}}">
|
||||
{{request.itemDescription}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{$ctrl.getState(request.isOk)}}</vn-td>
|
||||
<vn-td>
|
||||
<vn-icon
|
||||
ng-if="request.response.length"
|
||||
ranslate-attr="{title: request.response}"
|
||||
icon="insert_drive_file">
|
||||
</vn-icon>
|
||||
<vn-icon-button
|
||||
ng-if="request.isOk != 0"
|
||||
icon="thumb_down"
|
||||
ng-click="$ctrl.showDenyReason($event, request)"
|
||||
translate-attr="{title: 'Discard'}">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-ticket-descriptor-popover
|
||||
vn-id="ticketDescriptor">
|
||||
</vn-ticket-descriptor-popover>
|
||||
<vn-item-descriptor-popover
|
||||
vn-id="itemDescriptor">
|
||||
</vn-item-descriptor-popover>
|
||||
<vn-dialog
|
||||
vn-id="denyReason"
|
||||
on-response="$ctrl.denyRequest($response)">
|
||||
<tpl-body>
|
||||
<h5 class="vn-pa-md" translate>Specify the reasons to deny this request</h5>
|
||||
<vn-horizontal class="vn-pa-md">
|
||||
<vn-textarea
|
||||
ng-model="$ctrl.denyObservation">
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Save</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -0,0 +1,12 @@
|
|||
import ngModule from '../module';
|
||||
import Component from 'core/lib/component';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller extends Component {
|
||||
|
||||
}
|
||||
|
||||
ngModule.component('vnItemWaste', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,133 @@
|
|||
import './index.js';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('Item', () => {
|
||||
describe('Component vnItemRequest', () => {
|
||||
let $scope;
|
||||
let $element;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('item'));
|
||||
|
||||
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
$scope.model = crudModel;
|
||||
$scope.denyReason = {hide: () => {}};
|
||||
$element = angular.element('<vn-item-request></vn-item-request>');
|
||||
controller = $componentController('vnItemRequest', {$element, $scope});
|
||||
}));
|
||||
|
||||
afterAll(() => {
|
||||
$scope.$destroy();
|
||||
$element.remove();
|
||||
});
|
||||
|
||||
describe('getState()', () => {
|
||||
it(`should return an string depending to the isOK value`, () => {
|
||||
let isOk = null;
|
||||
let result = controller.getState(isOk);
|
||||
|
||||
expect(result).toEqual('Nueva');
|
||||
|
||||
isOk = 1;
|
||||
result = controller.getState(isOk);
|
||||
|
||||
expect(result).toEqual('Aceptada');
|
||||
|
||||
isOk = 0;
|
||||
result = controller.getState(isOk);
|
||||
|
||||
expect(result).toEqual('Denegada');
|
||||
});
|
||||
});
|
||||
|
||||
describe('confirmRequest()', () => {
|
||||
it(`should do nothing if the request does't have itemFk or saleQuantity`, () => {
|
||||
let request = {};
|
||||
spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
controller.confirmRequest(request);
|
||||
|
||||
expect(controller.vnApp.showSuccess).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should perform a query and call vnApp.showSuccess() and refresh if the conditions are met', () => {
|
||||
spyOn(controller.vnApp, 'showSuccess');
|
||||
let model = controller.$.model;
|
||||
spyOn(model, 'refresh');
|
||||
|
||||
const expectedResult = {concept: 'Melee Weapon'};
|
||||
let request = {itemFk: 1, saleQuantity: 1, id: 1};
|
||||
|
||||
$httpBackend.when('POST', `TicketRequests/${request.id}/confirm`).respond(expectedResult);
|
||||
$httpBackend.expect('POST', `TicketRequests/${request.id}/confirm`).respond(expectedResult);
|
||||
controller.confirmRequest(request);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('changeQuantity()', () => {
|
||||
it(`should call confirmRequest() if there's no sale id in the request`, () => {
|
||||
let request = {};
|
||||
spyOn(controller, 'confirmRequest');
|
||||
|
||||
controller.changeQuantity(request);
|
||||
|
||||
expect(controller.confirmRequest).toHaveBeenCalledWith(jasmine.any(Object));
|
||||
});
|
||||
|
||||
it(`should perform a query and call vnApp.showSuccess() if the conditions are met`, () => {
|
||||
let request = {saleFk: 1, saleQuantity: 1};
|
||||
spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
|
||||
$httpBackend.when('PATCH', `Sales/${request.saleFk}/`).respond();
|
||||
$httpBackend.expect('PATCH', `Sales/${request.saleFk}/`).respond();
|
||||
controller.changeQuantity(request);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('compareDate()', () => {
|
||||
it(`should return "success" if receives a future date`, () => {
|
||||
let date = '3019-02-18T11:00:00.000Z';
|
||||
|
||||
let result = controller.compareDate(date);
|
||||
|
||||
expect(result).toEqual('success');
|
||||
});
|
||||
|
||||
it(`should return "warning" if date is today`, () => {
|
||||
let date = new Date();
|
||||
|
||||
let result = controller.compareDate(date);
|
||||
|
||||
expect(result).toEqual('warning');
|
||||
});
|
||||
});
|
||||
|
||||
describe('denyRequest()', () => {
|
||||
it(`should perform a query and call vnApp.showSuccess(), refresh(), hide() and set denyObservation to null in the controller`, () => {
|
||||
spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
const request = {id: 1};
|
||||
const expectedResult = {isOk: false, attenderFk: 106, response: 'Denied!'};
|
||||
controller.selectedRequest = request;
|
||||
|
||||
$httpBackend.when('POST', `TicketRequests/${request.id}/deny`).respond(expectedResult);
|
||||
$httpBackend.expect('POST', `TicketRequests/${request.id}/deny`).respond(expectedResult);
|
||||
controller.denyRequest('accept');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Discard: Descartar
|
||||
Specify the reasons to deny this request: Especifica las razones para descartar la petición
|
||||
Buy requests: Peticiones de compra
|
||||
Search request by id or alias: Buscar peticiones por identificador o alias
|
||||
Requested: Solicitado
|
||||
Achieved: Conseguido
|
|
@ -0,0 +1,18 @@
|
|||
@import "variables";
|
||||
|
||||
vn-item-request {
|
||||
vn-dialog[vn-id="denyReason"] {
|
||||
button.close {
|
||||
display: none
|
||||
}
|
||||
vn-button {
|
||||
margin: 0 auto
|
||||
}
|
||||
vn-textarea {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
vn-icon[icon=insert_drive_file]{
|
||||
color: $color-font-secondary;
|
||||
}
|
||||
}
|
|
@ -29,6 +29,6 @@ module.exports = Self => {
|
|||
if (!isEditable)
|
||||
throw new UserError(`The sales of this ticket can't be modified`);
|
||||
|
||||
return Self.rawSql('CALL vn.ticketCalculateSale(?)', [id]);
|
||||
return Self.rawSql('CALL vn.sale_calculateComponent(?, null)', [id]);
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue