Files
hpt_inventory/app/Http/Controllers/InvoiceController.php
2026-06-10 16:42:20 +07:00

328 lines
18 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\RecordStatusEnum;
use App\Http\Controllers\Helper\GlobalController;
use App\Http\Requests\SampleCreateRequest;
use App\Http\Requests\UpdateRequests\SampleUpdateRequest;
use App\Http\Resources\SampleResource;
use App\Models\BaseModel;
use App\Models\Invoice;
use App\Models\InvoiceDetail;
use App\Models\Patient;
use App\Models\Sample;
use App\Models\LabConfigure;
use App\Models\Physician;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
class InvoiceController extends Controller
{
protected $model;
protected $sampleModel;
protected $patientModel;
protected $invoiceDetailModel;
protected $baseLabId;
protected $labs;
protected $base;
protected $laboratoryConfigures;
protected $physicianModel;
public function __construct(Invoice $invoiceModel, InvoiceDetail $invoiceDetailModel, Sample $sampleModel, Patient $patientModel, Physician $physicianModel){
$this->model = $invoiceModel;
$this->sampleModel = $sampleModel;
$this->invoiceDetailModel = $invoiceDetailModel;
$this->patientModel = $patientModel;
$this->laboratoryConfigures = new LabConfigure();
$this->physicianModel = $physicianModel;
$this->baseLabId = Session::get('base_lab_id');
$this->base = Session::get('base_lab');
$this->labs = parent::getAccessAbleLabs();
}
public function index(Request $request){
if(!GlobalController::user_can(Auth::user()->role_id, ['view_invoice'])) return redirect(url('my-profile'));
$recordStatusConditions = Auth::id()==1 ? [RecordStatusEnum::ACTIVE , RecordStatusEnum::DELETE] : [RecordStatusEnum::ACTIVE];
$oweInvoices = $this->model::with(['sample.patient'])->where(['lab_id' => $this->baseLabId, BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::ACTIVE])
->where('balance','>', 0)->get();
$physicians = $this->physicianModel::query()->where(['lab_id' => $this->baseLabId, BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::ACTIVE])->get();
$invoices = $this->model::with(['sample','repayments'])
->whereIn(BaseModel::RECORD_STATUS_FIELD, $recordStatusConditions)
->where('lab_id', $this->baseLabId)
->when(!empty($request->from_date) && !empty($request->to_date), function ($inv) use ($request){
$inv->whereBetween('invoice_date',[date('Y-m-d',strtotime($request->from_date)), date('Y-m-d',strtotime($request->to_date))]);
})
->when(isset($request->physician) && !empty($request->physician), function($inv) use ($request){
$inv->whereIn('sample_id', $this->sampleModel::query()->where('physician_id', $request->physician)->pluck('id'));
})
->when(!empty(trim($request->kword)), function ($inv) use($request, $recordStatusConditions){
$inv->whereRaw("replace(invoice_code, ' ','') like '%".str_replace(" ","",$request->kword)."%'")
->orWhereIn('sample_id', $this->sampleModel::query()
->whereIn('patient_id', $this->patientModel::query()
->whereRaw("replace(name_en, ' ','') like '%".str_replace(" ","",$request->kword)."%'")
->orWhereRaw("replace(phone_number, ' ','') like '%".str_replace(" ","",$request->kword)."%'")
->orWhere('patient_uuid','like','%'.$request->kword.'%')->pluck('id')->toArray()
)->orwhereRaw("replace(sample_number, ' ','') like '%".str_replace(" ","",$request->kword)."%'")->pluck('id')->toArray()
)->where('lab_id', $this->baseLabId)->whereIn(BaseModel::RECORD_STATUS_FIELD, $recordStatusConditions);
})->orderBy('invoice_code','desc')->paginate(20);
if(Auth::id()==1){
//dd($invoices->pluck('repayments'));
}
return view('v_invoice.invoice', ['invoices' => $invoices, 'labSettings' => (object) $this->location(), 'oweInvoices' => $oweInvoices, 'physicians' => $physicians]);
}
public function create($sample_id = null){
if(!GlobalController::user_can(Auth::user()->role_id, ['create_invoice'])) return redirect(url('my-profile'));
$samples = $this->sampleModel::query()->with('invoice')
->where(['lab_id' => $this->baseLabId, BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::ACTIVE])
->whereDoesntHave('invoice')->get();
return view('v_invoice.new_invoice', [
'samples' => $samples,
'sample_id' => $sample_id
]);
}
public function store(Request $request){
DB::beginTransaction();
try{
if(!GlobalController::user_can(Auth::user()->role_id, ['create_invoice'])) return redirect(url('my-profile'));
$invoiceNumber = $this->generateAutoId($request->invoice_date);
$is_hide_discount = isset($request->is_hide_discount) ? 1: 0;
$requests = collect($request)->merge(['lab_id'=>$this->baseLabId, 'invoice_code' => $invoiceNumber, 'is_hide_discount' => $is_hide_discount, 'exchange_rate' => ((object) $this->location())->exchange_rate])->except(['first_paid_date']);
$invoice = $this->model::query()->create($requests->all());
$invoiceDetailRequest = collect($request->test_sample_id);
$items = $invoiceDetailRequest->map(function ($row, $key) use($request, $invoice) {
$invoiceDetailRow = $this->invoiceDetailModel::query()->create([
'invoice_id' => $invoice->id,
'test_sample_id' => $request->test_sample_id[$key],
'discount_type' => $request->item_discount_type[$key],
'discount' => $request->item_discount[$key],
'test_name' => $request->test_name[$key],
'qty' => 1,
'unit_price' => $request->unit_price[$key],
]);
return [];
});
DB::commit();
$request->session()->flash('message','invoice-success');
if(isset($request->save_print_invoice) && $request->save_print_invoice=='save_preview_invoice'){
return redirect('invoice/edit/'.$invoice->id.'?print');
}
return redirect()->back();
} catch (\Exception $e){
DB::rollBack();
$request->session()->flash('message','invoice-error');
return redirect()->back();
}
}
public function edit($id){
if(!GlobalController::user_can(Auth::user()->role_id, ['view_invoice', 'update_invoice'])) return redirect(url('my-profile'));
$invoice = $this->model::query()->with('invoiceDetail.testSample.sample.department','creator','modifier')->where(['lab_id' => $this->baseLabId, 'id' => $id])->first();
$samples = $this->sampleModel::query()->where('id', $invoice->sample_id)->first();
$refreshItemItem = $this->refreshItemItem($invoice->sample_id);
$labConfigures = $this->laboratoryConfigures::query()->where(['lab_id' => $this->baseLabId, BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::ACTIVE])->get()->toArray();
return view('v_invoice.edit_invoice', [
'samples' => [$samples],
'invoice' => $invoice,
'invoice_id' => $id,
'sample_id' => $invoice->sample_id,
'labSettings' => (object) $this->location(),
'refreshItemItem' => $refreshItemItem,
'labConfigures' => $labConfigures,
'is_need_refresh_invoice' => (count($refreshItemItem) == count($invoice->invoiceDetail)) ? 0 : 1
]);
}
public function update(Request $invoiceUpdateRequest){
DB::beginTransaction();
try{
if(!GlobalController::user_can(Auth::user()->role_id, ['update_invoice'])) return redirect(url('my-profile'));
$is_hide_discount = isset($invoiceUpdateRequest->is_hide_discount) ? 1: 0;
$requests = collect($invoiceUpdateRequest)->only(['invoice_note','total','discount','gross_total','deposit' ,'bank_deposit', 'balance','invoice_date','exchange_rate'])->merge(['is_hide_discount' => $is_hide_discount, 'updated_by' => Auth::id(), 'updated_at' => date('Y-m-d H:i:s')]);
$invoice = $this->model::query()->where(['id' => $invoiceUpdateRequest->uid, 'lab_id' => $this->baseLabId])->update($requests->all());
$invoiceDetailRequest = collect($invoiceUpdateRequest->test_sample_id);
$items = $invoiceDetailRequest->map(function ($row, $key) use($invoiceUpdateRequest) {
$invDetail = $this->invoiceDetailModel::query()->where(['invoice_id' => $invoiceUpdateRequest->uid, 'test_sample_id' => $invoiceUpdateRequest->test_sample_id[$key]])->first();
if (empty($invDetail)) {
$invoiceDetailRow = $this->invoiceDetailModel::query()->create([
'invoice_id' => $invoiceUpdateRequest->uid,
'test_sample_id' => $invoiceUpdateRequest->test_sample_id[$key],
'discount_type' => $invoiceUpdateRequest->item_discount_type[$key],
'discount' => $invoiceUpdateRequest->item_discount[$key],
'test_name' => $invoiceUpdateRequest->test_name[$key],
'weight' => $invoiceUpdateRequest->weight[$key],
'qty' => 1,
'unit_price' => $invoiceUpdateRequest->unit_price[$key],
]);
}
else{
$invoiceDetailRow = $this->invoiceDetailModel::query()->where([
'invoice_id' => $invoiceUpdateRequest->uid,
'test_sample_id' => $invoiceUpdateRequest->test_sample_id[$key]
])->update([
'weight' => $invoiceUpdateRequest->weight[$key]
]);
}
return [];
});
$this->invoiceDetailModel::query()->where('invoice_id', $invoiceUpdateRequest->uid)
->whereNotIn('test_sample_id', $invoiceUpdateRequest->test_sample_id)->delete();
DB::commit();
$invoiceUpdateRequest->session()->flash('message','invoice-success');
return redirect()->back();
} catch (\Exception $e){
DB::rollBack();
$invoiceUpdateRequest->session()->flash('message','invoice-error');
return redirect()->back();
}
}
/** Perform by ajax function
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function delete(Request $request){
try{
if(!GlobalController::user_can(Auth::user()->role_id, ['delete_invoice'])) return false;
$invoice = $this->model::query()->where(['id' => $request->uid, 'lab_id' => $this->baseLabId])->first();
$invoice->update(array(BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::DELETE));
return response()->json(['success' => true, 'message' => __('invoice.delete_success')]);
} catch (\Exception $e){
return response()->json(['success' => false, 'message' => __('invoice.delete_fail'), 'errors' => $e->getMessage()]);
}
}
public function restore(Request $request){
try{
$this->model::query()->where('id', $request->uid)->update(array(BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::ACTIVE));
return response()->json(['success' => true, 'message' => __('invoice.restore_success')]);
} catch (\Exception $e){
return response()->json(['success' => false, 'message' => __('invoice.restore_fail'), 'errors' => $e->getMessage()]);
}
}
public function getSampleTest($sampleId){
try{
$patientTypes = $this->sampleModel::query()->with([])->where([
BaseModel::RECORD_STATUS_FIELD => RecordStatusEnum::ACTIVE,
'lab_id' => $this->baseLabId
])->get();
return response()->json(['success'=> true , 'data' => $patientTypes]);
} catch (\Exception $e)
{
return response()->json(['success'=> false , 'errors' => $e->getMessage()]);
}
}
public function generateAutoId($invoiceDate){
$prefix = date('y',strtotime($invoiceDate));
$invoiceCount = $this->model::query()->where('lab_id', $this->baseLabId)->whereRaw('year(invoice_date) ="'. date('Y',strtotime($invoiceDate)).'"')->count();
return 'I-'.$this->base['short_name'].'-'.$prefix.'-'.(str_pad(($invoiceCount+1),5,'0',STR_PAD_LEFT));
}
public function paid($id){
DB::beginTransaction();
try{
$invoice = $this->model::query()->find($id);
$invoice->balance = 0;
$invoice->deposit = $invoice->gross_total;
$invoice->first_paid_date = date('Y-m-d');
$invoice->save();
DB::commit();
return response()->json(['success' => true, 'message' => __('This invoice already paid')]);
} catch (\Exception $e){
DB::rollBack();
return response()->json(['success' => false, 'message' => __('Failed while trying to paid on invoice'), 'errors' => $e->getMessage()]);
}
}
function refreshItemItem($sampleId){
try{
$resultItems = DB::select('
SELECT
d.`id` AS department_id,
d.`name_en` AS department_name,
d.weight as dweight,
st.`id` AS sample_type_id,
st.weight as sweight,
st.`name_en` AS sample_type,
ts.`id` AS test_sample_id,
ts.`heading_id` AS parent_id,
ts.`field_type`,
ts.`usd_price`,
ts.group_result,
ts.description,
t.`id` AS test_id,
t.`name_en` AS test_name,
tr.id as test_result_id,
pct.`commission_type`,
ifnull(pct.`commission_rate`, 0.00) as commission_rate,
ifnull(pct.`partner_price`, 0.00) as partner_price,
ts.weight
FROM samples s
INNER JOIN test_results tr
ON tr.`sample_id` = s.`id`
AND s.`lab_id` = tr.`lab_id`
INNER JOIN test_samples ts
ON ts.id = tr.`test_sample_id`
and ts.lab_id = tr.lab_id
INNER JOIN tests t
ON t.`id` = ts.`test_id`
INNER JOIN sample_types st
ON st.`id` = ts.`sample_type_id`
INNER JOIN departments d
ON d.`id` = st.`department_id`
LEFT JOIN `physician_commisssion` AS pct
ON pct.`test_sample_id` = ts.`id`
AND pct.`physician_id` = s.`physician_id`
WHERE s.`id` = '.$sampleId.'
AND s.`lab_id`= '.$this->baseLabId.'
AND tr.`record_status_id` = '.BaseModel::RECORD_STATUS_ACTIVE.'
AND LENGTH(ts.group_result)>0
AND ts.usd_price>0
ORDER BY
d.`weight`,
st.`weight`,
ts.`weight`');
$departmentArray = array();
foreach ($resultItems as $row){
$net_amount = number_format((((!empty($row->commission_type) ? $row->commission_type : ((object) $this->location())->discount_type)) ==2 ? (($row->usd_price - $row->partner_price) - $row->commission_rate) :
(($row->usd_price - $row->partner_price) * (1-$row->commission_rate/100))),2);
$testItemArray = array(
'test_sample_id' => (string)$row->test_sample_id,
'test_id' => $row->test_id,
'test_name' => $row->test_name,
'closed_parent_id' => (string) (int)$row->parent_id,
'field_type' => (string) $row->field_type,
'usd_price' => $row->usd_price,
'group_result' => (string) $row->group_result,
'item_discount_type' => (!empty($row->commission_type) ? $row->commission_type : ((object) $this->location())->discount_type),
'item_discount_rate' => $row->commission_rate,
'item_discount' => $net_amount,
'discount_price' => ($row->usd_price - $net_amount)
);
$departmentArray[] = $testItemArray;
}
return $departmentArray;
} catch (\Exception $e){
return $e->getMessage();
}
}
}