| @@ -17,8 +17,9 @@ | ||
| 17 | 17 | use Exception; |
| 18 | 18 | use WC_Abstract_Order; |
| 19 | 19 | use WC_Data; |
| 20 | 20 | use WC_Email_Customer_Invoice; |
| 21 | +use WC_Order; | |
| 21 | 22 | use WC_Order_Item; |
| 22 | 23 | use WC_Order_Item_Fee; |
| 23 | 24 | use WC_Order_Item_Product; |
| 24 | 25 | use WC_REST_Orders_Controller; |
| @@ -25,8 +26,9 @@ | ||
| 25 | 26 | use WC_Tax; |
| 26 | 27 | use WCPOS\WooCommercePOS\Logger; |
| 27 | 28 | use WCPOS\WooCommercePOS\Services\Pos_Order_Audit; |
| 28 | 29 | use WCPOS\WooCommercePOS\Services\Settings as SettingsService; |
| 30 | +use WCPOS\WooCommercePOS\Services\Stock_Validator; | |
| 29 | 31 | use WCPOS\WooCommercePOS\Services\Tax_Id_Reader; |
| 30 | 32 | use WCPOS\WooCommercePOS\Services\Tax_Id_Types; |
| 31 | 33 | use WCPOS\WooCommercePOS\Services\Tax_Id_Writer; |
| 32 | 34 | use WCPOS\WooCommercePOS\Sync\Collection_Rules; |
| @@ -107,8 +109,45 @@ | ||
| 107 | 109 | } |
| 108 | 110 | } |
| 109 | 111 | |
| 110 | 112 | /** |
| 113 | + * Persist new checkout orders as pending until stock is reserved atomically. | |
| 114 | + * | |
| 115 | + * @param WP_REST_Request $request Full request details. | |
| 116 | + * @param bool $creating Whether a new order is being created. | |
| 117 | + * @return WC_Data|WP_Error | |
| 118 | + * @throws \Throwable If checkout stock validation cannot be completed. | |
| 119 | + */ | |
| 120 | + protected function save_object( $request, $creating = false ) { | |
| 121 | + $validator = Stock_Validator::instance(); | |
| 122 | + if ( ! $creating || ! \wcpos_request() || ! SettingsService::instance()->prevent_overselling_enabled() || ! $validator->should_validate_create_request( $request ) ) { | |
| 123 | + return parent::save_object( $request, $creating ); | |
| 124 | + } | |
| 125 | + | |
| 126 | + $target_status = $request->get_param( 'status' ); | |
| 127 | + $set_paid = $request->get_param( 'set_paid' ); | |
| 128 | + | |
| 129 | + try { | |
| 130 | + return $validator->around_paid_create( | |
| 131 | + array( | |
| 132 | + 'status' => $target_status, | |
| 133 | + 'set_paid' => rest_sanitize_boolean( $set_paid ), | |
| 134 | + 'transaction_id' => $request->get_param( 'transaction_id' ), | |
| 135 | + ), | |
| 136 | + function ( array $neutralised ) use ( $request, $creating ) { | |
| 137 | + $request->set_param( 'status', $neutralised['status'] ); | |
| 138 | + $request->set_param( 'set_paid', $neutralised['set_paid'] ); | |
| 139 | + | |
| 140 | + return parent::save_object( $request, $creating ); | |
| 141 | + } | |
| 142 | + ); | |
| 143 | + } finally { | |
| 144 | + $request->set_param( 'status', $target_status ); | |
| 145 | + $request->set_param( 'set_paid', $set_paid ); | |
| 146 | + } | |
| 147 | + } | |
| 148 | + | |
| 149 | + /** | |
| 111 | 150 | * Check if the current user can update an order. |
| 112 | 151 | * |
| 113 | 152 | * Overrides the parent to fix HPOS compatibility. When HPOS is enabled with |
| 114 | 153 | * sync disabled, get_post() returns a shop_order_placehold post type that has |
| @@ -297,9 +336,9 @@ | ||
| 297 | 336 | ), |
| 298 | 337 | ) |
| 299 | 338 | ), |
| 300 | 339 | ), |
| 301 | - 'schema' => array(), | |
| 340 | + 'schema' => array( $this, 'wcpos_get_public_send_email_schema' ), | |
| 302 | 341 | ) |
| 303 | 342 | ); |
| 304 | 343 | |
| 305 | 344 | register_rest_route( |
| @@ -972,8 +1011,34 @@ | ||
| 972 | 1011 | ), |
| 973 | 1012 | 'name' => array( |
| 974 | 1013 | 'description' => __( 'Display name of the order status.', 'woocommerce-pos' ), |
| 975 | 1014 | 'type' => 'string', |
| 1015 | + 'context' => array( 'view', 'edit' ), | |
| 1016 | + 'readonly' => true, | |
| 1017 | + ), | |
| 1018 | + ), | |
| 1019 | + ); | |
| 1020 | + } | |
| 1021 | + | |
| 1022 | + /** | |
| 1023 | + * Get the route schema for the send-email action. | |
| 1024 | + * | |
| 1025 | + * Registered as the route-level `schema` callback. WordPress invokes it with | |
| 1026 | + * `call_user_func()` whenever a namespace index is requested with | |
| 1027 | + * `context=help`, so it must be a real callable — an empty array there | |
| 1028 | + * passes `isset()` and then fatals with a TypeError. | |
| 1029 | + * | |
| 1030 | + * @return array | |
| 1031 | + */ | |
| 1032 | + public function wcpos_get_public_send_email_schema() { | |
| 1033 | + return array( | |
| 1034 | + '$schema' => 'http://json-schema.org/draft-04/schema#', | |
| 1035 | + 'title' => 'order_email', | |
| 1036 | + 'type' => 'object', | |
| 1037 | + 'properties' => array( | |
| 1038 | + 'success' => array( | |
| 1039 | + 'description' => __( 'Whether the order email was sent.', 'woocommerce-pos' ), | |
| 1040 | + 'type' => 'boolean', | |
| 976 | 1041 | 'context' => array( 'view', 'edit' ), |
| 977 | 1042 | 'readonly' => true, |
| 978 | 1043 | ), |
| 979 | 1044 | ), |