<?php namespace App\Services; use App\Models\{Intern,StipendBatch,StipendItem}; use Illuminate\Support\Facades\DB; use RuntimeException; class StipendService {public function calculate(string $period):StipendBatch{return DB::transaction(function()use($period){$b=StipendBatch::firstOrCreate(['period'=>$period],['status'=>'draft']);if($b->locked_at)throw new RuntimeException('Locked stipend batch cannot be recalculated.');$b->items()->delete();foreach(Intern::where('status','active')->get() as $i){$amount=(float)$i->stipend_amount;StipendItem::create(['stipend_batch_id'=>$b->id,'intern_id'=>$i->id,'stipend_amount'=>$amount,'deductions'=>0,'additions'=>0,'net_amount'=>$amount,'snapshot'=>['period'=>$period,'intern_code'=>$i->intern_code],'payment_status'=>'pending']);}$b->update(['status'=>'calculated']);return $b->fresh('items');});} public function approve(StipendBatch $b,int $uid):void{$b->update(['status'=>'approved','approved_by'=>$uid,'approved_at'=>now(),'locked_at'=>now()]);} public function markPaid(StipendBatch $b):void{DB::transaction(function()use($b){$b->items()->update(['payment_status'=>'paid','paid_at'=>now()]);$b->update(['status'=>'paid','paid_at'=>now()]);});}}