$mode,'reason'=>$reason,'performed_by_user_id'=>$actor]; }elseif(array_key_exists('custom_fee',$input))CatalogValidator::invalid('custom_fee',__('A custom fee requires the custom override mode.','abece-booking')); return $calculation+$this->service->payments->settlement->calculate(array_replace($b,['status'=>'cancelled','cancellation_fee'=>$calculation['calculated_fee']])); } public static function requireOverride(int $actor): void { if(!user_can($actor,Capabilities::MANAGE_BOOKINGS)||!user_can($actor,Capabilities::OVERRIDE_CANCELLATION_FEES))throw new CatalogException('abece_booking_fee_override_forbidden',__('You do not have permission to override cancellation fees.','abece-booking'),403); } public function quote(int $id,array $input,int $actor): array { $rid=$this->service->owned($id,$actor)['resource_id'];return $this->bookings->customerTransaction($id,[$rid],fn()=>$this->calculate($this->service->lockOwned($id,$actor,[$rid]),$input,$actor)); } public function cancel(int $id,array $input,int $actor,bool $notify=true): array { $reason=BookingValidator::note($input['reason']??null,'reason');$rid=$this->service->owned($id,$actor)['resource_id']; $booking=$this->bookings->customerTransaction($id,[$rid],function()use($id,$input,$actor,$reason,$rid){ $b=$this->service->lockOwned($id,$actor,[$rid]);$calculation=$this->calculate($b,$input,$actor); if(array_key_exists('expected_fee',$input)&&CatalogValidator::integer($input['expected_fee'],'expected_fee',0,Money::MAX)!==$calculation['calculated_fee'])throw new CatalogException('abece_booking_cancellation_quote_changed',__('The cancellation fee changed. Review a new quote before confirming.','abece-booking'),409); $stamp=current_time('mysql',true);$fields=($b['series_id']?['series_is_exception'=>1]:[])+['status'=>'cancelled','cancelled_at'=>$stamp,'cancelled_by_user_id'=>$actor,'cancellation_reason'=>$reason,'cancellation_fee'=>$calculation['calculated_fee'],'updated_at'=>$stamp];$this->bookings->update($id,$fields); $settled=$this->service->payments->settle(array_replace($b,$fields),$actor,$reason); $calculation['settled']=$settled;$calculation['processed_at']=$stamp; $this->service->recordHistory($id,'cancelled','confirmed','cancelled',$actor,$stamp,$reason,$calculation); if($calculation['override'])$this->service->recordHistory($id,'cancellation_fee_overridden','cancelled','cancelled',$actor,$stamp,$reason,$calculation); return $this->bookings->find($id); });if($notify)$this->mailer->send($booking,'cancelled');return $this->service->detail($id,$actor); } }