7152-devToTest_2414 #2228
|
@ -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
|
||||||
|
|
|
@ -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 ;
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -47,7 +47,6 @@ module.exports = Self => {
|
||||||
salesIds,
|
salesIds,
|
||||||
servicesIds,
|
servicesIds,
|
||||||
withWarehouse,
|
withWarehouse,
|
||||||
false,
|
|
||||||
true,
|
true,
|
||||||
myOptions
|
myOptions
|
||||||
);
|
);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -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();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -5,7 +5,7 @@ module.exports = Self => {
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'workerFk',
|
arg: 'workerFk',
|
||||||
type: 'int',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue