Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 6276-createNewWarehouse
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Jorge Penadés 2024-01-11 16:52:54 +01:00
commit ddcecb8f22
11 changed files with 140 additions and 14 deletions

View File

@ -1,4 +1,4 @@
FROM mariadb:10.7.7 FROM mariadb:10.11.6
ENV MYSQL_ROOT_PASSWORD root ENV MYSQL_ROOT_PASSWORD root
ENV TZ Europe/Madrid ENV TZ Europe/Madrid

View File

@ -0,0 +1,58 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`invoiceOut_beforeInsert`
BEFORE INSERT ON `invoiceOut`
FOR EACH ROW
BEGIN
/**
* Reference format:
* - 0: Serial [A-Z]
* - 1: Sage company id
* - 2-3: Last two digits of issued year
* - 4-8: Autoincrement identifier
**/
DECLARE vNewRef INT DEFAULT 0;
DECLARE vCompanyCode INT;
DECLARE vLastRef VARCHAR(255);
DECLARE vRefStr VARCHAR(255);
DECLARE vRefLen INT DEFAULT 5;
DECLARE vYearLen INT DEFAULT 2;
DECLARE vPrefixLen INT;
SELECT companyCode INTO vCompanyCode
FROM company
WHERE id = NEW.companyFk;
IF vCompanyCode IS NULL THEN
CALL util.throw('sageCompanyNotDefined');
END IF;
SELECT MAX(i.ref) INTO vLastRef
FROM invoiceOut i
WHERE i.serial = NEW.serial
AND i.issued BETWEEN util.firstDayOfYear(NEW.issued) AND util.dayEnd(util.lastDayOfYear(NEW.issued))
AND i.companyFk = NEW.companyFk;
IF vLastRef IS NOT NULL THEN
SET vPrefixLen = LENGTH(NEW.serial) + LENGTH(vCompanyCode) + vYearLen;
SET vRefLen = LENGTH(vLastRef) - vPrefixLen;
SET vRefStr = SUBSTRING(vLastRef, vPrefixLen + 1);
SET vNewRef = vRefStr + 1;
IF LENGTH(vNewRef) > vRefLen THEN
CALL util.throw('refLenExceeded');
END IF;
SET NEW.ref = CONCAT(
SUBSTRING(vLastRef, 1, vPrefixLen),
LPAD(vNewRef, LENGTH(vRefStr), '0')
);
ELSE
SET NEW.ref = CONCAT(
NEW.serial,
vCompanyCode,
RIGHT(YEAR(NEW.issued), vYearLen),
LPAD(1, vRefLen, '0')
);
END IF;
END$$
DELIMITER ;

View File

@ -2912,8 +2912,7 @@ INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`, `payMethodFk
INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`)
VALUES VALUES
(1, 12), (24, 7);
(8, 10);
INSERT INTO `vn`.`deviceProductionModels` (`code`) INSERT INTO `vn`.`deviceProductionModels` (`code`)
VALUES VALUES

View File

@ -225,7 +225,7 @@ describe('Ticket Edit sale path', () => {
}); });
it('should show error trying to delete a ticket with a refund', async() => { it('should show error trying to delete a ticket with a refund', async() => {
await page.accessToSearchResult('16'); await page.accessToSearchResult('6');
await page.waitToClick(selectors.ticketDescriptor.moreMenu); await page.waitToClick(selectors.ticketDescriptor.moreMenu);
await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket); await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket);
await page.waitToClick(selectors.globalItems.acceptButton); await page.waitToClick(selectors.globalItems.acceptButton);

View File

@ -78,7 +78,7 @@ module.exports = Self => {
const sales = await models.Sale.find(filterTicket, myOptions); const sales = await models.Sale.find(filterTicket, myOptions);
const salesIds = sales.map(sale => sale.id); const salesIds = sales.map(sale => sale.id);
const clonedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, false, false, myOptions); const clonedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, false, myOptions);
const clonedTicketIds = []; const clonedTicketIds = [];
for (const clonedTicket of clonedTickets) { for (const clonedTicket of clonedTickets) {

View File

@ -1,5 +1,5 @@
module.exports = Self => { module.exports = Self => {
Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, group, negative, options) => { Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, negative, options) => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {}; const myOptions = {};
let tx; let tx;
@ -28,8 +28,6 @@ module.exports = Self => {
const mappedTickets = new Map(); const mappedTickets = new Map();
if (group) ticketsIds = [ticketsIds[0]];
for (let ticketId of ticketsIds) { for (let ticketId of ticketsIds) {
const newTicket = await createTicket( const newTicket = await createTicket(
ctx, ctx,
@ -109,7 +107,10 @@ module.exports = Self => {
const newTicket = await models.Ticket.new(ctx, myOptions); const newTicket = await models.Ticket.new(ctx, myOptions);
if (negative) { const ticketRefund = await models.TicketRefund.findOne({
where: {refundTicketFk: ticketId}
}, myOptions);
if (negative && (withWarehouse || !ticketRefund?.id)) {
await models.TicketRefund.create({ await models.TicketRefund.create({
originalTicketFk: ticketId, originalTicketFk: ticketId,
refundTicketFk: newTicket.id refundTicketFk: newTicket.id

View File

@ -47,7 +47,6 @@ module.exports = Self => {
salesIds, salesIds,
servicesIds, servicesIds,
withWarehouse, withWarehouse,
false,
true, true,
myOptions myOptions
); );

View File

@ -0,0 +1,70 @@
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('Ticket cloning - clone function', () => {
let ctx;
let options;
let tx;
beforeEach(async() => {
ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'http://localhost'}
},
args: {}
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: ctx.req
});
options = {transaction: tx};
tx = await models.Sale.beginTransaction({});
options.transaction = tx;
});
afterEach(async() => {
await tx.rollback();
});
it('should create new tickets with cloned sales with warehouse', async() => {
const salesIds = [1, 2, 3];
const servicesIds = [];
const withWarehouse = true;
const negative = false;
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, withWarehouse, negative, options);
expect(newTickets).toBeDefined();
expect(newTickets.length).toBeGreaterThan(0);
});
it('should handle negative quantities correctly', async() => {
const negative = true;
const salesIds = [7, 8];
const servicesIds = [];
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, false, negative, options);
for (const ticket of newTickets) {
const sales = await models.Sale.find({where: {ticketFk: ticket.id}}, options);
sales.forEach(sale => {
expect(sale.quantity).toBeLessThan(0);
});
}
});
it('should create new components and services for cloned tickets', async() => {
const servicesIds = [2];
const salesIds = [5];
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, false, false, options);
for (const ticket of newTickets) {
const sale = await models.Sale.findOne({where: {ticketFk: ticket.id}}, options);
const components = await models.SaleComponent.find({where: {saleFk: sale.id}}, options);
const services = await models.TicketService.find({where: {ticketFk: ticket.id}}, options);
expect(components.length).toBeGreaterThan(0);
expect(services.length).toBeGreaterThan(0);
}
});
});

View File

@ -3,7 +3,6 @@ const LoopBackContext = require('loopback-context');
describe('ticket setDeleted()', () => { describe('ticket setDeleted()', () => {
const userId = 1106; const userId = 1106;
const employeeUser = 1110;
const activeCtx = { const activeCtx = {
accessToken: {userId: userId}, accessToken: {userId: userId},
}; };
@ -118,7 +117,7 @@ describe('ticket setDeleted()', () => {
return value; return value;
}; };
const ticketId = 12; const ticketId = 7;
await models.Ticket.setDeleted(ctx, ticketId, options); await models.Ticket.setDeleted(ctx, ticketId, options);
await tx.rollback(); await tx.rollback();

View File

@ -132,7 +132,7 @@ describe('sale model ', () => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(9)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(9));
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
const saleId = 13; const saleId = 32;
const newQuantity = -10; const newQuantity = -10;
try { try {

View File

@ -5,7 +5,7 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'workerFk', arg: 'workerFk',
type: 'int', type: 'number',
required: true, required: true,
}, },