Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into test
gitea/salix/test This commit looks good
Details
gitea/salix/test This commit looks good
Details
This commit is contained in:
commit
1841848b06
|
@ -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 ;
|
||||
|
|
@ -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 ;
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import ngModule from '../../module';
|
||||
import Dialog from '../dialog';
|
||||
import template from './confirm.html';
|
||||
import './style.scss';
|
||||
|
||||
export default class Confirm extends Dialog {
|
||||
constructor($element, $, $transclude) {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.vn-confirm .window {
|
||||
max-width: 30em
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
|
@ -0,0 +1,31 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('recalculateComponents', {
|
||||
description: 'Calculates the price of a sale and its components',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
description: 'The ticket id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'Number',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/recalculateComponents`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.recalculateComponents = async(ctx, id) => {
|
||||
const isEditable = await Self.isEditable(ctx, id);
|
||||
|
||||
if (!isEditable)
|
||||
throw new UserError(`The current ticket can't be modified`);
|
||||
|
||||
return Self.rawSql('CALL vn.ticket_recalcComponents(?)', [id]);
|
||||
};
|
||||
};
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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`
|
||||
|
|
|
@ -26,6 +26,7 @@ module.exports = Self => {
|
|||
require('../methods/ticket/addSale')(Self);
|
||||
require('../methods/ticket/transferSales')(Self);
|
||||
require('../methods/ticket/canHaveStowaway')(Self);
|
||||
require('../methods/ticket/recalculateComponents')(Self);
|
||||
|
||||
Self.observe('before save', async function(ctx) {
|
||||
if (ctx.isNewInstance) return;
|
||||
|
|
|
@ -198,6 +198,13 @@
|
|||
<vn-confirm
|
||||
vn-id="confirm-delivery-note"
|
||||
on-accept="$ctrl.sendDeliveryNote()"
|
||||
question="Send Delivery Note"
|
||||
message="Are you sure you want to send it?">
|
||||
question="Are you sure you want to send it?"
|
||||
message="Send Delivery Note">
|
||||
</vn-confirm>
|
||||
|
||||
<vn-confirm
|
||||
vn-id="recalculate-components-confirmation"
|
||||
on-accept="$ctrl.recalculateComponents()"
|
||||
question="Are you sure you want to recalculate the components?"
|
||||
message="Recalculate components">
|
||||
</vn-confirm>
|
|
@ -35,6 +35,11 @@ class Controller extends Component {
|
|||
callback: this.showRegenerateInvoiceDialog,
|
||||
show: () => this.hasInvoice()
|
||||
},
|
||||
{
|
||||
name: 'Recalculate components',
|
||||
callback: this.comfirmRecalculateComponents,
|
||||
show: () => this.isEditable
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -287,9 +292,26 @@ class Controller extends Component {
|
|||
return this.ticket.refFk !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a delivery-note send confirmation
|
||||
*/
|
||||
confirmDeliveryNote() {
|
||||
this.$.confirmDeliveryNote.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an invoice confirmation
|
||||
*/
|
||||
comfirmRecalculateComponents() {
|
||||
this.$.recalculateComponentsConfirmation.show();
|
||||
}
|
||||
|
||||
recalculateComponents() {
|
||||
const query = `Tickets/${this.ticket.id}/recalculateComponents`;
|
||||
this.$http.post(query).then(res => {
|
||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'aclService', '$httpParamSerializer'];
|
||||
|
|
|
@ -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!');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -26,3 +26,5 @@ Are you sure you want to regenerate the invoice?: ¿Seguro que quieres regenerar
|
|||
Invoice sent for a regeneration, will be available in a few minutes: La factura ha sido enviada para ser regenerada, estará disponible en unos minutos
|
||||
Shipped hour updated: Hora de envio modificada
|
||||
Deleted ticket: Ticket eliminado
|
||||
Recalculate components: Recalcular componentes
|
||||
Are you sure you want to recalculate the components?: ¿Seguro que quieres recalcular los componentes?
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue