reorder = $reorder; $this->forecasts = $forecasts; $this->scheduler = $scheduler; } /** * {@inheritDoc} */ public function register_routes(): void { register_rest_route( $this->namespace, '/reorder', array( array( 'methods' => 'GET', 'callback' => array( $this, 'index' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'severity' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_key', ), 'supplier' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), ), ) ); register_rest_route( $this->namespace, '/reorder/create-pos', array( array( 'methods' => 'POST', 'callback' => array( $this, 'create_pos' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); register_rest_route( $this->namespace, '/reorder/recompute', array( array( 'methods' => 'POST', 'callback' => array( $this, 'recompute' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); register_rest_route( $this->namespace, '/forecast/(?P\d+)', array( 'args' => array( 'id' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), array( 'methods' => 'GET', 'callback' => array( $this, 'forecast' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); } /** * GET /reorder * * @param WP_REST_Request $request Request. */ public function index( WP_REST_Request $request ): WP_REST_Response { return new WP_REST_Response( $this->reorder->list( array( 'severity' => (string) $request->get_param( 'severity' ), 'supplier' => $this->int_param( $request, 'supplier' ), ) ), 200 ); } /** * POST /reorder/create-pos * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function create_pos( WP_REST_Request $request ) { $selections = array(); foreach ( (array) ( $request->get_json_params()['selections'] ?? array() ) as $sel ) { $selections[] = array( 'product_id' => (int) ( $sel['product_id'] ?? 0 ), 'qty' => (float) ( $sel['qty'] ?? 0 ), ); } $result = $this->reorder->create_pos( $selections ); return is_wp_error( $result ) ? $result : new WP_REST_Response( $result, 201 ); } /** * POST /reorder/recompute — recompute all forecasts now (batched async). */ public function recompute(): WP_REST_Response { $processed = $this->scheduler->run_now(); return new WP_REST_Response( array( 'started' => true, 'processed' => $processed, ), 200 ); } /** * GET /forecast/{id} — transparent breakdown for one unit (recomputes live). * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function forecast( WP_REST_Request $request ) { $breakdown = $this->forecasts->recompute_one( (int) $request['id'] ); if ( null === $breakdown ) { return new WP_Error( 'profit_engine_forecast_unavailable', __( 'No forecast is available for this product. Configure its purchasing data first.', 'profit-engine' ), array( 'status' => 404 ) ); } return new WP_REST_Response( $breakdown, 200 ); } }