form_id; $form_name = DrugForm::find($form_id)->name??''; return $form_name; break; case 2: //get sundry item form $form_id = Sundry::find($item_id)->form_id; $form_name = GeneralForm::find($form_id)->name??''; return $form_name; break; case 3: //get dental item form $form_name=''; return $form_name; break; case 4: //get radiology item form $form_id = Radiology::find($item_id)->form_id; $form_name = GeneralForm::find($form_id)->name??''; return $form_name; break; case 5: //get labs item form $form_id = Lab::find($item_id)->form_id??''; $form_name = LabForm::find($form_id)->name??''; return $form_name; break; case 6: //get general_item item form $form_name=''; return $form_name; break; case 7: //get optical item form $form_name=''; return $form_name; break; } } public function find_item_batch_watcher($batch_item_id, $selected_columns): array|object|null { return ItemBatchWatcher::select($selected_columns)->find($batch_item_id); } public function move_item_between_sections($item_batch_watcher, $quantity_to_move, $other_stock) { $item_batch_watcher->store_stock -= $quantity_to_move; $item_batch_watcher->{$other_stock} =$item_batch_watcher->{$other_stock} + $quantity_to_move; $item_batch_watcher->save(); } public function move_next_available_item($item_type, $item_id,$column, $selected_columns, $quantity_to_move,$other_stock): array|object|null { if (batch_tracking_method() == "FIFO") { $random_batch_next = ItemBatchWatcher::where(['item_id' => $item_id, 'item_type' => $item_type])->where("{$column}", '>', 0)->orderBy('id', 'asc')->select($selected_columns)->first();; } elseif (batch_tracking_method() == "FEFO") { $random_batch_next = ItemBatchWatcher::where(['item_id' => $item_id, 'item_type' => $item_type])->where("{$column}", '>', 0)->orderBy(DB::raw('ABS(DATEDIFF(expiry_date, NOW()))'))->select($selected_columns)->first();; } if ($random_batch_next) { $random_batch_next->store_stock -= $quantity_to_move; $random_batch_next->{$other_stock} += $quantity_to_move; $random_batch_next->save(); return $random_batch_next; } return false; } public function move_batch_item_from_store_to_other_sections($item_type, $item_id, $batch_item_id, $quantity_to_move, $requisition_id,$item_name_table,$move_to,$selected_columns,$other_stock) { $item_batch_watcher = $this->find_item_batch_watcher($batch_item_id,$selected_columns); $batch_number = ""; if ($item_batch_watcher) { $this->move_item_between_sections($item_batch_watcher, $quantity_to_move, $other_stock); $batch_number = $item_batch_watcher->batch_number; } else{ //reduce the next one in line that has enough store stock. $batch_details= $this->move_next_available_item($item_type, $item_id,'store_stock', $selected_columns, $quantity_to_move,$other_stock); if($batch_details){ $batch_number = $batch_details->batch_number; } } record_store_stock_movement($item_type, $item_id, $batch_number, $quantity_to_move, "{$move_to}", $requisition_id); } //function to create optical reconciliation public function createOpticalReconciliation($item_type,$batche,$variance, $item_id, $physical_new_stock, $difference, $system_stock,$completion,$affected_account_id,$reconciliation_date,$general_comment,$max_stock_count_identifier):void { $batch = $batche[$item_id]; $physical_stock = new OpticalStockReconciliation; $physical_stock->item_id = $item_id; $physical_stock->system_stock = $system_stock; $physical_stock->physical_stock = $physical_new_stock; $physical_stock->difference = $difference; $physical_stock->variance = $variance; $physical_stock->batches = json_encode($batche[$item_id]); $physical_stock->reason_for_difference = null; $physical_stock->affected_account_id = $affected_account_id; $physical_stock->completion_status = $completion; $physical_stock->reconciliation_date = $reconciliation_date; $physical_stock->stock_count_identifier = $max_stock_count_identifier+1;//increase ID by 1 for new $physical_stock->general_comment = $general_comment; $physical_stock->type =$item_type; //1 - pharmarcy, 0 - stores $physical_stock->created_by = Auth::id(); $physical_stock->save(); if (isset($batch['reason_id'])){ foreach($batch['reason_id'] as $reason_id){ //update reconciliation reason StockReconciliationReason::where('id', $reason_id)->update(['reconciliation_id' => $physical_stock->id]); } } } //save reconciliation reason public function saveReconciliationReason($item_type,$item_id,$reason,$source):int { $reason_stock = new StockReconciliationReason; $reason_stock->item_id = $item_id; $reason_stock->item_type = $item_type; $reason_stock->reason_id = $reason; $reason_stock->source = $source; $reason_stock->created_by = Auth::id(); $reason_stock->save(); return $reason_stock->id; } public function reconcileBatches($batches,$reason,$source, $item_type, $item_id, $batch_number, $batch_quantity, $batch_expiry_date, $store_or_pharmacy, $batch_unit_cost, $batch_records_db_id, $ward_id): array { $batch_record = ItemBatchWatcher::find($batch_records_db_id); if ($batch_record) { $item_batch_watcher = $batch_record; } else { $item_batch_watcher = new ItemBatchWatcher; $item_batch_watcher->item_id = $item_id; $item_batch_watcher->item_type = $item_type; } // Determine the original quantity based on store_or_pharmacy $original_quantity = 0; switch ($store_or_pharmacy) { case 'store': $original_quantity = $item_batch_watcher->store_stock ?? 0; break; case 'pharmacy': $original_quantity = $item_batch_watcher->pharmacy_stock ?? 0; break; case 'lab': $original_quantity = $item_batch_watcher->lab_stock ?? 0; break; case 'ward': // Special handling for ward stock (aggregate or specific ward) $exploded_ward_stocks = $item_batch_watcher->ward_stock ? explode(",", $item_batch_watcher->ward_stock) : []; $exploded_ward_ids = $item_batch_watcher->ward_id ? explode(",", $item_batch_watcher->ward_id) : []; $ward_id_key = array_search($ward_id, $exploded_ward_ids); $original_quantity = $ward_id_key !== false ? ($exploded_ward_stocks[$ward_id_key] ?? 0) : 0; break; } $original_values = [ 'original_unit_cost' => $item_batch_watcher->cost_price ?? 0, 'original_quantity' => $original_quantity, 'original_batch_number' => $item_batch_watcher->batch_number ?? null, ]; $adjusted_values = [ 'batch_id' => $batch_record->id??null, 'unit_cost' => $batch_unit_cost, 'quantity' => $batch_quantity, 'expiry_date' => $batch_expiry_date, 'batch_number' => $batch_number, ]; if (isset($batches[$item_id])) { $batch_exists = false; foreach ($batches[$item_id] as &$data) { // Check if batch_id exists if(isset($data['batch_id'])){ if ($data['batch_id'] == $batch_record->id) { $batch_exists = true; // Update the existing batch $data['original_unit_cost'] = $original_values['original_unit_cost']; $data['original_quantity'] = $original_values['original_quantity']; $data['original_batch_number'] = $original_values['original_batch_number']; $data['unit_cost'] = $batch_unit_cost; $data['quantity'] = $batch_quantity; $data['expiry_date'] = $batch_expiry_date; $data['batch_number'] = $batch_number; break; } } } // If batch_id doesn't exist, add new batch if (!$batch_exists) { $batches[$item_id][] = array_merge($original_values, $adjusted_values); } } else { $batches[$item_id][] = array_merge($original_values, $adjusted_values); } // Update ItemBatchWatcher $item_batch_watcher->batch_number = $batch_number; is_null($batch_unit_cost) ? "" : $item_batch_watcher->cost_price = $batch_unit_cost; if ($store_or_pharmacy == "store") { $item_batch_watcher->store_stock = $batch_quantity; } if ($store_or_pharmacy == "pharmacy") { $item_batch_watcher->pharmacy_stock = $batch_quantity; } if ($store_or_pharmacy == "lab"){ $item_batch_watcher->lab_stock = $batch_quantity; } if ($store_or_pharmacy == "ward") { $exploded_ward_stocks = $item_batch_watcher->ward_stock ? explode(",",$item_batch_watcher->ward_stock) : []; $exploded_ward_ids = $item_batch_watcher->ward_id ? explode(",", $item_batch_watcher->ward_id) : []; $ward_id_key = array_search($ward_id, $exploded_ward_ids); if($ward_id_key !== false){ $exploded_ward_stocks[$ward_id_key] = $batch_quantity; } $item_batch_watcher->ward_stock = implode(",", $exploded_ward_stocks); } if($reason != ''){ $reason_id =$this->saveReconciliationReason($item_type,$item_id,$reason,$source); $batches[$item_id]['reason_id'][] = $reason_id; } $item_batch_watcher->expiry_date = $batch_expiry_date; $item_batch_watcher->save(); return $batches; } public function processReconcileItems($items_reconciled):EloquentCollection { foreach($items_reconciled as $item_reconciled){ $batches = json_decode($item_reconciled->batches,true) ; //remove reason_id if exist if(isset($batches['reason_id'])){ // Set reason_id property on the $item_reconciled object $item_reconciled->reason_id = $batches['reason_id']; // Remove reason_id from the batches array unset($batches['reason_id']); } //modified batches array to JSON //get reason if(isset($item_reconciled->reason_id)){ foreach($item_reconciled->reason_id as $val){ $store_reason = StockReconciliationReason::find($val); if (!is_null($store_reason)) { $reason = ReconilicationReason::find($store_reason->reason_id); if (!is_null($reason)){ $reasons[] = $reason->name; } } } } foreach($batches as $batch_key => $batch){ $batch['reason'] = isset($reasons[$batch_key]) ? $reasons[$batch_key] : null; $batches[$batch_key] = $batch; } $item_reconciled->batches = $batches; } return $items_reconciled; } //function to get all reconciliation reasons public function getAllReconciliationReasonsArray():array { return ReconilicationReason::orderBy('name','asc')->pluck('name','id')->prepend('Select Reason ', '')->toArray(); } //function to return stock to any col stores or pharmacy public function returnStockToAnySection($item_type,$drug_id,$ward_treatments_dispensation,$patient_id,$episode_id, $quantity_to_return,$stock_col,$selected_batch_id):void { if ($selected_batch_id !=null){ $batch_id = $selected_batch_id; }else{ $batch_id = WardTreatmentBatchDispensation::where(['patient_id'=>$patient_id,'episode_id'=>$episode_id,'item_id'=>$drug_id])->value('item_batch_id'); } //check for batch id if($batch_id != null){ //get batch number that was consumed $containsComma = array_filter([$batch_id], function($string) { return strpos($string, ',') !== false; }); if (!empty($containsComma)) { $batch_id = explode(', ', $batch_id); $batch_id = $batch_id[0]; } //get item batch watcher record using batch number, item_type, item_id, where stock is not 0 $item_batch_watcher = ItemBatchWatcher::find($batch_id); if ($item_batch_watcher) { $item_batch_watcher->{$stock_col} = $item_batch_watcher->{$stock_col} + $quantity_to_return; $item_batch_watcher->update(); }else{ // check if that drug has any batch number $item_batch_watcher = ItemBatchWatcher::where(['item_type'=>$item_type, 'item_id'=>$drug_id, ])->where("{$stock_col}", '>', '0')->orderBy(DB::raw('ABS(DATEDIFF(expiry_date, NOW()))'))->first(); if ($item_batch_watcher) { $item_batch_watcher->{$stock_col} = $item_batch_watcher->{$stock_col} + $quantity_to_return; $item_batch_watcher->update(); }else{ $item_batch_watcher = new ItemBatchWatcher; $item_batch_watcher->item_type = $item_type; $item_batch_watcher->item_id = $drug_id; $item_batch_watcher->batch_number = 'RTS-00'.$drug_id; $item_batch_watcher->{$stock_col} = $quantity_to_return; $item_batch_watcher->cost_price = $ward_treatments_dispensation->cost_price; // add one month to expiry date $item_batch_watcher->expiry_date = date('Y-m-d', strtotime('+1 month')); $item_batch_watcher->save(); } } }else{ // check if that drug has any batch number $item_batch_watcher = ItemBatchWatcher::where(['item_type'=>$item_type, 'item_id'=>$drug_id, ])->where("{$stock_col}", '>', '0')->orderBy(DB::raw('ABS(DATEDIFF(expiry_date, NOW()))'))->first(); if ($item_batch_watcher) { $item_batch_watcher->{$stock_col} = $item_batch_watcher->{$stock_col} + $quantity_to_return; $item_batch_watcher->update(); }else{ $item_batch_watcher = new ItemBatchWatcher; $item_batch_watcher->item_type = $item_type; $item_batch_watcher->item_id = $drug_id; $item_batch_watcher->batch_number = 'RTS-00'.$drug_id; $item_batch_watcher->{$stock_col} = $quantity_to_return; $item_batch_watcher->cost_price = $ward_treatments_dispensation->cost_price; // add one month to expiry date $item_batch_watcher->expiry_date = date('Y-m-d', strtotime('+1 month')); $item_batch_watcher->save(); } } } }