/**
 * Reduces earnings and sales stats when a purchase is refunded
 *
 * @since 1.8.2
 * @param $data Arguments passed
 * @return void
 */
function edd_undo_purchase_on_refund($payment_id, $new_status, $old_status)
{
    if ('publish' != $old_status && 'revoked' != $old_status) {
        return;
    }
    if ('refunded' != $new_status) {
        return;
    }
    $downloads = edd_get_payment_meta_cart_details($payment_id);
    if ($downloads) {
        foreach ($downloads as $download) {
            edd_undo_purchase($download['id'], $payment_id);
        }
    }
    // Decrease store earnings
    $amount = edd_get_payment_amount($payment_id);
    edd_decrease_total_earnings($amount);
    // Decrement the stats for the customer
    $customer_id = edd_get_payment_customer_id($payment_id);
    if ($customer_id) {
        $customer = new EDD_Customer($customer_id);
        $customer->decrease_value($amount);
        $customer->decrease_purchase_count();
    }
    // Clear the This Month earnings (this_monththis_month is NOT a typo)
    delete_transient(md5('edd_earnings_this_monththis_month'));
}
 /**
  * Decrements customer purchase stats
  *
  * @access  public
  * @since   2.1
  */
 public function decrement_stats($customer_id = 0, $amount = 0.0)
 {
     $customer = new EDD_Customer($customer_id);
     if (!$customer) {
         return false;
     }
     $decreased_count = $customer->decrease_purchase_count();
     $decreased_value = $customer->decrease_value($amount);
     return $decreased_count && $decreased_value ? true : false;
 }
/**
 * Process the payment details edit
 *
 * @access      private
 * @since       1.9
 * @return      void
*/
function edd_update_payment_details($data)
{
    if (!current_user_can('edit_shop_payments', $data['edd_payment_id'])) {
        wp_die(__('You do not have permission to edit this payment record', 'easy-digital-downloads'), __('Error', 'easy-digital-downloads'), array('response' => 403));
    }
    check_admin_referer('edd_update_payment_details_nonce');
    // Retrieve the payment ID
    $payment_id = absint($data['edd_payment_id']);
    $payment = new EDD_Payment($payment_id);
    // Retrieve existing payment meta
    $meta = $payment->get_meta();
    $user_info = $payment->user_info;
    $status = $data['edd-payment-status'];
    $unlimited = isset($data['edd-unlimited-downloads']) ? '1' : '';
    $date = sanitize_text_field($data['edd-payment-date']);
    $hour = sanitize_text_field($data['edd-payment-time-hour']);
    // Restrict to our high and low
    if ($hour > 23) {
        $hour = 23;
    } elseif ($hour < 0) {
        $hour = 00;
    }
    $minute = sanitize_text_field($data['edd-payment-time-min']);
    // Restrict to our high and low
    if ($minute > 59) {
        $minute = 59;
    } elseif ($minute < 0) {
        $minute = 00;
    }
    $address = array_map('trim', $data['edd-payment-address'][0]);
    $curr_total = edd_sanitize_amount($payment->total);
    $new_total = edd_sanitize_amount($_POST['edd-payment-total']);
    $tax = isset($_POST['edd-payment-tax']) ? edd_sanitize_amount($_POST['edd-payment-tax']) : 0;
    $date = date('Y-m-d', strtotime($date)) . ' ' . $hour . ':' . $minute . ':00';
    $curr_customer_id = sanitize_text_field($data['edd-current-customer']);
    $new_customer_id = sanitize_text_field($data['customer-id']);
    // Setup purchased Downloads and price options
    $updated_downloads = isset($_POST['edd-payment-details-downloads']) ? $_POST['edd-payment-details-downloads'] : false;
    if ($updated_downloads && !empty($_POST['edd-payment-downloads-changed'])) {
        foreach ($updated_downloads as $download) {
            // If this item doesn't have a log yet, add one for each quantity count
            $has_log = absint($download['has_log']);
            $has_log = empty($has_log) ? false : true;
            if ($has_log) {
                continue;
            }
            if (empty($download['item_price'])) {
                $download['item_price'] = 0.0;
            }
            $item_price = $download['item_price'];
            $download_id = absint($download['id']);
            $quantity = absint($download['quantity']) > 0 ? absint($download['quantity']) : 1;
            $price_id = false;
            if (edd_has_variable_prices($download_id) && isset($download['price_id'])) {
                $price_id = absint($download['price_id']);
            }
            // Set some defaults
            $args = array('quantity' => $quantity, 'item_price' => $item_price, 'price_id' => $price_id);
            $payment->add_download($download_id, $args);
        }
        $deleted_downloads = json_decode(stripcslashes($data['edd-payment-removed']), true);
        foreach ($deleted_downloads as $deleted_download) {
            $deleted_download = $deleted_download[0];
            if (empty($deleted_download['id'])) {
                continue;
            }
            $price_id = empty($deleted_download['price_id']) ? 0 : (int) $deleted_download['price_id'];
            $args = array('quantity' => (int) $deleted_download['quantity'], 'price_id' => (int) $price_id, 'item_price' => (double) $deleted_download['amount']);
            $payment->remove_download($deleted_download['id'], $args);
            do_action('edd_remove_download_from_payment', $payment_id, $deleted_download['id']);
        }
    }
    do_action('edd_update_edited_purchase', $payment_id);
    $payment->date = $date;
    $updated = $payment->save();
    if (0 === $updated) {
        wp_die(__('Error Updating Payment', 'easy-digital-downloads'), __('Error', 'easy-digital-downloads'), array('response' => 400));
    }
    $customer_changed = false;
    if (isset($data['edd-new-customer']) && $data['edd-new-customer'] == '1') {
        $email = isset($data['edd-new-customer-email']) ? sanitize_text_field($data['edd-new-customer-email']) : '';
        $names = isset($data['edd-new-customer-name']) ? sanitize_text_field($data['edd-new-customer-name']) : '';
        if (empty($email) || empty($names)) {
            wp_die(__('New Customers require a name and email address', 'easy-digital-downloads'));
        }
        $customer = new EDD_Customer($email);
        if (empty($customer->id)) {
            $customer_data = array('name' => $names, 'email' => $email);
            $user_id = email_exists($email);
            if (false !== $user_id) {
                $customer_data['user_id'] = $user_id;
            }
            if (!$customer->create($customer_data)) {
                // Failed to crete the new customer, assume the previous customer
                $customer_changed = false;
                $customer = new EDD_Customer($curr_customer_id);
                edd_set_error('edd-payment-new-customer-fail', __('Error creating new customer', 'easy-digital-downloads'));
            }
        }
        $new_customer_id = $customer->id;
        $previous_customer = new EDD_Customer($curr_customer_id);
        $customer_changed = true;
    } elseif ($curr_customer_id !== $new_customer_id) {
        $customer = new EDD_Customer($new_customer_id);
        $email = $customer->email;
        $names = $customer->name;
        $previous_customer = new EDD_Customer($curr_customer_id);
        $customer_changed = true;
    } else {
        $customer = new EDD_Customer($curr_customer_id);
        $email = $customer->email;
        $names = $customer->name;
    }
    // Setup first and last name from input values
    $names = explode(' ', $names);
    $first_name = !empty($names[0]) ? $names[0] : '';
    $last_name = '';
    if (!empty($names[1])) {
        unset($names[0]);
        $last_name = implode(' ', $names);
    }
    if ($customer_changed) {
        // Remove the stats and payment from the previous customer and attach it to the new customer
        $previous_customer->remove_payment($payment_id, false);
        $customer->attach_payment($payment_id, false);
        // If purchase was completed and not ever refunded, adjust stats of customers
        if ('revoked' == $status || 'publish' == $status) {
            $previous_customer->decrease_purchase_count();
            $previous_customer->decrease_value($new_total);
            $customer->increase_purchase_count();
            $customer->increase_value($new_total);
        }
        $payment->customer_id = $customer->id;
    }
    // Set new meta values
    $payment->user_id = $customer->user_id;
    $payment->email = $customer->email;
    $payment->first_name = $first_name;
    $payment->last_name = $last_name;
    $payment->address = $address;
    $payment->total = $new_total;
    $payment->tax = $tax;
    $payment->has_unlimited_downloads = $unlimited;
    // Check for payment notes
    if (!empty($data['edd-payment-note'])) {
        $note = wp_kses($data['edd-payment-note'], array());
        edd_insert_payment_note($payment->ID, $note);
    }
    // Set new status
    $payment->status = $status;
    // Adjust total store earnings if the payment total has been changed
    if ($new_total !== $curr_total && ('publish' == $status || 'revoked' == $status)) {
        if ($new_total > $curr_total) {
            // Increase if our new total is higher
            $difference = $new_total - $curr_total;
            edd_increase_total_earnings($difference);
        } elseif ($curr_total > $new_total) {
            // Decrease if our new total is lower
            $difference = $curr_total - $new_total;
            edd_decrease_total_earnings($difference);
        }
    }
    $payment->save();
    do_action('edd_updated_edited_purchase', $payment_id);
    wp_safe_redirect(admin_url('edit.php?post_type=download&page=edd-payment-history&view=view-order-details&edd-message=payment-updated&id=' . $payment_id));
    exit;
}
/**
 * Deletes a Purchase
 *
 * @since 1.0
 * @global $edd_logs
 *
 * @uses EDD_Logging::delete_logs()
 *
 * @param int $payment_id Payment ID (default: 0)
 * @param bool $update_customer If we should update the customer stats (default:true)
 * @param bool $delete_download_logs If we should remove all file download logs associated with the payment (default:false)
 *
 * @return void
 */
function edd_delete_purchase($payment_id = 0, $update_customer = true, $delete_download_logs = false)
{
    global $edd_logs;
    $post = get_post($payment_id);
    if (!$post) {
        return;
    }
    $downloads = edd_get_payment_meta_downloads($payment_id);
    if (is_array($downloads)) {
        // Update sale counts and earnings for all purchased products
        foreach ($downloads as $download) {
            edd_undo_purchase($download['id'], $payment_id);
        }
    }
    $amount = edd_get_payment_amount($payment_id);
    $status = $post->post_status;
    $customer_id = edd_get_payment_customer_id($payment_id);
    $customer = new EDD_Customer($customer_id);
    if ($status == 'revoked' || $status == 'publish') {
        // Only decrease earnings if they haven't already been decreased (or were never increased for this payment)
        edd_decrease_total_earnings($amount);
        // Clear the This Month earnings (this_monththis_month is NOT a typo)
        delete_transient(md5('edd_earnings_this_monththis_month'));
        if ($customer->id && $update_customer) {
            // Decrement the stats for the customer
            $customer->decrease_purchase_count();
            $customer->decrease_value($amount);
        }
    }
    do_action('edd_payment_delete', $payment_id);
    if ($customer->id && $update_customer) {
        // Remove the payment ID from the customer
        $customer->remove_payment($payment_id);
    }
    // Remove the payment
    wp_delete_post($payment_id, true);
    // Remove related sale log entries
    $edd_logs->delete_logs(null, 'sale', array(array('key' => '_edd_log_payment_id', 'value' => $payment_id)));
    if ($delete_download_logs) {
        $edd_logs->delete_logs(null, 'file_download', array(array('key' => '_edd_log_payment_id', 'value' => $payment_id)));
    }
    do_action('edd_payment_deleted', $payment_id);
}
/**
 * Reduces earnings and sales stats when a purchase is refunded
 *
 * @since 1.8.2
 * @param $data Arguments passed
 * @return void
 */
function edd_undo_purchase_on_refund($payment_id, $new_status, $old_status)
{
    global $edd_logs;
    if ('publish' != $old_status && 'revoked' != $old_status) {
        return;
    }
    if ('refunded' != $new_status) {
        return;
    }
    $payment = new EDD_Payment($payment_id);
    $downloads = $payment->cart_details;
    if ($downloads) {
        foreach ($downloads as $download) {
            edd_undo_purchase($download['id'], $payment->ID);
        }
    }
    // Decrease store earnings
    edd_decrease_total_earnings($payment->total);
    // Decrement the stats for the customer
    if (!empty($payment->customer_id)) {
        $customer = new EDD_Customer($payment->customer_id);
        $customer->decrease_value($payment->total);
        $customer->decrease_purchase_count();
    }
    // Remove related sale log entries
    $edd_logs->delete_logs(null, 'sale', array(array('key' => '_edd_log_payment_id', 'value' => $payment->ID)));
    // Clear the This Month earnings (this_monththis_month is NOT a typo)
    delete_transient(md5('edd_earnings_this_monththis_month'));
}
Example #6
0
/**
 * Process the payment details edit
 *
 * @access      private
 * @since       1.9
 * @return      void
*/
function edd_update_payment_details($data)
{
    if (!current_user_can('edit_shop_payments', $data['edd_payment_id'])) {
        wp_die(__('You do not have permission to edit this payment record', 'edd'), __('Error', 'edd'), array('response' => 403));
    }
    check_admin_referer('edd_update_payment_details_nonce');
    // Retrieve the payment ID
    $payment_id = absint($data['edd_payment_id']);
    // Retrieve existing payment meta
    $meta = edd_get_payment_meta($payment_id);
    $user_info = edd_get_payment_meta_user_info($payment_id);
    $status = $data['edd-payment-status'];
    $unlimited = isset($data['edd-unlimited-downloads']) ? '1' : '';
    $date = sanitize_text_field($data['edd-payment-date']);
    $hour = sanitize_text_field($data['edd-payment-time-hour']);
    // Restrict to our high and low
    if ($hour > 23) {
        $hour = 23;
    } elseif ($hour < 0) {
        $hour = 00;
    }
    $minute = sanitize_text_field($data['edd-payment-time-min']);
    // Restrict to our high and low
    if ($minute > 59) {
        $minute = 59;
    } elseif ($minute < 0) {
        $minute = 00;
    }
    $address = array_map('trim', $data['edd-payment-address'][0]);
    $curr_total = edd_sanitize_amount(edd_get_payment_amount($payment_id));
    $new_total = edd_sanitize_amount($_POST['edd-payment-total']);
    $tax = isset($_POST['edd-payment-tax']) ? edd_sanitize_amount($_POST['edd-payment-tax']) : 0;
    $date = date('Y-m-d', strtotime($date)) . ' ' . $hour . ':' . $minute . ':00';
    $curr_customer_id = sanitize_text_field($data['edd-current-customer']);
    $new_customer_id = sanitize_text_field($data['customer-id']);
    // Setup purchased Downloads and price options
    $updated_downloads = isset($_POST['edd-payment-details-downloads']) ? $_POST['edd-payment-details-downloads'] : false;
    if ($updated_downloads && !empty($_POST['edd-payment-downloads-changed'])) {
        $downloads = array();
        $cart_details = array();
        $i = 0;
        foreach ($updated_downloads as $download) {
            if (empty($download['amount'])) {
                $download['amount'] = '0.00';
            }
            $item = array();
            $item['id'] = absint($download['id']);
            $item['quantity'] = absint($download['quantity']) > 0 ? absint($download['quantity']) : 1;
            $price_id = (int) $download['price_id'];
            $has_log = absint($download['has_log']);
            if ($price_id !== false && edd_has_variable_prices($item['id'])) {
                $item['options'] = array('price_id' => $price_id);
            }
            $downloads[] = $item;
            $cart_item = array();
            $cart_item['item_number'] = $item;
            $item_price = round($download['amount'] / $item['quantity'], edd_currency_decimal_filter());
            $cart_details[$i] = array('name' => get_the_title($download['id']), 'id' => $download['id'], 'item_number' => $item, 'price' => $download['amount'], 'item_price' => $item_price, 'subtotal' => $download['amount'], 'quantity' => $download['quantity'], 'discount' => 0, 'tax' => 0);
            // If this item doesn't have a log yet, add one for each quantity count
            if (empty($has_log)) {
                $log_date = date('Y-m-d G:i:s', current_time('timestamp', true));
                $price_id = $price_id !== false ? $price_id : 0;
                $y = 0;
                while ($y < $download['quantity']) {
                    edd_record_sale_in_log($download['id'], $payment_id, $price_id, $log_date);
                    $y++;
                }
                edd_increase_purchase_count($download['id'], $download['quantity']);
                edd_increase_earnings($download['id'], $download['amount']);
            }
            $i++;
        }
        $meta['downloads'] = $downloads;
        $meta['cart_details'] = $cart_details;
        $deleted_downloads = json_decode(stripcslashes($data['edd-payment-removed']), true);
        foreach ($deleted_downloads as $deleted_download) {
            $deleted_download = $deleted_download[0];
            if (empty($deleted_download['id'])) {
                continue;
            }
            $price_id = empty($deleted_download['price_id']) ? 0 : (int) $deleted_download['price_id'];
            $log_args = array('post_type' => 'edd_log', 'post_parent' => $deleted_download['id'], 'numberposts' => $deleted_download['quantity'], 'meta_query' => array(array('key' => '_edd_log_payment_id', 'value' => $payment_id, 'compare' => '='), array('key' => '_edd_log_price_id', 'value' => $price_id, 'compare' => '=')));
            $found_logs = get_posts($log_args);
            foreach ($found_logs as $log) {
                wp_delete_post($log->ID, true);
            }
            edd_decrease_purchase_count($deleted_download['id'], $deleted_download['quantity']);
            edd_decrease_earnings($deleted_download['id'], $deleted_download['amount']);
            do_action('edd_remove_download_from_payment', $payment_id, $deleted_download['id']);
        }
    }
    do_action('edd_update_edited_purchase', $payment_id);
    // Update main payment record
    $updated = wp_update_post(array('ID' => $payment_id, 'post_date' => $date));
    if (0 === $updated) {
        wp_die(__('Error Updating Payment', 'edd'), __('Error', 'edd'), array('response' => 400));
    }
    $customer_changed = false;
    if (isset($data['edd-new-customer']) && $data['edd-new-customer'] == '1') {
        $email = isset($data['edd-new-customer-email']) ? sanitize_text_field($data['edd-new-customer-email']) : '';
        $names = isset($data['edd-new-customer-name']) ? sanitize_text_field($data['edd-new-customer-name']) : '';
        if (empty($email) || empty($names)) {
            wp_die(__('New Customers require a name and email address', 'edd'));
        }
        $customer = new EDD_Customer($email);
        if (empty($customer->id)) {
            $customer_data = array('name' => $names, 'email' => $email);
            $user_id = email_exists($email);
            if (false !== $user_id) {
                $customer_data['user_id'] = $user_id;
            }
            if (!$customer->create($customer_data)) {
                // Failed to crete the new customer, assume the previous customer
                $customer_changed = false;
                $customer = new EDD_Customer($curr_customer_id);
                edd_set_error('edd-payment-new-customer-fail', __('Error creating new customer', 'edd'));
            }
        }
        $new_customer_id = $customer->id;
        $previous_customer = new EDD_Customer($curr_customer_id);
        $customer_changed = true;
    } elseif ($curr_customer_id !== $new_customer_id) {
        $customer = new EDD_Customer($new_customer_id);
        $email = $customer->email;
        $names = $customer->name;
        $previous_customer = new EDD_Customer($curr_customer_id);
        $customer_changed = true;
    } else {
        $customer = new EDD_Customer($curr_customer_id);
        $email = $customer->email;
        $names = $customer->name;
    }
    // Setup first and last name from input values
    $names = explode(' ', $names);
    $first_name = !empty($names[0]) ? $names[0] : '';
    $last_name = '';
    if (!empty($names[1])) {
        unset($names[0]);
        $last_name = implode(' ', $names);
    }
    if ($customer_changed) {
        // Remove the stats and payment from the previous customer and attach it to the new customer
        $previous_customer->remove_payment($payment_id, false);
        $customer->attach_payment($payment_id, false);
        // If purchase was completed and not ever refunded, adjust stats of customers
        if ('revoked' == $status || 'publish' == $status) {
            $previous_customer->decrease_purchase_count();
            $previous_customer->decrease_value($new_total);
            $customer->increase_purchase_count();
            $customer->increase_value($new_total);
        }
        update_post_meta($payment_id, '_edd_payment_customer_id', $customer->id);
    }
    // Set new meta values
    $user_info['id'] = $customer->user_id;
    $user_info['email'] = $customer->email;
    $user_info['first_name'] = $first_name;
    $user_info['last_name'] = $last_name;
    $user_info['address'] = $address;
    $meta['user_info'] = $user_info;
    $meta['tax'] = $tax;
    // Check for payment notes
    if (!empty($data['edd-payment-note'])) {
        $note = wp_kses($data['edd-payment-note'], array());
        edd_insert_payment_note($payment_id, $note);
    }
    // Set new status
    edd_update_payment_status($payment_id, $status);
    edd_update_payment_meta($payment_id, '_edd_payment_user_id', $customer->user_id);
    edd_update_payment_meta($payment_id, '_edd_payment_user_email', $customer->email);
    edd_update_payment_meta($payment_id, '_edd_payment_meta', $meta);
    edd_update_payment_meta($payment_id, '_edd_payment_total', $new_total);
    // Adjust total store earnings if the payment total has been changed
    if ($new_total !== $curr_total && ('publish' == $status || 'revoked' == $status)) {
        if ($new_total > $curr_total) {
            // Increase if our new total is higher
            $difference = $new_total - $curr_total;
            edd_increase_total_earnings($difference);
        } elseif ($curr_total > $new_total) {
            // Decrease if our new total is lower
            $difference = $curr_total - $new_total;
            edd_decrease_total_earnings($difference);
        }
    }
    edd_update_payment_meta($payment_id, '_edd_payment_downloads', $new_total);
    edd_update_payment_meta($payment_id, '_edd_payment_unlimited_downloads', $unlimited);
    do_action('edd_updated_edited_purchase', $payment_id);
    wp_safe_redirect(admin_url('edit.php?post_type=download&page=edd-payment-history&view=view-order-details&edd-message=payment-updated&id=' . $payment_id));
    exit;
}
 /**
  * Used during the process of moving to refunded or pending, to decrement stats
  *
  * @since  2.5.10
  * @param  bool   $alter_store_earnings          If the method should alter the store earnings
  * @param  bool   $alter_customer_value          If the method should reduce the customer value
  * @param  bool   $alter_customer_purchase_count If the method should reduce the customer's purchase count
  * @return void
  */
 private function maybe_alter_stats($alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count)
 {
     edd_undo_purchase(false, $this->ID);
     // Decrease store earnings
     if (true === $alter_store_earnings) {
         edd_decrease_total_earnings($this->total);
     }
     // Decrement the stats for the customer
     if (!empty($this->customer_id)) {
         $customer = new EDD_Customer($this->customer_id);
         if (true === $alter_customer_value) {
             $customer->decrease_value($this->total);
         }
         if (true === $alter_customer_purchase_count) {
             $customer->decrease_purchase_count();
         }
     }
 }
 /**
  * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
  *
  * @since  2.5.7
  * @access private
  * @return void
  */
 private function process_refund()
 {
     global $edd_logs;
     $process_refund = true;
     // If the payment was not in publish or revoked status, don't decrement stats as they were never incremented
     if ('publish' != $this->old_status && 'revoked' != $this->old_status || 'refunded' != $this->status) {
         $process_refund = false;
     }
     // Allow extensions to filter for their own payment types, Example: Recurring Payments
     $process_refund = apply_filters('edd_should_process_refund', $process_refund, $this);
     if (false === $process_refund) {
         return;
     }
     do_action('edd_pre_refund_payment', $this);
     edd_undo_purchase(false, $this->ID);
     // Decrease store earnings
     $maybe_decrease_store_earnings = apply_filters('edd_decrease_store_earnings_on_refund', true, $this);
     if (true === $maybe_decrease_store_earnings) {
         edd_decrease_total_earnings($this->total);
     }
     // Decrement the stats for the customer
     if (!empty($this->customer_id)) {
         $customer = new EDD_Customer($this->customer_id);
         $maybe_decrease_value = apply_filters('edd_decrease_customer_value_on_refund', true, $this);
         if (true === $maybe_decrease_value) {
             $customer->decrease_value($this->total);
         }
         $maybe_decrease_purchase_count = apply_filters('edd_decrease_customer_purchase_count_on_refund', true, $this);
         if (true === $maybe_decrease_purchase_count) {
             $customer->decrease_purchase_count();
         }
     }
     // Remove related sale log entries
     $edd_logs->delete_logs(null, 'sale', array(array('key' => '_edd_log_payment_id', 'value' => $this->ID)));
     // Clear the This Month earnings (this_monththis_month is NOT a typo)
     delete_transient(md5('edd_earnings_this_monththis_month'));
     do_action('edd_post_refund_payment', $this);
 }