Recalculate ticket components #1770
gitea/salix/1770-calculate_components This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-11-21 12:00:56 +01:00
parent fee0d674a0
commit fd72f206bc
10 changed files with 202 additions and 11 deletions

View File

@ -0,0 +1,77 @@
USE `vn`;
DROP procedure IF EXISTS `ticket_recalcComponents`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_recalcComponents`(IN vTicketFk BIGINT )
proc: BEGIN
/**
* Este procedimiento trata de "rebionizar" un ticket,
* eliminando los componentes existentes e insertandolos de nuevo
*
* @param vTicketFk Id del ticket
* @return tmp.buyUltimate
*/
DECLARE vShipped DATE;
DECLARE vWarehouseFk SMALLINT;
DECLARE vAgencyModeFk INT;
DECLARE vAddressFk INT;
DECLARE vLanded DATE;
DECLARE vIsTicketEditable BOOLEAN;
DECLARE vZoneFk INTEGER;
SELECT (IFNULL(ts.alertLevel,0) >0 or IFNULL(t.refFk,"") != "") = FALSE, t.zoneFk
INTO vIsTicketEditable, vZoneFk
FROM ticket t LEFT JOIN ticketState ts ON t.id = ts.ticket
WHERE id = vTicketFk;
SELECT warehouseFk, date(shipped), addressFk, agencyModeFk, landed
INTO vWarehouseFk, vShipped, vAddressFk, vAgencyModeFk, vLanded
FROM ticket
WHERE id = vTicketFk;
CALL zoneGetShippedWarehouse(vLanded, vAddressFk , vAgencyModeFk);
CALL vn.buyUltimate (vWarehouseFk, vShipped); -- rellena la tabla buyUltimate con la ultima compra
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot
SELECT vWarehouseFk warehouseFk, NULL available,
s.itemFk, bu.buyFk
FROM sale s
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
WHERE s.ticketFk = vTicketFk
GROUP BY s.itemFk;
CALL vn.catalog_componentCalculate(vZoneFk, vAddressFk, vShipped);
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
CREATE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
SELECT id saleFk, vWarehouseFk warehouseFk
FROM sale s
WHERE s.ticketFk = vTicketFk;
CALL vn.ticketComponentUpdateSale(IF(vIsTicketEditable,1,6)); -- si el ticket esta facturado, respeta los precios
IF vLanded IS NULL THEN
CALL zoneGetLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk);
UPDATE vn2008.Tickets t
SET t.landing = (SELECT landed FROM tmp.zoneGetLanded)
WHERE Id_Ticket = vTicketFk;
DROP TEMPORARY TABLE tmp.zoneGetLanded;
END IF;
DROP TEMPORARY TABLE tmp.buyUltimate;
DROP TEMPORARY TABLE tmp.ticketComponentPrice;
DROP TEMPORARY TABLE tmp.ticketComponent;
DROP TEMPORARY TABLE tmp.sale;
END$$
DELIMITER ;

View File

@ -0,0 +1,77 @@
USE `vn`;
DROP procedure IF EXISTS `ticket_recalcComponentsForcePrice`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_recalcComponentsForcePrice`(IN vTicketFk BIGINT, vIsTicketEditable BOOLEAN )
proc: BEGIN
/**
* Este procedimiento trata de "rebionizar" un ticket,
* eliminando los componentes existentes e insertandolos de nuevo
*
* @param vTicketFk Id del ticket
* @return tmp.buyUltimate
*/
DECLARE vShipped DATE;
DECLARE vWarehouseFk SMALLINT;
DECLARE vAgencyModeFk INT;
DECLARE vAddressFk INT;
DECLARE vLanded DATE;
DECLARE vZoneFk INTEGER;
IF vIsTicketEditable IS NULL THEN
SELECT (IFNULL(ts.alertLevel,0) >0 or IFNULL(t.refFk,"") != "") = FALSE, t.zoneFk
INTO vIsTicketEditable, vZoneFk
FROM ticket t LEFT JOIN ticketState ts ON t.id = ts.ticket
WHERE id = vTicketFk;
END IF;
SELECT warehouseFk, date(shipped), addressFk, agencyModeFk, landed
INTO vWarehouseFk, vShipped, vAddressFk, vAgencyModeFk, vLanded
FROM ticket
WHERE id = vTicketFk;
CALL zoneGetShippedWarehouse(vLanded, vAddressFk , vAgencyModeFk);
CALL vn.buyUltimate (vWarehouseFk, vShipped); -- rellena la tabla buyUltimate con la ultima compra
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot
SELECT vWarehouseFk warehouseFk, NULL available,
s.itemFk, bu.buyFk
FROM sale s
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
WHERE s.ticketFk = vTicketFk
GROUP BY s.itemFk;
CALL vn.catalog_componentCalculate(vZoneFk, vAddressFk, vShipped);
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
CREATE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
SELECT id saleFk, vWarehouseFk warehouseFk
FROM sale s
WHERE s.ticketFk = vTicketFk;
CALL vn.ticketComponentUpdateSale(IF(vIsTicketEditable,1,6)); -- si el ticket esta facturado, respeta los precios
IF vLanded IS NULL THEN
CALL zoneGetLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk);
UPDATE vn2008.Tickets t
SET t.landing = (SELECT landed FROM tmp.zoneGetLanded)
WHERE Id_Ticket = vTicketFk;
DROP TEMPORARY TABLE tmp.zoneGetLanded;
END IF;
DROP TEMPORARY TABLE tmp.buyUltimate;
DROP TEMPORARY TABLE tmp.ticketComponentPrice;
DROP TEMPORARY TABLE tmp.ticketComponent;
DROP TEMPORARY TABLE tmp.sale;
END$$
DELIMITER ;

View File

@ -1,6 +1,6 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('calculate', {
Self.remoteMethodCtx('recalculatePrice', {
description: 'Calculates the price of a sale and its components',
accessType: 'WRITE',
accepts: [{
@ -15,12 +15,12 @@ module.exports = Self => {
root: true
},
http: {
path: `/:id/calculate`,
path: `/:id/recalculatePrice`,
verb: 'post'
}
});
Self.calculate = async(ctx, id) => {
Self.recalculatePrice = async(ctx, id) => {
const models = Self.app.models;
const sale = await Self.findById(id);

View File

@ -1,11 +1,11 @@
const app = require('vn-loopback/server/server');
describe('sale calculate()', () => {
describe('sale recalculatePrice()', () => {
const saleId = 7;
it('should update the sale price', async() => {
const ctx = {req: {accessToken: {userId: 9}}};
const response = await app.models.Sale.calculate(ctx, saleId);
const response = await app.models.Sale.recalculatePrice(ctx, saleId);
expect(response.affectedRows).toBeDefined();
});
@ -13,7 +13,7 @@ describe('sale calculate()', () => {
it('should throw an error if the ticket is not editable', async() => {
const ctx = {req: {accessToken: {userId: 9}}};
const immutableSaleId = 1;
await app.models.Sale.calculate(ctx, immutableSaleId)
await app.models.Sale.recalculatePrice(ctx, immutableSaleId)
.catch(response => {
expect(response).toEqual(new Error(`The sales of this ticket can't be modified`));
error = response;

View File

@ -24,7 +24,7 @@ module.exports = Self => {
const isEditable = await Self.isEditable(ctx, id);
if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`);
throw new UserError(`The current ticket can't be modified`);
return Self.rawSql('CALL vn.ticket_recalcComponents(?)', [id]);
};

View File

@ -0,0 +1,24 @@
const app = require('vn-loopback/server/server');
describe('ticket recalculateComponents()', () => {
const ticketId = 11;
it('should update the ticket components', async() => {
const ctx = {req: {accessToken: {userId: 9}}};
const response = await app.models.Ticket.recalculateComponents(ctx, ticketId);
expect(response.affectedRows).toBeDefined();
});
it('should throw an error if the ticket is not editable', async() => {
const ctx = {req: {accessToken: {userId: 9}}};
const immutableTicketId = 1;
await app.models.Ticket.recalculateComponents(ctx, immutableTicketId)
.catch(response => {
expect(response).toEqual(new Error(`The current ticket can't be modified`));
error = response;
});
expect(error).toBeDefined();
});
});

View File

@ -5,7 +5,7 @@ module.exports = Self => {
require('../methods/sale/updatePrice')(Self);
require('../methods/sale/updateQuantity')(Self);
require('../methods/sale/updateConcept')(Self);
require('../methods/sale/calculate')(Self);
require('../methods/sale/recalculatePrice')(Self);
Self.validatesPresenceOf('concept', {
message: `Concept cannot be blank`

View File

@ -1,6 +1,6 @@
import './index.js';
describe('Ticket Component vnTicketDescriptor', () => {
fdescribe('Ticket Component vnTicketDescriptor', () => {
let $httpParamSerializer;
let $httpBackend;
let controller;
@ -210,4 +210,17 @@ describe('Ticket Component vnTicketDescriptor', () => {
expect(controller.isTicketModule).toHaveBeenCalledWith();
});
});
describe('recalculateComponents()', () => {
it('should make a query and show a success snackbar', () => {
spyOn(controller.vnApp, 'showSuccess');
$httpBackend.when('POST', 'Tickets/2/recalculateComponents').respond();
$httpBackend.expect('POST', 'Tickets/2/recalculateComponents').respond();
controller.recalculateComponents();
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
});

View File

@ -548,7 +548,7 @@ class Controller {
calculateSalePrice() {
const sale = this.checkedLines()[0];
const query = `Sales/${sale.id}/calculate`;
const query = `Sales/${sale.id}/recalculatePrice`;
this.$http.post(query).then(res => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$scope.model.refresh();

View File

@ -349,7 +349,7 @@ describe('Ticket', () => {
it('should make an HTTP post query ', () => {
controller.sales[0].checked = true;
$httpBackend.when('POST', `Sales/4/calculate`).respond(200);
$httpBackend.when('POST', `Sales/4/recalculatePrice`).respond(200);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();