"use strict";
/**
* @module @magic.batua/points
* @overview Defines the `Ledger` class that manages loyalty points logic across the
* application.
*
* @author Animesh Mishra <hello@animesh.ltd>
* @copyright © 2018 Animesh Ltd. All Rights Reserved.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const Points = require("./Source/Points");
exports.Points = Points;
const error_1 = require("@magic.batua/error");
const error_2 = require("@magic.batua/error");
const Transaction_1 = require("./Source/Transaction");
exports.Transaction = Transaction_1.Transaction;
/**
* The Points Ledger keeps track of a user's Magic Points, their status, their availability
* and other points related arithmetic.
*
* Magic Points are awarded to users as rewards for continued usage and word-of-mouth publicity.
* The points are rewarded as following:
*
* - 600 points at signup. These points aren't redeemable until you've spent ₹1,000 or more on the
* Magic Batua platform.
*
* - 400 points if somebody signs up using your referral code. These points become redeemable once
* you've amassed 10 or more referrals, and each of those referrals have spent ₹1,000 or more.
*
* - 1 point for mobile recharge. Redeemable immediately. If were referred by someone, their account
* is credited with a point too.
*
* - 20 points for tuition fee payments. Redeemable immediately. If were referred by someone, their
* account is credited with 20 points too.
*
* To manage the points logic, we make use of three buckets: Signup, Referrals and Available. As points
* earned through Signup and Referrals become redeemable they are emptied into the Available bucket.
* Points earned through other activities such as mobile recharge or tuition fee payment are credited to
* the Available bucket straightaway.
*/
class Ledger {
constructor(transactions) {
/** Number of points available for redemption */
this.available = 0;
/**
* Points earned at signup. Becomes redeemable once the account has spent
* ₹1,000 or more on the Magic Batua platform.
*/
this.signup = 0;
/**
* Points earned through referrals. Becomes redeemable once the account has accrued
* 10 or more referrals.
*/
this.referral = 0;
/** Number of points accured since the creation of account */
this.redeemable = 0;
/** Points that have expired. */
this.expired = 0;
/** Points that have been redeemed since the creation of account */
this.redeemed = 0;
/** Points that have been refunded */
this.refunded = 0;
/** Points transactions listing all the issuance, redemption and refund transactions. */
this.transactions = new Array();
for (var entry of transactions) {
this.transactions.push(new Transaction_1.Transaction(entry));
}
// Count all points
this.count();
}
/**
* Goes over all point transactions one by one and separates all the points
* in their respective baskets.
*
* @param transactions An array of Points `Transaction`
*/
count() {
this.signup = 0;
this.referral = 0;
this.expired = 0;
this.redeemable = 0;
this.refunded = 0;
this.redeemed = 0;
for (var transaction of this.transactions) {
switch (transaction.type) {
case "Issue":
if (transaction.expiryDate.valueOf() <= Date.now()) {
this.expired += transaction.points;
break;
}
if (transaction.notes == "Signup") {
this.signup += transaction.points;
break;
}
if (transaction.notes == "Referral") {
this.referral += transaction.points;
break;
}
else {
this.redeemable += transaction.points;
break;
}
case "Redeem":
this.redeemed += transaction.points;
break;
case "Refund":
this.refunded += transaction.points;
}
}
this.available = this.redeemable - this.redeemed;
}
/** Issues a Magic Point for the given `reason` */
Issue(points, reason) {
let transaction = new Transaction_1.Transaction({
points: points,
type: "Issue",
notes: reason
});
// Add this transaction to the transactions array and count
// the points again
this.transactions.push(transaction);
this.count();
return transaction;
}
/** Redeems `points` from the balance */
Redeem(points, reason) {
if (points > this.available) {
throw new error_1.ClientError(error_2.Code.BadRequest, "Trying to redeem " + points + " points, but the account has " + this.redeemable + " redeemable points only.");
}
let transaction = new Transaction_1.Transaction({
points: points,
type: "Redeem",
notes: reason
});
// Add this transaction to the transactions array and count
// the points again
this.transactions.push(transaction);
this.count();
return transaction;
}
/**
* This method will be called by the `Account` module when the condition for
* unlocking signup bonus is met.
* To move points from Signup bucket `this.signup` to Redeemable bucket `this.redeemable`,
* we change the `notes` property of signup points issuance from "Signup" to
* "Signup Points become active".
*/
MakeSignupRedeemable() {
for (var transaction of this.transactions) {
if (transaction.notes == "Signup" && transaction.expiryDate.valueOf() >= Date.now()) {
transaction.notes = "Signup points can be redeemed now.";
}
}
this.count();
}
/**
* This method will be called by the `Account` module when the condition for
* unlocking signup bonus is met.
* To move points from Referrals bucket `this.signup` to Redeemable bucket `this.redeemable`,
* we change the `notes` property of signup points issuance from "Signup" to
* "Referral points can be redeemed now.".
*/
MakeReferralsRedeemable() {
for (var transaction of this.transactions) {
if (transaction.notes == "Referral" && transaction.expiryDate.valueOf() >= Date.now()) {
transaction.notes = "Referral points can now be redeemed.";
}
}
this.count();
}
}
exports.Ledger = Ledger;
//# sourceMappingURL=index.js.map