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);

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');
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() => {
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',
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();
});
});
}); });
}); });

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