paginate(10); $data = [ 'merchants'=>$merchants, 'merchants_list' => Models\Merchant::get(), 'page_title' => 'merchant_list' ]; return view('organisation.merchants',$data); } public function landing(){ $merchant_session = session('merchant'); $merchant = Models\Merchant::find($merchant_session->id); // dd($merchant); $merchant_trans = Models\Transaction::where('merchant_id', $merchant->id)->orderBy('id', 'DESC')->get(); $data = [ 'transaction_count' => $merchant_trans->count(), 'transaction_sum' => $merchant_trans->sum('amount'), 'transactions' => $merchant_trans->take(15), 'current_balance' => $merchant['balance'], 'transactions_graph' => $this->merchant_transactions($merchant), 'merchant' => $merchant, 'page_title' => 'Merchant Dashboard', ]; // dd($data['transactions_graph']); return view('merchants.landing',$data); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create(){ $data = [ 'page_title' => 'Merchant Registration', ]; return view('organisation.create_merchant', $data); } public function showrefund(){ $merchant = session('merchant'); $dealers = Models\Organisation::get(); $recent_refunds = Models\MerchantToDealerRefund::with('orgInfo')->orderBy('id', 'DESC')->paginate(15); $data = [ 'page_title' => 'Merchant Refund', 'dealers_arr' => $dealers, 'recent_refunds' => $recent_refunds, 'merchant' => $merchant ]; // dd($data); return view('merchants.refund', $data); } public function showchangepin(){ $merchant = session('merchant'); $data = [ 'page_title' => 'Merchant Refund', 'merchant' => $merchant ]; return view('merchants.showchangepin', $data); } public function refundStore(Request $request){ $this->validate($request, [ // 'dealer_id' => 'required|integer', // 'merchant_id' => 'required|integer', // 'amount' => 'required|numeric|min:0.01', 'transaction_id' => 'required|string', 'reason' => 'required|string', ]); /* $merchant = Models\Merchant::find($request->merchant_id); if ($merchant == null) { return redirect()->to('merchant/refunds')->with('error_message', 'Merchant not found'); } */ /* $organisation = Models\Organisation::find($request->dealer_id); if ($organisation == null) { return redirect()->to('merchant/refunds')->with('error_message', 'Dealer not found'); } */ $transaction = Models\MerchantTopUp::with('merchantInfo', 'orgInfo')->where('status', 'success')->where('transaction_id', $request->transaction_id)->first(); if ($transaction == null) { return response()->json([ 'success' => false, 'message' => 'Transaction not found.' ], 400); } $dealer = $transaction->orgInfo; #Models\OrgUser::findOrFail($request->dealer_id); if ($transaction->merchantInfo->balance < $request->amount) { //ask team to confirm if merchant can have a negative balance return response()->json([ 'success' => false, 'message' => 'Insufficient merchant balance to process this refund.' ], 400); } $merchant_name = $transaction->merchantInfo->fullname; $dealer_name = $transaction->orgInfo->name; $merchant = Models\Merchant::find($transaction->merchantInfo->id); $organisation = Models\Organisation::find($transaction->orgInfo->id); try { //todo : remove one of organisation or dealer DB::transaction(function () use ($request, $merchant, $organisation, $dealer, $transaction) { Models\MerchantToDealerRefund::create([ 'dealer_id' => $organisation->org_id, 'merchant_id' => $transaction->merchant_id, 'amount' => $transaction->amount, 'dealer_msisdn' => $transaction->orgInfo->phone, 'reason' => $request->reason, ]); $merchant->decrement('balance', $transaction->amount); $organisation->increment('balance', $transaction->amount); $desc = [ 'title' => 'Dealer Refund', 'data' => "Refunded a dealer with an amount of " . $transaction->amount, // Typo fixed 'type' => 'merchant', ]; $activity = new ActivityLog; $activity->user_id = $request->session()->get('current_merchant.id'); $activity->user_type = 'merchant'; $activity->description = json_encode($desc); $activity->save(); $transaction->status = 'refunded'; $transaction->save(); }); } catch (\Exception $e) { \Log::error("Refund Transaction Failed: " . $e->getMessage()); return response()->json([ 'success' => false, 'message' => "Refund Transaction Failed: " . $e->getMessage() ], 400); } $msg = "You have successfully refunded a dealer ($dealer_name) with an amount of $transaction->amount."; $dealer_msg = "You have received a refund amount of $transaction->amount from Airtime Merchant ($merchant_name)."; if (env('APP_ENV') !== 'local') { try { $smsgateway = new Smsgateway; $smsgateway->sendSmsNew($merchant->phone, $msg); $smsgateway->sendSmsNew($organisation->phone, $dealer_msg); } catch (\Exception $e) { \Log::error("Failed to send SMS for refund: " . $e->getMessage()); } } \Log::info($msg); \Log::info($dealer_msg); return response()->json([ 'success' => false, 'message' => "Dealer Refund successfully processed! " ], 200); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request){ $validatedData = $request->validate([ 'fullname' => 'required', // 'phone_number'=> 'required|unique:merchants,phone', 'phone_number' => ['required', 'unique:merchants,phone', new PhoneValidationRule], 'language' => 'required' ]); /* $check_phone = $this->validatePhoneNumber($request->phone_number); if ($check_phone == false) { if($request->ajax()){ return response()->json([ 'code' => 3, 'status' => 'fail', 'message' => 'Invalid phone number' ]); } else{ return redirect()->back()->withInput()->with('error_message', 'Invalid phone number!'); } } */ $fullname = $request->input('fullname'); $phone_number = $request->input('phone_number'); $pin = rand(1000, 9999); $merchant = Models\Merchant::create([ 'fullname' => $fullname, 'phone' => $request->phone_number, // $check_phone, 'pin' => md5($pin), 'org_id' => session('current_org_user.org_id'), 'language' => 'english' ]); $desc = [ 'title' => 'Created a merchant', 'data' => $fullname, 'type' => 'merchant', ]; $activity = new ActivityLog; $activity->user_id = $request->session()->get('current_org_user.id'); // org_user_id ; $activity->user_type = 'organisation'; $activity->description = json_encode($desc); $activity->save(); // TODO: send sms with PIN to merchant phone - $msg = "You have been Successfully registered as an Airtime sales merchant. Your 4-digit PIN is $pin. You will need it for all your activities. Dial *349# to begin."; $smsgateway = new Smsgateway; if(env('APP_ENV') !== 'local'){ $result = $smsgateway->sendSmsNew($check_phone, $msg); } \Log::info($msg); $this->sendNtfy($msg); if($request->ajax()){ return response()->json([ 'code' => 1, 'status' => 'success', 'message' => 'Merchant Created Successfully' ]); } else{ return redirect()->to('organisation/merchants')->with('success_message', 'Successfully Added New Merchant'); } } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { // dd($id); // $merchant = Merchant::where('id',$id)->with('transactions')->get()[0]; $merchant = Merchant::with('transactions')->find($id); $merchants = Models\Merchant::get(); $merchant_topups = Models\MerchantTopUp::where('merchant_id', $id)->latest()->paginate(20); $data = [ 'merchant' => $merchant, 'merchants_list' => $merchants, 'page_title' => 'Merchant Details | ' . $merchant->fullname, 'merchant_topups' => $merchant_topups, 'merchant_id' => $id, ]; return view('organisation.merchant_show',$data); } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit($id) { // $merchant = Models\Merchant::findOrfail($id); // $countries = Countries::all(); $data = [ 'merchant' => $merchant, 'page_title' => 'Merchant Edit', ]; // dd($data); return view('organisation.merchant_edit', $data); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { $this->validate($request, [ 'fullname' => 'required', 'phone'=> 'required', 'status' => 'required', 'language' => 'required' ]); $check_phone = $this->validatePhoneNumber($request->phone); if ($check_phone == false) { return redirect()->back()->withInput()->with('admin-error', 'Invalid phone number!'); } // dd($request->all()); Merchant::where('id', $id)->update([ 'fullname' => $request->fullname, 'phone' => $check_phone, 'language' => $request->language, 'status' => $request->status ]); $desc = [ 'title' =>'Updated merchant', 'data' => $request->fullname, 'type' => 'merchant', ]; $activity = new ActivityLog; $activity->user_id = session('current_org_user.id');// organisation user ID $activity->user_type = 'organisation'; $activity->description = json_encode($desc); $activity->save(); return redirect()->to('organisation/merchants')->with('admin-success', 'Successfully Updated Merchant details'); } public function changePin(Request $request) { // dd($request->ajax()); $this->validate($request, [ 'current_pin' => 'required', 'new_pin'=> 'required', 'merchant_id' => 'required' ]); // verify current PIN | 81dc9bdb52d04dc20036dbd8313ed055 $current_pin = trim($request->current_pin); $merchant = Merchant::find($request->merchant_id); if(md5($current_pin) !== $merchant->pin){ return response()->json([ 'code' => 3, 'status' => 'failed', 'message' => 'Current PIN is incorrect, check and try again!' ]); } $new_pin = md5($request->new_pin); Merchant::where('id', $request->merchant_id)->update(['pin' => $new_pin]); $desc = [ 'title' =>'Merchant PIN change', 'data' => "PIN successfully changed for merchant ID: " . $request->merchant_id, 'type' => 'merchant', ]; $activity = new ActivityLog; $activity->user_id = session('current_org_user.id');// organisation user ID $activity->user_type = 'organisation'; $activity->description = json_encode($desc); $activity->save(); return response()->json([ 'code' => 1, 'status' => 'success', 'message' => 'PIN Successfully Changed!' ]); } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { Models\Merchant::where('id', $id)->update([ 'status' => 'disabled', ]); $activity = new ActivityLog; $activity->user_id = session('current_org_user.id'); // organisation user ID $activity->user_type = 'organisation'; $activity->description = 'disabled a merchant with ID : ' . $id ; $activity->save(); return redirect()->to('organisation/merchant')->with('admin-sucsess', 'Successfully Disabled Merchant'); } public function enable($id) { Models\Merchant::where('id', $id)->update([ 'status'=>'active', ]); $activity = new ActivityLog; $activity->user_id = session('current_org_user.id'); $activity->user_type = 'organisation'; $activity->description = 'enable a merchant with ID : ' . $id ; $activity->save(); return redirect()->to('/organisation/merchant')->with('admin-sucsess', 'Successfully Enabled Merchant'); } public function addTopUp(Request $request){ // dd($request->all()); $validator = Validator::make($request->all(), [ 'amount' => 'required', 'payment'=>'required', 'merchant'=>'required', ]); if($validator->fails()){ return redirect()->back()->with('admin-error', 'Enter required data!'); } $amount = $request->input('amount'); $payment = $request->input('payment'); $merchant = $request->input('merchant'); $topup = new TopUp; $topup->amount = $amount; $topup->merchant_id = $merchant; $topup->created_by = $request->session()->get('current_org_user.id'); $topup->payment_method = $payment; $save = $topup->save(); //Update Merchant Amt // Models\Merchant::where('id', $merchant)->increment('balance', $amount); if ($save) { $merchant = Models\Merchant::find($merchant); $desc = [ 'title'=>'Added new Top Up', 'data'=>'K ' .$topup->amount.' for '.$merchant->fullname.' payment by '.$payment, 'type'=>'topup', ]; $activity = new ActivityLog; $activity->user_id = $request->session()->get('current_org_user.id'); $activity->user_type = 'organisation'; $activity->description = json_encode($desc); $activity->save(); return redirect()->to('/organisation/merchant/'.$merchant->id)->with('admin-sucsess', 'Successfully Added Top Up'); } else { return redirect()->back()->with('admin-error', 'Error'); } } public function transactions(){ $merchant = session('merchant'); // $transactions = Transaction::where('merchant_id', $merchant->id)->latest()->paginate(20); $data = [ // 'transactions'=>$transactions, 'merchant' => $merchant, 'page_title' => 'Merchant Transactions', ]; return view('merchants.transactions',$data); } public function getTransactionsJson(Request $request){ $merchant_id = session('merchant.id'); $transactions_arr = \DB::table('transactions') ->join('merchants', 'transactions.merchant_id', '=', 'merchants.id') ->select('merchants.fullname', 'transactions.id', 'transactions.status', 'transactions.msisdn', 'transactions.amount', 'transactions.created_at') ->whereRaw('transactions.merchant_id = '. $merchant_id) ->orderBy('transactions.created_at', 'DESC') ->paginate(20); if($request->has('keyword')){ $queries = []; $keyword = $request->keyword; $queries['keyword'] = $keyword; $transactions_arr = \DB::table('transactions') // ->join('org_users', 'transactions.org_user_id', '=', 'org_users.id') ->join('merchants', 'transactions.merchant_id', '=', 'merchants.id') ->select('merchants.fullname', 'transactions.id', 'transactions.status', 'transactions.msisdn', 'transactions.amount', 'transactions.created_at') ->whereRaw("merchants.fullname LIKE '%$keyword%' OR transactions.msisdn LIKE '%$keyword%' OR transactions.status LIKE '%$keyword%' OR transactions.amount LIKE '%$keyword%' OR transactions.created_at LIKE '%$keyword%'") ->whereRaw('transactions.merchant_id = '. $merchant_id) ->orderBy('transactions.created_at', 'DESC') ->paginate(20)->appends($queries); } return response()->json($transactions_arr); } public function dealer_transactions(){ $merchant = session('merchant'); $data = [ 'merchant' => $merchant, 'page_title' => 'Dealer Transactions', ]; // dd($data); return view('merchants.dealer-transactions',$data); } public function getDealerListJson(Request $request){ $merchant_id = session('merchant.id'); $dealer_arr = \DB::table('organisations')->orderBy('organisations.created_at', 'DESC')->paginate(20); if($request->has('keyword')){ $queries = []; $keyword = $request->keyword; $queries['keyword'] = $keyword; $dealer_arr = \DB::table('organisations') ->whereRaw("name LIKE '%$keyword%' OR phone LIKE '%$keyword%' OR status LIKE '%$keyword%' OR email LIKE '%$keyword%' OR created_at LIKE '%$keyword%'") ->orderBy('created_at', 'DESC') ->paginate(20)->appends($queries); } return response()->json($dealer_arr); } public function get_dealers(){ $merchant = session('merchant'); $data = [ 'merchant' => $merchant, 'page_title' => 'Dealers', ]; return view('merchants.dealer-list', $data); } public function getDealerTransactionsJson(Request $request){ $merchantId = session('merchant.id'); $query = \DB::table('merchant_top_ups') ->join('merchants', 'merchant_top_ups.merchant_id', '=', 'merchants.id') ->join('org_users', 'merchant_top_ups.org_user_id', '=', 'org_users.id') ->select([ 'merchants.fullname', 'org_users.phone', 'org_users.name', // 'merchant_top_ups.id', 'merchant_top_ups.transaction_id', 'merchant_top_ups.status', 'merchant_top_ups.amount', 'merchant_top_ups.created_at', ]) ->where('merchant_top_ups.merchant_id', $merchantId) ->orderByDesc('merchant_top_ups.created_at'); if ($request->filled('keyword')) { $keyword = $request->input('keyword'); $like = '%' . $keyword . '%'; $query->where(function ($q) use ($like, $keyword) { $q->where('org_users.phone', 'like', $like) ->orWhere('org_users.name', 'like', $like) ->orWhere('merchants.fullname', 'like', $like) ->orWhere('merchant_top_ups.status', 'like', $like) ->orWhere('merchant_top_ups.amount', 'like', $like) ->orWhere('merchant_top_ups.created_at', 'like', $like); }); } $transactions = $query->paginate(20); if ($request->filled('keyword')) { $transactions->appends(['keyword' => $request->input('keyword')]); } return response()->json($transactions); } public function showCustomerTopForm(){ //$merchant = Merchant::where('id',$id)->with('transactions')->get()[0]; $data = [ 'page_title' => 'Customer Top Up', 'page_title' => 'merchant_topups' ]; return view('merchant.customer-topup',$data); } public function customerTopupStore(Request $request){ $this->validate($request, [ 'phone_number'=> 'required|numeric', 'amount' => 'required|numeric|min:1' ]); $phone_number = preg_replace('/[+\s]+/', '', $request->phone_number); // preg_replace('/\s+/', '', $request->phone_number); /* $check_phone = $this->validatePhoneNumber($phone_number); if ($check_phone == false) { return redirect()->back()->withInput()->with('admin-error', 'Invalid phone number!'); } */ $merchant_session = session('merchant'); $merchant = Models\Merchant::find($merchant_session['id']); // dd($merchant); $country_prefix = substr($phone_number, 0, 3); // dd($country_prefix); $country = ''; switch ($country_prefix) { case '265': $country = 'MALAWI'; break; case '260': $country = 'ZAMBIA'; break; default: $country = ''; break; } if ($merchant->country !== $country) { // find out from team return redirect()->back()->withInput()->with('admin-error', 'Country not allowed!'); } $difference = $merchant->balance - $request->amount; if ($merchant->balance < $request->amount) { return redirect()->back()->withInput()->with('admin-error', 'Insufficient balance!'); } $prev_balance = $merchant->balance; //get merchant ID, amount, msisdn, $extRefId = uniqid() . '-' . date('YmdHis'); #$last_insert_id = saveTransaction($session_data['top_up_phone'], $session_data['top_up_amount'], $session_data['merchant_id'], $extRefId); $transaction_arr = [ 'msisdn' => $phone_number, 'amount' => $request->amount, 'merchant_id' => $merchant->id, 'session_id' => $extRefId ]; // dd($transaction_arr); $trans_result = Models\Transaction::create($transaction_arr); $transaction_id = $trans_result->id; $click_params = [ "msisdn" => $phone_number, "amount" => $request->amount, "extRefId" => $extRefId ]; \Log::info($click_params); //$merchant->orgInfo->api_email, $merchant->orgInfo->api_token $topup_result = $this->ClickADPHttp($click_params); // Click ADP \Log::info($topup_result); $this->sendNtfy($topup_result); $topup_result_arr = json_decode($topup_result, TRUE); \Log::info($topup_result_arr); if ($topup_result == false) { return redirect()->back()->withInput()->with('admin-error', 'Top Up Could not be processed at this time. Try again later!'); } $log_data = [ 'msisdn' => $phone_number, 'amount' => $request->tamount, 'user_id' => $merchant->id, 'merchant_balance' => $merchant->balance, 'session_id' => $extRefId, 'status' => $topup_result_arr, 'network' => 'n.a' ]; $desc = [ 'title' =>'customer top up by Merchant ID ' . $merchant->id, 'data' => $log_data, 'type' => 'merchant', ]; $activity = new ActivityLog; $activity->user_id = $merchant->id; $activity->user_type = 'merchant'; $activity->description = json_encode($desc); $activity->save(); if ($topup_result_arr['code'] == 1) { $merchant_update = Models\Merchant::find($merchant->id); $merchant_update->balance = $prev_balance - $request->amount; $merchant_update->save(); $desc = [ 'title' =>'Successful customer top up by Merchant ID ' . $merchant->id, 'data' => ['previous_balance' => $merchant->balance, 'current_balance' => $merchant->balance - $request->amount], 'type' => 'merchant', ]; #update transactions $transaction = Models\Transaction::find($transaction_id); $transaction->status = $topup_result_arr['message']; $transaction->save(); $activity = new ActivityLog; $activity->user_id = $merchant->id; $activity->user_type = 'merchant'; $activity->description = json_encode($desc); $activity->save(); Session::flash('success_message', 'Top Up Successfully processed!'); return redirect('merchant'); } return redirect('merchant/transactions'); } public function merchant_transactions($merchant){ $transactions = Models\Transaction::where('merchant_id', $merchant->id)->select('id', 'created_at')->get() ->groupBy(function($date) { //return Carbon::parse($date->created_at)->format('Y'); // grouping by years return Carbon::parse($date->created_at)->format('m'); // grouping by months }); $transactionmcount = []; $transactionArr = []; return response()->json(['transactions' => $transactions]); $pp = 1; $trans = []; foreach ($transactions as $value) { if ($pp == $value) { $trans[$pp]= $value; } else{ $trans[$pp] = 0; } } foreach ($transactions as $key => $value) { $transactionmcount[(int)$key] = count($value); } for($i = 1; $i <= 12; $i++){ if(!empty($transactionmcount[$i])){ $transactionArr[$i] = $transactionmcount[$i]; }else{ $transactionArr[$i] = 0; } } $transactions = ''; foreach ($transactionArr as $tran) { $transactions = $transactions.','.$tran; } return $transactions; } public function merchant_transactions_graph($merchant_id = 1){ $transactions = Models\Transaction::where('merchant_id', $merchant_id)->pluck('amount', 'created_at'); // return response()->json($transactions); // dump($transactions); return $transactions; } public function getActivity() { // $merchant = session('merchant'); $activities = ActivityLog::with('admin')->where('user_type', 'merchant')->where('user_id', $merchant->id) ->orderBy('created_at', 'desc')->paginate(30); $data = [ 'activities' => $activities, 'merchant' => $merchant, 'page_title' => 'Merchant Activity Log' ]; return view('merchants.activity', $data); } }