service = $service; $this->receiving = $receiving; } /** * {@inheritDoc} */ public function register_routes(): void { register_rest_route( $this->namespace, '/purchase-orders', array( array( 'methods' => 'GET', 'callback' => array( $this, 'index' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'status' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_key', ), 'supplier' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', ), 'search' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'page' => array( 'type' => 'integer', 'default' => 1, 'sanitize_callback' => 'absint', ), 'per_page' => array( 'type' => 'integer', 'default' => 20, 'sanitize_callback' => 'absint', ), ), ), array( 'methods' => 'POST', 'callback' => array( $this, 'create' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); register_rest_route( $this->namespace, '/purchase-orders/(?P\d+)', array( 'args' => array( 'id' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), array( 'methods' => 'GET', 'callback' => array( $this, 'show' ), 'permission_callback' => array( $this, 'check_permission' ), ), array( 'methods' => 'PUT, PATCH', 'callback' => array( $this, 'update' ), 'permission_callback' => array( $this, 'check_permission' ), ), array( 'methods' => 'DELETE', 'callback' => array( $this, 'destroy' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); register_rest_route( $this->namespace, '/purchase-orders/(?P\d+)/status', array( 'args' => array( 'id' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), array( 'methods' => 'POST', 'callback' => array( $this, 'set_status' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); register_rest_route( $this->namespace, '/purchase-orders/(?P\d+)/receive', array( 'args' => array( 'id' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), array( 'methods' => 'POST', 'callback' => array( $this, 'receive' ), 'permission_callback' => array( $this, 'check_permission' ), ), ) ); } /** * GET /purchase-orders * * @param WP_REST_Request $request Request. */ public function index( WP_REST_Request $request ): WP_REST_Response { $result = $this->service->list( array( 'status' => (string) $request->get_param( 'status' ), 'supplier' => $this->int_param( $request, 'supplier' ), 'search' => (string) $request->get_param( 'search' ), 'page' => $this->int_param( $request, 'page', 1 ), 'per_page' => $this->int_param( $request, 'per_page', 20 ), ) ); $per_page = max( 1, $this->int_param( $request, 'per_page', 20 ) ); $response = new WP_REST_Response( $result['items'], 200 ); $response->header( 'X-WP-Total', (string) $result['total'] ); $response->header( 'X-WP-TotalPages', (string) (int) ceil( $result['total'] / $per_page ) ); return $response; } /** * GET /purchase-orders/{id} * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function show( WP_REST_Request $request ) { $po = $this->service->get( (int) $request['id'] ); if ( ! $po ) { return new WP_Error( 'profit_engine_po_not_found', __( 'Purchase order not found.', 'profit-engine' ), array( 'status' => 404 ) ); } return new WP_REST_Response( $po, 200 ); } /** * POST /purchase-orders * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function create( WP_REST_Request $request ) { $result = $this->service->create( (array) $request->get_json_params() ); return is_wp_error( $result ) ? $result : new WP_REST_Response( $result, 201 ); } /** * PUT /purchase-orders/{id} * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function update( WP_REST_Request $request ) { $result = $this->service->update( (int) $request['id'], (array) $request->get_json_params() ); return is_wp_error( $result ) ? $result : new WP_REST_Response( $result, 200 ); } /** * DELETE /purchase-orders/{id} * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function destroy( WP_REST_Request $request ) { $result = $this->service->delete( (int) $request['id'] ); return is_wp_error( $result ) ? $result : new WP_REST_Response( array( 'deleted' => true ), 200 ); } /** * POST /purchase-orders/{id}/status * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function set_status( WP_REST_Request $request ) { $status = sanitize_key( (string) ( $request->get_json_params()['status'] ?? '' ) ); $result = $this->service->change_status( (int) $request['id'], $status ); return is_wp_error( $result ) ? $result : new WP_REST_Response( $result, 200 ); } /** * POST /purchase-orders/{id}/receive * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function receive( WP_REST_Request $request ) { $body = (array) $request->get_json_params(); $receipts = array(); foreach ( (array) ( $body['receipts'] ?? array() ) as $r ) { $receipts[] = array( 'item_id' => (int) ( $r['item_id'] ?? 0 ), 'qty' => (float) ( $r['qty'] ?? 0 ), ); } $result = $this->receiving->receive( (int) $request['id'], $receipts ); if ( is_wp_error( $result ) ) { return $result; } // Return the fresh PO so the UI reflects new quantities/status. return new WP_REST_Response( $this->service->get( (int) $request['id'] ), 200 ); } }