Add pricing system with tiers, seasons, and calculator (v0.2.0)
All checks were successful
Create Release Package / build-release (push) Successful in 1m19s
All checks were successful
Create Release Package / build-release (push) Successful in 1m19s
- Create PricingTier enum for short/mid/long-term pricing - Add Season class for seasonal pricing with date ranges - Implement Calculator for price calculations with breakdown - Add pricing meta box to Room post type - Create Seasons admin page for managing seasonal pricing - Add Pricing settings tab with tier thresholds - Support weekend surcharges and configurable weekend days - Add price column to room list admin Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
189
src/Plugin.php
189
src/Plugin.php
@@ -9,9 +9,11 @@ declare( strict_types=1 );
|
||||
|
||||
namespace Magdev\WpBnb;
|
||||
|
||||
use Magdev\WpBnb\Admin\Seasons as SeasonsAdmin;
|
||||
use Magdev\WpBnb\License\Manager as LicenseManager;
|
||||
use Magdev\WpBnb\PostTypes\Building;
|
||||
use Magdev\WpBnb\PostTypes\Room;
|
||||
use Magdev\WpBnb\Pricing\Season;
|
||||
use Magdev\WpBnb\Taxonomies\Amenity;
|
||||
use Magdev\WpBnb\Taxonomies\RoomType;
|
||||
use Twig\Environment;
|
||||
@@ -127,6 +129,9 @@ final class Plugin {
|
||||
// Admin menu and settings will be added here.
|
||||
add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
|
||||
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
||||
|
||||
// Initialize seasons admin page.
|
||||
SeasonsAdmin::init();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,9 +166,9 @@ final class Plugin {
|
||||
global $post_type;
|
||||
|
||||
// Check if we're on plugin pages or editing our custom post types.
|
||||
$is_plugin_page = strpos( $hook_suffix, 'wp-bnb' ) !== false;
|
||||
$is_plugin_page = strpos( $hook_suffix, 'wp-bnb' ) !== false;
|
||||
$is_our_post_type = in_array( $post_type, array( Building::POST_TYPE, Room::POST_TYPE ), true );
|
||||
$is_edit_screen = in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true );
|
||||
$is_edit_screen = in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true );
|
||||
|
||||
if ( ! $is_plugin_page && ! ( $is_our_post_type && $is_edit_screen ) ) {
|
||||
return;
|
||||
@@ -206,6 +211,9 @@ final class Plugin {
|
||||
'selectImages' => __( 'Select Images', 'wp-bnb' ),
|
||||
'addToGallery' => __( 'Add to Gallery', 'wp-bnb' ),
|
||||
'confirmRemove' => __( 'Are you sure you want to remove this image?', 'wp-bnb' ),
|
||||
'increase' => __( 'increase', 'wp-bnb' ),
|
||||
'discount' => __( 'discount', 'wp-bnb' ),
|
||||
'normalPrice' => __( 'Normal price', 'wp-bnb' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
@@ -353,6 +361,10 @@ final class Plugin {
|
||||
class="nav-tab <?php echo 'general' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e( 'General', 'wp-bnb' ); ?>
|
||||
</a>
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=pricing' ) ); ?>"
|
||||
class="nav-tab <?php echo 'pricing' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e( 'Pricing', 'wp-bnb' ); ?>
|
||||
</a>
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=license' ) ); ?>"
|
||||
class="nav-tab <?php echo 'license' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e( 'License', 'wp-bnb' ); ?>
|
||||
@@ -362,6 +374,9 @@ final class Plugin {
|
||||
<div class="tab-content">
|
||||
<?php
|
||||
switch ( $active_tab ) {
|
||||
case 'pricing':
|
||||
$this->render_pricing_settings();
|
||||
break;
|
||||
case 'license':
|
||||
$this->render_license_settings();
|
||||
break;
|
||||
@@ -427,6 +442,143 @@ final class Plugin {
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render pricing settings tab.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function render_pricing_settings(): void {
|
||||
$short_term_max = get_option( 'wp_bnb_short_term_max_nights', 6 );
|
||||
$mid_term_max = get_option( 'wp_bnb_mid_term_max_nights', 27 );
|
||||
$weekend_days = get_option( 'wp_bnb_weekend_days', '5,6' );
|
||||
$seasons = Season::all();
|
||||
|
||||
$days_of_week = array(
|
||||
1 => __( 'Monday', 'wp-bnb' ),
|
||||
2 => __( 'Tuesday', 'wp-bnb' ),
|
||||
3 => __( 'Wednesday', 'wp-bnb' ),
|
||||
4 => __( 'Thursday', 'wp-bnb' ),
|
||||
5 => __( 'Friday', 'wp-bnb' ),
|
||||
6 => __( 'Saturday', 'wp-bnb' ),
|
||||
7 => __( 'Sunday', 'wp-bnb' ),
|
||||
);
|
||||
$selected_days = array_map( 'intval', explode( ',', $weekend_days ) );
|
||||
?>
|
||||
<form method="post" action="">
|
||||
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
||||
|
||||
<h2><?php esc_html_e( 'Pricing Tier Thresholds', 'wp-bnb' ); ?></h2>
|
||||
<p class="description"><?php esc_html_e( 'Define the number of nights that determine which pricing tier applies.', 'wp-bnb' ); ?></p>
|
||||
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="wp_bnb_short_term_max_nights"><?php esc_html_e( 'Short-term (Nightly)', 'wp-bnb' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="number" name="wp_bnb_short_term_max_nights" id="wp_bnb_short_term_max_nights"
|
||||
value="<?php echo esc_attr( $short_term_max ); ?>"
|
||||
class="small-text" min="1" max="30">
|
||||
<?php esc_html_e( 'nights or fewer', 'wp-bnb' ); ?>
|
||||
<p class="description"><?php esc_html_e( 'Stays up to this many nights use the nightly rate.', 'wp-bnb' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="wp_bnb_mid_term_max_nights"><?php esc_html_e( 'Mid-term (Weekly)', 'wp-bnb' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="number" name="wp_bnb_mid_term_max_nights" id="wp_bnb_mid_term_max_nights"
|
||||
value="<?php echo esc_attr( $mid_term_max ); ?>"
|
||||
class="small-text" min="7" max="90">
|
||||
<?php esc_html_e( 'nights or fewer', 'wp-bnb' ); ?>
|
||||
<p class="description"><?php esc_html_e( 'Stays longer than short-term but up to this many nights use the weekly rate.', 'wp-bnb' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Long-term (Monthly)', 'wp-bnb' ); ?></th>
|
||||
<td>
|
||||
<p class="description">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: number of nights */
|
||||
esc_html__( 'Stays longer than %s nights use the monthly rate.', 'wp-bnb' ),
|
||||
'<strong id="wp-bnb-long-term-min">' . esc_html( $mid_term_max ) . '</strong>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><?php esc_html_e( 'Weekend Days', 'wp-bnb' ); ?></h2>
|
||||
<p class="description"><?php esc_html_e( 'Select which days are considered weekend days for weekend surcharges.', 'wp-bnb' ); ?></p>
|
||||
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Weekend Days', 'wp-bnb' ); ?></th>
|
||||
<td>
|
||||
<fieldset>
|
||||
<?php foreach ( $days_of_week as $day_num => $day_name ) : ?>
|
||||
<label style="display: inline-block; margin-right: 15px;">
|
||||
<input type="checkbox" name="wp_bnb_weekend_days[]" value="<?php echo esc_attr( $day_num ); ?>"
|
||||
<?php checked( in_array( $day_num, $selected_days, true ) ); ?>>
|
||||
<?php echo esc_html( $day_name ); ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</fieldset>
|
||||
<p class="description"><?php esc_html_e( 'Weekend surcharges (configured per room) apply to nights starting on these days.', 'wp-bnb' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><?php esc_html_e( 'Seasonal Pricing', 'wp-bnb' ); ?></h2>
|
||||
<p class="description">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: Link to seasons page */
|
||||
esc_html__( 'Manage seasonal pricing periods in the %s.', 'wp-bnb' ),
|
||||
'<a href="' . esc_url( admin_url( 'admin.php?page=wp-bnb-seasons' ) ) . '">' . esc_html__( 'Seasons Manager', 'wp-bnb' ) . '</a>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
|
||||
<?php if ( ! empty( $seasons ) ) : ?>
|
||||
<table class="widefat striped" style="max-width: 600px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Season', 'wp-bnb' ); ?></th>
|
||||
<th><?php esc_html_e( 'Period', 'wp-bnb' ); ?></th>
|
||||
<th><?php esc_html_e( 'Modifier', 'wp-bnb' ); ?></th>
|
||||
<th><?php esc_html_e( 'Status', 'wp-bnb' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ( $seasons as $season ) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html( $season->name ); ?></td>
|
||||
<td><?php echo esc_html( $season->start_date . ' - ' . $season->end_date ); ?></td>
|
||||
<td><?php echo esc_html( $season->getModifierLabel() ); ?></td>
|
||||
<td>
|
||||
<?php if ( $season->active ) : ?>
|
||||
<span class="dashicons dashicons-yes-alt" style="color: #00a32a;"></span>
|
||||
<?php else : ?>
|
||||
<span class="dashicons dashicons-marker" style="color: #646970;"></span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e( 'No seasons configured yet.', 'wp-bnb' ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php submit_button( __( 'Save Pricing Settings', 'wp-bnb' ) ); ?>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render license settings tab.
|
||||
*
|
||||
@@ -588,6 +740,9 @@ final class Plugin {
|
||||
*/
|
||||
private function save_settings( string $tab ): void {
|
||||
switch ( $tab ) {
|
||||
case 'pricing':
|
||||
$this->save_pricing_settings();
|
||||
break;
|
||||
case 'license':
|
||||
$this->save_license_settings();
|
||||
break;
|
||||
@@ -614,6 +769,36 @@ final class Plugin {
|
||||
settings_errors( 'wp_bnb_settings' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save pricing settings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function save_pricing_settings(): void {
|
||||
if ( isset( $_POST['wp_bnb_short_term_max_nights'] ) ) {
|
||||
$value = absint( $_POST['wp_bnb_short_term_max_nights'] );
|
||||
$value = max( 1, min( 30, $value ) );
|
||||
update_option( 'wp_bnb_short_term_max_nights', $value );
|
||||
}
|
||||
|
||||
if ( isset( $_POST['wp_bnb_mid_term_max_nights'] ) ) {
|
||||
$value = absint( $_POST['wp_bnb_mid_term_max_nights'] );
|
||||
$value = max( 7, min( 90, $value ) );
|
||||
update_option( 'wp_bnb_mid_term_max_nights', $value );
|
||||
}
|
||||
|
||||
if ( isset( $_POST['wp_bnb_weekend_days'] ) && is_array( $_POST['wp_bnb_weekend_days'] ) ) {
|
||||
$days = array_map( 'absint', $_POST['wp_bnb_weekend_days'] );
|
||||
$days = array_filter( $days, fn( $d ) => $d >= 1 && $d <= 7 );
|
||||
update_option( 'wp_bnb_weekend_days', implode( ',', $days ) );
|
||||
} else {
|
||||
update_option( 'wp_bnb_weekend_days', '' );
|
||||
}
|
||||
|
||||
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'Pricing settings saved.', 'wp-bnb' ), 'success' );
|
||||
settings_errors( 'wp_bnb_settings' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save license settings.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user