Minimum Quantity by Remaining Capacity

When a slot’s remaining capacity is at or above the configured threshold, the customer must book at least the minimum quantity. Once enough spots are taken that remaining capacity drops below the threshold, the minimum no longer applies.

Instructions

  1. Install this snippet by following the steps here: https://gravitywiz.com/documentation/how-do-i-install-a-snippet/

  2. Update the configuration at the bottom of the snippet.

Code

Filename: gpb-minimum-qty-by-remaining-capacity.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<?php
/**
 * Gravity Perks // Bookings // Minimum Quantity by Remaining Capacity
 * https://gravitywiz.com/documentation/gravity-forms-bookings/
 *
 * When a slot's remaining capacity is at or above the configured threshold,
 * the customer must book at least the minimum quantity. Once enough spots are
 * taken that remaining capacity drops below the threshold, the minimum no
 * longer applies.
 *
 * Instructions:
 *
 * 1. Install this snippet by following the steps here:
 *    https://gravitywiz.com/documentation/how-do-i-install-a-snippet/
 *
 * 2. Update the configuration at the bottom of the snippet.
 */
class GPB_Minimum_Quantity_By_Capacity {

	private $service_ids;
	private $threshold;
	private $min_quantity;

	public function __construct( array $args = array() ) {
		$this->service_ids  = array_map( 'intval', (array) ( $args['service_ids'] ?? array() ) );
		$this->threshold    = (int) ( $args['threshold'] ?? 10 );
		$this->min_quantity = (int) ( $args['min_quantity'] ?? 2 );

		add_filter( 'gform_validation', array( $this, 'validate_submission' ) );
	}

	public function validate_submission( $validation_result ) {
		$form = $validation_result['form'];

		foreach ( $form['fields'] as &$field ) {
			if ( 'gpb_booking_time' !== $field->type || \GFFormsModel::is_field_hidden( $form, $field, array() ) ) {
				continue;
			}

			$slot_value = rgpost( 'input_' . $field->id );
			if ( rgblank( $slot_value ) ) {
				continue;
			}

			$service = $this->get_service_for_booking( $form, $field->gpbBookingField ?? null );
			if ( ! $service ) {
				continue;
			}

			try {
				$range = \GP_Bookings\Booking::normalize_datetime_values( $slot_value, $slot_value, $service );
			} catch ( \Throwable $e ) {
				continue;
			}

			$remaining = $service->get_remaining_capacity(
				$range['start']->toDateTimeString(),
				$range['end']->toDateTimeString()
			);
			if ( $remaining->is_unlimited() || $remaining->to_int() < $this->threshold ) {
				continue;
			}

			if ( $this->get_submitted_quantity( $form, $field->gpbBookingField ) < $this->min_quantity ) {
				$field->failed_validation  = true;
				$field->validation_message = sprintf(
					/* translators: %d: required minimum quantity */
					__( 'A minimum quantity of %d is required for this time slot.', 'gp-bookings' ),
					$this->min_quantity
				);
				$validation_result['is_valid'] = false;
			}
		}
		unset( $field );

		$validation_result['form'] = $form;

		return $validation_result;
	}

	private function get_service_for_booking( $form, $booking_field_id ) {
		if ( ! $booking_field_id ) {
			return null;
		}

		foreach ( $form['fields'] as $field ) {
			if ( 'gpb_service' !== $field->type || (string) $field->gpbBookingField !== (string) $booking_field_id ) {
				continue;
			}

			$service_id = ( $field->gpbSelectionMode ?? 'preselected' ) === 'manual'
				? (int) rgpost( 'input_' . $field->id )
				: (int) ( $field->gpbService ?? 0 );

			$applies = ! $this->service_ids || in_array( $service_id, $this->service_ids, true );

			return $service_id && $applies ? \GP_Bookings\Service::get( $service_id ) : null;
		}

		return null;
	}

	private function get_submitted_quantity( $form, $booking_field_id ) {
		$quantity_fields = \GFCommon::get_product_fields_by_type( $form, array( 'quantity' ), $booking_field_id );

		if ( $quantity_fields && ! \GFFormsModel::is_field_hidden( $form, $quantity_fields[0], array() ) ) {
			return max( 1, (int) \RGFormsModel::get_field_value( $quantity_fields[0] ) );
		}

		return max( 1, (int) rgpost( 'input_' . $booking_field_id . '.3' ) );
	}

}

# Configuration

new GPB_Minimum_Quantity_By_Capacity(
	array(
		'service_ids'  => array( 123 ), // Enter service IDs, or leave empty for all
		'threshold'    => 10, // Apply the minimum when remaining capacity is this or higher
		'min_quantity' => 2, // Minimum quantity required when the threshold is met
	)
);

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.