Skip to content

kandekore/Booking-Manager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Native Pro Scheduler

A production-grade WordPress booking plugin with Google Calendar sync, Stripe payments, multi-provider support, and a fully configurable email notification system.


Table of Contents

  1. Requirements
  2. Installation
  3. Configuration
  4. Getting Started
  5. Shortcodes
  6. Booking Flow
  7. Payment Modes
  8. Admin Features
  9. Email Templates
  10. REST API
  11. File Structure
  12. Database Schema
  13. Changelog

Requirements

Requirement Minimum
WordPress 6.0
PHP 8.0
MySQL / MariaDB 5.7 / 10.3
SSL Required (Stripe, Google OAuth)

Optional but recommended:

  • Google Cloud project with Calendar API and Maps Geocoding API enabled
  • Stripe account (test or live)

Installation

  1. Copy the native-pro-scheduler folder into wp-content/plugins/.
  2. Activate the plugin via Plugins → Installed Plugins.
  3. Two database tables are created automatically on activation:
    • {prefix}nps_bookings
    • {prefix}nps_availability
  4. A Scheduler top-level menu appears in the WordPress admin.

To deactivate cleanly, use Plugins → Deactivate. The plugin's scheduled cron event is removed on deactivation; database tables are retained.


Configuration

Navigate to Scheduler → Settings to enter your API credentials.

General

Field Description
Currency Symbol Symbol prepended to all prices (e.g. $, £, , AU$). Default: $

Google Calendar

Field Where to find it
Google Client ID Google Cloud Console → APIs & Services → Credentials
Google Client Secret Same credential entry
Google Maps API Key Google Cloud Console → Maps Geocoding API

Required OAuth scopes: https://www.googleapis.com/auth/calendar

After saving the credentials, open any Provider post and click Connect Google Calendar. Complete the OAuth flow; the access and refresh tokens are stored encrypted in provider post meta.

Stripe

Field Where to find it
Publishable Key Stripe Dashboard → Developers → API Keys
Secret Key Same page (reveal once)

Use pk_test_… / sk_test_… keys during development; swap to live keys for production. Keys are stored AES-256-GCM encrypted using a key derived from WordPress's AUTH_KEY.

Blackout Dates

Enter dates in YYYY-MM-DD format, one per line. No slots are returned for these dates regardless of provider availability.


Getting Started

Creating a Provider

  1. Go to Scheduler → Providers → Add New (or find Providers under the custom post type menu).
  2. Fill in the provider's display name and any post content you want shown publicly.
  3. In the Provider Details meta box:
    • Timezone — provider's local timezone (used for display only; all storage is UTC).
    • Assigned Services — tick every service this provider can deliver.
    • Google Calendar — click Connect Google Calendar to authorise the OAuth flow.
  4. In the Weekly Availability meta box, set the working hours for each day of the week. Toggle days on/off and set start/end times. These are stored in UTC — enter times in UTC or adjust for the provider's timezone at the UI layer.
  5. Save the post. Availability rows are written to {prefix}nps_availability.

Date overrides: The availability table supports override_date rows that take precedence over the recurring schedule. These are not yet exposed in the UI but can be inserted directly into the database for one-off exceptions.

Creating a Service

  1. Go to Scheduler → Services → Add New.
  2. In the Service Details meta box:
Field Description
Duration (minutes) Length of the appointment
Buffer (minutes) Blocked time after each appointment (e.g. clean-up); not shown to clients
Price Full service price in your Stripe account's default currency
Payment Mode See Payment Modes
Deposit Amount Fixed deposit amount (deposit_fixed mode only)
Deposit % Percentage of price collected upfront (deposit_percent mode only)
Address Physical location; geocoded to lat/lng on save
  1. Assign one or more Service Categories using the taxonomy metabox in the right sidebar.
  2. Save the post. The booking form is automatically appended to this service's single page.

Service Categories

Manage categories via Scheduler → Categories in the admin menu.

  • Categories are hierarchical (like WordPress post categories).
  • Assign one or more categories to each service from the service edit screen.
  • The public /services/ archive automatically renders a category filter strip.
  • Taxonomy archive pages (/service-category/{slug}/) show only services in that category.

Displaying the Booking Form

Automatic: The form is appended to any single nps_services page via the the_content filter. No shortcode needed.

Manual / embed anywhere:

[nps_booking service_id="42"]

Replace 42 with the service post ID. Multiple shortcodes can appear on the same page (each initialises its own isolated booking flow).

Services Listing Page

The plugin registers /services/ as the post-type archive for nps_services. Visiting this URL displays all published services as Bootstrap-style cards (3 per row on desktop), each showing the featured image, title, excerpt, price, and a Book Now link. A category filter strip at the top links to the individual taxonomy archive pages.

Theme override: Place archive-nps_services.php or taxonomy-nps_service_category.php in your active theme directory to replace the plugin's default template.


Shortcodes

[nps_booking]

Embeds the multi-step booking form for a specific service.

Attribute Default Description
service_id (required) Post ID of the service to book
label service title Override the displayed service name
[nps_booking service_id="42"]
[nps_booking service_id="42" label="Book a Massage"]

[nps_services]

Renders a Bootstrap-style card grid listing published services.

Attribute Default Description
category (none) Slug of a nps_service_category term; omit for all services
limit -1 (all) Maximum number of cards to render
[nps_services]
[nps_services category="massage" limit="6"]

When no category attribute is provided, a category filter strip is rendered above the grid. Clicking a category tag reloads the page with ?nps_cat=slug to filter the results.


Booking Flow

The public multi-step form works as follows:

Step 1 — Date picker
         ↓  (fetches /nps/v1/slots)
Step 2 — Available time slots grid
         ↓  (slot selected → POST /nps/v1/create-intent)
Step 3 — Client details (name, email, phone)
         ↓
Step 4 — Payment capture (Stripe card element) or direct confirm (no-payment mode)
         ↓  (POST /nps/v1/book)
Success — Confirmation message + emails sent

All times displayed to the client are formatted according to WordPress's Time Format setting (Settings → General). All internal storage and API communication use UTC.


Payment Modes

Set per service in the Service Details meta box.

Mode Behaviour
None No payment collected. Booking confirmed immediately on submit.
Full Full service price charged at booking time.
Fixed Deposit A specific dollar amount charged upfront; remainder collected separately.
Percentage Deposit A percentage of the service price charged upfront.

For all modes except None, Stripe's Authorize-then-Capture flow is used:

  1. A PaymentIntent is created and authorised (card held but not charged) before the booking is confirmed.
  2. Availability is re-validated server-side.
  3. The hold is captured only after the booking row is successfully inserted.
  4. If the slot is taken between step 1 and 3, the hold is released automatically.

Admin Features

Dashboard (Scheduler → Dashboard)

  • Total Bookings — all-time count.
  • Confirmed — bookings with confirmed status.
  • Today's Appointments — non-cancelled bookings for today.
  • Recent bookings table (last 5).

Bookings (Scheduler → Bookings)

  • Filter by status (pending / confirmed / cancelled / completed).
  • Search by client name or email.
  • Paginated at 20 rows per page.
  • Per-row actions for confirmed bookings:
    • Reschedule — opens a date/slot picker; updates the DB, recreates the Google Calendar event, and emails the client a reschedule notification.
    • Complete — marks the booking completed.
    • Cancel — marks cancelled, deletes the Google Calendar event, and refunds/voids the Stripe charge. Prompts for confirmation.

Settings (Scheduler → Settings)

General (currency symbol), Google API keys, Stripe keys, and blackout dates.

Service Categories (Scheduler → Categories)

Hierarchical category management for the nps_services post type. Categories are used for filtering on the services archive page and in the [nps_services] shortcode.

Email Templates (Scheduler → Email Templates)

Edit subject line and HTML body for each of the five template types (see Email Templates).


Email Templates

Five template types are editable under Scheduler → Email Templates:

Template Sent when
Booking Confirmation Client books; also sent to the provider
Appointment Reminder 24 hours before the appointment (WP-Cron)
Cancellation Alert Booking is cancelled
Admin New Booking Alert Sent to site admin on every new booking
Reschedule Notification Sent to client when admin reschedules their appointment

Templates support a rich text editor (TinyMCE) for the body and a plain text subject line.

Available Tokens

Use these placeholders anywhere in the subject or body; they are replaced at send time.

Token Value
{{client_name}} Client's full name
{{client_email}} Client's email address
{{client_phone}} Client's phone number
{{service_name}} Service title
{{provider_name}} Provider display name
{{booking_date}} Appointment date (WordPress date format)
{{start_time}} Start time (WordPress time format)
{{end_time}} End time (WordPress time format)
{{booking_id}} Booking database ID
{{site_name}} WordPress site name
{{site_url}} WordPress site URL
{{admin_url}} Direct URL to the Bookings admin page
{{new_date}} New date after reschedule
{{new_start_time}} New start time after reschedule
{{new_end_time}} New end time after reschedule

REST API

Base URL: /wp-json/nps/v1/

All POST endpoints require the X-WP-Nonce header set to a wp_rest nonce.


GET /slots

Returns available time slots for a service on a given date.

Query parameters

Param Type Description
service_id int Service post ID
date string YYYY-MM-DD (UTC)

Response

{
  "success": true,
  "slots": [
    {
      "start": "09:00",
      "end": "10:00",
      "provider_ids": [25, 31]
    }
  ]
}

POST /create-intent

Creates a Stripe PaymentIntent for the service. For none payment mode returns a signal to skip payment.

Body (JSON)

Param Type Required
service_id int yes
nonce string yes (nps_booking_nonce)

Response

{
  "success": true,
  "no_payment": false,
  "client_secret": "pi_…_secret_…",
  "amount_cents": 5000,
  "payment_mode": "full"
}

For none mode: { "success": true, "no_payment": true }


POST /book

Atomic booking endpoint. Validates the slot, inserts the booking, creates a Google Calendar event, captures payment, and sends confirmation emails.

Body (JSON)

Param Type Required
service_id int yes
provider_id int yes
date string yes (YYYY-MM-DD)
start_time string yes (HH:MM)
client_name string yes
client_email string yes
client_phone string no
payment_intent_id string only for paid modes
nonce string yes (nps_booking_nonce)

Response

{
  "success": true,
  "booking_id": 42,
  "message": "Your booking is confirmed!"
}

POST /cancel

Cancels a booking. Requires manage_options capability.

Body (JSON)

Param Type Required
booking_id int yes
nonce string yes (nps_cancel_nonce)

File Structure

native-pro-scheduler/
├── native-pro-scheduler.php        # Plugin bootstrap, constants, autoload
│
├── includes/
│   ├── class-nps-plugin.php        # Singleton service locator + NPS() helper
│   ├── class-nps-installer.php     # Activation: dbDelta tables, cron scheduling
│   ├── class-nps-cpt.php           # Provider & Service custom post types + meta boxes
│   ├── class-nps-availability-manager.php  # Slot engine (schedule + GCal + DB)
│   ├── class-nps-google-calendar.php       # OAuth2, FreeBusy, event CRUD
│   ├── class-nps-stripe.php        # PaymentIntent create/verify/capture/cancel/refund
│   ├── class-nps-email.php         # HTML email sending + token substitution
│   ├── class-nps-encryption.php    # AES-256-GCM encrypt/decrypt (API key storage)
│   ├── class-nps-geocoding.php     # Address → lat/lng via Maps Geocoding API
│   ├── class-nps-cron.php          # Daily reminder cron job
│   └── class-nps-rest-controller.php  # WP REST API route handlers
│
├── admin/
│   ├── class-nps-admin.php         # Admin menu, dashboard page
│   ├── class-nps-bookings-admin.php  # Bookings table + reschedule flow
│   ├── class-nps-settings.php      # Settings page (API keys, blackout dates)
│   └── class-nps-email-editor.php  # Email template editor (wp_editor)
│
├── public/
│   ├── class-nps-public.php        # Asset enqueue + script localisation + archive template
│   ├── class-nps-booking-shortcode.php  # [nps_booking] shortcode
│   └── class-nps-services-shortcode.php # [nps_services] shortcode
│
├── templates/
│   ├── booking-form.php            # Multi-step booking form HTML
│   ├── services-archive.php        # Services archive / category taxonomy template
│   └── emails/
│       ├── confirmation.php
│       ├── reminder.php
│       └── cancellation.php
│
├── assets/
│   ├── css/
│   │   ├── public.css              # Booking form styles
│   │   └── admin.css               # Admin UI styles
│   └── js/
│       ├── booking.js              # Multi-step form JS + Stripe Elements
│       └── admin.js                # Admin UI JS
│
├── README.md
└── CHANGELOG.md

Database Schema

{prefix}nps_bookings

Column Type Notes
id bigint UNSIGNED PK Auto-increment
service_id bigint UNSIGNED Service post ID
provider_id bigint UNSIGNED Provider post ID
booking_date date UTC
start_time time UTC
end_time time UTC (start + duration)
client_name varchar(150)
client_email varchar(200)
client_phone varchar(30)
status varchar(20) pending / confirmed / cancelled / completed
stripe_payment_intent_id varchar(200)
stripe_charge_id varchar(200) Set after capture
google_event_id varchar(200) Set after GCal event creation
created_at datetime Auto
updated_at datetime Auto-updated

{prefix}nps_availability

Column Type Notes
id bigint UNSIGNED PK Auto-increment
provider_id bigint UNSIGNED Provider post ID
day_of_week tinyint 0 = Sunday … 6 = Saturday
start_time time UTC
end_time time UTC
is_available tinyint(1) 1 = working, 0 = day off
override_date date NULL NULL = recurring; date = one-off override

Recurring rows have override_date = NULL. Date-specific overrides take precedence over recurring rows for the same provider on a given date.


Changelog

See CHANGELOG.md for the full version history.

About

A production-grade WordPress booking plugin with Google Calendar sync, Stripe payments, multi-provider support, and a fully configurable email notification system.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors