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

This commit is contained in:
Carlos Jimenez Ruiz 2020-07-01 14:45:53 +02:00
commit c801d8a969
33 changed files with 904 additions and 1017 deletions

View File

@ -35,5 +35,5 @@ ENTRYPOINT ["docker-start.sh"]
CMD ["mysqld"] CMD ["mysqld"]
#HEALTHCHECK --interval=5s --timeout=10s --retries=200 \ HEALTHCHECK --interval=5s --timeout=10s --retries=200 \
# CMD mysqladmin ping -h 127.0.0.1 -u root || exit 1 CMD mysqladmin ping -h 127.0.0.1 -u root || exit 1

View File

@ -1,5 +0,0 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('WorkerDms', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'),
('WorkerDms', 'downloadFile', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL` WHERE (`id` = '205');

View File

@ -1,119 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `zone_getEvents`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getEvents`(
vGeoFk INT,
vAgencyModeFk INT)
BEGIN
/**
* Returns available events for the passed province/postcode and agency.
*
* @param vGeoFk The geo id
* @param vAgencyModeFk The agency mode id
*/
DECLARE vDeliveryMethodFk VARCHAR(255);
DROP TEMPORARY TABLE IF EXISTS tZone;
CREATE TEMPORARY TABLE tZone
(id INT PRIMARY KEY)
ENGINE = MEMORY;
SELECT dm.`code` INTO vDeliveryMethodFk
FROM agencyMode am
JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
WHERE am.id = vAgencyModeFk;
IF vDeliveryMethodFk = 'PICKUP' THEN
INSERT INTO tZone
SELECT id
FROM zone
WHERE agencyModeFk = vAgencyModeFk;
ELSE
CALL zone_getFromGeo(vGeoFk);
IF vAgencyModeFk IS NOT NULL THEN
INSERT INTO tZone
SELECT t.id
FROM tmp.zone t
JOIN zone z ON z.id = t.id
WHERE z.agencyModeFk = vAgencyModeFk;
ELSE
INSERT INTO tZone
SELECT t.id
FROM tmp.zone t
JOIN zone z ON z.id = t.id
JOIN agencyMode am ON am.id = z.agencyModeFk
JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
WHERE dm.`code` IN ('AGENCY', 'DELIVERY');
END IF;
DROP TEMPORARY TABLE tmp.zone;
END IF;
SELECT e.zoneFk, e.`type`, e.dated, e.`started`, e.`ended`, e.weekDays
FROM tZone t
JOIN zoneEvent e ON e.zoneFk = t.id;
SELECT e.zoneFk, e.dated
FROM tZone t
JOIN zoneExclusion e ON e.zoneFk = t.id;
DROP TEMPORARY TABLE tZone;
END$$
DELIMITER ;
USE `vn`;
DROP procedure IF EXISTS `zone_getEvents__`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getEvents__`(
vProvinceFk INT,
vPostCode VARCHAR(255),
vAgencyModeFk INT)
BEGIN
/**
* Returns available events for the passed province/postcode and agency.
*
* @param vAgencyModeFk The agency mode id
* @param vProvinceFk The province id
* @param vPostCode The postcode or %NULL to use the province
*/
DECLARE vGeoFk INT;
IF vPostCode IS NOT NULL THEN
SELECT p.geoFk INTO vGeoFk
FROM postCode p
JOIN town t ON t.id = p.townFk
WHERE p.`code` = vPostCode
AND t.provinceFk = vProvinceFk;
ELSE
SELECT geoFk INTO vGeoFk
FROM province
WHERE id = vProvinceFk;
END IF;
CALL zone_getFromGeo(vGeoFk);
IF vAgencyModeFk IS NOT NULL THEN
DELETE t FROM tmp.zone t
JOIN zone z ON z.id = t.id
WHERE z.agencyModeFk != vAgencyModeFk;
END IF;
SELECT e.zoneFk, e.`type`, e.dated, e.`started`, e.`ended`, e.weekDays
FROM tmp.zone t
JOIN zoneEvent e ON e.zoneFk = t.id;
SELECT e.zoneFk, e.dated
FROM tmp.zone t
JOIN zoneExclusion e ON e.zoneFk = t.id;
DROP TEMPORARY TABLE tmp.zone;
END$$
DELIMITER ;

View File

@ -1,87 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `zone_getWarehouse`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getWarehouse`(vAddress INT, vLanded DATE, vWarehouse INT)
BEGIN
/**
* Devuelve el listado de agencias disponibles para la fecha,
* dirección y almacén pasados.
*
* @param vAddress
* @param vWarehouse warehouse
* @param vLanded Fecha de recogida
* @select Listado de agencias disponibles
*/
CALL zone_getFromGeo(address_getGeo(vAddress));
CALL zone_getOptionsForLanding(vLanded, FALSE);
SELECT am.id agencyModeFk,
am.name agencyMode,
am.description,
am.deliveryMethodFk,
TIMESTAMPADD(DAY, -zo.travelingDays, vLanded) shipped,
zw.warehouseFk,
z.id zoneFk
FROM tmp.zoneOption zo
JOIN zone z ON z.id = zo.zoneFk
JOIN agencyMode am ON am.id = z.agencyModeFk
JOIN zoneWarehouse zw ON zw.zoneFk = zo.zoneFk
WHERE zw.warehouseFk = vWarehouse
GROUP BY z.agencyModeFk
ORDER BY agencyMode;
DROP TEMPORARY TABLE
tmp.zone,
tmp.zoneOption;
END$$
DELIMITER ;
USE `vn`;
DROP procedure IF EXISTS `zone_getWarehouse__`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getWarehouse__`(vAddress INT, vLanded DATE, vWarehouse INT)
BEGIN
/**
* Devuelve el listado de agencias disponibles para la fecha,
* dirección y almacén pasados.
*
* @param vAddress
* @param vWarehouse warehouse
* @param vLanded Fecha de recogida
* @select Listado de agencias disponibles
*/
CALL zone_getFromGeo(address_getGeo(vAddress));
CALL zone_getOptionsForLanding(vLanded, FALSE);
SELECT am.id agencyModeFk,
am.name agencyMode,
am.description,
am.deliveryMethodFk,
TIMESTAMPADD(DAY, -zo.travelingDays, vLanded) shipped,
zw.warehouseFk,
z.id zoneFk
FROM tmp.zoneOption zo
JOIN zone z ON z.id = zo.zoneFk
JOIN agencyMode am ON am.id = z.agencyModeFk
JOIN zoneWarehouse zw ON zw.zoneFk = zo.zoneFk
WHERE zw.warehouseFk
GROUP BY z.agencyModeFk
ORDER BY agencyMode;
DROP TEMPORARY TABLE
tmp.zone,
tmp.zoneOption;
END$$
DELIMITER ;

View File

@ -1,4 +1,5 @@
UPDATE `salix`.`ACL` SET `accessType`='WRITE' WHERE `id`='213'; UPDATE `salix`.`ACL` SET `accessType`='WRITE' WHERE `id`='213';
UPDATE `salix`.`ACL` SET `property` = 'deleteSales' WHERE (`id` = '80');
INSERT IGNORE INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('CustomsAgent', '*', '*', 'ALLOW', 'ROLE', 'employee'); INSERT IGNORE INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('CustomsAgent', '*', '*', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,4 @@
/*
Hay una versión en salix que machacará toda esta función/procedimiento
avisa a ___ de los cambios que quieres hacer
*/

View File

@ -39,8 +39,7 @@ module.exports = class Docker {
let runChown = process.platform != 'linux'; let runChown = process.platform != 'linux';
const healthCheck = `--health-cmd='mysqladmin ping --silent'`; const container = await this.execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
const container = await this.execP(`docker run ${healthCheck} --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
this.id = container.stdout; this.id = container.stdout;
try { try {
@ -54,7 +53,7 @@ module.exports = class Docker {
this.dbConf.port = netSettings.Ports['3306/tcp'][0]['HostPort']; this.dbConf.port = netSettings.Ports['3306/tcp'][0]['HostPort'];
} }
if (runChown) await this.wait(); await this.waitForHealthy();
} catch (err) { } catch (err) {
if (this.isRandom) if (this.isRandom)
await this.rm(); await this.rm();

View File

@ -1455,6 +1455,9 @@ INSERT INTO `vn`.`clientContact`(`id`, `clientFk`, `name`, `phone`)
(3, 101, 'contact 3', 222333444), (3, 101, 'contact 3', 222333444),
(4, 102, 'contact 1', 876543219); (4, 102, 'contact 1', 876543219);
INSERT INTO `vn`.`workerManaExcluded`(`workerFk`)
VALUES
(9);
/* /*
el mana de los trabajadores lo podemos poner a mano en la tabla si lo calculamos antes, el mana de los trabajadores lo podemos poner a mano en la tabla si lo calculamos antes,
pero si hazemos alguna modificacion en alguna tabla que utiliza para calcularlo ya no seria correcto pero si hazemos alguna modificacion en alguna tabla que utiliza para calcularlo ya no seria correcto

View File

@ -83,8 +83,6 @@ async function backTestOnce(done) {
port: container.dbConf.port port: container.dbConf.port
}); });
log('[Debug] dataSources', dataSources.vn);
let bootOptions = {dataSources}; let bootOptions = {dataSources};
let app = require(`./loopback/server/server`); let app = require(`./loopback/server/server`);
@ -92,8 +90,6 @@ async function backTestOnce(done) {
try { try {
app.boot(bootOptions); app.boot(bootOptions);
log('[Debug] back started');
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
const jasmine = require('gulp-jasmine'); const jasmine = require('gulp-jasmine');

View File

@ -67,5 +67,6 @@
"Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member",
"Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member", "Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member",
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}", "Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}",
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment" "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
"NOT_ZONE_WITH_THIS_PARAMETERS": "NOT_ZONE_WITH_THIS_PARAMETERS"
} }

View File

@ -4,17 +4,15 @@ module.exports = Self => {
Self.remoteMethodCtx('createFromSales', { Self.remoteMethodCtx('createFromSales', {
description: 'Create a claim', description: 'Create a claim',
accepts: [{ accepts: [{
arg: 'claim', arg: 'ticketId',
type: 'object', type: 'Number',
required: true, required: true,
description: ' newTicketFk, clientFk, ticketCreated', description: 'The origin ticket id'
http: {source: 'body'}
}, { }, {
arg: 'sales', arg: 'sales',
type: 'object', type: ['Object'],
required: true, required: true,
description: '[sales IDs]', description: 'The claimed sales'
http: {source: 'body'}
}], }],
returns: { returns: {
type: 'object', type: 'object',
@ -26,28 +24,27 @@ module.exports = Self => {
} }
}); });
Self.createFromSales = async(ctx, params) => { Self.createFromSales = async(ctx, ticketId, sales) => {
let models = Self.app.models; const models = Self.app.models;
let userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
let tx = await Self.beginTransaction({}); const tx = await Self.beginTransaction({});
try { try {
let options = {transaction: tx}; let options = {transaction: tx};
const ticketId = params.claim.ticketFk;
const ticket = await models.Ticket.findById(ticketId, null, options); const ticket = await models.Ticket.findById(ticketId, null, options);
if (ticket.isDeleted) if (ticket.isDeleted)
throw new UserError(`You can't create a claim for a removed ticket`); throw new UserError(`You can't create a claim for a removed ticket`);
const worker = await models.Worker.findOne({ const newClaim = await Self.create({
where: {userFk: userId} ticketFk: ticketId,
clientFk: ticket.clientFk,
ticketCreated: ticket.shipped,
workerFk: userId
}, options); }, options);
const promises = [];
params.claim.workerFk = worker.id; for (const sale of sales) {
let newClaim = await Self.create(params.claim, options);
let promises = [];
for (const sale of params.sales) {
const newClaimBeginning = models.ClaimBeginning.create({ const newClaimBeginning = models.ClaimBeginning.create({
saleFk: sale.id, saleFk: sale.id,
claimFk: newClaim.id, claimFk: newClaim.id,

View File

@ -1,7 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('Claim Create', () => { describe('Claim createFromSales()', () => {
let newDate = new Date();
let createdClaimFk; let createdClaimFk;
afterAll(async done => { afterAll(async done => {
@ -10,28 +9,18 @@ describe('Claim Create', () => {
done(); done();
}); });
let newClaim = { const ticketId = 2;
ticketFk: 2, const newSale = [{
clientFk: 101,
ticketCreated: newDate
};
let newSale = [{
id: 3, id: 3,
instance: 0, instance: 0,
quantity: 10 quantity: 10
}]; }];
const ctx = {req: {accessToken: {userId: 1}}};
let params = {claim: newClaim, sales: newSale};
let ctx = {req: {accessToken: {userId: 1}}};
it('should create a new claim', async() => { it('should create a new claim', async() => {
let claim = await app.models.Claim.createFromSales(ctx, params); let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
expect(claim.ticketFk).toEqual(newClaim.ticketFk); expect(claim.ticketFk).toEqual(ticketId);
expect(claim.clientFk).toEqual(newClaim.clientFk);
expect(claim.ticketCreated).toEqual(newClaim.ticketCreated);
expect(claim.workerFk).toEqual(newClaim.workerFk);
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}}); let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}});
@ -44,7 +33,7 @@ describe('Claim Create', () => {
it('should not be able to create a claim if exists that sale', async() => { it('should not be able to create a claim if exists that sale', async() => {
let error; let error;
await app.models.Claim.createFromSales(ctx, params) await app.models.Claim.createFromSales(ctx, ticketId, newSale)
.catch(e => { .catch(e => {
error = e; error = e;

View File

@ -0,0 +1,43 @@
let UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('deleteSales', {
description: 'Deletes the selected sales',
accessType: 'WRITE',
accepts: [{
arg: 'sales',
type: ['Object'],
required: true,
description: 'The sales to remove'
},
{
arg: 'ticketId',
type: 'Number',
required: true,
description: 'The ticket id'
}],
returns: {
type: ['Object'],
root: true
},
http: {
path: `/deleteSales`,
verb: 'POST'
}
});
Self.deleteSales = async(ctx, sales, ticketId) => {
const models = Self.app.models;
const isTicketEditable = await models.Ticket.isEditable(ctx, ticketId);
if (!isTicketEditable)
throw new UserError(`The sales of this ticket can't be modified`);
const promises = [];
for (let sale of sales) {
const deletedSale = models.Sale.destroyById(sale.id);
promises.push(deletedSale);
}
return Promise.all(promises);
};
};

View File

@ -1,35 +0,0 @@
let UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('removes', {
description: 'Change the state of a ticket',
accessType: 'WRITE',
accepts: [{
arg: 'params',
type: 'object',
required: true,
description: '[sales IDs], actualTicketFk',
http: {source: 'body'}
}],
returns: {
type: 'string',
root: true
},
http: {
path: `/removes`,
verb: 'post'
}
});
Self.removes = async(ctx, params) => {
let thisTicketIsEditable = await Self.app.models.Ticket.isEditable(ctx, params.actualTicketFk);
if (!thisTicketIsEditable)
throw new UserError(`The sales of this ticket can't be modified`);
let promises = [];
for (let i = 0; i < params.sales.length; i++)
promises.push(Self.app.models.Sale.destroyById(params.sales[i].id));
return Promise.all(promises);
};
};

View File

@ -6,28 +6,43 @@ module.exports = Self => {
description: 'Change the state of a ticket', description: 'Change the state of a ticket',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'params', arg: 'ticketId',
type: 'object', type: 'Number',
required: true, required: true,
description: '[sales IDs], ticketFk, reserved', description: 'The ticket id'
http: {source: 'body'} }, {
arg: 'sales',
type: ['Object'],
required: true,
description: 'The sale to reserve'
},
{
arg: 'reserved',
type: 'Boolean',
required: true
}], }],
returns: { returns: {
type: 'string', type: ['Object'],
root: true root: true
}, },
http: { http: {
path: `/reserve`, path: `/reserve`,
verb: 'post' verb: 'POST'
} }
}); });
Self.reserve = async(ctx, params) => { Self.reserve = async(ctx, ticketId, sales, reserved) => {
let thisTicketIsEditable = await Self.app.models.Ticket.isEditable(ctx, params.ticketFk); const models = Self.app.models;
if (!thisTicketIsEditable) const isTicketEditable = await models.Ticket.isEditable(ctx, ticketId);
if (!isTicketEditable)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
for (let i = 0; i < params.sales.length; i++) const promises = [];
await Self.app.models.Sale.update({id: params.sales[i].id}, {reserved: params.reserved}); for (let sale of sales) {
const reservedSale = models.Sale.update({id: sale.id}, {reserved: reserved});
promises.push(reservedSale);
}
return Promise.all(promises);
}; };
}; };

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('sale removes()', () => { describe('sale deleteSales()', () => {
let sale; let sale;
let newsale; let newsale;
@ -16,13 +16,11 @@ describe('sale removes()', () => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let error; let error;
let params = { const sales = [{id: 1, instance: 0}, {id: 2, instance: 1}];
sales: [{id: 1, instance: 0}, {id: 2, instance: 1}], const ticketId = 2;
actualTicketFk: 2
};
try { try {
await app.models.Sale.removes(ctx, params); await app.models.Sale.deleteSales(ctx, sales, ticketId);
} catch (e) { } catch (e) {
error = e; error = e;
} }
@ -32,12 +30,11 @@ describe('sale removes()', () => {
it('should delete the sales', async() => { it('should delete the sales', async() => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let params = {
sales: [{id: newsale.id, instance: 0}],
actualTicketFk: 16
};
let res = await app.models.Sale.removes(ctx, params); const sales = [{id: newsale.id, instance: 0}];
const ticketId = 16;
let res = await app.models.Sale.deleteSales(ctx, sales, ticketId);
expect(res).toEqual([{count: 1}]); expect(res).toEqual([{count: 1}]);
}); });

View File

@ -1,6 +1,7 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('sale reserve()', () => { describe('sale reserve()', () => {
const ctx = {req: {accessToken: {userId: 9}}};
afterAll(async done => { afterAll(async done => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let params = { let params = {
@ -17,13 +18,12 @@ describe('sale reserve()', () => {
}); });
it('should throw an error if the ticket can not be modified', async() => { it('should throw an error if the ticket can not be modified', async() => {
let ctx = {req: {accessToken: {userId: 9}}};
let error; let error;
let params = {ticketFk: 2, const ticketId = 2;
sales: [{id: 5}], const sales = [{id: 5}];
reserved: false}; const reserved = false;
await app.models.Sale.reserve(ctx, params) await app.models.Sale.reserve(ctx, ticketId, sales, reserved)
.catch(response => { .catch(response => {
expect(response).toEqual(new Error(`The sales of this ticket can't be modified`)); expect(response).toEqual(new Error(`The sales of this ticket can't be modified`));
error = response; error = response;
@ -38,18 +38,13 @@ describe('sale reserve()', () => {
expect(originalTicketSales[0].reserved).toEqual(0); expect(originalTicketSales[0].reserved).toEqual(0);
expect(originalTicketSales[1].reserved).toEqual(0); expect(originalTicketSales[1].reserved).toEqual(0);
let ctx = {req: {accessToken: {userId: 9}}}; const ticketId = 11;
let params = { const sales = [{id: 7}, {id: 8}];
sales: [ const reserved = true;
{id: 7},
{id: 8}],
ticketFk: 11,
reserved: true
};
await app.models.Sale.reserve(ctx, params); await app.models.Sale.reserve(ctx, ticketId, sales, reserved);
let reservedTicketSales = await app.models.Ticket.getSales(11); const reservedTicketSales = await app.models.Ticket.getSales(ticketId);
expect(reservedTicketSales[0].reserved).toEqual(1); expect(reservedTicketSales[0].reserved).toEqual(1);
expect(reservedTicketSales[1].reserved).toEqual(1); expect(reservedTicketSales[1].reserved).toEqual(1);

View File

@ -56,7 +56,9 @@ module.exports = Self => {
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
let usesMana = await models.WorkerMana.findOne({where: {workerFk: userId}, fields: 'amount'}, options); let usesMana = await models.WorkerMana.findOne({where: {workerFk: userId}, fields: 'amount'}, options);
let componentCode = usesMana ? 'mana' : 'buyerDiscount'; let componentCode = usesMana ? 'mana' : 'buyerDiscount';
let discount = await models.Component.findOne({where: {code: componentCode}}, options); let discount = await models.Component.findOne({where: {code: componentCode}}, options);
@ -80,7 +82,6 @@ module.exports = Self => {
value: componentValue value: componentValue
}, options); }, options);
} }
await sale.updateAttributes({price: newPrice}, options); await sale.updateAttributes({price: newPrice}, options);
query = `CALL vn.manaSpellersRequery(?)`; query = `CALL vn.manaSpellersRequery(?)`;

View File

@ -1,12 +1,12 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('getSalesPersonMana', { Self.remoteMethod('getSalesPersonMana', {
description: 'Returns mana of a salesperson of a ticket', description: 'Returns the mana amount of a salesperson for a ticket',
accessType: 'READ', accessType: 'READ',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'number', type: 'number',
required: true, required: true,
description: 'ticket id', description: 'The ticket id',
http: {source: 'path'} http: {source: 'path'}
}], }],
returns: { returns: {
@ -18,8 +18,9 @@ module.exports = Self => {
} }
}); });
Self.getSalesPersonMana = async ticketFk => { Self.getSalesPersonMana = async ticketId => {
let ticket = await Self.app.models.Ticket.findById(ticketFk, { const models = Self.app.models;
const ticket = await models.Ticket.findById(ticketId, {
include: [{ include: [{
relation: 'client', relation: 'client',
scope: { scope: {
@ -29,10 +30,12 @@ module.exports = Self => {
fields: ['id', 'clientFk'] fields: ['id', 'clientFk']
}); });
if (!ticket) if (!ticket) return 0;
return 0;
let mana = await Self.app.models.WorkerMana.findOne({where: {workerFk: ticket.client().salesPersonFk}, fields: 'amount'}); const mana = await models.WorkerMana.findOne({
where: {
workerFk: ticket.client().salesPersonFk
}, fields: 'amount'});
return mana ? mana.amount : 0; return mana ? mana.amount : 0;
}; };

View File

@ -8,7 +8,7 @@ describe('sale updateDiscount()', () => {
beforeAll(async done => { beforeAll(async done => {
originalSale = await app.models.Sale.findById(originalSaleId); originalSale = await app.models.Sale.findById(originalSaleId);
let manaDiscount = await app.models.Component.findOne({where: {code: 'mana'}}); let manaDiscount = await app.models.Component.findOne({where: {code: 'buyerDiscount'}});
componentId = manaDiscount.id; componentId = manaDiscount.id;
let ticket = await app.models.Ticket.findById(originalSale.ticketFk); let ticket = await app.models.Ticket.findById(originalSale.ticketFk);
@ -26,7 +26,6 @@ describe('sale updateDiscount()', () => {
done(); done();
}); });
it('should throw an error if no sales were selected', async() => { it('should throw an error if no sales were selected', async() => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
let error; let error;
@ -76,6 +75,28 @@ describe('sale updateDiscount()', () => {
}); });
it('should update the discount if the salesPerson has mana', async() => { it('should update the discount if the salesPerson has mana', async() => {
let ctx = {req: {accessToken: {userId: 18}}};
const ticketId = 11;
const sales = [originalSaleId];
const newDiscount = 100;
let manaDiscount = await app.models.Component.findOne({where: {code: 'mana'}});
componentId = manaDiscount.id;
await app.models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount);
let updatedSale = await app.models.Sale.findById(originalSaleId);
let createdSaleComponent = await app.models.SaleComponent.findOne({
where: {
componentFk: componentId,
saleFk: originalSaleId
}
});
expect(createdSaleComponent.componentFk).toEqual(componentId);
expect(updatedSale.discount).toEqual(100);
});
it('should update the discount and add company discount component if the worker does not have mana', async() => {
let ctx = {req: {accessToken: {userId: 9}}}; let ctx = {req: {accessToken: {userId: 9}}};
const ticketId = 11; const ticketId = 11;
const sales = [originalSaleId]; const sales = [originalSaleId];

View File

@ -35,7 +35,6 @@ module.exports = Self => {
}); });
Self.updateDiscount = async(ctx, id, salesIds, newDiscount) => { Self.updateDiscount = async(ctx, id, salesIds, newDiscount) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models; const models = Self.app.models;
const tx = await Self.beginTransaction({}); const tx = await Self.beginTransaction({});
@ -69,6 +68,7 @@ module.exports = Self => {
if (!allFromSameTicket) if (!allFromSameTicket)
throw new UserError('All sales must belong to the same ticket'); throw new UserError('All sales must belong to the same ticket');
const userId = ctx.req.accessToken.userId;
const isLocked = await models.Ticket.isLocked(id); const isLocked = await models.Ticket.isLocked(id);
const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson'); const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson');
const state = await Self.app.models.TicketState.findOne({ const state = await Self.app.models.TicketState.findOne({
@ -79,18 +79,9 @@ module.exports = Self => {
if (isLocked || (!isSalesPerson && alertLevel > 0)) if (isLocked || (!isSalesPerson && alertLevel > 0))
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
const ticket = await models.Ticket.findById(id, {
include: {
relation: 'client',
scope: {
fields: ['salesPersonFk']
}
},
}, options);
const salesPersonId = ticket.client().salesPersonFk;
const usesMana = await models.WorkerMana.findOne({ const usesMana = await models.WorkerMana.findOne({
where: { where: {
workerFk: salesPersonId workerFk: userId
}, },
fields: 'amount'}, options); fields: 'amount'}, options);
@ -99,7 +90,6 @@ module.exports = Self => {
where: {code: componentCode}}, options); where: {code: componentCode}}, options);
const componentId = discountComponent.id; const componentId = discountComponent.id;
let promises = []; let promises = [];
for (let sale of sales) { for (let sale of sales) {
const value = ((-sale.price * newDiscount) / 100); const value = ((-sale.price * newDiscount) / 100);
@ -115,10 +105,8 @@ module.exports = Self => {
await Promise.all(promises); await Promise.all(promises);
if (salesPersonId) { const query = `call vn.manaSpellersRequery(?)`;
const query = `call vn.manaSpellersRequery(?)`; await Self.rawSql(query, [userId], options);
await Self.rawSql(query, [salesPersonId], options);
}
await tx.commit(); await tx.commit();
} catch (error) { } catch (error) {

View File

@ -1,7 +1,7 @@
module.exports = Self => { module.exports = Self => {
require('../methods/sale/getClaimableFromTicket')(Self); require('../methods/sale/getClaimableFromTicket')(Self);
require('../methods/sale/reserve')(Self); require('../methods/sale/reserve')(Self);
require('../methods/sale/removes')(Self); require('../methods/sale/deleteSales')(Self);
require('../methods/sale/updatePrice')(Self); require('../methods/sale/updatePrice')(Self);
require('../methods/sale/updateQuantity')(Self); require('../methods/sale/updateQuantity')(Self);
require('../methods/sale/updateConcept')(Self); require('../methods/sale/updateConcept')(Self);

View File

@ -18,7 +18,6 @@ import './expedition';
import './volume'; import './volume';
import './package/index'; import './package/index';
import './sale'; import './sale';
import './sale/editDiscount';
import './tracking/index'; import './tracking/index';
import './tracking/edit'; import './tracking/edit';
import './sale-checked'; import './sale-checked';

View File

@ -1,16 +0,0 @@
<section class="header vn-pa-md">
<h5>MANÁ: {{$ctrl.mana | currency: 'EUR':0}}</h5>
</section>
<div class="vn-pa-md">
<vn-input-number
vn-focus
label="Discount"
ng-model="$ctrl.newDiscount"
on-change="$ctrl.updateDiscount()"
suffix="%">
</vn-input-number>
<div class="simulator">
<p class="simulatorTitle" translate>New price</p>
<p>{{$ctrl.newPrice | currency: 'EUR':2}}</p>
</div>
</div>

View File

@ -1,88 +0,0 @@
import ngModule from '../module';
import Component from 'core/lib/component';
class Controller extends Component {
set edit(value) {
this._edit = value;
this.clearDiscount();
this.setNewDiscount();
}
get edit() {
return this._edit;
}
set bulk(value) {
this._bulk = value;
this.setNewDiscount();
}
get bulk() {
return this._bulk;
}
get newDiscount() {
return this._newDiscount;
}
set newDiscount(value) {
this._newDiscount = value;
this.updateNewPrice();
}
updateNewPrice() {
if (this.newDiscount && this.edit[0])
this.newPrice = (this.edit[0].quantity * this.edit[0].price) - ((this.newDiscount * (this.edit[0].quantity * this.edit[0].price)) / 100);
}
setNewDiscount() {
if (!this.newDiscount && this.edit[0])
this.newDiscount = this.edit[0].discount;
}
updateDiscount() {
let salesIds = [];
let modified = false;
if (this.newDiscount == null) return;
for (let i = 0; i < this.edit.length; i++) {
if (this.newDiscount != this.edit[0].discount || this.bulk || !this.newDiscount) {
salesIds.push(this.edit[i].id);
modified = true;
}
}
if (modified) {
const params = {salesIds: salesIds, newDiscount: this.newDiscount};
const query = `Tickets/${this.$params.id}/updateDiscount`;
this.$http.post(query, params).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
console.log(this.edit[0].sale);
this.edit[0].sale.price = 277;
this.clearDiscount();
modified = false;
}).catch(e => {
this.vnApp.showError(e.message);
});
this.onHide();
} else
this.vnApp.showError(this.$translate.instant('There are no changes to save'));
}
clearDiscount() {
this.newDiscount = null;
}
}
ngModule.component('vnTicketSaleEditDiscount', {
template: require('./editDiscount.html'),
controller: Controller,
bindings: {
edit: '<?',
mana: '<?',
bulk: '<?',
onHide: '&'
}
});

View File

@ -141,7 +141,7 @@
<vn-textfield class="dense" vn-focus <vn-textfield class="dense" vn-focus
vn-id="concept" vn-id="concept"
ng-model="sale.concept" ng-model="sale.concept"
on-change="$ctrl.changeConcept(sale)"> on-change="$ctrl.updateConcept(sale)">
</vn-textfield> </vn-textfield>
</field> </field>
</vn-td-editable> </vn-td-editable>

View File

@ -130,23 +130,6 @@ class Controller extends Section {
}); });
} }
/**
* Returns an array of index
* from checked instances
*
* @return {Array} Index list of checked instances
*/
selectedSalesIndex() {
if (!this.sales) return;
const indexList = [];
this.sales.forEach((sale, index) => {
if (sale.checked) indexList.push(index);
});
return indexList;
}
resetChanges() { resetChanges() {
if (this.newInstances().length === 0) if (this.newInstances().length === 0)
this.$.watcher.updateOriginalData(); this.$.watcher.updateOriginalData();
@ -162,8 +145,8 @@ class Controller extends Section {
removeSales() { removeSales() {
const sales = this.selectedValidSales(); const sales = this.selectedValidSales();
const params = {sales: sales, actualTicketFk: this.ticket.id}; const params = {sales: sales, ticketId: this.ticket.id};
this.$http.post(`Sales/removes`, params).then(() => { this.$http.post(`Sales/deleteSales`, params).then(() => {
this.removeSelectedSales(); this.removeSelectedSales();
this.vnApp.showSuccess(this.$t('Data saved!')); this.vnApp.showSuccess(this.$t('Data saved!'));
}).finally(() => this.resetChanges()); }).finally(() => this.resetChanges());
@ -181,15 +164,7 @@ class Controller extends Section {
createClaim() { createClaim() {
const sales = this.selectedValidSales(); const sales = this.selectedValidSales();
const params = { const params = {ticketId: this.ticket.id, sales: sales};
claim: {
ticketFk: this.ticket.id,
clientFk: this.ticket.clientFk,
ticketCreated: this.ticket.shipped
},
sales: sales
};
this.resetChanges(); this.resetChanges();
this.$http.post(`Claims/createFromSales`, params) this.$http.post(`Claims/createFromSales`, params)
.then(res => this.$state.go('claim.card.basicData', {id: res.data.id})); .then(res => this.$state.go('claim.card.basicData', {id: res.data.id}));
@ -197,8 +172,7 @@ class Controller extends Section {
showTransferPopover(event) { showTransferPopover(event) {
this.setTransferParams(); this.setTransferParams();
this.$.transfer.parent = event.target; this.$.transfer.show(event);
this.$.transfer.show();
} }
setTransferParams() { setTransferParams() {
@ -357,21 +331,11 @@ class Controller extends Section {
} }
setReserved(reserved) { setReserved(reserved) {
let selectedSales = this.selectedValidSales(); const selectedSales = this.selectedValidSales();
let params = {sales: selectedSales, ticketFk: this.ticket.id, reserved: reserved}; const params = {ticketId: this.ticket.id, sales: selectedSales, reserved: reserved};
this.$http.post(`Sales/reserve`, params).then(() => {
let reservedSales = new Map(); selectedSales.forEach(sale => {
this.$http.post(`Sales/reserve`, params).then(res => { sale.reserved = reserved;
let isReserved = res.config.data.reserved;
res.config.data.sales.forEach(sale => {
reservedSales.set(sale.id, {reserved: isReserved});
});
this.sales.forEach(sale => {
const reservedSale = reservedSales.get(sale.id);
if (reservedSale)
sale.reserved = reservedSale.reserved;
}); });
}).finally(() => this.resetChanges()); }).finally(() => this.resetChanges());
} }
@ -444,7 +408,7 @@ class Controller extends Section {
/* /*
* Changes a sale concept * Changes a sale concept
*/ */
changeConcept(sale) { updateConcept(sale) {
const data = {newConcept: sale.concept}; const data = {newConcept: sale.concept};
this.$http.post(`Sales/${sale.id}/updateConcept`, data).then(() => { this.$http.post(`Sales/${sale.id}/updateConcept`, data).then(() => {
this.vnApp.showSuccess(this.$t('Data saved!')); this.vnApp.showSuccess(this.$t('Data saved!'));
@ -481,12 +445,12 @@ class Controller extends Section {
} }
isTicketEditable() { isTicketEditable() {
this.$http.get(`Tickets/${this.$state.params.id}/isEditable`) this.$http.get(`Tickets/${this.$params.id}/isEditable`)
.then(res => this.isEditable = res.data); .then(res => this.isEditable = res.data);
} }
isTicketLocked() { isTicketLocked() {
this.$http.get(`Tickets/${this.$state.params.id}/isLocked`) this.$http.get(`Tickets/${this.$params.id}/isLocked`)
.then(res => this.isLocked = res.data); .then(res => this.isLocked = res.data);
} }

View File

@ -0,0 +1,718 @@
import './index.js';
import watcher from 'core/mocks/watcher';
import crudModel from 'core/mocks/crud-model';
describe('Ticket', () => {
describe('Component vnTicketSale', () => {
let controller;
let $scope;
let $state;
let $httpBackend;
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$state_, _$httpBackend_) => {
const ticket = {
id: 1,
clientFk: 101,
shipped: 1,
created: new Date(),
client: {salesPersonFk: 1},
address: {mobile: 111111111}
};
const sales = [
{
id: 1,
concept: 'Item 1',
quantity: 5,
price: 23.5,
discount: 0,
}, {
id: 4,
concept: 'Item 2',
quantity: 20,
price: 5.5,
discount: 0,
}
];
$state = _$state_;
$scope = $rootScope.$new();
$scope.watcher = watcher;
$scope.sms = {open: () => {}};
$scope.ticket = ticket;
$scope.model = crudModel;
$httpBackend = _$httpBackend_;
Object.defineProperties($state.params, {
id: {
value: ticket.id,
writable: true
},
go: {
value: () => {},
writable: false
}
});
const $element = angular.element('<vn-ticket-sale></vn-ticket-sale>');
controller = $componentController('vnTicketSale', {$element, $scope});
controller.card = {reload: () => {}};
controller._ticket = ticket;
controller._sales = sales;
}));
describe('ticket() setter', () => {
it('should set the ticket data an then call the isTicketEditable() and isTicketLocked() methods', () => {
jest.spyOn(controller, 'isTicketEditable').mockReturnThis();
jest.spyOn(controller, 'isTicketLocked').mockReturnThis();
controller.ticket = {id: 1};
expect(controller.isTicketEditable).toHaveBeenCalledWith();
expect(controller.isTicketLocked).toHaveBeenCalledWith();
});
});
describe('sales() setter', () => {
it('should set the sales data an then call the refreshTotal() method', () => {
jest.spyOn(controller, 'refreshTotal').mockReturnThis();
controller.sales = [{id: 1}];
expect(controller.refreshTotal).toHaveBeenCalledWith();
});
});
describe('getSubTotal()', () => {
it('should make an HTTP GET query and then set the subtotal property', () => {
const expectedAmount = 128;
$httpBackend.expect('GET', 'Tickets/1/subtotal').respond(200, expectedAmount);
controller.getSubTotal();
$httpBackend.flush();
expect(controller.subtotal).toEqual(expectedAmount);
});
});
describe('getSaleTotal()', () => {
it('should return the sale total amount', () => {
const sale = {
quantity: 10,
price: 2,
discount: 10
};
const expectedAmount = 18;
const result = controller.getSaleTotal(sale);
expect(result).toEqual(expectedAmount);
});
});
describe('getMana()', () => {
it('should make an HTTP GET query and return the worker mana', () => {
controller.edit = {};
const expectedAmount = 250;
$httpBackend.expect('GET', 'Tickets/1/getSalesPersonMana').respond(200, expectedAmount);
controller.getMana();
$httpBackend.flush();
expect(controller.edit.mana).toEqual(expectedAmount);
});
});
describe('getVat()', () => {
it('should make an HTTP GET query and return the ticket VAT', () => {
controller.edit = {};
const expectedAmount = 67;
$httpBackend.expect('GET', 'Tickets/1/getVAT').respond(200, expectedAmount);
controller.getVat();
$httpBackend.flush();
expect(controller.VAT).toEqual(expectedAmount);
});
});
describe('selectedSales()', () => {
it('should return a list of selected sales', () => {
controller.sales[1].checked = true;
const expectedSaleId = 4;
const result = controller.selectedSales();
const firstSelectedSale = result[0];
expect(result.length).toEqual(1);
expect(firstSelectedSale.id).toEqual(expectedSaleId);
});
});
describe('selectedValidSales()', () => {
it('should return a list of selected sales having a sale id', () => {
const newEmptySale = {quantity: 10, checked: true};
controller.sales.push(newEmptySale);
controller.sales[0].checked = true;
const expectedSaleId = 1;
const result = controller.selectedValidSales();
const firstSelectedSale = result[0];
expect(result.length).toEqual(1);
expect(firstSelectedSale.id).toEqual(expectedSaleId);
});
});
describe('selectedSalesCount()', () => {
it('should return the number of selected sales', () => {
controller.sales[0].checked = true;
const result = controller.selectedSalesCount();
expect(result).toEqual(1);
});
});
describe('hasSelectedSales()', () => {
it('should return truthy if atleast one sale is selected', () => {
controller.sales[0].checked = true;
const result = controller.hasSelectedSales();
expect(result).toBeTruthy();
});
});
describe('hasOneSaleSelected()', () => {
it('should return truthy if just one sale is selected', () => {
controller.sales[0].checked = true;
const result = controller.hasOneSaleSelected();
expect(result).toBeTruthy();
});
it('should return falsy if more than one sale is selected', () => {
controller.sales[0].checked = true;
controller.sales[1].checked = true;
const result = controller.hasOneSaleSelected();
expect(result).toBeFalsy();
});
});
describe('newInstances()', () => {
it(`should return a list of sales that doesn't have an id`, () => {
const newEmptySale = {quantity: 10, checked: true};
controller.sales.push(newEmptySale);
const result = controller.newInstances();
const firstNewSale = result[0];
expect(result.length).toEqual(1);
expect(firstNewSale.id).toBeUndefined();
expect(firstNewSale.quantity).toEqual(10);
});
});
describe('resetChanges()', () => {
it(`should not call the watcher updateOriginalData() method`, () => {
jest.spyOn(controller.$.watcher, 'updateOriginalData').mockReturnThis();
const newEmptySale = {quantity: 10};
controller.sales.push(newEmptySale);
controller.resetChanges();
expect(controller.$.watcher.updateOriginalData).not.toHaveBeenCalledWith();
});
it(`should call the watcher updateOriginalData() method`, () => {
jest.spyOn(controller.$.watcher, 'updateOriginalData').mockReturnThis();
controller.resetChanges();
expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});
describe('changeState()', () => {
it('should make an HTTP post query, then call the showSuccess(), reload() and resetChanges() methods', () => {
jest.spyOn(controller.card, 'reload').mockReturnThis();
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const expectedParams = {ticketFk: 1, code: 'OK'};
$httpBackend.expect('POST', `TicketTrackings/changeState`, expectedParams).respond(200);
controller.changeState('OK');
$httpBackend.flush();
expect(controller.card.reload).toHaveBeenCalledWith();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('removeSales()', () => {
it('should make an HTTP post query, then call the showSuccess(), removeSelectedSales() and resetChanges() methods', () => {
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
jest.spyOn(controller, 'removeSelectedSales').mockReturnThis();
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const firstSale = controller.sales[0];
firstSale.checked = true;
const expectedParams = {sales: [firstSale], ticketId: 1};
$httpBackend.expect('POST', `Sales/deleteSales`, expectedParams).respond(200);
controller.removeSales();
$httpBackend.flush();
expect(controller.removeSelectedSales).toHaveBeenCalledWith();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('removeSelectedSales()', () => {
it('should remove the selected sales from the controller sale property', () => {
jest.spyOn(controller, 'refreshTotal').mockReturnThis();
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const firstSale = controller.sales[0];
firstSale.checked = true;
controller.removeSelectedSales();
const lastSale = controller.sales[0];
expect(controller.sales.length).toEqual(1);
expect(lastSale.id).toEqual(4);
expect(controller.refreshTotal).toHaveBeenCalledWith();
});
});
describe('createClaim()', () => {
it('should perform a query and call windows open', () => {
jest.spyOn(controller, 'resetChanges').mockReturnThis();
jest.spyOn(controller.$state, 'go').mockReturnThis();
const newEmptySale = {quantity: 10};
controller.sales.push(newEmptySale);
const firstSale = controller.sales[0];
firstSale.checked = true;
const expectedParams = {ticketId: 1, sales: [firstSale]};
$httpBackend.expect('POST', `Claims/createFromSales`, expectedParams).respond(200, {id: 1});
controller.createClaim();
$httpBackend.flush();
expect(controller.resetChanges).toHaveBeenCalledWith();
expect(controller.$state.go).toHaveBeenCalledWith('claim.card.basicData', {id: 1});
});
});
describe('setTransferParams()', () => {
it('should define the transfer object on the controller and its default properties', () => {
const firstSale = controller.sales[0];
firstSale.checked = true;
const expectedResponse = [firstSale];
$httpBackend.expect('GET', `clients/101/lastActiveTickets?ticketId=1`).respond(expectedResponse);
controller.setTransferParams();
$httpBackend.flush();
const lastActiveTickets = controller.transfer.lastActiveTickets;
expect(controller.transfer).toBeDefined();
expect(lastActiveTickets).toBeDefined();
expect(lastActiveTickets[0].id).toEqual(1);
});
});
describe('transferSales()', () => {
it('should transfer sales to a ticket and then call to the $state go() method', () => {
jest.spyOn(controller.$state, 'go').mockReturnThis();
controller.transfer = {
sales: [{id: 1, itemFk: 1}, {id: 2, itemFk: 4}]
};
const ticketIdToTransfer = 13;
const expectedResponse = {id: ticketIdToTransfer};
const params = {
ticketId: 13,
sales: controller.transfer.sales
};
$httpBackend.expect('POST', `tickets/1/transferSales`, params).respond(expectedResponse);
controller.transferSales(ticketIdToTransfer);
$httpBackend.flush();
expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', {id: ticketIdToTransfer});
});
});
describe('updatePrice()', () => {
it('should make an HTTP POST query, update the sale price and then call to the resetChanges() method', () => {
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const selectedSale = controller.sales[0];
selectedSale.checked = true;
controller.$.editPricePopover = {hide: jest.fn()};
controller.edit = {
price: 2,
sale: selectedSale
};
const expectedParams = {newPrice: 2};
$httpBackend.expect('POST', `Sales/1/updatePrice`, expectedParams).respond(200, {price: 2});
controller.updatePrice();
$httpBackend.flush();
expect(selectedSale.price).toEqual(2);
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.$.editPricePopover.hide).toHaveBeenCalledWith();
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('changeDiscount()', () => {
it('should call to the updateDiscount() method and then to the editDiscount hide() method', () => {
jest.spyOn(controller, 'updateDiscount').mockReturnThis();
const selectedSale = controller.sales[0];
selectedSale.checked = true;
const expectedSale = selectedSale;
controller.$.editDiscount = {hide: jest.fn()};
controller.edit = {
discount: 10,
sale: selectedSale
};
controller.changeDiscount();
expect(controller.updateDiscount).toHaveBeenCalledWith([expectedSale]);
expect(controller.$.editDiscount.hide).toHaveBeenCalledWith();
});
});
describe('changeMultipleDiscount()', () => {
it('should call to the updateDiscount() method and then to the editDiscountDialog hide() method', () => {
jest.spyOn(controller, 'updateDiscount').mockReturnThis();
const firstSelectedSale = controller.sales[0];
firstSelectedSale.checked = true;
const secondSelectedSale = controller.sales[1];
secondSelectedSale.checked = true;
const expectedSales = [firstSelectedSale, secondSelectedSale];
controller.$.editDiscountDialog = {hide: jest.fn()};
controller.edit = {
discount: 10,
sales: expectedSales
};
controller.changeMultipleDiscount();
expect(controller.updateDiscount).toHaveBeenCalledWith(expectedSales);
expect(controller.$.editDiscountDialog.hide).toHaveBeenCalledWith();
});
it('should not call to the updateDiscount() method and then to the editDiscountDialog hide() method', () => {
jest.spyOn(controller, 'updateDiscount').mockReturnThis();
const firstSelectedSale = controller.sales[0];
firstSelectedSale.checked = true;
firstSelectedSale.discount = 10;
const secondSelectedSale = controller.sales[1];
secondSelectedSale.checked = true;
secondSelectedSale.discount = 10;
const expectedSales = [firstSelectedSale, secondSelectedSale];
controller.$.editDiscountDialog = {hide: jest.fn()};
controller.edit = {
discount: 10,
sales: expectedSales
};
controller.changeMultipleDiscount();
expect(controller.updateDiscount).not.toHaveBeenCalledWith(expectedSales);
expect(controller.$.editDiscountDialog.hide).toHaveBeenCalledWith();
});
});
describe('updateDiscount()', () => {
it('should make an HTTP POST query, update the sales discount and then call to the resetChanges() method', () => {
jest.spyOn(controller, 'resetChanges').mockReturnThis();
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
const expectedDiscount = 10;
const firstSelectedSale = controller.sales[0];
firstSelectedSale.checked = true;
const secondSelectedSale = controller.sales[1];
secondSelectedSale.checked = true;
controller.edit = {
discount: expectedDiscount
};
const expectedSales = [firstSelectedSale, secondSelectedSale];
const expectedSaleIds = [firstSelectedSale.id, secondSelectedSale.id];
const expectedParams = {salesIds: expectedSaleIds, newDiscount: expectedDiscount};
$httpBackend.expect('POST', `Tickets/1/updateDiscount`, expectedParams).respond(200, {discount: 10});
controller.updateDiscount(expectedSales);
$httpBackend.flush();
expect(firstSelectedSale.discount).toEqual(expectedDiscount);
expect(secondSelectedSale.discount).toEqual(expectedDiscount);
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('getNewPrice()', () => {
it('should return the total price simulation from a price change', () => {
const selectedSale = controller.sales[0];
selectedSale.checked = true;
controller.edit = {
price: 2,
sale: selectedSale
};
const expectedAmount = 10;
const result = controller.getNewPrice();
expect(result).toEqual(expectedAmount);
});
it('should return the total price simulation from a discount change', () => {
const selectedSale = controller.sales[0];
selectedSale.checked = true;
controller.edit = {
discount: 10,
sale: selectedSale
};
const expectedAmount = 105.75;
const result = controller.getNewPrice();
expect(result).toEqual(expectedAmount);
});
});
describe('hasReserves()', () => {
it('should return true for any sale marked as reserved', () => {
const selectedSale = controller.sales[0];
selectedSale.reserved = true;
const result = controller.hasReserves();
expect(result).toBeTruthy();
});
});
describe('unmarkAsReserved()', () => {
it('should call setReserved with false', () => {
jest.spyOn(controller, 'setReserved');
controller.unmarkAsReserved(false);
expect(controller.setReserved).toHaveBeenCalledWith(false);
});
});
describe('markAsReserved()', () => {
it('should call setReserved with true', () => {
jest.spyOn(controller, 'setReserved');
controller.markAsReserved(true);
expect(controller.setReserved).toHaveBeenCalledWith(true);
});
});
describe('setReserved()', () => {
it('should call getCheckedLines, $.index.accept and make a query ', () => {
const selectedSale = controller.sales[0];
selectedSale.checked = true;
const expectedParams = {
sales: [selectedSale],
ticketId: 1,
reserved: false
};
$httpBackend.expectPOST(`Sales/reserve`, expectedParams).respond();
controller.unmarkAsReserved(false);
$httpBackend.flush();
});
});
describe('newOrderFromTicket()', () => {
it('should make an HTTP post query and then open the new order on a new tab', () => {
const expectedParams = {ticketFk: 1};
const expectedResponse = {id: 123};
window.open = jasmine.createSpy('open');
controller.$state.href = jasmine.createSpy('href')
.and.returnValue('/somePath');
$httpBackend.expect('POST', `Orders/newFromTicket`, expectedParams).respond(expectedResponse);
controller.newOrderFromTicket();
$httpBackend.flush();
expect(window.open).toHaveBeenCalledWith('/somePath', '_blank');
});
});
describe('showSMSDialog()', () => {
it('should open an SMS dialog with specified data', () => {
jest.spyOn(controller.$.sms, 'open');
const selectedSale = controller.sales[0];
selectedSale.checked = true;
controller.showSMSDialog();
expect(controller.$.sms.open).toHaveBeenCalledWith();
expect(controller.newSMS.destination).toEqual(111111111);
expect(controller.newSMS.message).not.toEqual('');
});
});
describe('changeQuantity()', () => {
it('should not call addSale() or updateQuantity() methods', () => {
jest.spyOn(controller, 'addSale');
jest.spyOn(controller, 'updateQuantity');
const sale = {itemFk: 4};
controller.changeQuantity(sale);
expect(controller.addSale).not.toHaveBeenCalled();
expect(controller.updateQuantity).not.toHaveBeenCalled();
});
it('should call addSale() method', () => {
jest.spyOn(controller, 'addSale');
const sale = {itemFk: 4, quantity: 5};
controller.changeQuantity(sale);
expect(controller.addSale).toHaveBeenCalledWith(sale);
});
it('should call updateQuantity() method', () => {
jest.spyOn(controller, 'addSale');
jest.spyOn(controller, 'updateQuantity');
const sale = {id: 1, itemFk: 4, quantity: 5};
controller.changeQuantity(sale);
expect(controller.addSale).not.toHaveBeenCalled();
expect(controller.updateQuantity).toHaveBeenCalledWith(sale);
});
});
describe('updateQuantity()', () => {
it('should make a POST query saving sale quantity', () => {
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const selectedSale = controller.sales[0];
selectedSale.checked = true;
selectedSale.quantity = 10;
const expectedParams = {quantity: 10};
$httpBackend.expect('POST', `Sales/1/updateQuantity`, expectedParams).respond();
controller.updateQuantity(selectedSale);
$httpBackend.flush();
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('updateConcept()', () => {
it('should make a POST query saving sale concept', () => {
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const selectedSale = controller.sales[0];
selectedSale.checked = true;
selectedSale.concept = 'My new weapon';
const expectedParams = {newConcept: 'My new weapon'};
$httpBackend.expect('POST', `Sales/1/updateConcept`, expectedParams).respond();
controller.updateConcept(selectedSale);
$httpBackend.flush();
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('addSale()', () => {
it('should make a POST query adding a new sale', () => {
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
jest.spyOn(controller, 'resetChanges').mockReturnThis();
const newSale = {itemFk: 4, quantity: 10};
const expectedParams = {itemId: 4, quantity: 10};
const expectedResult = {
id: 30,
quantity: 10,
discount: 0,
price: 0,
itemFk: 4,
item: {
subName: 'Item subName',
image: '30.png'
}
};
$httpBackend.expect('POST', `tickets/1/addSale`, expectedParams).respond(expectedResult);
controller.addSale(newSale);
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.resetChanges).toHaveBeenCalledWith();
});
});
describe('isTicketEditable()', () => {
it('should make a HTTP GET query and set the isEditable property on the controller', () => {
$httpBackend.expect('GET', `Tickets/1/isEditable`).respond(200, true);
controller.isTicketEditable();
$httpBackend.flush();
expect(controller.isEditable).toBeDefined();
expect(controller.isEditable).toBeTruthy();
});
});
describe('isTicketLocked()', () => {
it('should make a HTTP GET query and set the isLocked property on the controller', () => {
$httpBackend.expect('GET', `Tickets/1/isLocked`).respond(200, false);
controller.isTicketLocked();
$httpBackend.flush();
expect(controller.isLocked).toBeDefined();
expect(controller.isLocked).toBeFalsy();
});
});
describe('calculateSalePrice()', () => {
it('should make an HTTP post query ', () => {
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
const selectedSale = controller.sales[0];
selectedSale.checked = true;
$httpBackend.expect('POST', `Sales/1/recalculatePrice`).respond(200);
controller.calculateSalePrice();
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.$.model.refresh).toHaveBeenCalledWith();
});
});
});
});

View File

@ -1,87 +0,0 @@
import '../editDiscount.js';
describe('Ticket', () => {
describe('Component vnTicketSaleEditDiscount', () => {
let controller;
let $httpBackend;
let $state;
let $scope;
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_, $rootScope) => {
$httpBackend = _$httpBackend_;
$scope = $rootScope.$new();
$scope.index = {model: {instances: [{id: 1}, {id: 2}]}, accept: () => {
return {
then: () => {}
};
}};
$state = _$state_;
$state.params.id = 11;
const $element = angular.element('<vn-ticket-sale-edit-discount></vn-ticket-sale-edit-discount>');
controller = $componentController('vnTicketSaleEditDiscount', {$element, $scope});
controller._edit = [{id: 3}];
controller.onHide = () => {};
}));
describe('edit() setter', () => {
it('should set _edit value and call setNewDiscount', () => {
jest.spyOn(controller, 'setNewDiscount');
controller.edit = {id: 1};
expect(controller.edit).toEqual({id: 1});
expect(controller.setNewDiscount).toHaveBeenCalledWith();
});
});
describe('bulk() setter', () => {
it('should set _bulk value and call setNewDiscount', () => {
jest.spyOn(controller, 'setNewDiscount');
controller.bulk = true;
expect(controller.bulk).toEqual(true);
expect(controller.setNewDiscount).toHaveBeenCalledWith();
});
});
describe('setNewDiscount()', () => {
it('should set NewDiscount to edit[0].discount value if it doesnt exists', () => {
controller.edit = [{discount: 1}];
controller.setNewDiscount();
expect(controller.newDiscount).toEqual(1);
});
});
describe('updateDiscount()', () => {
it('should make a query if the discount value has been modified or the bulk value is true', () => {
controller.bulk = true;
controller.newDiscount = 15;
$httpBackend.expectPOST(`Tickets/11/updateDiscount`).respond();
controller.updateDiscount();
$httpBackend.flush();
});
it(`should throw if there's no changes on discount and it isn't bulk`, () => {
controller.bulk = false;
controller.newDiscount = 15;
controller.edit = [{discount: 15}];
jest.spyOn(controller.vnApp, 'showError');
controller.updateDiscount();
expect(controller.vnApp.showError).toHaveBeenCalledWith('There are no changes to save');
});
});
describe('clearDiscount()', () => {
it('should set newDiscount to null', () => {
controller.clearDiscount();
expect(controller.newDiscount).toEqual(null);
});
});
});
});

View File

@ -1,409 +0,0 @@
import '../index.js';
import watcher from 'core/mocks/watcher';
import crudModel from 'core/mocks/crud-model';
describe('Ticket', () => {
describe('Component vnTicketSale', () => {
let controller;
let $scope;
let $state;
let $httpBackend;
const ticket = {
id: 1,
clientFk: 101,
shipped: 1,
created: new Date(),
client: {salesPersonFk: 1},
address: {mobile: 111111111}
};
const sales = [
{
id: 1,
concept: 'Item 1',
quantity: 5,
price: 23.5,
discount: 0,
}, {
id: 4,
concept: 'Item 2',
quantity: 20,
price: 5.5,
discount: 0,
}
];
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$state_, _$httpBackend_) => {
$state = _$state_;
$scope = $rootScope.$new();
$scope.watcher = watcher;
$scope.sms = {open: () => {}};
$scope.ticket = ticket;
$scope.model = crudModel;
$httpBackend = _$httpBackend_;
Object.defineProperties($state.params, {
id: {
value: ticket.id,
writable: true
},
go: {
value: () => {},
writable: false
}
});
const $element = angular.element('<vn-ticket-sale></vn-ticket-sale>');
controller = $componentController('vnTicketSale', {$element, $scope});
controller.card = {reload: () => {}};
controller.ticket = ticket;
controller.sales = sales;
}));
describe('createClaim()', () => {
it('should perform a query and call windows open', () => {
jest.spyOn(controller.$state, 'go');
const claim = {id: 1};
const sales = [{id: 1}, {id: 2}];
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
$httpBackend.when('POST', `Claims/createFromSales`, {claim: claim, sales: sales}).respond(claim);
$httpBackend.expect('POST', `Claims/createFromSales`).respond(claim);
controller.createClaim();
$httpBackend.flush();
expect(controller.subtotal).toEqual(227.5);
expect(controller.VAT).toEqual(10.5);
expect(controller.total).toEqual(238);
expect(controller.$state.go).toHaveBeenCalledWith('claim.card.basicData', {id: 1});
});
});
describe('isChecked() getter', () => {
it('should set isChecked value to true when one of the instances has the value checked to true', () => {
controller.sales[0].checked = true;
expect(controller.isChecked).toBeTruthy();
});
});
describe('checkedLines()', () => {
it('should make an array of the instances with the property checked true()', () => {
let sale = controller.sales[0];
sale.checked = true;
let expectedResult = [sale];
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
let result = controller.checkedLines();
$httpBackend.flush();
expect(result).toEqual(expectedResult);
});
});
describe('onStateOkClick()', () => {
it('should perform a get and then call a function', () => {
let filter = {where: {code: 'OK'}, fields: ['id']};
filter = encodeURIComponent(JSON.stringify(filter));
let res = [{id: 3}];
jest.spyOn(controller, 'onStateChange').mockReturnThis();
$httpBackend.whenGET(`States?filter=${filter}`).respond(res);
$httpBackend.expectGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.expectGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.onStateOkClick();
$httpBackend.flush();
expect(controller.onStateChange).toHaveBeenCalledWith(3);
});
});
describe('onStateChange()', () => {
it('should perform a post and then call a function', () => {
$httpBackend.expectPOST(`TicketTrackings/changeState`).respond();
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.onStateChange(3);
$httpBackend.flush();
});
});
describe('onRemoveLinesClick()', () => {
it('should call getCheckedLines, call removeInstances, and make a query', () => {
controller.sales[0].checked = true;
$httpBackend.whenPOST(`Sales/removes`).respond();
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.onRemoveLinesClick('accept');
$httpBackend.flush();
expect(controller.sales.length).toEqual(1);
});
});
describe('unmarkAsReserved()', () => {
it('should call setReserved with false', () => {
jest.spyOn(controller, 'setReserved');
controller.unmarkAsReserved(false);
expect(controller.setReserved).toHaveBeenCalledWith(false);
});
});
describe('markAsReserved()', () => {
it('should call setReserved with true', () => {
jest.spyOn(controller, 'setReserved');
controller.markAsReserved(true);
expect(controller.setReserved).toHaveBeenCalledWith(true);
});
});
describe('setReserved()', () => {
it('should call getCheckedLines, $.index.accept and make a query ', () => {
const sale = controller.sales[0];
sale.checked = true;
let expectedRequest = {
sales: [sale],
ticketFk: ticket.id,
reserved: false
};
$httpBackend.expectPOST(`Sales/reserve`, expectedRequest).respond();
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.unmarkAsReserved(false);
$httpBackend.flush();
});
});
describe('showSMSDialog()', () => {
it('should open an SMS dialog with specified data', () => {
jest.spyOn(controller.$.sms, 'open');
controller.sales[0].checked = true;
controller.showSMSDialog();
expect(controller.$.sms.open).toHaveBeenCalledWith();
expect(controller.newSMS.destination).toEqual(111111111);
expect(controller.newSMS.message).not.toEqual('');
});
});
describe('onChangeQuantity()', () => {
it('should not call addSale() or updateQuantity() methods', () => {
jest.spyOn(controller, 'addSale');
jest.spyOn(controller, 'updateQuantity');
const sale = {itemFk: 4};
controller.onChangeQuantity(sale);
expect(controller.addSale).not.toHaveBeenCalled();
expect(controller.updateQuantity).not.toHaveBeenCalled();
});
it('should call addSale() method', () => {
jest.spyOn(controller, 'addSale');
const sale = {itemFk: 4, quantity: 5};
controller.onChangeQuantity(sale);
expect(controller.addSale).toHaveBeenCalledWith(sale);
});
it('should call updateQuantity() method', () => {
jest.spyOn(controller, 'updateQuantity');
jest.spyOn(controller, 'addSale');
const sale = {id: 1, itemFk: 4, quantity: 5};
controller.onChangeQuantity(sale);
expect(controller.addSale).not.toHaveBeenCalled();
expect(controller.updateQuantity).toHaveBeenCalledWith(sale);
});
});
describe('updateQuantity()', () => {
it('should make a POST query saving sale quantity', () => {
jest.spyOn(controller.$.watcher, 'updateOriginalData');
const data = {quantity: 10};
const sale = sales[0];
sale.quantity = 10;
$httpBackend.when('POST', `Sales/4/updateQuantity`, data).respond();
$httpBackend.expect('POST', `Sales/4/updateQuantity`, data).respond();
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.updateQuantity(sale);
$httpBackend.flush();
expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});
describe('updateConcept()', () => {
it('should make a POST query saving sale concept', () => {
jest.spyOn(controller.$.watcher, 'updateOriginalData');
const data = {newConcept: 'My new weapon'};
const sale = sales[0];
sale.concept = 'My new weapon';
$httpBackend.when('POST', `Sales/4/updateConcept`, data).respond();
$httpBackend.expect('POST', `Sales/4/updateConcept`, data).respond();
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.updateConcept(sale);
$httpBackend.flush();
expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});
describe('addSale()', () => {
it('should make a POST query adding a new sale', () => {
jest.spyOn(controller.$.watcher, 'updateOriginalData');
const newSale = {itemFk: 4, quantity: 10};
const params = {itemId: 4, quantity: 10};
const expectedResult = {
id: 30,
quantity: 10,
discount: 0,
price: 0,
itemFk: 4,
item: {
subName: 'Item subName',
image: '30.png'
}
};
$httpBackend.when('POST', `tickets/1/addSale`, params).respond(expectedResult);
$httpBackend.expect('POST', `tickets/1/addSale`, params).respond(expectedResult);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.addSale(newSale);
$httpBackend.flush();
expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});
describe('transferSales()', () => {
it('should transfer sales to a ticket', () => {
jest.spyOn(controller, 'goToTicket');
controller.transfer = {
sales: [{id: 1, itemFk: 1}, {id: 2, itemFk: 4}]
};
const expectedResponse = {id: 13};
const params = {
ticketId: 13,
sales: controller.transfer.sales
};
$httpBackend.when('POST', `tickets/1/transferSales`, params).respond(expectedResponse);
$httpBackend.expect('POST', `tickets/1/transferSales`, params).respond(expectedResponse);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.transferSales(13);
$httpBackend.flush();
expect(controller.goToTicket).toHaveBeenCalledWith(13);
});
});
describe('setTransferParams()', () => {
it('should define the transfer object on the controller and its default properties', () => {
let sale = controller.sales[0];
sale.checked = true;
const expectedResponse = [sale];
$httpBackend.when('GET', `clients/101/lastActiveTickets?ticketId=1`).respond(expectedResponse);
$httpBackend.expect('GET', `clients/101/lastActiveTickets?ticketId=1`).respond(expectedResponse);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.setTransferParams();
$httpBackend.flush();
const lastActiveTickets = controller.transfer.lastActiveTickets;
expect(controller.transfer).toBeDefined();
expect(lastActiveTickets).toBeDefined();
expect(lastActiveTickets[0].id).toEqual(4);
});
});
describe('newOrderFromTicket()', () => {
it('should make an HTTP post query and then open the new order on a new tab', () => {
const params = {ticketFk: 1};
const expectedResponse = {id: 123};
window.open = jasmine.createSpy('open');
controller.$state.href = jasmine.createSpy('href')
.and.returnValue('/somePath');
$httpBackend.when('POST', `Orders/newFromTicket`, params).respond(expectedResponse);
$httpBackend.expect('POST', `Orders/newFromTicket`, params).respond(expectedResponse);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.newOrderFromTicket();
$httpBackend.flush();
expect(window.open).toHaveBeenCalledWith('/somePath', '_blank');
});
});
describe('hasOneSaleSelected()', () => {
it('should return true if just one sale is selected', () => {
controller.sales[0].checked = true;
expect(controller.hasOneSaleSelected()).toBeTruthy();
});
});
describe('calculateSalePrice()', () => {
it('should make an HTTP post query ', () => {
controller.sales[0].checked = true;
$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();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.calculateSalePrice();
$httpBackend.flush();
});
});
});
});

View File

@ -14,16 +14,13 @@ module.exports = Self => {
}); });
Self.getCurrentWorkerMana = async ctx => { Self.getCurrentWorkerMana = async ctx => {
let currentClientId = ctx.req.accessToken.userId; let userId = ctx.req.accessToken.userId;
let currentWorker = await Self.app.models.Worker.findOne({
where: {userFk: currentClientId}, let workerMana = await Self.app.models.WorkerMana.findOne({
fields: 'id' where: {workerFk: userId},
});
let currentWorkerMana = await Self.app.models.WorkerMana.findOne({
where: {workerFk: currentWorker.id},
fields: 'amount' fields: 'amount'
}); });
return currentWorkerMana ? currentWorkerMana.amount : 0; return workerMana ? workerMana.amount : 0;
}; };
}; };

View File

@ -32,7 +32,7 @@ module.exports = Self => {
zoneFk: id zoneFk: id
}, },
include: { include: {
relation: 'state', relation: 'ticketState',
scope: { scope: {
fields: ['id', 'alertLevel', 'code'] fields: ['id', 'alertLevel', 'code']
} }
@ -49,7 +49,7 @@ module.exports = Self => {
ticketList.forEach(ticket => { ticketList.forEach(ticket => {
promises.push(ticket.updateAttributes({zoneFk: null}, options)); promises.push(ticket.updateAttributes({zoneFk: null}, options));
if (ticket.state().alertLevel == 0 && ticket.shipped >= today) { if (ticket.ticketState().alertLevel == 0 && ticket.shipped >= today) {
promises.push(models.TicketTracking.create({ promises.push(models.TicketTracking.create({
ticketFk: ticket.id, ticketFk: ticket.id,
stateFk: fixingState.id, stateFk: fixingState.id,

View File

@ -33,6 +33,7 @@ describe('component vnZoneCalendar', () => {
describe('step()', () => { describe('step()', () => {
it('should set the date month to 4 months backwards', () => { it('should set the date month to 4 months backwards', () => {
const now = new Date(); const now = new Date();
now.setDate(15);
now.setMonth(now.getMonth() - 4); now.setMonth(now.getMonth() - 4);
controller.step(-1); controller.step(-1);
@ -45,6 +46,7 @@ describe('component vnZoneCalendar', () => {
it('should set the date month to 4 months forwards', () => { it('should set the date month to 4 months forwards', () => {
const now = new Date(); const now = new Date();
now.setDate(15);
now.setMonth(now.getMonth() + 4); now.setMonth(now.getMonth() + 4);
controller.step(1); controller.step(1);