Files

1592 lines
93 KiB
PHP
Executable File

<?php
namespace Modules\Journals\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Modules\Invoices\Services\InvoicesService;
use Modules\PatientFinance\Services\DepositHelpers;
use Streamline\Models\Banking;
use Streamline\Models\CashierIncome;
use Streamline\Models\ChartOfAccount;
use Streamline\Models\Debtor;
use Streamline\Models\Equity;
use Streamline\Models\FixedAsset;
use Streamline\Models\HospitalBill;
use Streamline\Models\InvoicePayment;
use Streamline\Models\Journal;
use Streamline\Models\OtherIncome;
use Streamline\Models\PatientCategoryInvoice;
use Streamline\Models\Payment;
use Streamline\Models\TrackInvoice;
use Streamline\Models\TrackReceipt;
use Streamline\Services\PatientDiscounts\DebtorsService;
use Streamline\Services\ReceiptService;
class JournalController extends Controller
{
public function __construct(
protected InvoicesService $invoicesService,
protected DebtorsService $debtorsService,
protected ReceiptService $receiptService
) {
}
public function index()
{
$accounts = DB::table('chart_of_accounts')->whereNull('deleted_at')->orderBy('name', 'asc')->get();
$customers = DB::table('patients')->whereNull('deleted_at')->orderBy('first_name', 'asc')->get();
$suppliers = DB::table('suppliers')->where('available', 1)->whereNull('deleted_at')->orderBy('name', 'asc')->get();
$employees = DB::table('users')->whereNull('deleted_at')->orderBy('first_name', 'asc')->get();
$patient_categories = DB::table('patient_categories')->whereNull('deleted_at')->orderBy('name', 'asc')->get();
$payment_items = DB::table('payment_items')->whereNull('deleted_at')->orderBy('name', 'asc')->get();
$latest_journal = DB::table('journals')->latest('updated_at')->first();
$journal_number = is_null($latest_journal) ? 1 : $latest_journal->journal_number + 1;
return view('journals::journals.index', compact('accounts', 'customers', 'suppliers', 'employees', 'patient_categories', 'payment_items', 'journal_number'));
}
/**
* Search for journals records with given parameters
*
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Foundation\Application|\Illuminate\View\View
*/
public function records(Request $request)
{
$created_by = $request->created_by;
$dates = $request->dates;
$filters = [];
if ($created_by == null) :
// pass
elseif ($created_by != 'all') :
array_push($filters, ['created_by', '=', $created_by]);
endif;
switch ($dates) {
case 'today':
$today = Carbon::today()->format('Y-m-d');
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', $today)->paginate(1000);
break;
case 'yesterday':
$yesterday = Carbon::yesterday()->format('Y-m-d');
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', $yesterday)->paginate(1000);
break;
case 'week':
$week_ago = Carbon::today()->subDays(7)->format('Y-m-d');
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', '>=', $week_ago)->paginate(1000);
break;
case 'month':
$month_ago = Carbon::today()->subDays(30)->format('Y-m-d');
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', '>=', $month_ago)->paginate(1000);
break;
case 'custom-date':
$start_date = Carbon::parse($request->start_date)->format('Y-m-d');
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', '=', $start_date)->paginate(1000);
break;
case 'custom-range':
$start_date = Carbon::parse($request->start_date)->format('Y-m-d');
$end_date = Carbon::parse($request->end_date)->format('Y-m-d');
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->whereBetween('created_at', [$start_date, $end_date])->paginate(1000);
break;
default:
$journals = Journal::orderBy('created_at', 'desc')->where($filters)->paginate(1000);
break;
}
if ($journals->count() <= 0) {
flash("There are no records found in the search")->error();
}
// users with activity
$created_by_array = DB::table('journals')->groupBy('created_by')->select('created_by')->get()->toArray();
$created_by = array(count($created_by_array));
foreach ($created_by_array as $value) {
$created_by[$value->created_by] = get_full_name($value->created_by, 'id', 'first_name', 'last_name', 'users');
}
// remove the count from the array
unset($created_by[0]);
// add --select--
$created_by = ['all' => 'ALL'] + $created_by;
// get all first names
$first_names = DB::table('users')->pluck('first_name', 'id');
// get all last names
$last_names = DB::table('users')->pluck('last_name', 'id');
return view('journals::journals.records', compact('journals', 'created_by'));
}
public function save(Request $request)
{
$validator = Validator::make($request->all(), [
'journal_date' => 'required',
'journal_number' => 'required',
]);
if ($validator->fails()) {
$string = "";
foreach ($validator->errors()->getMessages() as $item) {
$string .= "{$item[0]}<br>";
}
flash($string)->error();
return back()->withErrors($validator)->withInput();
} else {
if ($request->journal_action == 'save') {
$account_ids = $request->account_id;
$debits = $request->debit;
$credits = $request->credit;
$descriptions = $request->description;
$type_ids = $request->type_id;
//create an array of the journaled account types using the account_ids
$journaled_account_types = $journaled_liability_amounts = $journaled_expense_amounts = [];
for ($i=0; $i < count($account_ids) ; $i++) {
$journaled_account_types[] = get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts');
if (in_array(get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts'), [6,9,11,12])) {
$journaled_liability_amounts[] = $debits[$i] ? $debits[$i] : $credits[$i];
}
if (get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts') == 2) {
$journaled_expense_amounts[] = $debits[$i] ? $debits[$i] : $credits[$i];
}
}
//track the affected tables, affected table record ids
$affected_tables_by_the_journal = [];
// The name_id can belong to a customer, supplier or employee
// As you loop through data from each row, be sure to reference the related item in the array
$name_ids = $request->name_id;
$invoice_numbers = $request->invoice_number;
$logged_in_user = Auth::id();
$journal_number = $this->validate_journal_number($request->journal_number);
$journal = new Journal;
$journal->journal_date = Carbon::parse($request->journal_date)->toDateString();
$journal->journal_number = $journal_number;
$journal->account_ids = implode(",", $account_ids);
$journal->debits = implode(",", $debits);
$journal->credits = implode(",", $credits);
$journal->descriptions = implode(",", $descriptions);
$journal->type_ids = implode(",", $type_ids);
$journal->name_ids = implode(",", $name_ids);
$journal->created_by = $logged_in_user;
$item_account = null;
$payment_item = null;
// If an expense account is tagged, set it as an $item_account
$expense_accounts_count = 0;
for ($i = 0; $i < count($type_ids); $i++) {
// If expense account was tagged
if (get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts') == 2) {
$item_account = $account_ids[$i];
//reject journal if no payment item has been specified
if ($type_ids[$i] != '5' || $name_ids[$i] == '') {
flash("Please specify the payment item for the expense")->error();
return redirect('journals');
}
}
// If payment item tagged
if ($type_ids[$i] == '5') {
$expense_accounts_count += 1;
if ($expense_accounts_count > 1) {
flash("Multiple expense accounts are not yet supported in Journals! Deal with one at a time!")->error();
return redirect('journals');
}
$payment_item = $name_ids[$i];
}
// If a Supplier is tagged (for a debit of an account of type Accounts Payable), reject Journal if no matching bill is found
if (get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts') == 9 && $debits[$i] != '' && $type_ids[$i] == '2' && $name_ids[$i] != '') {
$matching_bill = HospitalBill::whereNull('deleted_at')->whereNull('balance')->where('total_amount', '>=', (int)$debits[$i])->where('vendor', $name_ids[$i])->where('payable_account', $account_ids[$i])->first();
if (is_null($matching_bill)) {
// $matching_bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debits[$i])->where('vendor', $name_ids[$i])->first(); // Old query
$matching_bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debits[$i])->where('vendor', $name_ids[$i])->where('payable_account', $account_ids[$i])->first();
if (is_null($matching_bill)) {
// Reject Journal and send them to pay bill 👍 ¯\_(ツ)_/¯
flash("Journals could not find a Hospital bill of value greater than or equal to " . ugandan_shillings((int)$debits[$i]) . ", for Supplier: " . get_name($name_ids[$i], 'id', 'name', 'suppliers') . "!")->error();
return redirect('/payments/bills/');
}
}
}
// If a Liability account is tagged
if (in_array(get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts'), [6, 11, 12])) {
// Reject Journal if no matching bill is found
if ($debits[$i] != '') {
// If not Patient Category
if ($type_ids[$i] != '4') {
// If vendor/supplier
if ($type_ids[$i] == '2') {
// (is_null($bill->balance) ? $bill->total_amount : $bill->balance)
// ponder the above check on what's left to pay and implement below
$matching_bill = HospitalBill::whereNull('deleted_at')->whereNull('balance')->where('total_amount', '>=', (int)$debits[$i])->where('vendor', $name_ids[$i])->where('payable_account', $account_ids[$i])->first();
if (is_null($matching_bill)) {
$matching_bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debits[$i])->where('vendor', $name_ids[$i])->where('payable_account', $account_ids[$i])->first();
if (is_null($matching_bill)) {
// Reject Journal and send them to pay bill 👍 ¯\_(ツ)_/¯
flash("Journals could not find a Hospital bill of value greater than or equal to " . ugandan_shillings((int)$debits[$i]) . ", tagged to the Liability Account: " . get_name($account_ids[$i], 'id', 'name', 'chart_of_accounts') . "!")->error();
return redirect('/payments/bills/');
}
}
} else {
$matching_bill = HospitalBill::whereNull('deleted_at')->whereNull('balance')->where('total_amount', '>=', (int)$debits[$i])->whereNull('vendor')->where('payable_account', $account_ids[$i])->first();
if (is_null($matching_bill)) {
$matching_bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debits[$i])->whereNull('vendor')->where('payable_account', $account_ids[$i])->first();
if (is_null($matching_bill)) {
// Reject Journal and send them to pay bill 👍 ¯\_(ツ)_/¯
flash("Journals could not find a Hospital bill of value greater than or equal to " . ugandan_shillings((int)$debits[$i]) . ", tagged to the Liability Account: " . get_name($account_ids[$i], 'id', 'name', 'chart_of_accounts') . ". Please double check the journal entry and ensure to pick a supplier where necessary!")->error();
return redirect('/payments/bills/');
}
}
}
}
}
// Reject journal if the credit entry doesn't have type "Supplier" and name is not selected
if ($credits[$i] != '') {
// If not vendor/supplier
if ($type_ids[$i] != '2' || $name_ids[$i] == '') {
// Reject Journal
flash("You must select a supplier when crediting a Liability account!")->error();
flash("The Journal entry has NOT been submitted! Please try again!")->error();
return redirect('journals');
}
}
}
// If accounts receivable is tagged for credit with an invoice number for a patient category
if (get_name($account_ids[$i], 'id', 'type', 'chart_of_accounts') == 8 && $credits[$i] != '' && $type_ids[$i] == '4' && $name_ids[$i] != '') {
// If no invoice is found for the tagged patient category, reject the journal
$uncleared_invoices = DB::table('patient_category_invoices')->where('invoice_generated', 1)
->where('status', 0)
->where('patient_category', (int)$name_ids[$i])
->where('invoice_number', $invoice_numbers[$i])
->whereNull('balance_remaining')
->get();
if (count($uncleared_invoices) < 1) {
$uncleared_invoices = DB::table('patient_category_invoices')->where('invoice_generated', 1)
->where('status', 1)
->where('patient_category', (int)$name_ids[$i])
->where('invoice_number', $invoice_numbers[$i])
->where('balance_remaining', '>=', (int)$credits[$i])
->get();
if (count($uncleared_invoices) < 1) {
flash("No uncleared Patient Category Invoice found for Patient Category: " . get_name($name_ids[$i], 'id', 'name', 'patient_categories') . " and invoice number " . $invoice_numbers[$i] . "!")->error();
return redirect('/invoices/receive_patient_invoices/');
}
}
}
}
for ($x = 0; $x < count($account_ids); $x++) {
$account = $account_ids[$x];
$debit = $debits[$x];
$credit = $credits[$x];
$description = $descriptions[$x];
$type_id = $type_ids[$x];
$name_id = $name_ids[$x];
$new_balance = $old_balance = (int)get_name($account, 'id', 'balance', 'chart_of_accounts');
$account_type = get_name($account, 'id', 'type', 'chart_of_accounts');
$account_name = get_name($account, 'id', 'name', 'chart_of_accounts');
// Account Type: [Non-Current Assets (a.k.a Fixed Assets), Current Assets, Other Current Assets]
// TODO: Figure out how to deal with Platinum's `Other assets` account type of id 15
$action = "-";
$affected_amount = 0;
$flash_msg = "";
if (in_array($account_type, [3, 10, 12, 15])) {
if ($debit != '') {
// Increase this Asset's value
$new_balance = $old_balance + (int)$debit;
$action = "addition";
$affected_amount = $debit;
$flash_msg = "debited";
// TODO: Deal with other related tables when assets are debited
} else if ($credit != '') {
// Decrease this Asset's value
$new_balance = $old_balance - (int)$credit;
$action = "deduction";
$affected_amount = $credit;
$flash_msg = "credited";
}
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
/******************* insert or update into fixed assets table ******************/
$fixed_asset = new FixedAsset;
if ($debit != '') {
$fixed_asset->name = "Journal (" . $request->journal_number . ") Debit - " . $account_name;
$fixed_asset->description = $fixed_asset->name;
} else{
$fixed_asset->name = "Journal (" . $request->journal_number . ") Credit - " . $account_name;
$fixed_asset->description = $fixed_asset->name;
}
$fixed_asset->cost_price = ($debit != '') ? $debit : -(int)$credit;
$fixed_asset->item_condition = 1;
$fixed_asset->acquisition_date = Carbon::parse($request->journal_date)->toDateString();
$fixed_asset_supplier_id = null;
//if supplier is provided
$fixed_asset->supplier_id = ($type_id==2 && $name_id!='') ? $name_id : "N/A";
$fixed_asset->fixed_asset_account_id = $account;
$fixed_asset->save();
flash("Fixed asset: " . $fixed_asset->name . " has been ". $flash_msg." with ". ugandan_shillings($fixed_asset->cost_price) ." on Account: " . $account_name . " has been created!")->success();
$affected_tables_by_the_journal[] = ["table" => "fixed_assets", "record_id" => $fixed_asset->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
/******************** end insertion into fixed assets table ***********************/
}
// Account Type: [Current Liabilities, Non-Current Liabilities, Other current liabilities]
else if (in_array($account_type, [6, 11, 12])) {
$affected_amount = 0;
$action = "-";
if ($debit != '') {
// Decrease this Liability Account's value
$new_balance = $old_balance - (int)$debit;
// If a supplier is tagged, pay off a bill!!!
if ($type_id == 2 && $name_id != '') {
// Somewhat like a Russian roulette implementation to knock off one of the bills tagged to the supplier
$bill = HospitalBill::whereNull('deleted_at')->whereNull('balance')->where('total_amount', '>=', (int)$debit)->where('vendor', $name_id)->where('payable_account', $account)->first();
if (is_null($bill)) {
// $bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debit)->where('vendor', $name_id)->first(); // Old query
$bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debit)->where('vendor', $name_id)->where('payable_account', $account)->first();
if (!is_null($bill)) {
$affected_tables_by_the_journal[] = $this->store_bill_payment($bill->id, $request->journal_date, $description, (int)$debit, $account, $logged_in_user);
} else {
flash("No Hospital bill of value greater than or equal to " . ugandan_shillings((int)$debit) . ", for Supplier: " . get_name($name_id, 'id', 'name', 'suppliers') . "!")->error();
}
} else {
$affected_tables_by_the_journal[] = $this->store_bill_payment($bill->id, $request->journal_date, $description, (int)$debit, $account, $logged_in_user);
}
} else {
// Somewhat like a Russian roulette implementation to knock off one of the bills tagged to the liability account
$bill = HospitalBill::whereNull('deleted_at')->whereNull('balance')->where('total_amount', '>=', (int)$debit)->whereNull('vendor')->where('payable_account', $account)->first();
if (is_null($bill)) {
$bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debit)->whereNull('vendor')->where('payable_account', $account)->first();
if (!is_null($bill)) {
$affected_tables_by_the_journal[] = $this->store_bill_payment($bill->id, $request->journal_date, $description, (int)$debit, $account, $logged_in_user);
} else {
flash("No Hospital bill of value greater than or equal to " . ugandan_shillings((int)$debit) . "!")->error();
}
} else {
$affected_tables_by_the_journal[] = $this->store_bill_payment($bill->id, $request->journal_date, $description, (int)$debit, $account, $logged_in_user);
}
}
$affected_amount = $debit;
$action = "deduction";
} else if ($credit != '') {
// Increase this Liability Account's value
$new_balance = $old_balance + (int)$credit;
// Create a bill
$affected_amount = $credit;
$action = "addition";
$affected_tables_by_the_journal[] = $this->save_bill(($name_id != '') ? $name_id : null, $request->journal_date, $description, (int)$credit, $account, $item_account, $payment_item, $logged_in_user, $journal_number);
}
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
}
// Account Type: Equity
else if ($account_type == 5) {
$affected_amount = 0;
$action = "-";
$equity = new Equity;
$equity->account_id = $account;
if ($debit != '') {
// Decrease this Equity Account's value
$new_balance = $old_balance - (int)$debit;
$affected_amount = $debit;
$action = "deduction";
// Record the transaction
$equity->name = "Journal (" . $journal_number . ") Debit - " . $account_name;
$equity->amount = -(int)$debit;
} else if ($credit != '') {
// Increase this Equity Account's value
$new_balance = $old_balance + (int)$credit;
$affected_amount = $credit;
$action = "addition";
// Record the transaction
$equity->name = "Journal (" . $journal_number . ") Credit - " . $account_name;
$equity->amount = (int)$credit;
}
// Save the Equity transaction record
$equity->transaction_date = Carbon::parse($request->journal_date)->toDateTimeString(); //use the journal date
$equity->created_at = Carbon::now();
$equity->created_by = Auth::id();
$equity->updated_by = Auth::id();
$equity->save();
$affected_tables_by_the_journal[] = ["table" => "equities", "record_id" => $equity->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
flash("Transacted " . ugandan_shillings($equity->amount) . " on Equity Account: " . $account_name . "!")->success();
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
}
// Account Type: Income
// TODO: Figure out how to deal with Platinum's `Other Income` account type of id 16
else if (in_array($account_type, [1, 16])) {
$affected_amount = 0;
$action = "-";
//1.record money into banking and cashier_income tables
//2.record into other_incomes_income table
//3 if selected account is not undeposited funds then
$new_receipt_number = $this->receiptService->createReceipt("journals-other income");
//start insert into the banking table
/*$new_receipt_number = generateReceiptNumber();
$undeposited_funds_account_balance_days_record = get_latest_banking_record(get_name("undeposited_funds", "slug", "id", "chart_of_accounts"), Carbon::parse($request->journal_date)->toDateString());
$undeposited_funds_account_balance_for_the_day = ($undeposited_funds_account_balance_days_record != null) ? $undeposited_funds_account_balance_days_record->account_balance : 0;
$last_insert_id_to_account = capture_bank_record('DEPOSIT', Carbon::parse($request->journal_date)->toDateString(), 10, '', $undeposited_funds_account_balance_for_the_day, $amount_on_applying_journal_rule, 0, "Journal (" . $request->journal_number . ")", $new_receipt_number);
$affected_tables_by_the_journal[] = ["table" => "banking", "record_id" => $last_insert_id_to_account, "amount" => "-", "action" => "insertion", "table_column" => "-"];
$undeposited_funds_account_balance_after_deposit = $undeposited_funds_account_balance_for_the_day + $amount_on_applying_journal_rule;
update_banking_record_balances(Carbon::parse($request->journal_date)->toDateString(), 10, $last_insert_id_to_account, $undeposited_funds_account_balance_after_deposit);*/
//end insert into banking table
//insert into cashier income table
/*$cashier_income = new CashierIncome;
$cashier_income->cashier_id = Auth::id();
$cashier_income->brought_by = Auth::id();
$cashier_income->expected_amount = $amount_on_applying_journal_rule;
$cashier_income->reason = "Journal (" . $request->journal_number . ")";
$cashier_income->amount = $amount_on_applying_journal_rule;
$cashier_income->balance = 0;
$cashier_income->receipt_number = $new_receipt_number;
//
$undeposited_funds_account_balance_today_record = get_latest_banking_record(get_name("undeposited_funds", "slug", "id", "chart_of_accounts"), Carbon::parse($request->journal_date)->toDateString());
$undeposited_funds_account_balance_today = ($undeposited_funds_account_balance_today_record != null) ? $undeposited_funds_account_balance_today_record->account_balance : 0;
//
$cashier_income->previous_balance = (int)$undeposited_funds_account_balance_today;
$cashier_income->account_balance = (int)$undeposited_funds_account_balance_today + $cashier_income->amount;
$cashier_income->banked = $last_insert_id_to_account;
$cashier_income->save();
$cashier_income_id = $cashier_income->id;
$affected_tables_by_the_journal[] = ["table" => "cashier_incomes", "record_id" => $cashier_income_id, "amount" => "-", "action" => "insertion", "table_column" => "-"];*/
//end insert into cashier income table
$other_income = new OtherIncome;
$other_income->income_account = $account;
$other_income->deposit_date = Carbon::parse($request->journal_date)->toDateString();
$trans_id = $new_receipt_number;
$other_income->trans_id = $trans_id;
if ($debit != '') {
// Decrease this Income Account's value
$new_balance = $old_balance - (int)$debit;
$affected_amount = $debit;
$action = "deduction";
// TODO: Deal with other related tables when incomes are debited
$other_income->deposit_amount = -(int)$debit;
$other_income->deposit_memo = "Journal (" . $journal_number . ") Debit - " . $account_name;
} else if ($credit != '') {
// Increase this Income Account's value
$new_balance = $old_balance + (int)$credit;
$affected_amount = $credit;
$action = "addition";
// TODO: Deal with other related tables when incomes are credited
$other_income->deposit_amount = (int)$credit;
$other_income->deposit_memo = "Journal (" . $journal_number . ") Credit - " . $account_name;
}
//save the record into the other_incomes table
$other_income->created_by = Auth::id();
$other_income->updated_by = Auth::id(); //should be really null but table needs it
if ($other_income->save()) {
$affected_tables_by_the_journal[] = ["table" => "other_incomes", "record_id" => $other_income->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
}
// Account Type: Expense
else if ($account_type == 2) {
$affected_amount = 0;
$action = "-";
$flash_msg = "";
if ($debit != '') {
// Increase this Expense Account's value
$new_balance = $old_balance + (int)$debit;
$affected_amount = $debit;
$action = "addition";
$flash_msg = "debited";
} else if ($credit != '') {
// Decrease this Expense Account's value
$new_balance = $old_balance - (int)$credit;
$affected_amount = $credit;
$action = "deduction";
$flash_msg = "credited";
}
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
//check if the journal has liablities & expenses and ignore insertion into payments table if amounts equate [liabilities type ids are 6,9,11,12]
if (in_array(6, $journaled_account_types) || in_array(9, $journaled_account_types) || in_array(11, $journaled_account_types) || in_array(12, $journaled_account_types)) {
$all_payables_sum = array_sum($journaled_liability_amounts);
$all_expenses_sum = array_sum($journaled_expense_amounts);
if ($all_payables_sum != $all_expenses_sum) {
//if the type is payment item, add an insertion in payment table
if($type_id == '5'){
$payment = new Payment;
$payment->item_id = $name_id;
//$payment->vendor = $vendor_array[$x];
$payment->unit_cost = ($debit != '') ? $debit : -(int)$credit;
$payment->amount = ($debit != '') ? $debit : -(int)$credit;
$payment->quantity = 1;
if ($debit != '') {
$payment->memo = "Journal (" . $request->journal_number . ") Debit - " . $account_name;
} else{
$payment->memo = "Journal (" . $request->journal_number . ") Credit - " . $account_name;
}
//$payment->account_balance = $account_balance_on_expense_date_after_payment;
$trans_id = $this->receiptService->createReceipt("journals-payment");
$payment->transaction_id = $trans_id;
//$payment->account_id = $request->bank;
$payment->created_by = Auth::id();
$payment->expense_date = Carbon::parse($request->journal_date)->toDateString();
$payment->expense_account = $account;
if($payment->save()){
flash("Payment: " . get_name($name_id, "id", "name", "payment_items") . " has been ". $flash_msg." with ". $payment->amount ." on Account: " . $account_name . " has been created!")->success();
}
$affected_tables_by_the_journal[] = ["table" => "payments", "record_id" => $payment->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
}
} else {
//if the type is payment item, add an insertion in payment table
if($type_id == '5'){
$payment = new Payment;
$payment->item_id = $name_id;
//$payment->vendor = $vendor_array[$x];
$payment->unit_cost = ($debit != '') ? $debit : -(int)$credit;
$payment->amount = ($debit != '') ? $debit : -(int)$credit;
$payment->quantity = 1;
if ($debit != '') {
$payment->memo = "Journal (" . $request->journal_number . ") Debit - " . $account_name;
} else{
$payment->memo = "Journal (" . $request->journal_number . ") Credit - " . $account_name;
}
//$payment->account_balance = $account_balance_on_expense_date_after_payment;
$trans_id = $this->receiptService->createReceipt("journals-payment");
$payment->transaction_id = $trans_id;
//$payment->account_id = $request->bank;
$payment->created_by = Auth::id();
$payment->expense_date = Carbon::parse($request->journal_date)->toDateString();
$payment->expense_account = $account;
if($payment->save()){
flash("Payment: " . get_name($name_id, "id", "name", "payment_items") . " has been ". $flash_msg." with ". $payment->amount ." on Account: " . $account_name . " has been created!")->success();
}
$affected_tables_by_the_journal[] = ["table" => "payments", "record_id" => $payment->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
}
}
// Account Type: Bank
else if ($account_type == 4) {
$affected_amount = 0;
$action = "-";
$transaction_date = Carbon::parse($request->journal_date)->toDateString();
$banking_record = get_latest_banking_record_based_on_transaction_date($account, Carbon::today()->toDateString());
$bank_balance_that_day = ($banking_record != null) ? (int)$banking_record->account_balance : 0;
$old_balance = $bank_balance_that_day;
if ($debit != '') {
// Increase this Bank Account's value
$new_balance = $old_balance + (int)$debit;
$affected_amount = $debit;
$action = "addition";
// Save an entry to the Banking table
// NOTE: The debit value goes in as the credit value so that the bank register is satisfied
// In a bank register, an increase on the balance is placed on the credit side
$last_insert_id = capture_bank_record('DEPOSIT', $transaction_date, $account, '', $new_balance, (int)$debit, 0, $description, $this->receiptService->createReceipt("journals-banking"));
$affected_tables_by_the_journal[] = ["table" => "banking", "record_id" => $last_insert_id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
update_banking_record_balances($transaction_date, $account, $last_insert_id, $new_balance);
flash("Deposited " . ugandan_shillings((int)$debit) . " to Bank Account: " . $account_name . "!")->success();
} else if ($credit != '') {
// Decrease this Bank Account's value
$new_balance = $old_balance - (int)$credit;
$affected_amount = $credit;
$action = "deduction";
// Save an entry to the Banking table
// NOTE: The credit value goes in as the debit value so that the bank register is satisfied
// In a bank register, a decrease on the balance is placed on the debit side
$last_insert_id = capture_bank_record('PAYMENT', $transaction_date, $account, '', $new_balance, 0, (int)$credit, $description, $this->receiptService->createReceipt("journals-banking"));
$affected_tables_by_the_journal[] = ["table" => "banking", "record_id" => $last_insert_id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
update_banking_record_balances($transaction_date, $account, $last_insert_id, $new_balance);
flash("Used " . ugandan_shillings((int)$credit) . " from Bank Account: " . $account_name . " for a payment!")->success();
}
$track_receipt = new TrackReceipt;
$track_receipt->reason = "Bank ".$action." by Journal number " . $request->journal_number;
$track_receipt->created_by = Auth::id();
$track_receipt->save();
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
//add an insertion in payment table
if($type_id == '5'){
//if the type chosen is payment item then save into payments table
$payment = new Payment;
$payment->item_id = $name_id;
//$payment->vendor = $vendor_array[$x];
$payment->unit_cost = ($debit != '') ? $debit : -(int)$credit;
$payment->amount = ($debit != '') ? $debit : -(int)$credit;
$payment->quantity = 1;
if ($debit != '') {
$payment->memo = "Journal (" . $request->journal_number . ") Debit - " . $account_name;
} else{
$payment->memo = "Journal (" . $request->journal_number . ") Credit - " . $account_name;
}
//$payment->account_balance = $account_balance_on_expense_date_after_payment;
$trans_id = $this->receiptService->createReceipt("journals-payment");
$payment->transaction_id = $trans_id;
//$payment->account_id = $request->bank;
$payment->created_by = Auth::id();
$payment->expense_date = Carbon::parse($request->journal_date)->toDateString();
$payment->expense_account = $account;
if($payment->save()){
flash("Payment: " . get_name($name_id, "id", "name", "payment_items") . " has been ". $flash_msg." with ". $payment->amount ." on Account: " . $account_name . " has been created!")->success();
}
$affected_tables_by_the_journal[] = ["table" => "payments", "record_id" => $payment->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
}
// Account Type: Accounts Payable
else if ($account_type == 9) {
/**
* For example:
* 1. If getting items from a Supplier on credit:
* - credit a payable a/c
* - debit an inventory a/c
* 2. If paying for items from a supplier
* - debit a payable a/c
* - credit a bank a/c
*/
$affected_amount = 0;
$action = "-";
if ($debit != '') {
// Decrease this Accounts Payable' value
$new_balance = $old_balance - (int)$debit;
$affected_amount = $debit;
$action = "deduction";
// If a supplier is tagged, pay off a bill!!!
if ($type_id == 2 && $name_id != '') {
// Somewhat like a Russian roulette implementation to knock off one of the bills tagged to the supplier
// $bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debit)->where('vendor', $name_id)->first(); // Old query
$bill = HospitalBill::whereNull('deleted_at')->whereNull('balance')->where('total_amount', '>=', (int)$debit)->where('vendor', $name_id)->where('payable_account', $account)->first();
if (is_null($bill)) {
$bill = HospitalBill::whereNull('deleted_at')->where('balance', '>=', (int)$debit)->where('vendor', $name_id)->where('payable_account', $account)->first();
if (!is_null($bill)) {
$affected_tables_by_the_journal[] = $this->store_bill_payment($bill->id, $request->journal_date, $description, (int)$debit, $account, $logged_in_user);
} else {
flash("No Hospital bill of value greater than or equal to " . ugandan_shillings((int)$debit) . ", for Supplier: " . get_name($name_id, 'id', 'name', 'suppliers') . "!")->error();
}
} else {
$affected_tables_by_the_journal[] = $this->store_bill_payment($bill->id, $request->journal_date, $description, (int)$debit, $account, $logged_in_user);
}
}
} else if ($credit != '') {
// Increase this Accounts Payable' value
// e.g. when getting items from a supplier on credit
$new_balance = $old_balance + (int)$credit;
$affected_amount = $credit;
$action = "addition";
// Create a bill
$affected_tables_by_the_journal[] = $this->save_bill(($name_id != '') ? $name_id : null, $request->journal_date, $description, (int)$credit, $account, $item_account, $payment_item, $logged_in_user, $journal_number);
}
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
}
// Account Type: Accounts Receivable
else if ($account_type == 8) {
$affected_amount = 0;
$action = "-";
if ($debit != '') {
// Increase this Accounts Receivable's value
$new_balance = $old_balance + (int)$debit;
$affected_amount = $debit;
$action = "addition";
// If a customer is tagged, generate an invoice!!!
// This should be available under Finance->Reports->Debtors Report
if ($type_id == 1 && $name_id != '') {
DepositHelpers::debt($name_id, 0, (int)$debit, '', '');
$last_inserted_debt = Debtor::orderBy('id', 'desc')->first();
if ($account != 16) {
$last_inserted_debt->receivable_account = $account;
$last_inserted_debt->update();
}
$affected_tables_by_the_journal[] = ["table" => "debtors", "record_id" => $last_inserted_debt->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
// track the invoice
$track = new TrackInvoice;
$track->reason = "Journal (" . $journal_number . ") Debit Accounts Receivable (Patient ID: " . $name_id . ")";
$track->created_by = $logged_in_user;
$track->save();
$affected_tables_by_the_journal[] = ["table" => "track_invoices","record_id" => $track->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
// If a patient category is tagged, generate an invoice!!!
// This should be available under Finance->Invoices->Receive Invoice Payments
if ($type_id == 4 && $name_id != '') {
$new_patient_category_invoice = new PatientCategoryInvoice;
// track the invoice
$track_invoice = new TrackInvoice;
$track_invoice->reason = get_name($name_id, 'id', 'name', 'patient_categories');
$track_invoice->created_by = $logged_in_user;
$track_invoice->save();
$invoice_number = sprintf("%04u", $track_invoice->id);
$new_patient_category_invoice->patient_category = $name_id;
$new_patient_category_invoice->invoice_number = $invoice_number;
$new_patient_category_invoice->patient_amount = (int)$debit;
$new_patient_category_invoice->created_by = $logged_in_user;
$new_patient_category_invoice->invoice_generated = 1;
$new_patient_category_invoice->invoice_date = $request->journal_date . '/' . $request->journal_date;
if ($account != 16) {
$new_patient_category_invoice->receivable_account = $account;
}
$new_patient_category_invoice->items_ids = "Journal - " . $request->journal_number;
$new_patient_category_invoice->transaction_date = Carbon::parse($request->journal_date)->toDateString();
$new_patient_category_invoice->save();
$affected_tables_by_the_journal[] = ["table" => "patient_category_invoices","record_id" => $new_patient_category_invoice->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
// track the invoice
$track = new TrackInvoice;
$track->reason = get_name($name_id, 'id', 'name', 'patient_categories');
$track->created_by = $logged_in_user;
$track->save();
$affected_tables_by_the_journal[] = ["table" => "track_invoices","record_id" => $track->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
} else if ($credit != '') {
// Decrease this Accounts Receivable's value
$new_balance = $old_balance - (int)$credit;
$affected_amount = $credit;
$action = "deduction";
// Pay off an invoice tagged to the patient category
if ($type_id == 4 && $name_id != '') {
$uncleared_invoices = DB::table('patient_category_invoices')->where('invoice_generated', 1)
->where('status', 0)
->where('patient_category', (int)$name_id)
->where('invoice_number', $invoice_numbers[$x])
->whereNull('balance_remaining')
->get();
if (count($uncleared_invoices) < 1) {
$uncleared_invoices = DB::table('patient_category_invoices')->where('invoice_generated', 1)
->where('status', 1)
->where('patient_category', (int)$name_id)
->where('invoice_number', $invoice_numbers[$x])
->where('balance_remaining', '>=', (int)$credit)
->get();
if (count($uncleared_invoices) > 0) {
$invoice_number = $invoice_numbers[$x];
$amount_to_clear_off = 0;
$invoice_date = $uncleared_invoices[0]->invoice_date;
if (is_null($credit)) {
$amount_being_paid = (int)$debit;
} else {
$amount_being_paid = (int)$credit;
}
foreach ($uncleared_invoices as $invoice) {
$amount_to_clear_off += (int)$invoice->patient_amount;
}
if ($amount_being_paid > $amount_to_clear_off) {
flash("Amount to clear off invoice is more than the required amount!")->error();
return redirect('journals');
} else {
$affected_tables_by_the_journal[] = $this->pay_off_patient_category_invoice($request->journal_date, $journal_number, $invoice_number, $name_id, $logged_in_user, $amount_being_paid, $amount_to_clear_off, $invoice_date);
}
} else {
flash("No uncleared Patient Category Invoice found for Patient Category: " . get_name($name_id, 'id', 'name', 'patient_categories') . " and invoice number: " . $invoice_numbers[$x] . "!")->error();
}
} else {
if (count($uncleared_invoices) > 0) {
$invoice_number = $invoice_numbers[$x];
$amount_to_clear_off = 0;
$invoice_date = $uncleared_invoices[0]->invoice_date;
if (is_null($credit)) {
$amount_being_paid = (int)$debit;
} else {
$amount_being_paid = (int)$credit;
}
foreach ($uncleared_invoices as $invoice) {
$amount_to_clear_off += $invoice->patient_amount;
}
if ($amount_being_paid > $amount_to_clear_off) {
flash("Amount to clear off invoice is more than the required amount!")->error();
return redirect('journals');
} else {
$affected_tables_by_the_journal[] = $this->pay_off_patient_category_invoice($request->journal_date, $journal_number, $invoice_number, $name_id, $logged_in_user, $amount_being_paid, $amount_to_clear_off, $invoice_date);
}
} else {
flash("No uncleared Patient Category Invoice found for Patient Category: " . get_name($name_id, 'id', 'name', 'patient_categories') . " and invoice number: " . $invoice_numbers[$x] . "!")->error();
}
}
}
// Pay off a patient debt if a customer has been tagged. This is under Finance->Reports->Debtors Report
if ($type_id == 1 && $name_id != '') {
$new_receipt_number = $this->receiptService->createReceipt("journals-payment of patient debt");
$debt_record = Debtor::where('patient_id', $name_id)->where(function ($query) {
$query->whereNull('balance_remaining')
->orWhere('balance_remaining', '!=', 0);
})->first();
$debtorPayment = $this->debtorsService->createDebtorPayment($debt_record->id, $new_receipt_number, $credit, date('d-m-Y'),
($debt_record->balance - $credit), "Journal (" . $request->journal_number . ") Credit - " . $account_name, 0);
if ($debtorPayment) {
$this->debtorsService->clearDebt($debt_record->id);
flash("Payment Received Successfully")->success();
$affected_tables_by_the_journal[] = ["table" => "debtor_payments","record_id" => $payment->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
$affected_tables_by_the_journal[] = ["table" => "track_receipts","record_id" => $track_receipt->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
} else {
flash("Payment Not Received")->error();
}
//record cleared debt
$affected_tables_by_the_journal[] = ["table" => "debtors", "record_id" => $debt_record->id, "amount" => $affected_amount, "action" => "cleared_debt", "table_column" => "-"];
}
}
// Update the specific Chart of Accounts balance
ChartOfAccount::where('id', $account)->update(['balance' => (int)$new_balance]);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts","record_id" => $account, "amount" => $affected_amount, "action" => $action, "table_column" => "balance"];
}
// e.g. Cost of Goods
else {
flash("Journal entries for `" . get_name($account_type, 'id', 'name', 'account_types') . "` not yet implemented!")->error();
}
}
$affected_tables_created_array = $this->create_an_array_of_affected_tables_by_journal($affected_tables_by_the_journal);
$journal->affected_tables = implode(",", $affected_tables_created_array[0]);
$journal->table_records_affected = implode(",", $affected_tables_created_array[1]);
$journal->table_amount_affected = implode(",", $affected_tables_created_array[2]);
$journal->table_action_affected = implode(",", $affected_tables_created_array[3]);
$journal->table_column_affected = implode(",", $affected_tables_created_array[4]);
if ($journal->save()) {
flash("Journal saved successfully")->success();
} else {
flash('Failed to save Journal.')->error();
}
return redirect('journals');
}
}
}
private function save_bill($name_id, $bill_date, $memo, $amount, $payable_account, $item_account, $payment_item, $logged_in_user, $journal_number)
{
$affected_tables_by_the_journal = [];
$bill = new HospitalBill;
$bill->vendor = $name_id;
$bill->bill_date = Carbon::parse($bill_date)->toDateString();
$bill->bill_memo = $memo;
$bill->bill_number = 'Journal (' . $journal_number . ')';
$bill->total_amount = $amount;
$bill->balance = $amount;
$bill->item_accounts = $item_account;
$bill->item_ids = $payment_item;
$bill->item_quantities = '' . 1; // string
$bill->item_subtotals = '' . $amount;
$bill->payable_account = '' . $payable_account;
$bill->created_by = $logged_in_user;
$bill->bill_type = 'PAY';
$bill->balance_history = serialize(array());
$bill->receipt_history = serialize(array());
$bill->staff_incharge_history = serialize(array());
$bill->amount_paid_history = serialize(array());
$bill->date_paid_history = serialize(array());
$track_invoice = new TrackInvoice;
$track_invoice->reason = $memo;
$track_invoice->created_by = $logged_in_user;
$track_invoice->save();
if ($bill->save() && $track_invoice->save()) {
$affected_tables_by_the_journal[] = ["table" => "hospital_bills", "record_id" => $bill->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
$affected_tables_by_the_journal[] = ["table" => "track_invoices", "record_id" => $track_invoice->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
flash('A bill worth ' . ugandan_shillings((int)$amount) . ' for Supplier: ' . get_name($name_id, 'id', 'name', 'suppliers') . ' has successfully been saved.')->success();
} else {
flash('Failed to save Bill.')->error();
}
return $affected_tables_by_the_journal;
}
private function store_bill_payment($bill_id, $payment_date, $memo, $amount_to_pay, $payable_account, $logged_in_user)
{
$affected_tables_by_the_journal = [];
$hospital_bill = HospitalBill::find($bill_id);
$track_receipt = new TrackReceipt;
$track_receipt->reason = "Bill Payment on Bill number " . $hospital_bill->bill_number;
$track_receipt->created_by = $logged_in_user;
$track_receipt->save();
$receipt_number = sprintf("%04u", $track_receipt->id);
$bill_balance = ($hospital_bill->balance != null) ? ($hospital_bill->balance - $amount_to_pay) : ($hospital_bill->total_amount - $amount_to_pay);
$hospital_bill->balance = $bill_balance;
$date_paid_history = unserialize($hospital_bill->date_paid_history);
array_push($date_paid_history, $payment_date);
$date_paid_serial = serialize($date_paid_history);
$amount_paid_history = unserialize($hospital_bill->amount_paid_history);
array_push($amount_paid_history, $amount_to_pay);
$amount_paid_serial = serialize($amount_paid_history);
$staff_incharge_history = unserialize($hospital_bill->staff_incharge_history);
array_push($staff_incharge_history, $logged_in_user);
$staff_in_charge_serial = serialize($staff_incharge_history);
$receipt_history = unserialize($hospital_bill->receipt_history);
array_push($receipt_history, $receipt_number);
$receipt_serial = serialize($receipt_history);
$balance_history = unserialize($hospital_bill->balance_history);
array_push($balance_history, $bill_balance);
$balance_serial = serialize($balance_history);
$hospital_bill->amount_paid_history = $amount_paid_serial;
$hospital_bill->date_paid_history = $date_paid_serial;
$hospital_bill->staff_incharge_history = $staff_in_charge_serial;
$hospital_bill->receipt_history = $receipt_serial;
$hospital_bill->balance_history = $balance_serial;
$hospital_bill->payment_status = 1;
$hospital_bill->updated_by = $logged_in_user;
$hospital_bill->save();
$affected_tables_by_the_journal[] = ["table" => "hospital_bills", "record_id" => $hospital_bill->id, "amount" => $amount_to_pay, "action" => "deduction", "table_column" => "balance"];
flash("Payment of " . ugandan_shillings($amount_to_pay) . " made on Bill of Number: " . $hospital_bill->bill_number)->success();
$this->clear_bill_with_tagged_payable($bill_id, $payable_account);
$track_receipt = new TrackReceipt;
$track_receipt->reason = "Bill Payment on Bill number " . $hospital_bill->bill_number;
$track_receipt->created_by = $logged_in_user;
$track_receipt->save();
$affected_tables_by_the_journal[] = ["table" => "track_receipts", "record_id" => $track_receipt->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
$item_id_array = explode(',', $hospital_bill->item_ids);
$items_quantity_array = explode(',', $hospital_bill->item_quantities);
$payment = new Payment;
for ($x = 0; $x < count($item_id_array); $x++) {
$item_id = $item_id_array[$x];
if (is_numeric($item_id)) {
$payment->item_id = $item_id;
$payment->unit_cost = get_name($item_id, 'id', 'unit_cost', 'payment_items');
$payment->expense_account = get_name($item_id, 'id', 'account_id', 'payment_items');
}
$payment->amount = $amount_to_pay;
$payment->quantity = is_numeric($items_quantity_array[$x]) ? $items_quantity_array[$x] : null;
$payment->memo = $memo;
$payment->transaction_id = $receipt_number;
$payment->created_by = $logged_in_user;
$payment->expense_date = Carbon::parse($payment_date)->toDateTimeString();
$payment->bill_id = $bill_id;
$payment->save();
$affected_tables_by_the_journal[] = ["table" => "payments", "record_id" => $payment->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
}
return $affected_tables_by_the_journal;
}
private function clear_bill_with_tagged_payable($id, $payable_account)
{
$bill = HospitalBill::find($id);
$payable_account_array = [];
$item_amount_paid = [];
$item_balance_remaining = [];
$deductions = [];
$items_array = explode(',', $bill->item_ids);
$items_subtotal_array = explode(',', $bill->item_subtotals);
$bill_balance = $bill->balance != null ? $bill->balance : $bill->total_amount;
$bill_total = $bill->total_amount;
$bill_amount_paid = (is_null($bill_balance) ? 0 : (int)$bill_total - (int)$bill_balance);
for ($x = 0; $x < count($items_array); $x++) {
$new_amount = $bill_amount_paid - array_sum($deductions);
$payable_account_array[] = $payable_account;
if (is_null($bill_balance)) {
$item_amount_paid[] = 0;
$item_balance_remaining[] = $items_subtotal_array[$x];
} else if ($bill_balance == 0) {
$item_amount_paid[] = $items_subtotal_array[$x];
$item_balance_remaining[] = 0;
} else {
if ($items_subtotal_array[$x] <= $new_amount) {
$item_amount_paid[] = $items_subtotal_array[$x];
$item_balance_remaining[] = 0;
$deductions[] = $items_subtotal_array[$x];
} else {
$item_amount_paid[] = $new_amount;
$item_balance_remaining[] = (int)$items_subtotal_array[$x] - (int)$new_amount;
$deductions[] = $new_amount;
}
}
}
HospitalBill::where('id', $id)->update([
'payable_account' => implode(',', $payable_account_array),
'item_amount_paid' => implode(',', $item_amount_paid),
'item_balance_remaining' => implode(',', $item_balance_remaining)
]);
}
private function pay_off_patient_category_invoice($journal_date, $journal_number, $invoice_number, $name_id, $logged_in_user, $amount_to_pay, $amount_to_clear_off, $invoice_date)
{
// Identify undeposited funds from that day
$undeposited_funds = get_latest_banking_record_based_on_transaction_date(get_name("undeposited_funds", "slug", "id", "chart_of_accounts"), $journal_date);
// Track the receipt for this payment
$track_receipt = new TrackReceipt;
$track_receipt->reason = get_name($name_id, 'id', 'name', 'patient_categories');
$track_receipt->created_by = $logged_in_user;
$track_receipt->save();
$affected_tables_by_the_journal[] = ["table" => "track_receipts", "record_id" => $track_receipt->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
$new_receipt_number = sprintf("%04u", $track_receipt->id);
// pay directly to the cashier
$cashier_income = new CashierIncome;
$cashier_income->cashier_id = $logged_in_user;
$cashier_income->brought_by = $logged_in_user;
$cashier_income->expected_amount = $amount_to_pay;
$cashier_income->reason = "Received from patient category invoices via Journal (" . $journal_number . ")";
$cashier_income->amount = $amount_to_pay;
$cashier_income->balance = 0;
$cashier_income->receipt_number = $new_receipt_number;
$cashier_income->previous_balance = (int)$undeposited_funds->account_balance;
$cashier_income->account_balance = (int)$undeposited_funds->account_balance + $amount_to_pay;
$cashier_income->save();
$affected_tables_by_the_journal[] = ["table" => "cashier_incomes", "record_id" => $cashier_income->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
// A key identifier, I presume
$cashier_income_id = $cashier_income->id;
$transaction_date = Carbon::parse($journal_date)->toDateString();
$account_balance_after_payment = (int)$undeposited_funds->account_balance + $amount_to_pay;
// Populate the banking table
$last_insert_id = capture_bank_record(
'DEPOSIT',
$transaction_date,
10,
'',
$account_balance_after_payment,
$amount_to_pay,
0,
"Deposit to undeposited funds",
$new_receipt_number
);
$affected_tables_by_the_journal[] = ["table" => "banking", "record_id" => $last_insert_id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
update_banking_record_balances($transaction_date, 10, $last_insert_id, $account_balance_after_payment);
// determine if a payment was already made
$past_invoice_payment = InvoicePayment::where('invoice_number', $invoice_number)->first();
if (is_null($past_invoice_payment)) {
$other_parameters = [
'received_id' => $cashier_income_id,
'received_amount' => $amount_to_pay,
];
$invoice_payment = $this->invoicesService->saveInvoicePayment($invoice_number, $amount_to_clear_off, $amount_to_pay, ($amount_to_clear_off - $amount_to_pay),
$journal_date, $name_id);
$this->invoicesService->saveInvoicePaymentRecord($invoice_number, $new_receipt_number, $amount_to_pay, $journal_date,
0, null, $other_parameters);
$affected_tables_by_the_journal[] = ["table" => "invoice_payments", "record_id" => $invoice_payment->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
// Get that invoice by it's id!
$patient_category_invoice = PatientCategoryInvoice::where(['invoice_number' => $invoice_number])
->update(['status' => 1]);
$affected_tables_by_the_journal[] = ["table" => "patient_category_invoices", "record_id" => $invoice_number, "amount" => "-", "action" => "updated", "table_column" => "status"];
update_account_balance_by_id(10, $amount_to_pay);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => 10, "amount" => $amount_to_pay, "action" => "addition", "table_column" => "balance"];
if (!is_null($patient_category_invoice)) {
$this->invoicesService->clearInvoice($invoice_number);
//record cleared invoice number
$affected_tables_by_the_journal[] = ["table" => "patient_category_invoices", "record_id" => $invoice_number, "amount" => $amount_to_pay, "action" => "cleared_invoice", "table_column" => "-"];
}
flash("Invoice for Patient Category: " . get_name($name_id, 'id', 'name', 'patient_categories') . " and invoice number: " . $invoice_number . " cleared off (" . ugandan_shillings($amount_to_pay) . ") with a balance of " . ugandan_shillings($payment->balance))->success();
} else {
// perform an update
$this->update_patient_category_invoice_payment($past_invoice_payment, $new_receipt_number, $track_receipt, $cashier_income_id, $amount_to_pay, $name_id, $journal_date, $logged_in_user);
}
return $affected_tables_by_the_journal;
}
public function update_patient_category_invoice_payment(InvoicePayment $past_invoice_payment, $new_receipt_number, $track_receipt, $cashier_income_id, $amount_to_pay, $name_id, $journal_date, $logged_in_user)
{
$date_paid_history = unserialize($past_invoice_payment->date_paid_history);
array_push($date_paid_history, $journal_date);
$date_paid_history = serialize($date_paid_history);
$amount_paid_history = unserialize($past_invoice_payment->amount_paid_history);
array_push($amount_paid_history, $amount_to_pay);
$amount_paid_history = serialize($amount_paid_history);
$staff_incharge_history = unserialize($past_invoice_payment->staff_incharge_history);
array_push($staff_incharge_history, $logged_in_user);
$staff_incharge_history = serialize($staff_incharge_history);
$receipt_number = unserialize($past_invoice_payment->receipt_number);
array_push($receipt_number, $new_receipt_number);
$receipt_number = serialize($receipt_number);
if (!is_null($past_invoice_payment->received_id_history)) {
$received_id_history = unserialize($past_invoice_payment->received_id_history);
array_push($received_id_history, $cashier_income_id);
$received_id_history = serialize($received_id_history);
} else {
$received_id_history = serialize(array($cashier_income_id));
}
if (!is_null($past_invoice_payment->received_amount_history)) {
$received_amount_history = unserialize($past_invoice_payment->received_amount_history);
array_push($received_amount_history, $amount_to_pay);
$received_amount_history = serialize($received_amount_history);
} else {
$received_amount_history = serialize(array($amount_to_pay));
}
// Get that invoice by it's id!
PatientCategoryInvoice::where(['id' => $past_invoice_payment->id])
->update(['status' => 1, 'received' => $cashier_income_id]);
$affected_tables_by_the_journal[] = ["table" => "patient_category_invoices", "record_id" => $past_invoice_payment->id, "amount" => "-", "action" => "updated_status_and_received", "table_column" => "received"];
$this->invoicesService->clearInvoice($past_invoice_payment->invoice_number);
//record cleared invoice number
$affected_tables_by_the_journal[] = ["table" => "patient_category_invoices", "record_id" => $past_invoice_payment->invoice_number, "amount" => $amount_to_pay, "action" => "cleared_invoice", "table_column" => "-"];
$payment = InvoicePayment::where('id', $past_invoice_payment->id)
->update(
[
'total' => $past_invoice_payment->total,
'amount_paid' => $past_invoice_payment->amount_paid + $amount_to_pay,
'balance' => $past_invoice_payment->balance - $amount_to_pay,
'receipt_number' => $receipt_number,
'amount_paid_history' => $amount_paid_history,
'staff_incharge_history' => $staff_incharge_history,
'date_paid_history' => $date_paid_history,
'received_id_history' => !is_null($cashier_income_id) ? $received_id_history : null,
'received_amount_history' => !is_null($cashier_income_id) ? $received_amount_history : null,
'received' => is_null($cashier_income_id) ? null : $cashier_income_id,
'banked_history' => is_null($past_invoice_payment->banked_history) ? null : $past_invoice_payment->banked_history,
'banked' => is_null($past_invoice_payment->banked) ? null : $past_invoice_payment->banked,
]
);
$affected_tables_by_the_journal[] = ["table" => "invoice_payments", "record_id" => $past_invoice_payment->id, "amount" => $amount_to_pay, "action" => "addition", "table_column" => "amount_paid"];
update_account_balance_by_id(10, $amount_to_pay);
$affected_tables_by_the_journal[] = ["table" => "chart_of_accounts", "record_id" => 10, "amount" => $amount_to_pay, "action" => "addition", "table_column" => "balance"];
$this->invoicesService->clearInvoice($past_invoice_payment->invoice_number);
//record cleared invoice number
$affected_tables_by_the_journal[] = ["table" => "patient_category_invoices", "record_id" => $past_invoice_payment->invoice_number, "amount" => $amount_to_pay, "action" => "cleared_invoice", "table_column" => "-"];
$track_receipt->save();
$affected_tables_by_the_journal[] = ["table" => "track_receipts", "record_id" => $track_receipt->id, "amount" => "-", "action" => "insertion", "table_column" => "-"];
flash("Invoice for Patient Category: " . get_name($name_id, 'id', 'name', 'patient_categories') . " and invoice number: " . $past_invoice_payment->invoice_number . " updated with payment (" . ugandan_shillings($amount_to_pay) . ") and a balance of " . ugandan_shillings($past_invoice_payment->balance - $amount_to_pay))->success();
return $affected_tables_by_the_journal;
}
public function create_an_array_of_affected_tables_by_journal($affected_tables_by_the_journal)
{
$tables_affected = [];
$table_records_affected = [];
$table_amount_affected = [];
$table_action_affected = [];
$table_column_affected = [];
//cater for 4 levels matrix
foreach ($affected_tables_by_the_journal as $effect) {
foreach ($effect as $key => $value) {
if (is_array($value)) {
foreach ($value as $key1 => $value1){
if (is_array($value1)) {
foreach ($value1 as $key2 => $value2){
if (is_array($value2)) {
foreach ($value2 as $key3 => $value3){
if ($key3 == "table") {
$tables_affected[] = $value3;
}
if ($key3 == "record_id") {
$table_records_affected[] = $value3;
}
if ($key3 == "amount") {
$table_amount_affected[] = $value3;
}
if ($key3 == "action") {
$table_action_affected[] = $value3;
}
if ($key3 == "table_column") {
$table_column_affected[] = $value3;
}
}
} else {
if ($key2 == "table") {
$tables_affected[] = $value2;
}
if ($key2 == "record_id") {
$table_records_affected[] = $value2;
}
if ($key2 == "amount") {
$table_amount_affected[] = $value2;
}
if ($key2 == "action") {
$table_action_affected[] = $value2;
}
if ($key2 == "table_column") {
$table_column_affected[] = $value2;
}
}
}
} else {
if ($key1 == "table") {
$tables_affected[] = $value1;
}
if ($key1 == "record_id") {
$table_records_affected[] = $value1;
}
if ($key1 == "amount") {
$table_amount_affected[] = $value1;
}
if ($key1 == "action") {
$table_action_affected[] = $value1;
}
if ($key1 == "table_column") {
$table_column_affected[] = $value1;
}
}
}
} else{
if ($key == "table") {
$tables_affected[] = $value;
}
if ($key == "record_id") {
$table_records_affected[] = $value;
}
if ($key == "amount") {
$table_amount_affected[] = $value;
}
if ($key == "action") {
$table_action_affected[] = $value;
}
if ($key == "table_column") {
$table_column_affected[] = $value;
}
}
}
}
$array_returned = [$tables_affected, $table_records_affected, $table_amount_affected, $table_action_affected, $table_column_affected];
return $array_returned;
}
public function delete_journal(Request $request, $id)
{
$status = false;
$journal_to_delete = Journal::find($id);
$affected_tables_by_the_journal = explode(",", $journal_to_delete->affected_tables);
$table_records_affected = explode(",", $journal_to_delete->table_records_affected);
$table_amount_affected = explode(",", $journal_to_delete->table_amount_affected);
$table_action_affected = explode(",", $journal_to_delete->table_action_affected);
$table_column_affected = explode(",", $journal_to_delete->table_column_affected);
// To Note:
// create an array of affected tables, amounts, operation done
for ($i=0; $i < count($affected_tables_by_the_journal); $i++) {
if ($table_action_affected[$i] == "addition") {
DB::table($affected_tables_by_the_journal[$i])->where('id', $table_records_affected[$i])->decrement($table_column_affected[$i], $table_amount_affected[$i]);
} elseif ($table_action_affected[$i] == "deduction") {
DB::table($affected_tables_by_the_journal[$i])->where('id', $table_records_affected[$i])->increment($table_column_affected[$i], $table_amount_affected[$i]);
} elseif ($table_action_affected[$i] == "insertion") {
/***** if bank was affected, re-run the bank register *****/
if ($affected_tables_by_the_journal[$i] == "banking") {
$inserted_bank_id = $table_records_affected[$i];
$banking_record = Banking::withTrashed()->find($inserted_bank_id);
}
/*** first exit for now if journal was banking *****/
DB::table($affected_tables_by_the_journal[$i])->where('id', '=', $table_records_affected[$i])->delete();
/**** come back if it was banking ****/
if ($affected_tables_by_the_journal[$i] == "banking") {
if ($banking_record) {
$this->re_run_bank_register($journal_to_delete->journal_date, $banking_record->bank);
}
}
/** end of banking rollback **/
}
// if patient_category_invoices remember to update the status to 0 and remove the received column value to null
if ($affected_tables_by_the_journal[$i] == "patient_category_invoices" && $table_action_affected[$i] == "cleared_invoice") {
$invoice_number = $table_records_affected[$i];
$invoice_amount_to_reverse = $table_amount_affected[$i];
$this->invoicesService->reverseClearedInvoice($invoice_number, $invoice_amount_to_reverse);
}
if ($affected_tables_by_the_journal[$i] == "debtors" && $table_action_affected[$i] == "cleared_debt") {
$debt_id = $table_records_affected[$i];
$amount_to_reverse = $table_amount_affected[$i];
$this->debtorsService->reverseDebt($debt_id);
}
}
$journal_to_delete->delete();
flash('journal number '.$journal_to_delete->journal_number.' has been deleted')->success();
return redirect('journals_records');
}
public function check_if_journal_can_be_deleted(Request $request)
{
$journal_id = $request->journal_id;
$journal_id = (int)$journal_id;
$message = "";
$journal = Journal::find($journal_id);
$journal_affected_tables_array = explode(",", $journal->affected_tables);
$is_journal_deleteable = true;
$tables_records_affected_array = explode(",", $journal->table_records_affected);
if (in_array("invoice_payments", $journal_affected_tables_array)) {
$item_position = array_search("invoice_payments", $journal_affected_tables_array);
$invoice_payment_id_affected = $tables_records_affected_array[$item_position];
$invoice_payment = InvoicePayment::find($invoice_payment_id_affected);
$cashier_income_record_id = $invoice_payment->received; //get record of undeposited fund
$cashier_income_record = CashierIncome::find($cashier_income_record_id);
//check if this money was banked and refuse deletion
if (!is_null($cashier_income_record->banked)) {
$is_journal_deleteable = false;
$message = "Journal can not be deleted because it has an invoice with banked money";
}
}
if (in_array("hospital_bills", $journal_affected_tables_array)) {
$item_position1 = array_search("hospital_bills", $journal_affected_tables_array);
$hospital_bills_id_affected = $tables_records_affected_array[$item_position1];
$hospital_bill = HospitalBill::find($hospital_bills_id_affected);
$amount_paid_history_array = unserialize($hospital_bill->amount_paid_history);
if (count($amount_paid_history_array) > 0) {
$is_journal_deleteable = false;
$message = "Journal can not be deleted because it has a bill with a payment";
}
}
if (in_array("banking", $journal_affected_tables_array)) {
$item_position1 = array_search("banking", $journal_affected_tables_array);
$banking_id_affected = $tables_records_affected_array[$item_position1];
$banking_record = Banking::find($banking_id_affected);
if ($banking_record) {
if ($banking_record->reconciled != 0) {
$is_journal_deleteable = false;
$message = "Journal can not be deleted because the bank transaction has been reconciled.";
}
}
}
return [$is_journal_deleteable, $message];
}
/**
* Recursive function to verify that a Journal number is not already in use.
* For example, when two users on different PCs open the Journals screen,
* they'll both see the same journal number
*
* @param $journal_number // auto-incremented int displayed on the Journal creation screen
* @return $journal_number The validated journal number integer
*/
public function validate_journal_number($journal_number) {
$journal_duplicate = DB::table('journals')->orderByDesc('journal_number')->where('journal_number', $journal_number)->first();
if ($journal_duplicate != null) {
return $this->validate_journal_number($journal_number + 1);
} else {
return $journal_number;
}
}
public function re_run_bank_register($journal_date, $bank_account_id)
{
$orderByTransIdQuery = "CAST(trans_id AS DECIMAL(10,0)) ASC";
$bank_record = Banking::where('bank', $bank_account_id)->whereNull('deleted_at')->whereDate('trans_date', '<', $journal_date)->orderBy('id', 'desc')->first();
if ($bank_record) {
$banking_records = Banking::where('bank', $bank_account_id)->where('trans_date', '>', Carbon::parse($bank_record->trans_date)->toDateString())
->whereNull('deleted_at')
->where('id', '!=', $bank_record->id)
->orderBy('trans_date', 'asc')
->orderByRaw($orderByTransIdQuery)
->get();
$prev_balance = $bank_record->account_balance;
foreach ($banking_records as $record) {
$prev_balance = $prev_balance + (int)$record->credit - (int)$record->debit;
Banking::where('id', $record->id)->update(['account_balance' => $prev_balance]);
}
} else{
//if there is not record that whose transaction date is less than the journal date, do this
$banking_records = Banking::where('bank', $bank_account_id)->where('trans_date', '>', Carbon::parse($journal_date)->toDateString())
->whereNull('deleted_at')
->where('id', '!=', $bank_record->id)
->orderBy('trans_date', 'asc')
->orderByRaw($orderByTransIdQuery)
->get();
$prev_balance = 0;
foreach ($banking_records as $record) {
$prev_balance = $prev_balance + (int)$record->credit - (int)$record->debit;
Banking::where('id', $record->id)->update(['account_balance' => $prev_balance]);
}
}
}
}