3802-ticket_sale_mana #924

Merged
carlosjr merged 10 commits from 3802-ticket_sale_mana into dev 2022-04-11 10:50:20 +00:00
11 changed files with 301 additions and 10 deletions

View File

@ -0,0 +1,2 @@
INSERT INTO `vn`.`component` (`name`,`typeFk`,`classRate`,`isRenewable`,`code`,`isRequired`)
VALUES ('maná reclamacion',7,4,0,'manaClaim',0);
vicent marked this conversation as resolved Outdated

The column code should be in lowerCamelCase

The column code should be in lowerCamelCase

View File

@ -0,0 +1,106 @@
DROP PROCEDURE IF EXISTS `bs`.`manaCustomerUpdate`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `bs`.`manaCustomerUpdate`()
BEGIN
DECLARE vToDated DATE;
DECLARE vFromDated DATE;
DECLARE vForDeleteDated DATE;
DECLARE vManaId INT;
DECLARE vManaAutoId INT;
DECLARE vClaimManaId INT;
DECLARE vManaBankId INT;
DECLARE vManaGreugeTypeId INT;
SELECT id INTO vManaId
FROM `component` WHERE code = 'mana';
SELECT id INTO vManaAutoId
FROM `component` WHERE code = 'autoMana';
SELECT id INTO vClaimManaId
FROM `component` WHERE code = 'manaClaim';
SELECT id INTO vManaBankId
FROM `bank` WHERE code = 'mana';
SELECT id INTO vManaGreugeTypeId
FROM `greugeType` WHERE code = 'mana';
SELECT IFNULL(max(dated), '2016-01-01')
INTO vFromDated
FROM bs.manaCustomer;
DELETE
FROM bs.manaCustomer
WHERE dated = vFromDated;
SELECT IFNULL(max(dated), '2016-01-01')
INTO vFromDated
FROM bs.manaCustomer;
WHILE timestampadd(DAY,30,vFromDated) < CURDATE() DO
SELECT
timestampadd(DAY,30,vFromDated),
timestampadd(DAY,-90,vFromDated)
INTO
vToDated,
vForDeleteDated;
DELETE FROM bs.manaCustomer
WHERE dated <= vForDeleteDated;
INSERT INTO bs.manaCustomer(Id_Cliente, Mana, dated)
SELECT
Id_Cliente,
cast(sum(mana) as decimal(10,2)) as mana,
vToDated as dated
FROM
(
SELECT cs.Id_Cliente, Cantidad * Valor as mana
FROM vn2008.Tickets t
JOIN vn2008.Consignatarios cs using(Id_Consigna)
JOIN vn2008.Movimientos m on m.Id_Ticket = t.Id_Ticket
JOIN vn2008.Movimientos_componentes mc on mc.Id_Movimiento = m.Id_Movimiento
WHERE Id_Componente IN (vManaAutoId, vManaId, vClaimManaId)
AND t.Fecha > vFromDated
AND date(t.Fecha) <= vToDated
UNION ALL
SELECT r.Id_Cliente, - Entregado
FROM vn2008.Recibos r
WHERE Id_Banco = vManaBankId
AND Fechacobro > vFromDated
AND Fechacobro <= vToDated
UNION ALL
SELECT g.Id_Cliente, g.Importe
FROM vn2008.Greuges g
WHERE Greuges_type_id = vManaGreugeTypeId
AND Fecha > vFromDated
AND Fecha <= vToDated
UNION ALL
SELECT Id_Cliente, mana
FROM bs.manaCustomer
WHERE dated = vFromDated
) sub
GROUP BY Id_Cliente
HAVING Id_Cliente;
SET vFromDated = vToDated;
END WHILE;
END$$
DELIMITER ;

View File

@ -0,0 +1,75 @@
DROP PROCEDURE IF EXISTS `vn`.`manaSpellersRequery`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`manaSpellersRequery`(vWorkerFk INTEGER)
BEGIN
/**
* Recalcula el mana consumido por un trabajador
*
* @param vWorkerFk Id Trabajador
*/
DECLARE vWorkerIsExcluded BOOLEAN;
DECLARE vFromDated DATE;
DECLARE vToDated DATE DEFAULT TIMESTAMPADD(DAY,1,CURDATE());
DECLARE vMana INT;
DECLARE vAutoMana INT;
DECLARE vClaimMana INT;
DECLARE vManaBank INT;
DECLARE vManaGreugeType INT;
SELECT COUNT(*) INTO vWorkerIsExcluded
FROM workerManaExcluded
WHERE workerFk = vWorkerFk;
IF NOT vWorkerIsExcluded THEN
SELECT id INTO vMana
FROM `component` WHERE code = 'mana';
SELECT id INTO vAutoMana
FROM `component` WHERE code = 'autoMana';
SELECT id INTO vClaimMana
FROM `component` WHERE code = 'manaClaim';
SELECT id INTO vManaBank
FROM `bank` WHERE code = 'mana';
SELECT id INTO vManaGreugeType
FROM `greugeType` WHERE code = 'mana';
SELECT max(dated) INTO vFromDated
FROM clientManaCache;
REPLACE workerMana (workerFk, amount)
SELECT vWorkerFk, sum(mana) FROM
(
SELECT s.quantity * sc.value as mana
FROM ticket t
JOIN address a ON a.id = t.addressFk
JOIN client c ON c.id = a.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleComponent sc ON sc.saleFk = s.id
WHERE c.salesPersonFk = vWorkerFk AND sc.componentFk IN (vMana, vAutoMana, vClaimMana)
AND t.shipped > vFromDated AND t.shipped < vToDated
UNION ALL
SELECT - r.amountPaid
FROM receipt r
JOIN client c ON c.id = r.clientFk
WHERE c.salesPersonFk = vWorkerFk AND bankFk = vManaBank
AND payed > vFromDated
UNION ALL
SELECT g.amount
FROM greuge g
JOIN client c ON c.id = g.clientFk
WHERE c.salesPersonFk = vWorkerFk AND g.greugeTypeFk = vManaGreugeType
AND g.shipped > vFromDated and g.shipped < CURDATE()
UNION ALL
SELECT cc.mana
FROM clientManaCache cc
JOIN client c ON c.id = cc.clientFk
WHERE c.salesPersonFk = vWorkerFk AND cc.dated = vFromDated
) sub;
END IF;
END$$
DELIMITER ;

View File

@ -585,6 +585,7 @@ export default {
firstSalePriceInput: '.vn-popover.shown input[ng-model="$ctrl.field"]', firstSalePriceInput: '.vn-popover.shown input[ng-model="$ctrl.field"]',
firstSaleDiscount: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(10) > span', firstSaleDiscount: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(10) > span',
firstSaleDiscountInput: '.vn-popover.shown [ng-model="$ctrl.field"]', firstSaleDiscountInput: '.vn-popover.shown [ng-model="$ctrl.field"]',
saveSaleDiscountButton: '.vn-popover.shown vn-button[label="Save"]',
firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(11)', firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(11)',
firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(3)', firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(3)',
firstSaleColour: 'vn-ticket-sale vn-tr:nth-child(1) vn-fetched-tags section', firstSaleColour: 'vn-ticket-sale vn-tr:nth-child(1) vn-fetched-tags section',

View File

@ -175,7 +175,8 @@ describe('Ticket Edit sale path', () => {
it('should update the discount', async() => { it('should update the discount', async() => {
await page.waitToClick(selectors.ticketSales.firstSaleDiscount); await page.waitToClick(selectors.ticketSales.firstSaleDiscount);
await page.waitForSelector(selectors.ticketSales.firstSaleDiscountInput); await page.waitForSelector(selectors.ticketSales.firstSaleDiscountInput);
await page.type(selectors.ticketSales.firstSaleDiscountInput, '50\u000d'); await page.type(selectors.ticketSales.firstSaleDiscountInput, '50');
vicent marked this conversation as resolved Outdated

since you added a click on a submit button on the next line, the u000d of this input is no longer needed.

since you added a click on a submit button on the next line, the u000d of this input is no longer needed.
await page.waitToClick(selectors.ticketSales.saveSaleDiscountButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');

View File

@ -90,7 +90,7 @@ describe('sale updateDiscount()', () => {
expect(error.message).toEqual(`The sales of this ticket can't be modified`); expect(error.message).toEqual(`The sales of this ticket can't be modified`);
}); });
it('should update the discount if the salesPerson has mana', async() => { it('should update the discount if the salesPerson has mana and manaCode = "mana"', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
try { try {
@ -108,8 +108,49 @@ describe('sale updateDiscount()', () => {
const newDiscount = 100; const newDiscount = 100;
const manaDiscount = await models.Component.findOne({where: {code: 'mana'}}, options); const manaDiscount = await models.Component.findOne({where: {code: 'mana'}}, options);
const componentId = manaDiscount.id; const componentId = manaDiscount.id;
const manaCode = 'mana';
await models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount, options); await models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount, manaCode, options);
const updatedSale = await models.Sale.findById(originalSaleId, null, options);
const createdSaleComponent = await models.SaleComponent.findOne({
where: {
componentFk: componentId,
saleFk: originalSaleId
}
}, options);
expect(createdSaleComponent.componentFk).toEqual(componentId);
expect(updatedSale.discount).toEqual(100);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should update the discount if the salesPerson has mana and manaCode = "manaClaim"', async() => {
vicent marked this conversation as resolved Outdated

if the code gets updated to lowerCamelCase this line and the test should be updated to match the code.

also manaType doesn't seem to be correct, manaCode or manaComponentCode are more specifics

if the code gets updated to lowerCamelCase this line and the test should be updated to match the code. also manaType doesn't seem to be correct, manaCode or manaComponentCode are more specifics
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {
req: {
accessToken: {userId: 18},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const ticketId = 11;
const sales = [originalSaleId];
const newDiscount = 100;
const manaDiscount = await models.Component.findOne({where: {code: 'manaClaim'}}, options);
const componentId = manaDiscount.id;
const manaCode = 'manaClaim';
await models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount, manaCode, options);
const updatedSale = await models.Sale.findById(originalSaleId, null, options); const updatedSale = await models.Sale.findById(originalSaleId, null, options);
const createdSaleComponent = await models.SaleComponent.findOne({ const createdSaleComponent = await models.SaleComponent.findOne({

View File

@ -23,6 +23,12 @@ module.exports = Self => {
description: 'The new discount', description: 'The new discount',
type: 'number', type: 'number',
required: true required: true
},
{
arg: 'manaCode',
vicent marked this conversation as resolved Outdated

manaCode

manaCode
description: 'The type of mana',
type: 'string',
required: false
} }
], ],
returns: { returns: {
@ -35,7 +41,7 @@ module.exports = Self => {
} }
}); });
Self.updateDiscount = async(ctx, id, salesIds, newDiscount, options) => { Self.updateDiscount = async(ctx, id, salesIds, newDiscount, manaCode, options) => {
const $t = ctx.req.__; // $translate const $t = ctx.req.__; // $translate
const models = Self.app.models; const models = Self.app.models;
const myOptions = {}; const myOptions = {};
@ -98,7 +104,7 @@ module.exports = Self => {
}, },
fields: 'amount'}, myOptions); fields: 'amount'}, myOptions);
const componentCode = usesMana ? 'mana' : 'buyerDiscount'; const componentCode = usesMana ? manaCode : 'buyerDiscount';
const discountComponent = await models.Component.findOne({ const discountComponent = await models.Component.findOne({
where: {code: componentCode}}, myOptions); where: {code: componentCode}}, myOptions);

View File

@ -285,10 +285,21 @@
vn-focus vn-focus
label="Discount" label="Discount"
ng-model="$ctrl.edit.discount" ng-model="$ctrl.edit.discount"
on-change="$ctrl.changeDiscount()"
clear-disabled="true" clear-disabled="true"
suffix="%"> suffix="%">
</vn-input-number> </vn-input-number>
<vn-vertical ng-if="$ctrl.currentWorkerMana != 0">
<vn-radio
label="Promotion mana"
val="mana"
ng-model="$ctrl.manaCode">
</vn-radio>
<vn-radio
label="Claim mana"
val="manaClaim"
ng-model="$ctrl.manaCode">
</vn-radio>
</vn-vertical>
<div class="simulator"> <div class="simulator">
<p class="simulatorTitle" translate>New price</p> <p class="simulatorTitle" translate>New price</p>
<p> <p>
@ -297,6 +308,16 @@
</div> </div>
</div> </div>
</div> </div>
<vn-horizontal >
<vn-button
label="Cancel"
ng-click="$ctrl.cancel()">
</vn-button>
<vn-button
label="Save"
ng-click="$ctrl.save()">
</vn-button>
</vn-horizontal>
</div> </div>
</vn-popover> </vn-popover>

View File

@ -6,6 +6,15 @@ class Controller extends Section {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this._sales = []; this._sales = [];
this.manaCode = 'mana';
}
get manaCode() {
return this._manaCode;
}
set manaCode(value) {
this._manaCode = value;
} }
get ticket() { get ticket() {
@ -66,6 +75,14 @@ class Controller extends Section {
this.$.editPricePopover.relocate(); this.$.editPricePopover.relocate();
}); });
}); });
this.getCurrentWorkerMana();
}
getCurrentWorkerMana() {
this.$http.get(`WorkerManas/getCurrentWorkerMana`)
.then(res => {
this.currentWorkerMana = res.data;
});
} }
/** /**
@ -273,7 +290,7 @@ class Controller extends Section {
return sale.id; return sale.id;
}); });
const params = {salesIds: saleIds, newDiscount: this.edit.discount}; const params = {salesIds: saleIds, newDiscount: this.edit.discount, manaCode: this.manaCode};
const query = `Tickets/${this.$params.id}/updateDiscount`; const query = `Tickets/${this.$params.id}/updateDiscount`;
this.$http.post(query, params).then(() => { this.$http.post(query, params).then(() => {
this.vnApp.showSuccess(this.$t('Data saved!')); this.vnApp.showSuccess(this.$t('Data saved!'));
@ -479,6 +496,14 @@ class Controller extends Section {
? {id: $search} ? {id: $search}
: {name: {like: '%' + $search + '%'}}; : {name: {like: '%' + $search + '%'}};
} }
save() {
this.changeDiscount();
}
cancel() {
this.$.editDiscount.hide();
}
} }
ngModule.vnComponent('vnTicketSale', { ngModule.vnComponent('vnTicketSale', {

View File

@ -43,7 +43,7 @@ describe('Ticket', () => {
$scope.sms = {open: () => {}}; $scope.sms = {open: () => {}};
$scope.ticket = ticket; $scope.ticket = ticket;
$scope.model = crudModel; $scope.model = crudModel;
$scope.editDiscount = {relocate: () => {}}; $scope.editDiscount = {relocate: () => {}, hide: () => {}};
$scope.editPricePopover = {relocate: () => {}}; $scope.editPricePopover = {relocate: () => {}};
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
Object.defineProperties($state.params, { Object.defineProperties($state.params, {
@ -115,10 +115,12 @@ describe('Ticket', () => {
const expectedAmount = 250; const expectedAmount = 250;
$httpBackend.expect('GET', 'Tickets/1/getSalesPersonMana').respond(200, expectedAmount); $httpBackend.expect('GET', 'Tickets/1/getSalesPersonMana').respond(200, expectedAmount);
$httpBackend.expect('GET', 'WorkerManas/getCurrentWorkerMana').respond(200, expectedAmount);
controller.getMana(); controller.getMana();
$httpBackend.flush(); $httpBackend.flush();
expect(controller.edit.mana).toEqual(expectedAmount); expect(controller.edit.mana).toEqual(expectedAmount);
expect(controller.currentWorkerMana).toEqual(expectedAmount);
}); });
}); });
@ -446,7 +448,7 @@ describe('Ticket', () => {
const expectedSales = [firstSelectedSale, secondSelectedSale]; const expectedSales = [firstSelectedSale, secondSelectedSale];
const expectedSaleIds = [firstSelectedSale.id, secondSelectedSale.id]; const expectedSaleIds = [firstSelectedSale.id, secondSelectedSale.id];
const expectedParams = {salesIds: expectedSaleIds, newDiscount: expectedDiscount}; const expectedParams = {salesIds: expectedSaleIds, newDiscount: expectedDiscount, manaCode: 'mana'};
$httpBackend.expect('POST', `Tickets/1/updateDiscount`, expectedParams).respond(200, {discount: 10}); $httpBackend.expect('POST', `Tickets/1/updateDiscount`, expectedParams).respond(200, {discount: 10});
controller.updateDiscount(expectedSales); controller.updateDiscount(expectedSales);
$httpBackend.flush(); $httpBackend.flush();
@ -732,5 +734,14 @@ describe('Ticket', () => {
expect(result).toEqual({name: {like: '%' + itemName + '%'}}); expect(result).toEqual({name: {like: '%' + itemName + '%'}});
}); });
}); });
describe('cancel()', () => {
it('should call hide()', () => {
jest.spyOn(controller.$.editDiscount, 'hide').mockReturnThis();
controller.cancel();
expect(controller.$.editDiscount.hide).toHaveBeenCalledWith();
});
});
}); });
vicent marked this conversation as resolved Outdated

This test is testing the function's implementation, there's no logic worth a test here.

This test is testing the function's implementation, there's no logic worth a test here.
}); });

View File

@ -37,3 +37,5 @@ Agency: Agencia
Shipped: F. envio Shipped: F. envio
Packaging: Encajado Packaging: Encajado
Pay Back: Abono Pay Back: Abono
Promotion mana: Maná promoción
Claim mana: Maná reclamación