multiple bug fixes including sender ID filtering

This commit is contained in:
Kwesi Banson Jnr
2026-04-16 14:22:04 +00:00
parent 72180de8e4
commit 5dbe76dbd4
380 changed files with 175085 additions and 203 deletions

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Http\Controllers\HolidaysController;
class ProcessHolidayAlert extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'holidayalerts:send';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send Upcoming Holiday Alerts to team members';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(HolidaysController $hoidays_alerts)
{
parent::__construct();
$this->hoidays_alerts = $hoidays_alerts;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->hoidays_alerts->getHolidayDetails();
}
}

View File

@@ -14,7 +14,8 @@ class Kernel extends ConsoleKernel
*/
protected $commands = [
Commands\SendContractRenewalReminders::class,
Commands\ProcessClientContractRenewalAlert::class
Commands\ProcessClientContractRenewalAlert::class,
Commands\ProcessHolidayAlert::class
];
/**
@@ -30,6 +31,7 @@ class Kernel extends ConsoleKernel
$schedule->command('renewal:send')->weekdays()->at('13:00');
$schedule->command('client_renewal:send')->weekdays()->at('14:00');
$schedule->command('support_fees_renewal:send')->weekdays()->at('15:00');
$schedule->command('holidayalerts:send')->weekdays()->at('16:00');
}
/**

View File

@@ -0,0 +1,159 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models;
use Session;
class DailyQuotesController extends Controller
{
public function index(){
// $quote_arr = Models\DailyQuote::orderBy('created_at', 'DESC')->paginate(5);
$search = request('keyword');
// Start the query builder
$query = Models\DailyQuote::query();
// Apply search filters if a search term is present
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('quote', 'like', '%' . $search . '%')
->orWhere('author', 'like', '%' . $search . '%');
});
}
// Paginate the results
$quote_arr = $query->orderBy('created_at', 'DESC')->paginate(10); // 10 items per page
// Append the search parameter to the pagination links
// This is crucial for maintaining the search results when navigating pages
if ($search) {
$quote_arr->appends(['q' => $search]);
}
// Pass the paginated data to the view
// return view('search_results', ['users' => $users, 'search' => $search]);
$data = [
'page_title' => 'Daily Quotes',
'quote_arr' => $quote_arr,
'search' => $search
// 'current_user' => session('current_user')
];
// dump($data);
// return view('daily_quotes.index', $data);
return view('daily_quotes.index-raw', $data);
}
public function getDailyQuotesJson(Request $request)
{
#$this->log_query();
$quote_arr = \DB::table('daily_quotes')
->join('staff_members AS staffcreate', 'staffcreate.id', '=', 'daily_quotes.added_by_id')
->select('daily_quotes.id', 'daily_quotes.author', 'daily_quotes.quote_date', 'daily_quotes.quote', 'daily_quotes.status', 'staffcreate.name As addedBy')
->orderBy('daily_quotes.quote', 'ASC')
->paginate(15);
if($request->has('keyword')){
$queries = [];
$keyword = $request->keyword;
$request->session()->put('current_user.quote_keyword', $keyword);
$queries['keyword'] = $keyword;
$quote_arr = \DB::table('daily_quotes')
->join('staff_members AS staffcreate', 'staffcreate.id', '=', 'daily_quotes.added_by_id')
->select('daily_quotes.id', 'daily_quotes.author', 'daily_quotes.quote_date', 'daily_quotes.quote', 'daily_quotes.status', 'staffcreate.name As addedBy')
->whereRaw("daily_quotes.quote LIKE '%$keyword%' OR daily_quotes.status LIKE '%$keyword%' OR daily_quotes.author LIKE '%$keyword%' OR daily_quotes.quote_date LIKE '%$keyword%' OR staffcreate.name LIKE '%$keyword%'")
->orderBy('daily_quotes.quote', 'ASC')
->paginate(15)->appends($queries);
}
return response()->json($quote_arr);
}
public function create(){
$status = [
'active' => 'active',
'inactive' => 'inactive',
];
$data = [
'page_title' => 'New Daily Quote',
'status' => $status,
];
return view('daily_quotes.create', $data);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate([
'quote' => 'required',
'author' => 'required',
'quote_date' => 'sometimes',
'status' => 'required',
]);
$check_duplicate = Models\DailyQuote::where('quote', $request->quote)->first();
if ($check_duplicate) {
return redirect()->back()->withInput()->withErrors("Daily Quote already exist!");
}
$quote_arr = $request->except('_token');
$quote_arr['added_by_id'] = session('current_user.id');
$result = Models\DailyQuote::create($quote_arr);
Session::flash('success_message', 'Daily Quote successfully added');
return redirect(url('dailyquotes'));
}
public function edit($id){
$quote = Models\DailyQuote::findOrFail($id);
$status = [
'active' => 'active',
'inactive' => 'inactive',
];
$data = [
'page_title' => 'Edit Daily Quote',
'status' => $status,
'clients' => $client_arr,
'quote' => $quote,
];
return view('quote.edit', $data);
}
public function update(Request $request, $id)
{
$request->validate([
'quote' => 'required|max:11',
'author' => 'required_if:direct_mno,YES',
'quote_date' => 'required_if:direct_mno,NO',
'status' => 'required',
'remarks' => 'sometimes',
]);
// dd($request->all());
$quote = Models\DailyQuote::findOrFail($id);
$quote->quote = $request->quote;
$quote->author = $request->author ?? '';
$quote->status = $request->status;
$quote->quote_date = $request->quote_date ?? '';
$quote->added_by_id = session('current_user.id');
$quote->save();
Session::flash('success_message', 'Daily Quote successfully Updated');
return redirect(url('dailyquotes'));
}
}

View File

@@ -24,11 +24,8 @@ class DashboardController extends Controller
$recent_clients = Models\Client::with('auth_user_info')->orderBy('id', 'DESC')->take(5)->get();
// $upcoming_birthdays = Models\StaffMember::whereDate('dob', '>=', $currentdate)->orderBy('dob', 'ASC')->take(5)->get();
$upcoming_birthdays = Models\StaffMember::whereRaw("(month(dob) >= month(curdate())) AND day(dob) >= day(curdate())")->orderBy('dob', 'ASC')->take(5)->get();
$upcoming_hodidays = Models\NationalHoliday::whereRaw("(month(event_date) >= month(curdate()))")->whereRaw("(year(event_date) >= year(curdate()))")->orderBy('event_date', 'ASC')->take(15)->get();
// dd($upcoming_hodidays);
// $recent_clients = Models\Client::orderBy('id', 'DESC')->take(5)->get();
// dd($recent_clients);
$upcoming_hodidays = Models\NationalHoliday::whereRaw("(month(event_date) >= month(curdate()))")->whereRaw("(year(event_date) >= year(curdate()))")->whereRaw("(date(event_date) >= curdate())")->orderBy('event_date', 'ASC')->take(15)->get();
$main_quote = Models\DailyQuote::where('status', 'active')->first();
$data = [
'page_title' => 'Dashboard',
'sms' => $sms_clients,
@@ -36,6 +33,7 @@ class DashboardController extends Controller
'voice' => $voice_clients,
'airtime' => $airtime_clients,
'total' => $total_clients,
'main_quote' => $main_quote,
'recent_clients' => $recent_clients,
'user_activities' => $user_activities,
'expiring_contracts' => $expiring_contracts,
@@ -67,7 +65,6 @@ class DashboardController extends Controller
$daily_quotes = DB::table('daily_quotes')
->where('id', '>=', DB::raw('(SELECT FLOOR(RAND() * (SELECT MAX(id) FROM daily_quotes)))'))
// ->limit(5)
->first();
return response()->json($daily_quotes);

View File

@@ -3,11 +3,102 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models;
use Session;
use Illuminate\Support\Arr;
use App\Jobs\SendHolidayEmailAlerts;
use App\Http\Requests;
use Carbon\Carbon;
class HolidaysController extends Controller
{
protected $guarded = array('id');
public $table = "holidays";
class HolidaysController extends Controller{
public function getHolidayDetails(){
$upcoming_hodidays = Models\NationalHoliday::whereRaw("(month(event_date) >= month(curdate()))")->whereRaw("(year(event_date) >= year(curdate()))")->orderBy('event_date', 'ASC')->take(15)->get();
if ($upcoming_hodidays->isEmpty() == false) {
dispatch(new SendHolidayEmailAlerts($upcoming_hodidays->toArray()));
}
}
public function index(){
// Using pagination is generally better than get() for lists
$holidays = Models\NationalHoliday::orderBy('event_date', 'asc')->paginate(15);
dd($holidays);
return view('holidays.index', compact('holidays'));
}
/**
* Show the form for creating a new holiday.
*/
public function create(){
return view('holidays.create');
}
/**
* Store a newly created holiday in the database.
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|string|max:191',
'country' => 'required|string|max:191',
'event_date' => 'required|date',
]);
Models\NationalHoliday::create($validatedData);
return redirect()->route('holidays.index')
->with('success', 'Holiday created successfully.');
}
/**
* Display the specified holiday.
*/
public function show($id)
{
$holiday = Models\NationalHoliday::findOrFail($id);
return view('holidays.show', compact('holiday'));
}
/**
* Show the form for editing the specified holiday.
*/
public function edit($id)
{
$holiday = Models\NationalHoliday::findOrFail($id);
return view('holidays.edit', compact('holiday'));
}
/**
* Update the specified holiday in the database.
*/
public function update(Request $request, $id)
{
$validatedData = $request->validate([
'name' => 'required|string|max:191',
'country' => 'required|string|max:191',
'event_date' => 'required|date',
]);
$holiday = Models\NationalHoliday::findOrFail($id);
$holiday->update($validatedData);
return redirect()->route('holidays.index')
->with('success', 'Holiday updated successfully.');
}
/**
* Remove the specified holiday from the database.
*/
public function destroy($id)
{
$holiday = Models\NationalHoliday::findOrFail($id);
$holiday->delete();
return redirect()->route('holidays.index')
->with('success', 'Holiday deleted successfully.');
}
}

View File

@@ -7,6 +7,8 @@ use App\Models;
use Spatie\Activitylog\Models\Activity;
use Illuminate\Support\Str;
use App\Jobs\SendOtpEmailAlert;
use Illuminate\Support\Facades\Hash;
use Session;
class LoginController extends Controller
@@ -18,6 +20,80 @@ class LoginController extends Controller
];
return view('login.index', $data);
}
public function passwordResetPage(){
$data = [
'page_title' => "Password Reset"
];
return view('login.reset_form', $data);
}
public function passwordResetLink(Request $request){
$request->validate([
'email' => 'required',
]);
// dd($request->email);
$logged_in = Models\StaffMember::where('email', $request->email)->first();
if($logged_in == false ){
return redirect()->back()->withErrors(array("Email not found. Check and try again!"));
}
$request->session()->regenerate(true);
$request->session()->put('current_reset_user.id', $logged_in->id);
$request->session()->put('current_reset_user.email', $logged_in->email);
// $data = [
// 'page_title' => "Password Reset",
// 'user_id' => base64_encode($logged_in->id)
// ];
return redirect('reset_form_show');
}
public function passwordResetFormShow(){
$data = [
'page_title' => "Password Reset"
];
return view('login.reset_submit', $data);
}
public function passwordReset(Request $request){
$request->validate([
'password' => 'required|confirmed|min:6',
]);
if($request->password == 'password' ){
return redirect()->back()->withErrors(array("It is extremely dangerous to use password as your password."));
}
$user_id = session('current_reset_user.id');
$user_email = session('current_reset_user.email');
$staff = Models\StaffMember::where('email', $user_email)->first();
$staff->password = Hash::make($request->password);
$staff->save();
$data = [
'page_title' => "Password Reset"
];
$content = $user_email . " Successfully changed their password";
$this->logUsersActivity($type = 'staff', $content, $user_id);
$this->deleteLoggedUser();
$this->storeLoggedUser();
Session::flash('success_message', 'Password successfully reset');
return redirect('login');
#return view('login.index', $data);
}
public function passwordResetHandle(Request $request){
$request->validate([
'email' => 'required',
'password' => 'required',
'confirm_password' => 'required',
]);
dd($request->all());
$data = [
'page_title' => "Password Reset"
];
return view('login.index', $data);
}
public function resendOtp(){
if(!request()->session()->has('current_otpuser')){
return redirect(url('login'))->withErrors("No session found. You need to be logged in!");
@@ -64,7 +140,19 @@ class LoginController extends Controller
if(empty($logged_in)){
return redirect("/")->withErrors(array("Incorrect Email/Password. Check and try again!"))->withInput();
}
if ($logged_in->is_password_changed == 'NO') {
$hashedPassword = Hash::make($request->password);
$staff_member = Models\StaffMember::where('email', $logged_in->email)->first();
if ($staff_member) {
$staff_member->password = $hashedPassword;
$staff_member->permissions = $logged_in->permissions;
$staff_member->designation = $logged_in->designation;
$staff_member->save();
$logged_in->is_password_changed = 'YES';
$logged_in->save();
}
}
$otp_code = Str::random(6);
$request->session()->regenerate(true);
$request->session()->put('current_otpuser.id', $logged_in->id);

View File

@@ -499,6 +499,7 @@ class NetworkOperatorsController extends Controller
'mno_id' => 'required',
'ip_address' => 'required|ipv4',
'service' => 'required',
'system_id' => 'sometimes',
'port' => 'sometimes|numeric',
'status' => 'required'
]);
@@ -508,6 +509,7 @@ class NetworkOperatorsController extends Controller
'ip_address' => $request->ip_address,
'mno_id' => $request->mno_id,
'service' => $request->service,
'system_id' => ($request->system_id) ? $request->system_id : "",
'port' => $request->port,
'status' => $request->status,
'created_by' => $auth_user['id'],

View File

@@ -20,7 +20,7 @@ class OfficeLocationsController extends Controller
];
// dd($data);
// dd($offices_arr->isEmpty());
return view('officelocations.index-new', $data);
return view('officelocations.index', $data);
}
public function showfiles($id){
$branch_files = Models\BranchFile::where('branch_id', $id)->get();

View File

@@ -22,7 +22,7 @@ class SenderIdController extends Controller
];
return view('senderid.index', $data);
}
public function getSenderIdsJson(Request $request)
public function getSenderIdsJsonBak(Request $request)
{
#$this->log_query();
$senderid_arr = \DB::table('sender_ids')
@@ -35,7 +35,7 @@ class SenderIdController extends Controller
->paginate(15);
if($request->has('keyword')){
$queries = [];
$keyword = $request->keyword;
$request->session()->put('current_user.senderid_keyword', $keyword);
@@ -52,6 +52,76 @@ class SenderIdController extends Controller
}
return response()->json($senderid_arr);
}
function getSenderIdsJson(Request $request){
$query = \DB::table('sender_ids')
->join('staff_members AS staffcreate', 'staffcreate.id', '=', 'sender_ids.created_by')
->join('staff_members AS staffmodify', 'staffmodify.id', '=', 'sender_ids.last_modified_by')
->select(
'sender_ids.id',
'mno_name',
'supplier_name',
'sender_ids.senderid',
'sender_ids.status',
'sender_ids.remarks',
'staffcreate.name AS createdBy',
'sender_ids.direct_mno',
'staffmodify.name AS modifiedBy'
);
// 2. Handle Tabulator's Column Header Filters
if ($request->has('filter')) {
$filters = $request->input('filter');
// Map the Tabulator JS fields to the actual database table columns
$columnMap = [
'createdBy' => 'staffcreate.name',
'modifiedBy' => 'staffmodify.name',
'mno_name' => 'mno_name', // Add table prefixes here if needed
'supplier_name' => 'supplier_name'
];
foreach ($filters as $filter) {
$field = $filter['field'];
$value = $filter['value'];
// Determine the correct DB column. Default to sender_ids table to avoid 'ambiguous column' errors
$dbColumn = $columnMap[$field] ?? 'sender_ids.' . $field;
// Securely bind the value using Laravel's active record (prevents SQL injection)
$query->where($dbColumn, 'LIKE', '%' . $value . '%');
}
}
// 3. Handle your existing Global Keyword Search (if you still have a global search box)
if ($request->has('keyword')) {
$keyword = $request->input('keyword');
$request->session()->put('current_user.senderid_keyword', $keyword);
// Group the OR conditions in a closure so they don't break the Tabulator filters above
$query->where(function($q) use ($keyword) {
$q->where('sender_ids.senderid', 'LIKE', "%{$keyword}%")
->orWhere('sender_ids.status', 'LIKE', "%{$keyword}%")
->orWhere('mno_name', 'LIKE', "%{$keyword}%")
->orWhere('supplier_name', 'LIKE', "%{$keyword}%")
->orWhere('staffcreate.name', 'LIKE', "%{$keyword}%")
->orWhere('staffmodify.name', 'LIKE', "%{$keyword}%")
->orWhere('sender_ids.direct_mno', 'LIKE', "%{$keyword}%");
});
}
// 4. Order and fetch the final Paginated results
$query->orderBy('sender_ids.senderid', 'ASC');
// Grab Tabulator's requested page size, default to 15
$perPage = $request->input('size', 15);
$senderid_arr = $query->paginate($perPage);
// If using the global keyword, append it to the pagination links
if ($request->has('keyword')) {
$senderid_arr->appends(['keyword' => $request->keyword]);
}
return response()->json($senderid_arr);
}
public function create()
{
#$network_arr = Models\NetworkOps::pluck('name','country');

View File

@@ -10,14 +10,14 @@ class StaffMembersController extends Controller
{
public function index(){
$staff_members_arr = Models\StaffMember::paginate(10);
// dd($staff_members_arr);
// dd($staff_members_arr);
$data = [
'page_title' => 'Staff Members',
'staff_members' => $staff_members_arr,
'current_user' => session('current_user')
];
return view('staff_members.index-two', $data);
return view('staff_members.index-cards', $data);
}
public function profile($staff_member_id){
$staff_member = Models\StaffMember::find($staff_member_id);

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Support\Facades\Log;
class SendHolidayEmailAlerts implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $holiday_arr;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($holiday_arr)
{
$this->holiday_arr = $holiday_arr;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(Mailer $mailer)
{
Log::info("Holidays in mailer job started.");
$holiday_arr = $this->holiday_arr;
$emails = [
'clicmobile@click-mobile.com',
];
$data = [
'holiday_arr' => $holiday_arr
];
$mailer->send('emails.holidays', $data, function ($message) use ($data, $emails) {
$message->from('alerts@click-mobile.com', 'Click Mobile ERP Team');
$message->to($emails)->subject('Upcoming Holidays');
});
Log::info("Holiday emails dispatched successfully.");
}
}

View File

@@ -6,5 +6,5 @@ use Illuminate\Database\Eloquent\Model;
class DailyQuote extends Model
{
//
protected $guarded = array('id');
}

View File

@@ -6,5 +6,6 @@ use Illuminate\Database\Eloquent\Model;
class Holiday extends Model
{
//
protected $guarded = array('id');
public $table = "holidays";
}

View File

@@ -13,15 +13,15 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
#$monolog = \Log::getMonolog();
// $monolog = \Log::getMonolog();
//new --- > xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a
//old ---> xoxp-677819906294-675678554016-720956680656-4a6b5d0fcb00e9e0512c14341d3a7563
//clickml_erp_ntfy
//click_erp_notify
// team_erp
// $slackHandler = new \Monolog\Handler\SlackHandler('xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a', '#team_erp', 'Monolog', true, null, \Monolog\Logger::ERROR);
// $slackHandler = new \Monolog\Handler\SlackHandler('xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a', '#team_erp', 'Monolog', true, null, \Monolog\Logger::INFO);
// $slackHandler = new \Monolog\Handler\SlackHandler('xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a', '#team_erp', 'Monolog', true, null, \Monolog\Logger::DEBUG);
// $slackHandler = new \Monolog\Handler\SlackHandler('xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a', '#click-erp', 'Monolog', true, null, \Monolog\Logger::ERROR);
// $slackHandler = new \Monolog\Handler\SlackHandler('xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a', '#click-erp', 'Monolog', true, null, \Monolog\Logger::INFO);
// $slackHandler = new \Monolog\Handler\SlackHandler('xoxp-677819906294-675678554016-693747277911-5166bcbb9a5fc3d5434b42a10c4d358a', '#click-erp', 'Monolog', true, null, \Monolog\Logger::DEBUG);
// $monolog->pushHandler($slackHandler);