<?php
namespace App\Http\Controllers\Admin;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Customer\PaymentController;
use App\Library\Tool;
use App\Models\Invoices;
use App\Models\Keywords;
use App\Models\PhoneNumbers;
use App\Models\Senderid;
use App\Models\Subscription;
use App\Models\SubscriptionLog;
use App\Models\SubscriptionTransaction;
use App\Models\User;
use App\Notifications\SubscriptionPurchase;
use Carbon\Carbon;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use JetBrains\PhpStorm\NoReturn;
class InvoiceController extends Controller
{
/**
* view invoices
*
* @return Application|Factory|View
* @throws AuthorizationException
*/
public function index(): Factory|View|Application
{
$this->authorize('view invoices');
$breadcrumbs = [
['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Dashboard')],
['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Reports')],
['name' => __('locale.menu.All Invoices')],
];
return view('admin.Invoices.index', compact('breadcrumbs'));
}
/**
* @param Request $request
*
* @return void
*/
#[NoReturn] public function search(Request $request): void
{
$columns = [
0 => 'responsive_id',
1 => 'uid',
2 => 'uid',
3 => 'created_at',
4 => 'id',
5 => 'type',
6 => 'description',
7 => 'amount',
8 => 'status',
9 => 'user_id',
10 => 'actions',
];
$totalData = Invoices::count();
$totalFiltered = $totalData;
$limit = $request->input('length');
$start = $request->input('start');
$order = $columns[$request->input('order.0.column')];
$dir = $request->input('order.0.dir');
if (empty($request->input('search.value'))) {
$invoices = Invoices::offset($start)
->limit($limit)
->orderBy($order, $dir)
->get();
} else {
$search = $request->input('search.value');
$invoices = Invoices::whereLike(['uid', 'type', 'created_at', 'description', 'amount', 'status', 'user.first_name', 'user.last_name'], $search)
->offset($start)
->limit($limit)
->orderBy($order, $dir)
->get();
$totalFiltered = Invoices::whereLike(['uid', 'type', 'created_at', 'description', 'amount', 'status', 'user.first_name', 'user.last_name'], $search)->count();
}
$data = [];
if ( ! empty($invoices)) {
foreach ($invoices as $invoice) {
$show = route('admin.invoices.view', $invoice->uid);
$customer_profile = route('admin.customers.show', $invoice->user->uid);
$customer_name = $invoice->user->displayName();
$user_id = "<a href='$customer_profile' class='text-primary mr-1'>$customer_name</a>";
$invoice_number = "<a href='$show' class='text-primary fw-bold'>#$invoice->id</a>";
$nestedData['responsive_id'] = '';
$nestedData['uid'] = $invoice->uid;
$nestedData['id'] = $invoice_number;
$nestedData['user_id'] = $user_id;
$nestedData['avatar'] = route('admin.customers.avatar', $invoice->user->uid);
$nestedData['email'] = $invoice->user->email;
$nestedData['created_at'] = Tool::customerDateTime($invoice->created_at);
$nestedData['type'] = strtoupper($invoice->type);
$nestedData['description'] = str_limit($invoice->description, 35);
$nestedData['amount'] = Tool::format_price($invoice->amount, $invoice->currency->format);
$nestedData['status'] = $invoice->getStatus();
$nestedData['get_status'] = $invoice->status;
$nestedData['status_locale'] = __('locale.labels.approve');
$nestedData['edit'] = $show;
$nestedData['delete'] = $invoice->uid;
$data[] = $nestedData;
}
}
$json_data = [
"draw" => intval($request->input('draw')),
"recordsTotal" => intval($totalData),
"recordsFiltered" => intval($totalFiltered),
"data" => $data,
];
echo json_encode($json_data);
exit();
}
/**
* view invoice
*
* @param Invoices $invoice
*
* @return Factory|View|Application
*/
public function view(Invoices $invoice): Factory|View|Application
{
$breadcrumbs = [
['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Dashboard')],
['link' => url(config('app.admin_path')."/invoices"), 'name' => __('locale.menu.All Invoices')],
['name' => __('locale.labels.invoice')],
];
return view('admin.Invoices.view', compact('breadcrumbs', 'invoice'));
}
/**
* print invoice
*
* @param Invoices $invoice
*
* @return Application|Factory|View
*/
public function print(Invoices $invoice): View|Factory|Application
{
$pageConfigs = ['pageHeader' => false];
return view('admin.Invoices.print', compact('invoice', 'pageConfigs'));
}
/**
* @param Invoices $invoice
*
* @return JsonResponse
* @throws Exception
*/
public function destroy(Invoices $invoice): JsonResponse
{
if (config('app.stage') == 'demo') {
return response()->json([
'status' => 'error',
'message' => 'Sorry! This option is not available in demo mode',
]);
}
if ( ! $invoice->delete()) {
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
return response()->json([
'status' => 'success',
'message' => 'Invoice was deleted successfully.',
]);
}
/**
* batch actions
*
* @param Request $request
*
* @return JsonResponse
*/
public function batchAction(Request $request): JsonResponse
{
if (config('app.stage') == 'demo') {
return response()->json([
'status' => 'error',
'message' => 'Sorry! This option is not available in demo mode',
]);
}
$ids = $request->get('ids');
if (Invoices::whereIn('uid', $ids)->delete()) {
return response()->json([
'status' => 'success',
'message' => __('locale.subscription.invoices_deleted'),
]);
}
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
public function approve(Invoices $invoice)
{
$data = explode("|", $invoice->transaction_id);
$paymentController = new PaymentController();
if (is_array($data) && count($data) == 2) {
switch ($data[0]) {
case 'top_up':
$user = User::find($invoice->user_id);
if ($user->sms_unit != '-1') {
$user->sms_unit += $data['1'];
$user->save();
}
$subscription = $user->customer->activeSubscription();
$transaction = $subscription->addTransaction(SubscriptionTransaction::TYPE_SUBSCRIBE, [
'status' => SubscriptionTransaction::STATUS_SUCCESS,
'title' => 'Add '.$data['1'].' sms units',
'amount' => $data['1'].' sms units',
]);
$invoice->update([
'status' => 'paid',
'transaction_id' => $transaction->uid,
]);
return response()->json([
'status' => 'success',
'message' => 'Invoice marked as paid',
]);
case 'sender_id':
$senderid = Senderid::findByUid($data[1]);
$current = Carbon::now();
$senderid->validity_date = $current->add($senderid->frequency_unit, $senderid->frequency_amount);
$senderid->status = 'active';
$senderid->save();
$paymentController->createNotification('senderid', $senderid->sender_id, User::find($senderid->user_id)->displayName());
$invoice->update([
'status' => 'paid',
'transaction_id' => $senderid->uid,
]);
return response()->json([
'status' => 'success',
'message' => 'Invoice marked as paid',
]);
case 'number':
$number = PhoneNumbers::findByUid($data[1]);
$current = Carbon::now();
$number->validity_date = $current->add($number->frequency_unit, $number->frequency_amount);
$number->status = 'assigned';
$number->save();
$paymentController->createNotification('number', $number->number, User::find($number->user_id)->displayName());
$invoice->update([
'status' => 'paid',
'transaction_id' => $number->uid,
]);
return response()->json([
'status' => 'success',
'message' => 'Invoice marked as paid',
]);
case 'keyword':
$keyword = Keywords::findByUid($data[1]);
$current = Carbon::now();
$keyword->validity_date = $current->add($keyword->frequency_unit, $keyword->frequency_amount);
$keyword->status = 'assigned';
$keyword->save();
$paymentController->createNotification('keyword', $keyword->keyword_name, User::find($keyword->user_id)->displayName());
$invoice->update([
'status' => 'paid',
'transaction_id' => $keyword->uid,
]);
case 'subscription':
$subscription = Subscription::findByUid($data[1]);
//set active subscription
$subscription->setActive();
// add transaction
$subscription->addTransaction(SubscriptionTransaction::TYPE_SUBSCRIBE, [
'end_at' => $subscription->end_at,
'current_period_ends_at' => $subscription->current_period_ends_at,
'status' => SubscriptionTransaction::STATUS_SUCCESS,
'title' => trans('locale.subscription.subscribed_to_plan', ['plan' => $subscription->plan->getBillableName()]),
'amount' => $subscription->plan->getBillableFormattedPrice(),
]);
// add log
$subscription->addLog(SubscriptionLog::TYPE_ADMIN_APPROVED, [
'plan' => $subscription->plan->getBillableName(),
'price' => $subscription->plan->getBillableFormattedPrice(),
]);
sleep(1);
// add log
$subscription->addLog(SubscriptionLog::TYPE_SUBSCRIBED, [
'plan' => $subscription->plan->getBillableName(),
'price' => $subscription->plan->getBillableFormattedPrice(),
]);
$invoice->update([
'status' => 'paid',
'transaction_id' => $subscription->uid,
]);
$user = User::find($invoice->user_id);
if ($user->sms_unit == null || $user->sms_unit == '-1' || $subscription->plan->getOption('sms_max') == '-1') {
$user->sms_unit = $subscription->plan->getOption('sms_max');
} else {
if ($subscription->plan->getOption('add_previous_balance') == 'yes') {
$user->sms_unit += $subscription->plan->getOption('sms_max');
} else {
$user->sms_unit = $subscription->plan->getOption('sms_max');
}
}
$user->save();
if (Helper::app_config('subscription_notification_email')) {
$admin = User::find(1);
$admin->notify(new SubscriptionPurchase(route('admin.invoices.view', $invoice->uid)));
}
if ($user->customer->getNotifications()['subscription'] == 'yes') {
$user->notify(new SubscriptionPurchase(route('customer.invoices.view', $invoice->uid)));
}
return response()->json([
'status' => 'success',
'message' => 'Invoice marked as paid',
]);
default:
return response()->json([
'status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),
]);
}
}
return response()->json(['status' => 'error',
'message' => __('locale.exceptions.something_went_wrong'),]);
}
}