modified it for multiple organisations

This commit is contained in:
Kwesi Banson Jnr
2026-06-23 10:07:20 +00:00
parent 5e97905786
commit 1c77a23963
11 changed files with 221 additions and 64 deletions

2
API.md
View File

@@ -243,3 +243,5 @@ How it updates `messages`:
Missing or invalid `Authorization: Bearer <API Key>` returns a `ProblemDetail` response with `status=401`. Missing or invalid `Authorization: Bearer <API Key>` returns a `ProblemDetail` response with `status=401`.
http://206.225.84.201:9990/api/clients?page=0&size=20&sort=createdAt,desc

View File

@@ -20,3 +20,18 @@
http://10.199.0.11/botswana/bpc/web http://10.199.0.11/botswana/bpc/web
https://smsgateway.clickmlapps.com/api/
## Sunking Mozambique
{
"id": 14,
"name": "Sunking Mozambique",
"email": "mozambiqueinf@sunking.com",
"country": "Mozambique",
"phoneNumber": "+258858480000",
"status": "NEW",
"createdAt": "2026-06-22T10:20:10.319231Z",
"updatedAt": "2026-06-22T10:20:10.319244Z"
}
info@sunkingmozambique.com/oc4P6i@510A8U6

View File

@@ -0,0 +1,18 @@
http://localhost:9990/api/ucm/reports/daily-sms-units-by-network?from={{reportDateFrom}}&to={{reportDateTo}}&ucm_org_id=701
http://localhost:9990/api/ucm/reports/daily-sms-units-by-network?from={{reportDateFrom}}&to={{reportDateTo}}&ucm_org_id=701
Expected response:{
"reportDate": "2026-02-26 to 2026-03-27",
"orgId": 701,
"movitelMzSmsUnits": 0,
"tmcelMzSmsUnits": 0,
"vodacomMzSmsUnits": 0
}
{{baseUrl}}/api/ucm/reports/daily-sms-units?from={{reportDateFrom}}&to={{reportDateTo}}&ucm_org_id=629
expected response: {
"reportDate": "2026-02-26 to 2026-03-27",
"orgId": 629,
"smsUnits": 908202,
"clientChargeTotal": 6596.267261251807
}

View File

@@ -44,7 +44,6 @@ class ClientsLoginController extends Controller
} }
public function activation(Request $request){ public function activation(Request $request){
$this->validate($request, [ $this->validate($request, [
// 'activation_hash' => 'required',
'password' => 'required', 'password' => 'required',
// 'password' => ['required', 'min:8', 'confirmed'] // 'password' => ['required', 'min:8', 'confirmed']
'password' => ['required','confirmed', Password::min(8)->letters()->numbers(),] 'password' => ['required','confirmed', Password::min(8)->letters()->numbers(),]
@@ -83,19 +82,21 @@ class ClientsLoginController extends Controller
$logged_in = ''; $logged_in = '';
$client = Models\ClientSession::where('email', $request->email)->first(); $client = Models\ClientSession::where('email', $request->email)->first();
// dump($client);
if ($client == false) { if ($client == false) {
return redirect()->back()->withErrors(['Invalid credentials']); return redirect()->back()->withErrors(['Invalid credentials']);
} }
$client_url = "clients/" . $client->client_id; $client_url = "clients/" . $client->client_id;
$result = ApiCalls::CurlGet($client_url); $result = ApiCalls::CurlGet($client_url);
// dd($result);
$result_arr = json_decode($result, true); $result_arr = json_decode($result, true);
$logged_in = $result_arr; $logged_in = $result_arr;
// dd($logged_in); // dd($logged_in);
$request->session()->regenerate(true); $request->session()->regenerate(true);
$request->session()->put('current_user.user_id', $logged_in['id']); $request->session()->put('current_user.user_id', $logged_in['id']);
$request->session()->put('current_user.org_id', $logged_in['id']); $request->session()->put('current_user.org_id', $logged_in['id']);
$request->session()->put('current_user.ucm_org_id', $client->ucm_org_id);
$request->session()->put('current_user.name', $logged_in['name']); $request->session()->put('current_user.name', $logged_in['name']);
$request->session()->put('current_user.email', $logged_in['email']); $request->session()->put('current_user.email', $logged_in['email']);
$request->session()->put('current_user.role', $client['role']); $request->session()->put('current_user.role', $client['role']);

View File

@@ -38,26 +38,36 @@ class ClientsTrafficController extends Controller
['path' => $request->url(), 'query' => $request->query()] ['path' => $request->url(), 'query' => $request->query()]
); );
} }
public function indexTest(){
$data = ['page_title' => 'Test Page'];
return view('client-traffic.test', $data);
}
public function index(){ public function index(){
$client_id = session('current_user.org_id'); $client_id = session('current_user.org_id');
$ucm_org_id = session('current_user.ucm_org_id');
// dd($client_id);
$clients_url = "messages/client/$client_id?page=0&size=1000&sort=createdAt,desc"; $clients_url = "messages/client/$client_id?page=0&size=1000&sort=createdAt,desc";
$result = ApiCalls::CurlGet($clients_url); $result = ApiCalls::CurlGet($clients_url);
$result_arr = json_decode($result); $result_arr = json_decode($result);
// dd($result_arr);
$current_date = new DateTime(); $current_date = new DateTime();
$start_date = $current_date->modify('-10 days'); $start_date = $current_date->modify('-10 days');
$start_date = $start_date->format('Y-m-d'); $start_date = $start_date->format('Y-m-d');
$end_date = date('Y-m-d'); $end_date = date('Y-m-d');
$daily_smsunits_url = "ucm/reports/daily-sms-units?from=$start_date&to=$end_date"; $daily_smsunits_url = "ucm/reports/daily-sms-units?from=$start_date&to=$end_date&ucm_org_id=$ucm_org_id";
$result = ApiCalls::CurlGet($daily_smsunits_url); $result = ApiCalls::CurlGet($daily_smsunits_url);
$sms_units_arr = json_decode($result, true); $sms_units_arr = json_decode($result, true);
$daily_smsunits_url_split = "ucm/reports/daily-sms-units-by-network?from=$start_date&to=$end_date";
$daily_smsunits_url_split = "ucm/reports/daily-sms-units-by-network?from=$start_date&to=$end_date&ucm_org_id=$ucm_org_id";
// dump($daily_smsunits_url_split);
$result = ApiCalls::CurlGet($daily_smsunits_url_split); $result = ApiCalls::CurlGet($daily_smsunits_url_split);
$split_sms_units_arr = json_decode($result, true); $split_sms_units_arr = json_decode($result, true);
// dd($split_sms_units_arr);
$orgId = session('current_user.org_id'); $orgId = session('current_user.org_id');
$sms_balance_url = "clients/$orgId/balance"; $sms_balance_url = "clients/$orgId/balance";
$result = ApiCalls::CurlGet($sms_balance_url); $result = ApiCalls::CurlGet($sms_balance_url);
@@ -77,14 +87,15 @@ class ClientsTrafficController extends Controller
"TNM SMSUnits" => 18796 "TNM SMSUnits" => 18796
*/ */
// dump($split_sms_units_arr); // dump($split_sms_units_arr);
if ($ucm_org_id == 629) {
$airtel_rate = 14; $airtel_rate = 14;
$tnm_rate = 18; $tnm_rate = 18;
$airtel_computation = $split_sms_units_arr['Airtel SMSUnits'] * $airtel_rate; $airtel_computation = $split_sms_units_arr['Airtel SMSUnits'] * $airtel_rate;
$tnm_computation = $split_sms_units_arr['TNM SMSUnits'] * $tnm_rate; $tnm_computation = $split_sms_units_arr['TNM SMSUnits'] * $tnm_rate;
$charge_computation = $airtel_computation + $tnm_computation; $charge_computation = $airtel_computation + $tnm_computation;
$split_sms_units_arr['charge_computation'] = number_format($charge_computation); $split_sms_units_arr['charge_computation'] = number_format($charge_computation);
$data = [ $data = [
'page_title' => 'SMS Traffic', 'page_title' => 'SMS Traffic',
'traffic_arr' => $result_arr, 'traffic_arr' => $result_arr,
@@ -93,6 +104,32 @@ class ClientsTrafficController extends Controller
'charge_computation' => $charge_computation, 'charge_computation' => $charge_computation,
'balance_arr' => $balance_arr 'balance_arr' => $balance_arr
]; ];
}
elseif($ucm_org_id == 701){
// "movitelMzSmsUnits" => 0
// "tmcelMzSmsUnits" => 0
// "vodacomMzSmsUnits" => 1
$movitel_rate = 0.32;
$tmcell_rate = 0.32;
$vodacom_rate = 0.32;
$movitel_computation = $split_sms_units_arr['movitelMzSmsUnits'] * $movitel_rate;
$tmcell_computation = $split_sms_units_arr['tmcelMzSmsUnits'] * $tmcell_rate;
$vodacom_computation = $split_sms_units_arr['tmcelMzSmsUnits'] * $vodacom_rate;
$charge_computation = $movitel_computation + $tmcell_computation + $vodacom_computation;
$split_sms_units_arr['charge_computation'] = number_format($charge_computation);
$split_sms_units_arr['units_computation'] = $split_sms_units_arr['movitelMzSmsUnits'] + $split_sms_units_arr['tmcelMzSmsUnits'] + $split_sms_units_arr['vodacomMzSmsUnits'];
$data = [
'page_title' => 'SMS Traffic',
'traffic_arr' => $result_arr,
'sms_units_arr' => $sms_units_arr,
'split_sms_units_arr' => $split_sms_units_arr,
'charge_computation' => $charge_computation,
'balance_arr' => $balance_arr
];
}
// dd($data); // dd($data);
return view('client-traffic.index-main', $data); return view('client-traffic.index-main', $data);
} }
@@ -210,19 +247,61 @@ class ClientsTrafficController extends Controller
]); ]);
$start_date = $request->start_date; $start_date = $request->start_date;
$end_date = $request->end_date; $end_date = $request->end_date;
$client_id = session('current_user.org_id');
$ucm_org_id = session('current_user.ucm_org_id');
/* /*
$daily_smsunits_url = "ucm/reports/daily-sms-units?from=$start_date&to=$end_date"; $daily_smsunits_url = "ucm/reports/daily-sms-units?from=$start_date&to=$end_date";
$result = ApiCalls::CurlGet($daily_smsunits_url); $result = ApiCalls::CurlGet($daily_smsunits_url);
\Log::info('SMS Units Response ' . $result); \Log::info('SMS Units Response ' . $result);
*/ */
$daily_smsunits_url_split = "ucm/reports/daily-sms-units-by-network?from=$start_date&to=$end_date"; $daily_smsunits_url_split = "ucm/reports/daily-sms-units-by-network?from=$start_date&to=$end_date&ucm_org_id=$ucm_org_id";
$result = ApiCalls::CurlGet($daily_smsunits_url_split); $result = ApiCalls::CurlGet($daily_smsunits_url_split);
$split_sms_units_arr = json_decode($result, true); $split_sms_units_arr = json_decode($result, true);
\Log::info('SMS Units Response ' . $result); \Log::info('SMS Units Response ' . $result);
$data = json_decode($result, true); $data = json_decode($result, true);
if ($ucm_org_id == 629) {
$airtel_rate = 14;
$tnm_rate = 18;
$airtel_computation = $split_sms_units_arr['Airtel SMSUnits'] * $airtel_rate;
$tnm_computation = $split_sms_units_arr['TNM SMSUnits'] * $tnm_rate;
$charge_computation = (int)$airtel_computation + (int)$tnm_computation;
$data['ucm_org_id'] = $ucm_org_id;
$data['charge_computation'] = number_format($charge_computation);
$data['airtel_sms_units'] = number_format($split_sms_units_arr['Airtel SMSUnits']);
$data['tnm_sms_units'] = number_format($split_sms_units_arr['TNM SMSUnits']);
return response()->json($data);
}
elseif($ucm_org_id == 701){
// "movitelMzSmsUnits" => 0
// "tmcelMzSmsUnits" => 0
// "vodacomMzSmsUnits" => 1
$movitel_rate = 0.32;
$tmcell_rate = 0.32;
$vodacom_rate = 0.32;
$movitel_computation = $split_sms_units_arr['movitelMzSmsUnits'] * $movitel_rate;
$tmcell_computation = $split_sms_units_arr['tmcelMzSmsUnits'] * $tmcell_rate;
$vodacom_computation = $split_sms_units_arr['tmcelMzSmsUnits'] * $vodacom_rate;
$charge_computation = (int)$movitel_computation + (int)$tmcell_computation + (int)$vodacom_computation;
$data['ucm_org_id'] = $ucm_org_id;
$data['charge_computation'] = number_format($charge_computation);
$units_computation = (int)$split_sms_units_arr['movitelMzSmsUnits'] + (int)$split_sms_units_arr['tmcelMzSmsUnits'] + (int)$split_sms_units_arr['vodacomMzSmsUnits'];
$data['units_computation'] = $units_computation;
return response()->json($data);
}
/*
$airtel_rate = 14; $airtel_rate = 14;
$tnm_rate = 18; $tnm_rate = 18;
@@ -237,8 +316,9 @@ class ClientsTrafficController extends Controller
$data['charge_computation'] = number_format($charge_computation); $data['charge_computation'] = number_format($charge_computation);
$data['airtel_sms_units'] = number_format($split_sms_units_arr['Airtel SMSUnits']); $data['airtel_sms_units'] = number_format($split_sms_units_arr['Airtel SMSUnits']);
$data['tnm_sms_units'] = number_format($split_sms_units_arr['TNM SMSUnits']); $data['tnm_sms_units'] = number_format($split_sms_units_arr['TNM SMSUnits']);
*/
return response()->json($data);
} }
public function dailySmsUnitsSplit(){ public function dailySmsUnitsSplit(){

View File

@@ -42,7 +42,7 @@ class ApiCalls
$api_key = $result_arr->content[0]->apiKey; $api_key = $result_arr->content[0]->apiKey;
$header_part = "Authorization: Bearer " . $api_key; //env('SUNKING_APIKEY'); $header_part = "Authorization: Bearer " . $api_key; //env('SUNKING_APIKEY');
} }
// dd($header_part);
\Log::info('Request Params :' . $data); \Log::info('Request Params :' . $data);
$curl = curl_init(); $curl = curl_init();
curl_setopt_array($curl, array( curl_setopt_array($curl, array(

View File

@@ -13,28 +13,7 @@
format: 'yyyy-mm-dd' format: 'yyyy-mm-dd'
}); });
function sendDailySmsUnitsOld() {
document.getElementById('loadingOverlay').style.display = 'flex';
const endpoint = "client-dailysmsunits";
const startDate = startDateElement.value;
const endDate = endDateElement.value;
fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-TOKEN': token },
body: 'start_date=' + encodeURIComponent(startDate) + '&end_date=' + encodeURIComponent(endDate)
})
.then(response => response.json())
.then(data => {
// document.getElementById('loadingSpinner').style.display = 'none';
document.getElementById('loadingOverlay').style.display = 'none';
const theReportRange = document.getElementById('reportRange');
const theSmsUnitsValue = document.getElementById('smsUnitsValue');
theReportRange.innerHTML = data.reportDate;
theSmsUnitsValue.innerHTML = "SMS Units : " + data.smsUnits + "| Charge : " + data.clientChargeTotal.toFixed(2);
})
.catch(error => console.error('Error:', error));
}
function sendDailySmsUnits() { function sendDailySmsUnits() {
document.getElementById('loadingOverlay').style.display = 'flex'; document.getElementById('loadingOverlay').style.display = 'flex';
const endpoint = "client-dailysmsunits"; const endpoint = "client-dailysmsunits";
@@ -53,17 +32,16 @@
const theSmsChargeTotalValue = document.getElementById('smsUnitsCharge'); const theSmsChargeTotalValue = document.getElementById('smsUnitsCharge');
theReportRange.innerHTML = data.reportDate; theReportRange.innerHTML = data.reportDate;
//const formattedTNMUnits = Number(data.tnm_sms_units']).toLocaleString('en-GH');
// const formattedAirtelUnits = Number(data.data['airtel_sms_units']).toLocaleString('en-GH', {
// minimumFractionDigits: 2,
// maximumFractionDigits: 2
// });
if (data.ucm_org_id === 629) {
theSmsChargeTotalValue.innerHTML = 'SMS Charge (MWK) : <b>' + data.charge_computation + '</b>'; theSmsChargeTotalValue.innerHTML = 'SMS Charge (MWK) : <b>' + data.charge_computation + '</b>';
console.log(data.charge_computation);
console.log(data.airtel_sms_units);
theSmsUnitsValue.innerHTML = 'SMS Units: Airtel <b>' + data.airtel_sms_units + '</b> | TNM: <b>' + data.tnm_sms_units + '</b>'; theSmsUnitsValue.innerHTML = 'SMS Units: Airtel <b>' + data.airtel_sms_units + '</b> | TNM: <b>' + data.tnm_sms_units + '</b>';
}
else {
theSmsChargeTotalValue.innerHTML = 'SMS Charge (MZM) : <b>' + data.charge_computation + '</b>';
theSmsUnitsValue.innerHTML = 'SMS Units: ' + data.units_computation;
}
}) })
.catch(error => console.error('Error:', error)); .catch(error => console.error('Error:', error));
} }

View File

@@ -63,9 +63,9 @@
<h2 class="h5 mb-3">Recent activity</h2> <h2 class="h5 mb-3">Recent activity</h2>
<div class="timeline-item pt-0 mt-0 border-0"> <div class="timeline-item pt-0 mt-0 border-0">
<div class="fw-semibold">Sender ID approved</div> <!-- <div class="fw-semibold">Sender ID approved</div>
<div class="muted-label">CLICKINFO added </div> <div class="muted-label">CLICKINFO added </div>
<div class="small text-secondary mt-1">09:04</div> <div class="small text-secondary mt-1">09:04</div> -->
</div> </div>
<!-- <div class="timeline-item"> <!-- <div class="timeline-item">
@@ -75,9 +75,9 @@
</div> --> </div> -->
<div class="timeline-item"> <div class="timeline-item">
<div class="fw-semibold">Campaign completed</div> <!-- <div class="fw-semibold">Campaign completed</div>
<div class="muted-label">[campaign name] batch finished</div> <div class="muted-label">[campaign name] batch finished</div>
<div class="small text-secondary mt-1">08:41</div> <div class="small text-secondary mt-1">08:41</div> -->
</div> </div>
</aside> </aside>
</div> </div>

View File

@@ -81,9 +81,12 @@
</div> </div>
<div class="muted-label mb-2">Sent Messages (last 10 days)</div> <div class="muted-label mb-2">Sent Messages (last 10 days)</div>
<!-- <div class="h3 mb-2">183,372</div> --> <!-- <div class="h3 mb-2">183,372</div> -->
<div class="h5 mb-2 pt-1" id="smsUnitsCharge">SMS Charge(MWK) : <b>{{ $split_sms_units_arr['charge_computation'] }}</b></div> <div class="h5 mb-2 pt-1" id="smsUnitsCharge">SMS Charge(<?php echo (session('current_user.ucm_org_id') == 629)? "MWK" : "MZM"; ?>) : <b>{{ $split_sms_units_arr['charge_computation'] }}</b></div>
@if(session('current_user.ucm_org_id') == 629)
<div class="h5 mb-2 pt-1" id="smsUnitsValue">SMS Units : Airtel : <b>{{ number_format($split_sms_units_arr['Airtel SMSUnits']) }}</b> | TNM : <b>{{ number_format($split_sms_units_arr['TNM SMSUnits']) }}</b></div> <div class="h5 mb-2 pt-1" id="smsUnitsValue">SMS Units : Airtel : <b>{{ number_format($split_sms_units_arr['Airtel SMSUnits']) }}</b> | TNM : <b>{{ number_format($split_sms_units_arr['TNM SMSUnits']) }}</b></div>
@else
<div class="h5 mb-2 pt-1" id="smsUnitsValue">SMS Units : <b>{{ number_format($split_sms_units_arr['units_computation']) }}</div>
@endif
<div class="mini-chart"><span style="width: 57%;"></span></div> <div class="mini-chart"><span style="width: 57%;"></span></div>
</article> </article>
</div> </div>

View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bootstrap 5 Starter</title>
<!-- Bootstrap CSS CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- Navigation Bar -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Test Bootstrap</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Main Content Area -->
<div class="container mt-5">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="card shadow">
<div class="card-header bg-primary text-white">
<h1>Welcome to the Test Page!</h1>
</div>
<div class="card-body">
<p class="lead">This is a clean, responsive section built with Bootstrap 5.
Components like forms, cards, and navigation on the way.</p>
<p>Grid system for layout and utility classes for styling.</p>
<button class="btn btn-success mt-3">Get Started</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap JS Bundle (Place before closing body tag for best performance) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js"></script>
</body>
</html>

View File

@@ -27,6 +27,7 @@
</head> </head>
<body> <body>
@include('client-traffic.partials.new-app') @include('client-traffic.partials.new-app')
<?php //dump($page_title); ?>
<div class="container py-3 py-lg-4"> <div class="container py-3 py-lg-4">
<header class="topbar"> <header class="topbar">
<div class="topbar-card d-flex flex-column flex-lg-row align-items-lg-center justify-content-between gap-3"> <div class="topbar-card d-flex flex-column flex-lg-row align-items-lg-center justify-content-between gap-3">