get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}abientot_payment_records WHERE appointment_id = %d AND provider <> %s", $appointment_id, 'manual' ) ); return null === $count || '' !== $wpdb->last_error || (int) $count > 0; } /** * Creates or updates the manual payment record for an appointment. */ public function mark_manual_status( int $appointment_id, string $status, int $amount_cents, string $currency ): bool { global $wpdb; if ( $appointment_id <= 0 || $this->has_online_records( $appointment_id ) ) { return false; } // Planned bookings retain immutable receipts. A supported ordinary edit is a no-op. try { $plan = ( new PaymentPlanRepository() )->plan( $appointment_id ); if ( $plan ) { $receipts = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}abientot_payment_records WHERE appointment_id=%d", $appointment_id ) ); if ( $wpdb->last_error ) { return false; } if ( (int) $receipts > 0 ) { $booking = ( new AppointmentsRepository() )->find( $appointment_id ); return $booking && $booking['payment_status'] === $status && (int) $plan['gross_cents'] === $amount_cents && $plan['currency'] === $currency; } } } catch ( \Throwable $error ) { return false; } $now = gmdate( 'Y-m-d H:i:s' ); $paid_at = 'paid' === $status ? $now : null; $existing = $wpdb->get_row( $wpdb->prepare( "SELECT id, status, paid_at FROM {$wpdb->prefix}abientot_payment_records WHERE appointment_id = %d AND provider = %s ORDER BY id ASC LIMIT 1", $appointment_id, 'manual' ), ARRAY_A ); $id = (int) ( $existing['id'] ?? 0 ); if ( 'paid' === $status && 'paid' === ( $existing['status'] ?? '' ) && ! empty( $existing['paid_at'] ) ) { $paid_at = $existing['paid_at']; } $data = array( 'appointment_id' => $appointment_id, 'provider' => 'manual', 'method' => 'on_site', 'status' => $status, 'amount_cents' => $amount_cents, 'currency' => $currency, 'paid_at' => $paid_at, 'updated_at' => $now, ); if ( $id > 0 ) { return $this->update( $id, $data ); } $data['created_at'] = $now; return $this->insert( $data ) > 0; } }