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]}
"; } 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]); } } } }