diff --git a/db/changes/10140-kings/00-waste_getDetail.sql b/db/changes/10140-kings/00-waste_getDetail.sql
new file mode 100644
index 000000000..9bf6cf049
--- /dev/null
+++ b/db/changes/10140-kings/00-waste_getDetail.sql
@@ -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 ;
+
diff --git a/modules/item/front/index.js b/modules/item/front/index.js
index 2be6f95c2..0f11c0563 100644
--- a/modules/item/front/index.js
+++ b/modules/item/front/index.js
@@ -20,4 +20,5 @@ import './niche';
import './botanical';
import './barcode';
import './summary';
+import './waste';
diff --git a/modules/item/front/routes.json b/modules/item/front/routes.json
index bda4f18a9..611bba785 100644
--- a/modules/item/front/routes.json
+++ b/modules/item/front/routes.json
@@ -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"]
}
]
}
\ No newline at end of file
diff --git a/modules/item/front/waste/index.html b/modules/item/front/waste/index.html
new file mode 100644
index 000000000..e7ddb25fd
--- /dev/null
+++ b/modules/item/front/waste/index.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+ Buyer
+ Family
+ Percentage
+ Mermas
+ Total
+
+
+
+
+
+
+ {{request.ticketFk}}
+
+
+
+
+ {{::request.shipped | date: 'dd/MM/yyyy'}}
+
+
+ {{::request.warehouse}}
+
+
+ {{::request.salesPersonNickname}}
+
+
+ {{::request.description}}
+ {{::request.quantity}}
+ {{::request.price | currency: 'EUR':2}}
+
+
+ {{::request.atenderNickname}}
+
+
+
+ {{request.itemFk}}
+
+
+
+
+
+
+ {{request.saleQuantity}}
+
+
+
+
+
+
+
+ {{request.itemDescription}}
+
+
+ {{$ctrl.getState(request.isOk)}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Specify the reasons to deny this request
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/item/front/waste/index.js b/modules/item/front/waste/index.js
new file mode 100644
index 000000000..f64cf3e1d
--- /dev/null
+++ b/modules/item/front/waste/index.js
@@ -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
+});
diff --git a/modules/item/front/waste/index.spec.js b/modules/item/front/waste/index.spec.js
new file mode 100644
index 000000000..4c1e31634
--- /dev/null
+++ b/modules/item/front/waste/index.spec.js
@@ -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('');
+ 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!');
+ });
+ });
+ });
+});
+
diff --git a/modules/item/front/waste/locale/es.yml b/modules/item/front/waste/locale/es.yml
new file mode 100644
index 000000000..33710a327
--- /dev/null
+++ b/modules/item/front/waste/locale/es.yml
@@ -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
\ No newline at end of file
diff --git a/modules/item/front/waste/style.scss b/modules/item/front/waste/style.scss
new file mode 100644
index 000000000..0af32c309
--- /dev/null
+++ b/modules/item/front/waste/style.scss
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/modules/ticket/back/methods/sale/recalculatePrice.js b/modules/ticket/back/methods/sale/recalculatePrice.js
index 1bd754f6a..9ad7e68e7 100644
--- a/modules/ticket/back/methods/sale/recalculatePrice.js
+++ b/modules/ticket/back/methods/sale/recalculatePrice.js
@@ -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]);
};
};