softoba_init_posttype(); $this->softoba_init_post_statuses(); } public function softoba_init_posttype() { $labels = array( 'name' => esc_html_x( 'Return Requests', 'Page title', 'astra' ), 'singular_name' => esc_html_x( 'Return Request', 'Post type singular name', 'astra' ), 'menu_name' => esc_html_x( 'Return Requests', 'admin menu', 'astra' ), 'name_admin_bar' => esc_html_x( 'Return Request', 'add new on admin bar', 'astra' ), 'add_new' => esc_html_x( 'Add New', 'Add New Return request', 'astra' ), 'add_new_item' => esc_html__( 'Add new Return request', 'astra' ), 'new_item' => esc_html__( 'New Return request', 'astra' ), 'edit_item' => esc_html__( 'Manage Return request', 'astra' ), 'view_item' => esc_html__( 'View Return request', 'astra' ), 'all_items' => esc_html__( 'All Return requests', 'astra' ), 'search_items' => esc_html__( 'Search Return requests', 'astra' ), 'parent_item_colon' => esc_html__( 'Parent Return requests:', 'astra' ), 'not_found' => esc_html__( 'No Return request found.', 'astra' ), 'not_found_in_trash' => esc_html__( 'No Return requests found in Trash.', 'astra' ) ); $args = array( 'hierarchical' => false, 'public' => false, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => false, 'show_in_admin_bar' => false, 'menu_position' => 58, 'can_export' => false, 'has_archive' => false, 'exclude_from_search' => true, 'menu_icon' => 'dashicons-money', 'query_var' => false, 'labels' => $labels, 'description' => esc_html__( 'Description.', 'astra' ), 'publicly_queryable' => true, 'capability_type' => 'post', 'capabilities' => array( 'create_posts' => 'do_not_allow' ), 'map_meta_cap' => true, 'supports' => array( 'title' ) ); $exchange_labels = array( 'name' => esc_html_x( 'Exchange Requests', 'Page title', 'astra' ), 'singular_name' => esc_html_x( 'Exchange Request', 'Post type singular name', 'astra' ), 'menu_name' => esc_html_x( 'Exchange Requests', 'admin menu', 'astra' ), 'name_admin_bar' => esc_html_x( 'Exchange Request', 'add new on admin bar', 'astra' ), 'add_new' => esc_html_x( 'Add New', 'Add New Exchange request', 'astra' ), 'add_new_item' => esc_html__( 'Add new Exchange request', 'astra' ), 'new_item' => esc_html__( 'New Exchange request', 'astra' ), 'edit_item' => esc_html__( 'Manage Exchange request', 'astra' ), 'view_item' => esc_html__( 'View Exchange request', 'astra' ), 'all_items' => esc_html__( 'All Exchange requests', 'astra' ), 'search_items' => esc_html__( 'Search Exchange requests', 'astra' ), 'parent_item_colon' => esc_html__( 'Parent Exchange requests:', 'astra' ), 'not_found' => esc_html__( 'No Exchange request found.', 'astra' ), 'not_found_in_trash' => esc_html__( 'No Exchange requests found in Trash.', 'astra' ) ); $exchange_args = array( 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => false, 'show_in_admin_bar' => false, 'menu_position' => 59, 'can_export' => false, 'has_archive' => true, 'exclude_from_search' => true, 'menu_icon' => 'dashicons-share-alt2', 'query_var' => false, 'labels' => $exchange_labels, 'description' => esc_html__( 'Description.', 'astra' ), 'publicly_queryable' => true, 'capability_type' => 'post', 'capabilities' => array( 'create_posts' => 'do_not_allow' ), 'map_meta_cap' => true, 'supports' => array( 'title' ) ); register_post_type( SOFTOBA_RETURN_POST_TYPE, $args ); register_post_type( SOFTOBA_EXCHANGE_POST_TYPE, $exchange_args ); } public function softoba_init_post_statuses() { register_post_status( 'softoba-new', array( 'label' => esc_html__( 'New Return request', 'astra' ), 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( esc_html__( 'New', 'astra' ) . ' (%s)', esc_html__( 'New', 'astra' ) . ' (%s)' ), ) ); register_post_status( 'softoba-processing', array( 'label' => esc_html__( 'Processing Return request', 'astra' ), 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( esc_html__( 'Processing', 'astra' ) . ' (%s)', esc_html__( 'Processing', 'astra' ) . ' (%s)' ), )); register_post_status( 'softoba-on-hold', array( 'label' => esc_html__( 'Return request on hold', 'astra' ), 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( esc_html__( 'On Hold', 'astra' ) . ' (%s)', esc_html__( 'On Hold', 'astra' ) . ' (%s)' ), )); register_post_status( 'softoba-approved', array( 'label' => esc_html__( 'Return request approved', 'astra' ), 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( esc_html__( 'Approved', 'astra' ) . ' (%s)', esc_html__( 'Approved', 'astra' ) . ' (%s)' ), )); register_post_status( 'softoba-rejected', array( 'label' => esc_html__( 'Return request rejected', 'astra' ), 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( esc_html__( 'Rejected', 'astra' ) . ' (%s)', esc_html__( 'Rejected', 'astra' ) . ' (%s)' ), )); register_post_status('wc-softoba-exchange-approve', array( 'label' => 'Exchange Approved', 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop('Exchange Approved (%s)', 'Exchange Approved (%s)'), )); // register_post_status('wc-softoba-exchange-request', array( // 'label' => 'Exchange Requested', // 'public' => true, // 'exclude_from_search' => false, // 'show_in_admin_all_list' => true, // 'show_in_admin_status_list' => true, // 'label_count' => _n_noop('Exchange Requested (%s)', 'Exchange Requested (%s)') // )); } // Remove view link for custom post type 'return_request' public function softoba_remove_return_request_view_link($actions, $post) { if ( $post->post_type === SOFTOBA_RETURN_POST_TYPE ) { unset($actions['view']); unset($actions['inline hide-if-no-js']); }elseif( $post->post_type === SOFTOBA_EXCHANGE_POST_TYPE ){ unset($actions['view']); unset($actions['inline hide-if-no-js']); } return $actions; } public function add_cpt_columns( $posts_columns ) { unset( $posts_columns['title'] ); unset( $posts_columns['date'] ); $posts_columns['title'] = esc_html__( 'Title', 'astra' ); $posts_columns['order'] = esc_html__( 'Order', 'astra' ); $posts_columns['customer'] = esc_html__( 'Customer', 'astra' ); $posts_columns['product'] = esc_html__( 'Product', 'astra' ); $posts_columns['date'] = esc_html__( 'Date', 'astra' ); return $posts_columns; } public function add_cpt_columns_content( $column_name, $post_id ) { if ( ! $post_id ) { return; } $request = new SOFTOBA_Return_Request( $post_id ); if ( ! $request->exists() ) { return; } if ( $column_name == 'order') { if ( $request->order_id ) { $order_number = wc_get_order( $request->order_id )->get_order_number(); echo '' . '#' . $order_number . ''; } } if ( $column_name == 'product') { if ( $request->products_data ) { foreach( $request->products_data['products'] as $ex_product) { $product = wc_get_product( $ex_product['product_id'] ); $id = softoba_get_base_product_id( $product ); if ( $product && $product->exists() ) { echo '' . $product->get_formatted_name() . ' -- '; } else { echo '' . esc_html__( 'N/A', 'astra' ) . ''; } } } } if ( $column_name == 'customer') { if ( $request->customer_id ) { echo version_compare( WC()->version, '3.0.0', '<' ) ? $request->get_customer_link_legacy() : $request->get_customer_link(); } } } public function add_exchange_cpt_columns( $posts_columns ) { unset( $posts_columns['title'] ); unset( $posts_columns['date'] ); $posts_columns['title'] = esc_html__( 'Title', 'astra' ); $posts_columns['exchange_fee'] = esc_html__( 'Exchange Fee', 'astra' ); $posts_columns['order'] = esc_html__( 'Order', 'astra' ); $posts_columns['customer'] = esc_html__( 'Customer', 'astra' ); $posts_columns['product'] = esc_html__( 'Product', 'astra' ); $posts_columns['date'] = esc_html__( 'Date', 'astra' ); return $posts_columns; } public function add_exchange_cpt_columns_content( $column_name, $post_id ) { if ( ! $post_id ) { return; } $request = new SOFTOBA_Exchange_Request( $post_id ); if ( ! $request->exists() ) { return; } if( $column_name == 'exchange_fee' ) { if( $request->exchange_fee === 'on-hold' ) { echo 'On hold'; }elseif( $request->exchange_fee === 'processing' || $request->exchange_fee === 'completed' ){ echo 'Paid'; }else{ echo 'Unpaid'; } } if ( $column_name == 'order') { if ( $request->order_id ) { $order_number = wc_get_order( $request->order_id )->get_order_number(); echo '' . '#' . $order_number . ''; } } if ( $column_name == 'product') { if ( $request->products_data ) { foreach( $request->products_data['products'] as $ex_product) { $product = wc_get_product( $ex_product['product_id'] ); $id = softoba_get_base_product_id( $product ); if ( $product && $product->exists() ) { echo '' . $product->get_formatted_name() . ' -- '; } else { echo '' . esc_html__( 'N/A', 'astra' ) . ''; } } } } if ( $column_name == 'customer') { if ( $request->customer_id ) { echo version_compare( WC()->version, '3.0.0', '<' ) ? $request->get_customer_link_legacy() : $request->get_customer_link(); } } } public function manage_meta_boxes( $post_type, $post ) { if ( $post_type && SOFTOBA_RETURN_POST_TYPE == $post_type ) { remove_meta_box( 'submitdiv', SOFTOBA_RETURN_POST_TYPE, 'side' ); add_meta_box( 'softoba-info-metabox', esc_html__( 'Request info', 'astra' ), array( $this, 'softoba_info_metabox_content' ), SOFTOBA_RETURN_POST_TYPE, 'side', 'core' ); add_meta_box( 'softoba-items-metabox', esc_html__( 'Items', 'astra' ), array( $this, 'softoba_items_metabox_content' ), SOFTOBA_RETURN_POST_TYPE, 'normal', 'core' ); } if ( $post_type && $post && 'shop_order' == $post_type ) { $order = wc_get_order( $post ); $requests = softoba_get_prop( $order, 'softoba_return_requests', true ); if ( $requests ) { add_meta_box( 'softoba-manage-return-requests', esc_html__( 'Return Request', 'astra' ), array( $this, 'softoba_manage_return_requests_content' ), 'shop_order', 'side', 'core' ); } } } /** * Exchange Post type metaboxes * * @param [SOFTOBA_EXCHANGE_POST_TYPE] $post_type * @param [type] $post * @return void */ public function manage_exchange_meta_boxes( $post_type, $post ) { if ( $post_type && SOFTOBA_EXCHANGE_POST_TYPE == $post_type ) { remove_meta_box( 'submitdiv', SOFTOBA_EXCHANGE_POST_TYPE, 'side' ); add_meta_box( 'softoba-info-metabox', esc_html__( 'Request info', 'astra' ), array( $this, 'softoba_exchange_info_metabox_content' ), SOFTOBA_EXCHANGE_POST_TYPE, 'side', 'core' ); add_meta_box( 'softoba-items-metabox', esc_html__( 'Items', 'astra' ), array( $this, 'softoba_exchange_items_metabox_content' ), SOFTOBA_EXCHANGE_POST_TYPE, 'normal', 'core' ); } if ( $post_type && $post && 'shop_order' == $post_type ) { $order = wc_get_order( $post ); $requests = softoba_get_prop( $order, 'softoba_exchange_requests', true ); if ( $requests ) { // add_meta_box( 'softoba-manage-exchange-requests', // esc_html__( 'Exchange Request', 'astra' ), // array( $this, 'softoba_manage_exchange_requests_content' ), 'shop_order', 'side', 'core' // ); } } } public function softoba_items_metabox_content( $post ) { if ( ! $post ) { return; } wc_get_template( 'admin/softoba-items-table.php', array( 'post' => $post ), '', SOFTOBA_TEMPLATE_PATH . '/' ); } public function softoba_exchange_items_metabox_content( $post ) { if ( ! $post ) { return; } wc_get_template( 'admin/softoba-exchange-items-table.php', array( 'post' => $post ), '', SOFTOBA_TEMPLATE_PATH . '/' ); } public function softoba_info_metabox_content( $post ) { if ( ! $post ) { return; } $request = new SOFTOBA_Return_Request( $post->ID ); if ( ! ( $request instanceof SOFTOBA_Return_Request && $request->exists() ) ) { return; } ?>
post_status ); ?>
version, '3.0.0', '<' ) ? $request->get_customer_link_legacy() : $request->get_customer_link(); ?>
get_date() ); ?>
ID ); if ( ! ( $request instanceof SOFTOBA_Exchange_Request && $request->exists() ) ) { return; } ?>
post_status ); ?>
version, '3.0.0', '<' ) ? $request->get_customer_link_legacy() : $request->get_customer_link(); ?>
exchange_fee === 'on-hold' ) { echo 'On hold'; }elseif( $request->exchange_fee === 'processing' || $request->exchange_fee === 'completed' ){ echo 'Paid'; }else{ echo 'Unpaid'; } ?>
get_date() ); ?>
process_requests_array( $requests, $action ); } public function register_email_classes( $email_classes ) { $email_classes['SOFTOBA_New_Return_Admin_Email'] = include( OB_THEME_CLASSES . '/emails/softoba_return_request_admin_email.php' ); $email_classes['SOFTOBA_New_Return_User_Email'] = include( OB_THEME_CLASSES . '/emails/softoba_return_request_user_email.php' ); $email_classes['SOFTOBA_New_Exchange_Admin_Email'] = include( OB_THEME_CLASSES . '/emails/softoba_exchange_request_admin_email.php' ); $email_classes['SOFTOBA_New_Exchange_User_Email'] = include( OB_THEME_CLASSES . '/emails/softoba_exchange_request_user_email.php' ); return $email_classes; } // Process a given array of SOFTOBA_Return_Request IDs in order to set them Approved or Rejected public function process_requests_array( $requests, $action ) { foreach ( $requests as $request_id ) { $request = new SOFTOBA_Return_Request( $request_id ); if ( ! $request->exists() ) continue; if ( $request->status == 'softoba-approved' || $request->status == 'softoba-rejected' ) continue; if ( $action == 'softoba-set-approved' ) // do_action( 'softoba_process_automatic_request', $request->ID ); $request->set_approved(); if ( $action == 'softoba-set-rejected' ) $request->set_rejected(); } } public function process_automatic_request( $request_id ) { $request = new SOFTOBA_Return_Request( $request_id ); if ( ! $request->exists() ) { return; } $open_request = apply_filters( 'softoba_open_request', ( 'softoba-approved' != $request->status && 'softoba-rejected' != $request->status && 'trash' != $request->status ), $request ); if ( ! $open_request ) { return; } $request_is_whole_order = $request->whole_order; $order_id = $request->order_id; $order = wc_get_order( $order_id ); $order_items = $order->get_items(); $payment_gateway = wc_get_payment_gateway_by_order( $order ); $supports_refunds = false !== $payment_gateway && $payment_gateway->supports( 'refunds' ); $refund_reason = esc_html__( 'Automatic refund', 'astra' ); $api_refund = !! $supports_refunds; $restock_refunded_items = !! ( 'yes' == get_option( 'yith_wcars_restock_items', 'no' ) ); $refund = false; $response_data = array(); $line_item_qtys = array(); $line_item_totals = array(); $line_item_tax_totals = array(); if ( $request_is_whole_order ) { foreach ( $order_items as $item_id => $item ) { if ( 'line_item' != $item['type'] ) { continue; } $line_item_qtys[ $item_id ] = $item['qty']; $line_item_totals[ $item_id ] = $item['line_total']; if ( ! wc_tax_enabled() ) { continue; } $tax_data = maybe_unserialize( isset( $item['line_tax_data'] ) ? $item['line_tax_data'] : '' ); if ( $tax_data && isset( $tax_data['total'] ) ) { $line_item_tax_totals[ $item_id ] = $tax_data['total']; } } $refund_amount = wc_format_decimal( sanitize_text_field( $request->refund_total ), wc_get_price_decimals() ); } else { $line_item_qtys[ $request->item_id ] = $request->qty; $line_item_totals[ $request->item_id ] = $request->item_refund_total; if ( wc_tax_enabled() ) { $line_item_tax_totals[ $request->item_id ] = $request->item_tax_data; } $taxes_sum = 0; foreach ( $request->item_tax_data as $tax ) { $taxes_sum += (int) $tax; } $refund_amount = wc_format_decimal( sanitize_text_field( $request->refund_total ), wc_get_price_decimals() ); } try { // Validate that the refund can occur $max_refund = wc_format_decimal( $order->get_total() - $order->get_total_refunded(), wc_get_price_decimals() ); if ( ! $refund_amount || $max_refund < $refund_amount || 0 > $refund_amount ) { throw new exception( esc_html__( 'Invalid refund amount', 'astra' ) ); } // Prepare line items which we are refunding $line_items = array(); $item_ids = array_unique( array_merge( array_keys( $line_item_qtys, $line_item_totals ) ) ); foreach ( $item_ids as $item_id ) { $line_items[ $item_id ] = array( 'qty' => 0, 'refund_total' => 0, 'refund_tax' => array() ); } foreach ( $line_item_qtys as $item_id => $qty ) { $line_items[ $item_id ]['qty'] = max( $qty, 0 ); } foreach ( $line_item_totals as $item_id => $total ) { $line_items[ $item_id ]['refund_total'] = wc_format_decimal( $total ); } foreach ( $line_item_tax_totals as $item_id => $tax_totals ) { $line_items[ $item_id ]['refund_tax'] = array_map( 'wc_format_decimal', $tax_totals ); } if ( version_compare( WC()->version, '3.0.0', '<' ) ) { // Create the refund object $refund = wc_create_refund( array( 'amount' => $refund_amount, 'reason' => $refund_reason, 'order_id' => $order_id, 'line_items' => $line_items, ) ); } else { $refund = wc_create_refund( array( 'amount' => $refund_amount, 'reason' => $refund_reason, 'order_id' => $order_id, 'line_items' => $line_items, 'refund_payment' => $api_refund, 'restock_items' => $restock_refunded_items, ) ); } if ( is_wp_error( $refund ) ) { throw new Exception( $refund->get_error_message() ); } if ( version_compare( WC()->version, '3.0.0', '<' ) ) { // Refund via API if ( $api_refund ) { if ( WC()->payment_gateways() ) { $payment_gateways = WC()->payment_gateways->payment_gateways(); } if ( isset( $payment_gateways[ $order->payment_method ] ) && $payment_gateways[ $order->payment_method ]->supports( 'refunds' ) ) { $result = $payment_gateways[ $order->payment_method ]->process_refund( $order_id, $refund_amount, $refund_reason ); do_action( 'woocommerce_refund_processed', $refund, $result ); if ( is_wp_error( $result ) ) { throw new Exception( $result->get_error_message() ); } elseif ( ! $result ) { throw new Exception( esc_html__( 'Refund failed', 'astra' ) ); } } } // restock items foreach ( $line_item_qtys as $item_id => $qty ) { if ( $restock_refunded_items && $qty && isset( $order_items[ $item_id ] ) ) { $order_item = $order_items[ $item_id ]; $_product = $order->get_product_from_item( $order_item ); if ( $_product && $_product->exists() && $_product->managing_stock() ) { $old_stock = wc_stock_amount( $_product->stock ); $new_quantity = $_product->increase_stock( $qty ); $order->add_order_note( sprintf( esc_html__( 'Item #%s stock increased from %s to %s.', 'astra' ), $order_item['product_id'], $old_stock, $new_quantity ) ); do_action( 'woocommerce_restock_refunded_item', $_product->id, $old_stock, $new_quantity, $order, $_product ); } } } // Trigger notifications and status changes if ( $order->get_remaining_refund_amount() > 0 || ( $order->has_free_item() && $order->get_remaining_refund_items() > 0 ) ) { /** * woocommerce_order_partially_refunded. * * @since 2.4.0 * Note: 3rd arg was added in err. Kept for bw compat. 2.4.3. */ do_action( 'woocommerce_order_partially_refunded', $order_id, $refund->id, $refund->id ); } else { do_action( 'woocommerce_order_fully_refunded', $order_id, $refund->id ); $order->update_status( apply_filters( 'woocommerce_order_fully_refunded_status', 'refunded', $order_id, $refund->id ) ); $response_data['status'] = 'fully_refunded'; } // Clear transients wc_delete_shop_order_transients( $order_id ); } else { if ( did_action( 'woocommerce_order_fully_refunded' ) ) { $response_data['status'] = 'fully_refunded'; } } $refund_id = version_compare( WC()->version, '3.0.0', '<' ) ? $refund->id : $refund->get_id(); $this->process_refund( $request_id, $refund_id, $order_id ); } catch ( Exception $e ) { if ( $refund && is_a( $refund, 'WC_Order_Refund' ) ) { $refund_id = version_compare( WC()->version, '3.0.0', '<' ) ? $refund->id : $refund->get_id(); wp_delete_post( $refund_id, true ); } } } public function process_refund( $softoba_request_id, $refund_id, $order_id ) { $request = new SOFTOBA_Return_Request( $softoba_request_id ); if ( ! ( $request instanceof SOFTOBA_Return_Request && $request->exists() ) ) { return; } $refund = new WC_Order_Refund( $refund_id ); $order = wc_get_order( $order_id ); $amount = version_compare( WC()->version, '3.0.0', '<' ) ? $refund->get_refund_amount() : $refund->get_amount(); $order_refunds = yit_get_prop( $order, '_order_softoba_refunds', true ); if ( ! empty( $order_refunds ) && is_array( $order_refunds ) ) { $order_refunds[] = array( 'wc_refund_id' => $refund_id, 'softoba_request_id' => $request->ID, 'amount' => $amount ); } else { $order_refunds = array( array( 'wc_refund_id' => $refund_id, 'softoba_request_id' => $request->ID, 'amount' => $amount ) ); } // Save metas yit_save_prop( $order, '_order_softoba_refunds', $order_refunds ); yit_save_prop( $refund, '_softoba_refund', 'yes' ); $request->refund_id = $refund_id; $request->refunded_amount = $amount; // Save order item metas if ( $request->whole_order ) { $items = $order->get_items(); foreach ( $items as $item_id => $item ) { wc_update_order_item_meta( $item_id, '_softoba_item_refunded', 'yes' ); } } else { wc_update_order_item_meta( $request->item_id, '_softoba_item_refunded', 'yes' ); } $request->set_approved(); } } }