This article will demonstrate a way of dynamically allocating Bank Accounts To the Agents/Tellecaller. This probem will fit perfectly in the allocation module of BFSI domain.
Introduction
This is a real time situation.
Context
Let us consider that we have a Financial Institution (FI) which provides loan to various customers. So the FI will have a list of customer bank accounts. Now the FI's will have multiple Agencies under them for the EMI collection purpose.Say suppose there are 1000 bank accounts list of customers for a FI. And 10 Agencies are working under them.Say the FI has given 100 Customer Bank Accounts to each Agencies and the Agencies has to collect the EMI's from the respective customers.For that to happen,each Agencies will employ multiple Agents/Telecaller under them.And then the Agents will assign various customers under each Field Agent and the later's responsibility is to collect the pending amount/EMI's from the customers. Kindly note at this juncture that these customers have delinquent accounts.
Problem Statement
In the current system, the Agencies are allocating the customers(or customer bank accounts) manually to the Agents.But the proposed system needs to happen the allocation dynamically.
Let's say under Agency (say "AGENCY1" ), there are 9 customer bank accounts and 4 Agents (say Agent1,Agent2,Agent3,Agent4). The system should be intelligent enough to allocate the customer bank accounts to the Agents in such a way that -
Constraint
- It has to be as evenly distributed as possible.
- The allocation has to be in a sequential order.
What it means is that, if we try to distribute evenly those 9 customer bank accounts (say Account1,Account2...,Account9) to the 4 Agents, then the allocation will happen as
Agent1 | Account1,Account5,Account9 |
Agent2 | Account2,Account6 |
Agent3 | Account3,Account7 |
Agent4 | Account4,Account8 |
Algorithm
Let us first write the algorithm
Step 1: Start
Step 2: Get the Customer Bank Accounts list.
Step 3: Get the Agents list.
Step 4: Count of Step 2
Step 5: Count of Step 3
Step 6:
Case 1 : If Count(Step 4) < Count(Step 5) Then Go To Step 7.
Case 2 : If Count(Step 4) = Count(Step 5) Then Go To Step 7.
Case 3 : If Count(Step 4) > Count(Step 5) Then Go To Step 7.
Step 7:
a) Divide Count(Step 4) / Count(Step 5) + 1
b) Number of Agents generated = Repeat of Agents in a Round Robin way till it exhausts Count(Step 5) * (a)
Step 8: Map in a sequential way Step 6 and Step 2 until the smaller of them exhausts.
Step 9: Group Customer Bank Accounts obtained in Step 7 by their Agents.
Step 10: Display.
Step 11: Stop.
Using the code
Let us now write the program satisfying the algorithm.We have intentionally left the Customer Bank Accounts list and Agents list as unpopulated collection because it will be filled on a case by case basis.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//step 1 - program starts
//Data to be filled on a Case By Case Basis
List<string> lstCustomerBankAccounts = new List<string>(); //Step 2
//Data to be filled on a Case By Case Basis
List<string> lstAgents = new List<string>(); //Step 3
var countCustomerBankAccounts = lstCustomerBankAccounts.Count; //Step 4
var countAgents = lstAgents.Count; //Step 5
var repeatCount = countCustomerBankAccounts / countAgents + 1; //Step 6
var numberOfAgentsGenerated = Enumerable.Repeat(lstAgents, repeatCount).SelectMany(m => m); //Step 7
var customerBankAccountToAgentMapping =
numberOfAgentsGenerated
.Zip(lstCustomerBankAccounts,
(agent, account) => new { Agent = agent, CustomerBankAccounts = account }
); //Step 8
var groupcustomerBankAccountByAgent = customerBankAccountToAgentMapping.GroupBy(a => a.Agent); //Step 9
var result = groupcustomerBankAccountByAgent
.Select(g => new
{
Agent = g.Key
,
Accounts = g.Select(x => x.CustomerBankAccounts).ToList()
});
foreach (var r in result)
{
Console.WriteLine("Agent Name: " + r.Agent);
foreach (var cba in r.Accounts)
{
Console.WriteLine(" Is holding " + cba);
}
Console.WriteLine(Environment.NewLine);
}//Step 10
Console.ReadKey();//Step 11
}
}
}
Now, it's time to check all the three cases.
Case 1: If Customer Bank Accounts list < Agents list
List<string> lstCustomerBankAccounts = new List<string>(){ "Account1", "Account2", "Account3"}; //Step 2
List<string> lstAgents = new List<string>(){ "Agent1", "Agent2", "Agent3", "Agent4" }; //Step 3
The output is as under

Case 2: If Customer Bank Accounts list = Agents list
List<string> lstCustomerBankAccounts = new List<string>(){ "Account1", "Account2", "Account3","Account4"}; //Step 2
List<string> lstAgents = new List<string>(){ "Agent1", "Agent2", "Agent3", "Agent4" }; //Step 3
The output is as under

Case 3: If Customer Bank Accounts list > Agents list
List<string> lstCustomerBankAccounts = new List<string>()
{ "Account1", "Account2", "Account3",
"Account4", "Account5", "Account6",
"Account7","Account8","Account9"
}; //Step 2
List<string> lstAgents = new List<string>(){ "Agent1", "Agent2", "Agent3", "Agent4" }; //Step 3
The output is as under

As can be figure out that, our algorithm worked in all the three situations and hence the proof for the algorithm that solves the Dynamic Allocation Of Bank Accounts To the Agents/TelleCaller problem
The above program can be written in a more compact way as under
Enumerable
.Repeat(lstAgents, lstCustomerBankAccounts.Count / lstAgents.Count + 1)
.SelectMany(x => x)
.Zip(lstCustomerBankAccounts, (agent, account) => new { Agent = agent, Account = account })
.GroupBy(x => x.Agent)
.Select(g => new { Agent = g.Key, Accounts = g.Select(x => x.Account).ToList() })
.ToList()
.ForEach(ag =>
{
Console.WriteLine("Agent Name: " + ag.Agent);
ag.Accounts
.ToList()
.ForEach(cba =>
{
Console.WriteLine(" Is holding " + cba);
}
); Console.WriteLine(Environment.NewLine);
});
Console.ReadKey();
Conclusion
In this article we have demonstrated the Dynamic Allocation Of Bank Accounts To the Agents/Tellecaller problem which is a very common use case for BFSI domain when the allocation module is consider and has come out with an algorithm that solves it as being proved by implementing the same using C# language.Hope this may come into help to some others who are working in a similar kind of domain or will serve as a reference to similar kind of problem.Thanks for reading. Zipped file attached.