![]() Server : Apache/2.4.52 (Ubuntu) System : Linux webserver 6.8.0-49-generic #49~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Nov 6 17:42:15 UTC 2 x86_64 User : www-data ( 33) PHP Version : 8.1.2-1ubuntu2.21 Disable Function : NONE Directory : /var/www/theprintave/wp-content/plugins/dokan-lite/includes/ReverseWithdrawal/ |
<?php namespace WeDevs\Dokan\ReverseWithdrawal; use WeDevs\Dokan\Cache; use WP_Error; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Database Manager Class * * @since 3.5.1 * * @class Manager * * @package WeDevs\Dokan\ReverseWithdrawal */ class Manager { /** * Table name for dokan_reverse_withdrawal table * * @var string * * @since 3.5.1 */ private $table; /** * Manager constructor. * * @since 3.5.1 */ public function __construct() { global $wpdb; $this->table = "{$wpdb->prefix}dokan_reverse_withdrawal"; } /** * This method will return data from dokan_reverse_withdrawal table * * @since 3.5.1 * * @param array $args * * @return array|int|WP_Error */ public function all( $args = [] ) { $default = [ 'id' => [], 'vendor_id' => [], // array of integers 'trn_id' => [], // array of integers 'trn_type' => [], // array of strings, possible values are: 'trn_date' => [ 'from' => '', 'to' => '', ], 'orderby' => 'added', 'order' => 'DESC', 'return' => 'balance', // possible values are vendor_transaction, vendor_transaction_count, balance, balance_count 'per_page' => 20, 'page' => 1, ]; $args = wp_parse_args( $args, $default ); global $wpdb; $fields = ''; $join = ''; $where = ''; $groupby = ''; $orderby = ''; $limits = ''; $query_args = [ 1, 1 ]; // determine which fields to return if ( in_array( $args['return'], [ 'vendor_transaction' ], true ) ) { $fields = 'trn.*'; } elseif ( in_array( $args['return'], [ 'count' ], true ) ) { $fields = 'COUNT(trn.id) AS count'; } elseif ( in_array( $args['return'], [ 'balance_count', 'vendor_transaction_count' ], true ) ) { $fields = 'COUNT(trn.id) AS total_transactions, SUM(trn.debit) AS debit, SUM(trn.credit) AS credit'; $fields .= 'balance_count' === $args['return'] ? ', COUNT( distinct vendor_id) AS total_vendors' : ''; } elseif ( 'balance' === $args['return'] ) { $fields = 'trn.vendor_id, SUM(trn.debit) AS debit, SUM(trn.credit) AS credit'; $fields .= ", (SELECT MAX(trn2.trn_date) AS last_transaction_date FROM {$this->table} As trn2 WHERE trn.vendor_id = trn2.vendor_id AND trn2.trn_type='vendor_payment') AS last_payment_date"; $fields .= ', u_meta.meta_value as store_name'; // join user meta table $join .= " LEFT JOIN {$wpdb->usermeta} AS u_meta ON trn.vendor_id = u_meta.user_id"; // include dokan_store_name under where param $where .= ' AND u_meta.meta_key=%s'; $query_args[] = 'dokan_store_name'; $groupby = 'GROUP BY trn.vendor_id'; // reset trn_date from if ( isset( $args['trn_date']['from'] ) ) { $args['trn_date']['from'] = ''; } } // check if id filter is applied if ( ! $this->is_empty( $args['id'] ) ) { $transaction_ids = implode( "','", array_map( 'absint', (array) $args['id'] ) ); $where .= " AND trn.id IN ('$transaction_ids')"; } // check if vendor id filter is applied if ( ! $this->is_empty( $args['trn_id'] ) ) { $trn_id = implode( "','", array_map( 'absint', (array) $args['trn_id'] ) ); $where .= " AND trn.trn_id IN ('$trn_id')"; } // check if vendor id filter is applied if ( ! $this->is_empty( $args['vendor_id'] ) ) { $vendor_id = implode( "','", array_map( 'absint', (array) $args['vendor_id'] ) ); $where .= " AND trn.vendor_id IN ('$vendor_id')"; } // transaction type validation if ( ! empty( $args['trn_type'] ) && array_key_exists( $args['trn_type'], Helper::get_transaction_types() ) ) { $where .= ' AND trn.trn_type = %s'; $query_args[] = $args['trn_type']; } // check if trn_date filter is applied // convert into timestamp $now = dokan_current_datetime(); if ( ! empty( $args['trn_date']['from'] ) ) { // fix date format if ( is_numeric( $args['trn_date']['from'] ) ) { $now = $now->setTimestamp( $args['trn_date']['from'] ); $args['trn_date']['from'] = $now ? $now->getTimestamp() : 0; } else { $now = $now->modify( $args['trn_date']['from'] ); $args['trn_date']['from'] = $now ? $now->setTime( 0, 0, 0 )->getTimestamp() : 0; } } // convert into timestamp if ( ! empty( $args['trn_date']['to'] ) ) { if ( is_numeric( $args['trn_date']['to'] ) ) { $now = $now->setTimestamp( $args['trn_date']['to'] ); $args['trn_date']['to'] = $now ? $now->getTimestamp() : 0; } else { $now = $now->modify( $args['trn_date']['to'] ); $args['trn_date']['to'] = $now ? $now->setTime( 23, 59, 59 )->getTimestamp() : 0; } } // check if min and max both values are set, search in between if ( ! empty( $args['trn_date']['from'] ) && ! empty( $args['trn_date']['to'] ) ) { // fix min max value if ( $args['trn_date']['from'] > $args['trn_date']['to'] ) { $temp = $args['trn_date']['from']; $args['trn_date']['from'] = $args['trn_date']['to']; $args['trn_date']['to'] = $temp; } $where .= ' AND trn.trn_date BETWEEN %d AND %d'; $query_args[] = $args['trn_date']['from']; $query_args[] = $args['trn_date']['to']; } elseif ( ! empty( $args['trn_date']['to'] ) ) { $where .= ' AND trn.trn_date <= %d'; $query_args[] = $args['trn_date']['to']; } elseif ( ! empty( $args['trn_date']['from'] ) ) { $where .= ' AND trn.trn_date >= %d'; $query_args[] = $args['trn_date']['from']; } // order and order by param // supported order by param $supported_order_by = [ 'id' => 'trn.id', 'trn_date' => 'trn.trn_date', 'debit' => 'trn.debit', 'credit' => 'trn.credit', ]; if ( ! empty( $args['orderby'] ) && array_key_exists( $args['orderby'], $supported_order_by ) ) { $order = in_array( strtolower( $args['order'] ), [ 'asc', 'desc' ], true ) ? strtoupper( $args['order'] ) : 'ASC'; $orderby = "ORDER BY {$supported_order_by[ $args['orderby'] ]} {$order}"; //no need for prepare, we've already whitelisted the parameters //second order by in case of similar value on first order by field if ( 'id' !== $args['orderby'] ) { $orderby .= ", trn.id {$order}"; } } // pagination param if ( ! empty( $args['per_page'] ) && -1 !== intval( $args['per_page'] ) && ! in_array( $args['return'], [ 'count', 'balance_count', 'vendor_transaction_count' ], true ) ) { $limit = absint( $args['per_page'] ); $page = absint( $args['page'] ); $page = $page > 0 ? $page : 1; $offset = ( $page - 1 ) * $limit; $limits = 'LIMIT %d, %d'; $query_args[] = $offset; $query_args[] = $limit; } $cache_group = 'reverse_withdrawal'; $cache_key = 'get_transactions_' . md5( wp_json_encode( $args ) ); if ( is_numeric( $args['vendor_id'] ) ) { $cache_group = "reverse_withdrawal_{$args['vendor_id']}"; } elseif ( ! $this->is_empty( $args['vendor_id'] ) && 1 === count( $args['vendor_id'] ) ) { $cache_group = "reverse_withdrawal_{$args['vendor_id'][0]}"; } $data = Cache::get( $cache_key, $cache_group ); if ( in_array( $args['return'], [ 'vendor_transaction' ], true ) && false === $data ) { // get all transactions of vendor(s) // @codingStandardsIgnoreStart $data = $wpdb->get_results( $wpdb->prepare( "SELECT $fields FROM {$this->table} AS trn $join WHERE %d=%d $where $orderby $limits", $query_args ), ARRAY_A ); // @codingStandardsIgnoreEnd // check for query error if ( ! empty( $wpdb->last_error ) ) { return new WP_Error( 'db_query_error', $wpdb->last_error, $wpdb->last_query ); } // if per_page is 1, send single item if ( 1 === $args['per_page'] ) { $data = is_array( $data ) && ! empty( $data ) ? $data[0] : []; } // store on cache Cache::set( $cache_key, $data, $cache_group ); } elseif ( 'count' === $args['return'] && false === $data ) { // get count of entries // @codingStandardsIgnoreStart $data = (int) $wpdb->get_var( $wpdb->prepare( "SELECT $fields FROM {$this->table} AS trn $join WHERE %d=%d $where", $query_args ) ); // @codingStandardsIgnoreEnd Cache::set( $cache_key, $data, $cache_group ); } elseif ( in_array( $args['return'], [ 'balance_count', 'vendor_transaction_count' ], true ) && false === $data ) { // @codingStandardsIgnoreStart $row = $wpdb->get_row( $wpdb->prepare( "SELECT $fields FROM {$this->table} AS trn $join WHERE %d=%d $where", $query_args ) ); $refund_amount = (float) $wpdb->get_var( $wpdb->prepare( "SELECT SUM(trn.credit) FROM {$this->table} AS trn $join WHERE %d=%d $where AND trn.trn_type='order_refund'", $query_args ) ); // check for query error if ( ! empty( $wpdb->last_error ) ) { return new WP_Error( 'db_query_error', $wpdb->last_error, $wpdb->last_query ); } $data = [ 'total_transactions' => (int) $row->total_transactions, 'debit' => (float) $row->debit, 'credit' => (float) $row->credit - $refund_amount, ]; if ( 'balance_count' === $args['return'] ) { $data['total_vendors'] = (int) $row->total_vendors; $data['balance'] = (float) $row->debit - (float) $row->credit; } // @codingStandardsIgnoreEnd Cache::set( $cache_key, $data, $cache_group ); } elseif ( 'balance' === $args['return'] && false === $data ) { // @codingStandardsIgnoreStart $data = $wpdb->get_results( $wpdb->prepare( "SELECT $fields FROM {$this->table} AS trn $join WHERE %d=%d $where $groupby $orderby $limits", $query_args ), ARRAY_A ); // @codingStandardsIgnoreEnd // check for query error if ( ! empty( $wpdb->last_error ) ) { return new WP_Error( 'db_query_error', $wpdb->last_error, $wpdb->last_query ); } // if per_page is 1, send single item if ( 1 === (int) $args['per_page'] ) { $data = is_array( $data ) && ! empty( $data ) ? $data[0] : []; } // store on cache Cache::set( $cache_key, $data, $cache_group ); } return $data; } /** * This method will get all/selected vendors balance * * @since 3.5.1 * * @param array $args * * @return array|WP_Error */ public function get_stores_balance( $args = [] ) { $query_params = [ 'vendor_id' => isset( $args['vendor_id'] ) ? $args['vendor_id'] : 0, 'trn_date' => isset( $args['trn_date'] ) ? $args['trn_date'] : '', 'per_page' => isset( $args['per_page'] ) ? $args['per_page'] : -1, 'page' => isset( $args['page'] ) ? $args['page'] : 1, 'orderby' => isset( $args['orderby'] ) ? $args['orderby'] : 'id', 'order' => isset( $args['order'] ) ? $args['order'] : 'DESC', ]; $items = []; // get item count $query_params['return'] = 'balance_count'; $count = $this->all( $query_params ); // check for errors if ( is_wp_error( $count ) ) { return $count; } // only run query if count value is greater than 0 if ( $count['total_transactions'] > 0 ) { $query_params['return'] = 'balance'; $items = $this->all( $query_params ); // check for errors if ( is_wp_error( $items ) ) { return $items; } } return [ 'count' => $count, 'items' => $items, ]; } /** * This method will return current balance of a vendor * * @since 3.5.1 * * @param array $args * * @return float|WP_Error */ public function get_store_balance( $args = [] ) { $query_params = [ 'vendor_id' => isset( $args['vendor_id'] ) ? $args['vendor_id'] : 0, 'trn_date' => isset( $args['trn_date'] ) && ! $this->is_empty( $args['trn_date'] ) ? $args['trn_date'] : '', 'per_page' => 1, 'return' => 'balance', ]; if ( empty( $query_params['vendor_id'] ) || ! is_numeric( $query_params['vendor_id'] ) ) { return new WP_Error( 'invalid_vendor_id', esc_html__( 'No vendor id provided', 'dokan-lite' ) ); } $balance = $this->all( $query_params ); if ( is_wp_error( $balance ) ) { return $balance; } return isset( $balance['debit'], $balance['credit'] ) ? floatval( $balance['debit'] - $balance['credit'] ) : 0; } /** * This method will get all the transactions for a vendor * * @since 3.5.1 * * @param array $args * * @return array|WP_Error */ public function get_store_transactions( $args = [] ) { $default_transactions_date = [ 'from' => dokan_current_datetime()->modify( '-1 month' )->format( 'Y-m-d' ), 'to' => dokan_current_datetime()->format( 'Y-m-d' ), ]; $query_params = [ 'vendor_id' => isset( $args['vendor_id'] ) ? $args['vendor_id'] : 0, 'trn_date' => isset( $args['trn_date'] ) && ! $this->is_empty( $args['trn_date'] ) ? $args['trn_date'] : $default_transactions_date, 'per_page' => isset( $args['per_page'] ) ? $args['per_page'] : -1, 'page' => isset( $args['page'] ) ? $args['page'] : 1, 'orderby' => 'id', 'order' => 'ASC', ]; if ( empty( $query_params['vendor_id'] ) || ! is_numeric( $query_params['vendor_id'] ) ) { return new WP_Error( 'invalid_vendor_id', esc_html__( 'No vendor id provided', 'dokan-lite' ) ); } $return = [ 'balance' => [], 'count' => [], 'items' => [], ]; // get balance date if ( ! empty( $query_params['trn_date']['from'] ) ) { $one_day_before = dokan_current_datetime()->modify( $query_params['trn_date']['from'] )->setTime( 0, 0, 0 )->getTimestamp(); } else { // get balance for 1 day before start date $one_day_before = dokan_current_datetime()->setTime( 0, 0, 0 )->getTimestamp(); } $balance_args = [ 'vendor_id' => $query_params['vendor_id'], 'trn_date' => [ 'to' => $one_day_before, ], 'return' => 'balance', 'per_page' => 1, ]; // we are getting opening balance here $balance = $this->all( $balance_args ); if ( is_wp_error( $balance ) ) { return $balance; } // prepare formatted balance $balance['trn_type'] = 'opening_balance'; $balance['trn_date'] = $one_day_before; $balance['vendor_id'] = isset( $balance['vendor_id'] ) ? absint( $balance['vendor_id'] ) : 0; // set balance $return['balance'] = $balance; // get item count $query_params['return'] = 'vendor_transaction_count'; $count = $this->all( $query_params ); // check for errors if ( is_wp_error( $count ) ) { return $count; } $return['count'] = $count; // only run query if count value is greater than 0 if ( $count['total_transactions'] === 0 ) { return $return; } $query_params['return'] = 'vendor_transaction'; $items = $this->all( $query_params ); // check for errors if ( is_wp_error( $items ) ) { return $items; } $return['items'] = $items; return $return; } /** * This method will return a single item from reverse withdrawal table * * @since 3.5.1 * * @param int $id * * @return WP_Error|array */ public function get( $id = 0 ) { $args = [ 'id' => $id, 'per_page' => 1, 'return' => 'all', ]; $data = $this->all( $args ); if ( empty( $data ) ) { return new WP_Error( 'get_reverse_withdrawal_error', esc_html__( 'No reverse withdrawal data found with given id.', 'dokan-lite' ) ); } return $data; } /** * Insert a new item into database. * * @since 3.5.1 * * @param array $args * * @return int|WP_Error */ public function insert( $args = [] ) { global $wpdb; $default = [ 'trn_id' => 0, 'trn_type' => 'order_commission', 'vendor_id' => 0, 'note' => '', 'debit' => 0, 'credit' => 0, 'trn_date' => time(), ]; $args = wp_parse_args( $args, $default ); // validate required fields if ( isset( $args['trn_id'] ) && ! is_numeric( $args['trn_id'] ) ) { return new WP_Error( 'insert_rw_invalid_transaction_id', esc_html__( 'Transaction id is required.', 'dokan-lite' ) ); } if ( empty( $args['trn_type'] ) || ! array_key_exists( $args['trn_type'], Helper::get_transaction_types() ) ) { return new WP_Error( 'insert_rw_invalid_transaction_type', esc_html__( 'Invalid transaction type is provide. Please check your input.', 'dokan-lite' ) ); } if ( empty( $args['vendor_id'] ) ) { return new WP_Error( 'insert_rw_invalid_vendor_id', esc_html__( 'Invalid vendor id provide. Please provide a valid vendor id.', 'dokan-lite' ) ); } // just to make sure $args doesn't contain any unnecessary elements $data = [ 'trn_id' => $args['trn_id'], 'trn_type' => $args['trn_type'], 'vendor_id' => $args['vendor_id'], 'note' => $args['note'], 'debit' => $args['debit'], 'credit' => $args['credit'], 'trn_date' => $args['trn_date'], ]; $format = [ '%d', '%s', '%d', '%s', '%f', '%f', '%d', ]; // add data into database $inserted = $wpdb->insert( $this->get_table(), $data, $format ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $insert_id = $wpdb->insert_id; if ( false === $inserted ) { dokan_log( '[Dokan Reverse Withdrawal] Error while inserting data: <strong>' . $wpdb->last_error . '</strong>, Data: ' . print_r( $data, true ) ); return new WP_Error( 'insert_reverse_withdrawal_error', esc_html__( 'Something went wrong while inserting reverse withdrawal data. Please contact site admin.', 'dokan-lite' ) ); } do_action( 'dokan_reverse_withdrawal_created', $data, $insert_id, $args ); return $insert_id; } /** * Check if reverse withdrawal already inserted for an order * * @since 3.5.1 * * @param int $order_id * * @return bool */ public function is_reverse_withdrawal_added( $order_id ) { $args = [ 'trn_id' => $order_id, 'trn_type' => 'order_commission', 'return' => 'count', ]; $count = $this->all( $args ); return $count > 0; } /** * Check if reverse withdrawal payment already inserted for an order * * @since 3.5.1 * * @param int $order_id * * @return bool */ public function is_payment_inserted( $order_id ) { $args = [ 'trn_id' => $order_id, 'trn_type' => 'vendor_payment', 'return' => 'count', ]; $count = $this->all( $args ); return $count > 0; } /** * This method will return all refunded amount for a specific order * * @since 3.5.1 * * @param int $order_id * * @return float */ public function get_total_refunded_amount_by_order( $order_id ) { global $wpdb; //@codingStandardsIgnoreStart return (float) $wpdb->get_var( $wpdb->prepare( "SELECT SUM(credit) FROM {$this->get_table()} WHERE trn_id = %d AND trn_type = %s", $order_id, 'order_refund' ) ); //@codingStandardsIgnoreEnd } /** * This method will return all the payments made by a vendor in a date range * * @since 3.5.1 * * @param array $args * * @return WP_Error|float */ public function get_payments_by_vendor( $args = [] ) { $default = [ 'vendor_id' => dokan_get_current_user_id(), 'trn_date' => [ 'from' => dokan_current_datetime()->modify( 'first day of this month' )->format( 'Y-m-d' ), 'to' => dokan_current_datetime()->modify( 'last day of this month' )->format( 'Y-m-d' ), ], ]; $args = wp_parse_args( $args, $default ); // validate vendor id if ( empty( $args['vendor_id'] ) ) { return new WP_Error( 'get_payments_by_vendor_error', esc_html__( 'Invalid vendor id provide. Please provide a valid vendor id.', 'dokan-lite' ) ); } $params = [ 'vendor_id' => $args['vendor_id'], 'trn_date' => $args['trn_date'], 'trn_type' => 'vendor_payment', 'return' => 'vendor_transaction_count', ]; $result = $this->all( $params ); if ( is_wp_error( $result ) ) { return $result; } return $result['credit']; } /** * This method will return commission amount for a specific order * * @since 3.5.1 * * @param int $order_id * * @return float */ public function get_commission_amount_by_order( $order_id ) { global $wpdb; //@codingStandardsIgnoreStart return (float) $wpdb->get_var( $wpdb->prepare( "SELECT debit FROM {$this->get_table()} WHERE trn_id = %d AND trn_type = %s", $order_id, 'order_commission' ) ); //@codingStandardsIgnoreEnd } /** * This method will return unique stores under reverse withdrawal table * * @param array $args * * @since 3.5.1 * * @return array|WP_Error */ public function get_stores( $args = [] ) { $default = [ 'per_page' => 20, 'page' => 1, ]; $args = wp_parse_args( $args, $default ); global $wpdb; $fields = ' DISTINCT trn.vendor_id as id, u_meta.meta_value as name '; $join = " LEFT JOIN {$wpdb->usermeta} AS u_meta ON trn.vendor_id = u_meta.user_id"; $where = ' AND u_meta.meta_key=%s'; $groupby = ''; $orderby = ' ORDER BY name ASC'; $limits = ''; $query_args = [ 1, 1, 'dokan_store_name' ]; // prepare search parameter if ( ! empty( $args['search'] ) ) { $like = '%' . $wpdb->esc_like( $args['search'] ) . '%'; $where .= ' AND u_meta.meta_value like %s'; $query_args[] = $like; } if ( $args['per_page'] ) { $limit = absint( $args['per_page'] ); $page = absint( $args['page'] ); $page = $page ? $page : 1; $offset = ( $page - 1 ) * $limit; $limits = 'LIMIT %d, %d'; $query_args[] = $offset; $query_args[] = $limit; } // @codingStandardsIgnoreStart $data = $wpdb->get_results( $wpdb->prepare( "SELECT $fields FROM {$this->table} AS trn $join WHERE %d=%d $where $groupby $orderby $limits", //phpcs:ignore $query_args ), ARRAY_A ); // @codingStandardsIgnoreEnd // check for db error if ( ! empty( $wpdb->last_error ) ) { dokan_log( '[Dokan Reverse Withdrawal] Error while fetching data: <strong>' . $wpdb->last_error . '</strong>' ); return new WP_Error( 'db_query_error', $wpdb->last_error, $wpdb->last_query ); } return null === $data ? [] : $data; } /** * Get dokan_reverse_withdrawal table with prefix * * @since 3.5.1 * * @return string */ public function get_table() { return $this->table; } /** * This will check if given var is empty or not. * * @since 3.5.1 * * @param mixed $var * * @return bool */ protected function is_empty( $var ) { if ( empty( $var ) ) { return true; } if ( isset( $var[0] ) && intval( $var[0] ) === 0 ) { return true; } return false; } }