public static function run_cron($debug = false) { // we only want to perform these cron actions if we're after a certain time of day // because we dont want to be generating these renewals and sending them at midnight, can get confusing $after_time = module_config::c('invoice_automatic_after_time', 7); $time_of_day = date('G'); if ($time_of_day < $after_time) { if ($debug) { echo "Not performing automatic subscription operations until after {$after_time}:00 - it is currently {$time_of_day}:" . date('i') . "<br>\n"; } return; } // find all automatic subscriptions and renew them (if applicable) $sql = "SELECT * FROM `" . _DB_PREFIX . "subscription` s "; $sql .= " WHERE s.automatic_renew = 1"; $subscriptions = qa($sql); foreach ($subscriptions as $subscription) { if ($subscription['automatic_renew']) { if ($debug) { echo "<br>\nProcessing subscription renewals for subscription " . module_subscription::link_open($subscription['subscription_id'], true) . "<br>\n<br>\n"; } // find all the members/customers from this subscription //$members = module_subscription::get_subscribed_members($subscription['subscription_id']); //$customers = module_subscription::get_subscribed_customers($subscription['subscription_id']); $owners = module_subscription::get_subscribed_owners($subscription['subscription_id']); foreach ($owners as $member) { if (!$member['next_generation_date'] || $member['next_generation_date'] == '0000-00-00') { continue; } if (!$member['next_due_date'] || $member['next_due_date'] == '0000-00-00') { continue; } if ($debug) { echo "Doing: " . $member['owner_table'] . " " . $member['owner_id'] . "<br>\n"; } // check permissions for logged in users, dont want the cron to run when someone is logged in and no access to this account. if (module_security::is_logged_in()) { switch ($member['owner_table']) { case 'website': $website_perm_check = module_website::get_website($member['owner_id']); if (!$website_perm_check || $website_perm_check['website_id'] != $member['owner_id']) { continue 2; } if ($debug) { echo "permission pass for website: " . $website_perm_check['website_id']; } break; case 'customer': $customer_perm_check = module_customer::get_customer($member['owner_id']); if (!$customer_perm_check || $customer_perm_check['customer_id'] != $member['owner_id']) { continue 2; } if ($debug) { echo "permission pass for customer: " . $customer_perm_check['customer_id']; } break; } } // is the last invoice unpaid? $history = self::get_subscription_history($subscription['subscription_id'], $member['owner_table'], $member['owner_id']); $next_due_time_invoice_created = false; $invoice_unpaid = false; if (isset($member['recur_limit']) && (int) $member['recur_limit'] > 0 && count($history) >= (int) $member['recur_limit']) { if ($debug) { echo " - not renewing this one because it has hit our recur limit of " . $member['recur_limit'] . "<br>\n"; } continue; } foreach ($history as $h) { $last_invoice = module_invoice::get_invoice($h['invoice_id']); if (!$last_invoice || $last_invoice['date_cancel'] != '0000-00-00') { continue; } // check the new 'next_due_date' entry in the db table if (isset($h['from_next_due_date']) && $h['from_next_due_date'] && $h['from_next_due_date'] != '0000-00-00') { // we're using the new method of checking when an invoice was generated, rather than the confusing invoice 'date_create' check below if ($debug) { echo " - checking if next_due_date " . print_date($member['next_due_date']) . " matches subscription history from_next_due_date for invoice " . module_invoice::link_open($h['invoice_id'], true, $last_invoice) . " from_next_due_date: " . print_date($h['from_next_due_date']) . " (invoice create_date: " . print_date($last_invoice['date_create']) . ")<br>\n"; } if (print_date($member['next_due_date']) == print_date($h['from_next_due_date'])) { //print_date($last_invoice['date_create'])){ // this invoice is for the next due date. $next_due_time_invoice_created = $last_invoice; } } else { if ($debug) { echo " - checking if next_generation_date (" . print_date($member['next_generation_date']) . ") or next_due_date (" . print_date($member['next_due_date']) . ") matches invoice " . module_invoice::link_open($h['invoice_id'], true, $last_invoice) . " created date (" . print_date($last_invoice['date_create']) . ") <br>\n"; } if (print_date($member['next_generation_date']) == print_date($last_invoice['date_create']) || print_date($member['next_due_date']) == print_date($last_invoice['date_create'])) { //print_date($last_invoice['date_create'])){ // this invoice is for the next due date. $next_due_time_invoice_created = $last_invoice; } } if ($last_invoice['total_amount_due'] > 0) { $invoice_unpaid = true; } } //self::generate_subscription_invoice($subscription_id, $customer_hack, $member_id, $date, $amount) $next_due_time = strtotime($member['next_generation_date']); if ($debug) { echo " - next subscription time is " . $member['next_generation_date'] . " <br>\n"; } if ($next_due_time <= strtotime(date('Y-m-d')) && !$next_due_time_invoice_created) { if ($debug) { echo " - Yes its time to generate an invoice!<br>\n"; } if (module_config::c('invoice_auto_renew_only_paid_invoices', 1) && $invoice_unpaid) { if ($debug) { echo " - skipping generating renewal for " . $member['owner_table'] . " " . $member['owner_id'] . " because a previous subscription is unpaid <br>\n"; } continue; } // time to generate! woo! if ($debug) { echo " - generating subscription renewal for " . $member['owner_table'] . " " . $member['owner_id'] . "<br>\n"; } $invoice_id = self::generate_subscription_invoice($subscription['subscription_id'], $member['owner_table'], $member['owner_id'], $member['next_generation_date'], $subscription['amount']); if ($debug) { echo " - generated invoice " . module_invoice::link_open($invoice_id, true) . " for subscription <br>\n"; } if ($subscription['automatic_email']) { if ($debug) { echo " - emailing invoice to " . $member['owner_table'] . "... <br>\n"; } if (module_invoice::email_invoice_to_customer($invoice_id, $debug)) { if ($debug) { echo "send successfully <br>\n"; } } else { echo " - failed to send invoice " . module_invoice::link_open($invoice_id, true) . " to " . $member['owner_table'] . " <br>\n"; } } } else { if ($debug) { echo " - skipping generating renewal for " . $member['owner_table'] . " " . $member['owner_id'] . " because the due date has already been generated <br>\n"; } } } } } }
public static function create_new_invoice_for_subscription_payment($invoice_id, $invoice_payment_id, $invoice_payment_subscription_id) { // we have an inbound subscription payment for an invoice. // we have to generate a new invoice (or find the generated invoice if one exists) // first we have to check if this payment is for this invoice (ie: the first subscription payment) $invoice_data = self::get_invoice($invoice_id); if ($invoice_data['total_amount_due'] > 0) { // this invoice is unpaid, we apply this subscription payment against thsi invoice return array('invoice_id' => $invoice_id, 'invoice_payment_id' => $invoice_payment_id); } // first we look for a generated invoice, this is easiest. if (class_exists('module_subscription', false)) { // check if this invoice is part of a subscription. // if it is we hunt through the subscription history until we find a recent unpaid invoice // THIS CODE IS SIMILAR TO module_invoice::is_automatic_paying_invoice($invoice_id) $subscription_history_item = get_single('subscription_history', 'invoice_id', $invoice_id); if ($subscription_history_item && $subscription_history_item['subscription_owner_id']) { // we have an invoice that is on a subscription! $subscription_owner = module_subscription::get_subscription_owner($subscription_history_item['subscription_owner_id']); // check if there are unpaid invoices that were generated after this invoice. if ($subscription_owner['subscription_owner_id'] == $subscription_history_item['subscription_owner_id']) { $subscription_history = get_multiple('subscription_history', array('subscription_owner_id' => $subscription_owner['subscription_owner_id'])); foreach ($subscription_history as $h) { if ($h['invoice_id'] > $invoice_id && $h['paid_date'] == '0000-00-00') { // found an invoice for this subscription that was generated after the initial invoice that is unpaid. // apply subscription payment to this one. $invoice_data = module_invoice::get_invoice($h['invoice_id']); if ($invoice_data['total_amount_due'] > 0) { $invoice_payment_id = update_insert('invoice_payment_id', false, 'invoice_payment', array('invoice_id' => $h['invoice_id'], 'payment_type' => _INVOICE_PAYMENT_TYPE_NORMAL, 'method' => _l('Pending Subscription'), 'currency_id' => $invoice_data['currency_id'], 'invoice_payment_subscription_id' => $invoice_payment_subscription_id)); return array('invoice_id' => $h['invoice_id'], 'invoice_payment_id' => $invoice_payment_id); } } } // if we get here it means we have a subscription invoice that hasn't been renewed yet. $subscription = module_subscription::get_subscription($subscription_owner['subscription_id']); // we force the renewal of the next invoice in this subscription lot and mark it as paid. $invoice_id = module_subscription::generate_subscription_invoice($subscription_owner['subscription_id'], $subscription_owner['owner_table'], $subscription_owner['owner_id'], date('Y-m-d'), $subscription['amount']); if ($invoice_id) { $invoice_data = module_invoice::get_invoice($invoice_id); $invoice_payment_id = update_insert('invoice_payment_id', false, 'invoice_payment', array('invoice_id' => $invoice_id, 'payment_type' => _INVOICE_PAYMENT_TYPE_NORMAL, 'method' => _l('Pending Subscription'), 'currency_id' => $invoice_data['currency_id'], 'invoice_payment_subscription_id' => $invoice_payment_subscription_id)); if ($subscription['automatic_email'] && module_config::c('invoice_subscription_send_due_email_before_payment', 1)) { if (module_invoice::email_invoice_to_customer($invoice_id)) { } else { echo " - failed to send subscription invoice " . module_invoice::link_open($invoice_id, true) . " to customer <br>\n"; } exit; } return array('invoice_id' => $invoice_id, 'invoice_payment_id' => $invoice_payment_id); } } } } }
public function run_cron($debug = false) { // we only want to perform these cron actions if we're after a certain time of day // because we dont want to be generating these renewals and sending them at midnight, can get confusing $after_time = module_config::c('invoice_automatic_after_time', 7); $time_of_day = date('G'); if ($time_of_day < $after_time) { if ($debug) { echo "Not performing automatic invoice operations until after {$after_time}:00 - it is currently {$time_of_day}:" . date('i') . "<br>\n"; } return; } // find automatic job renewals $sql = "SELECT p.* FROM `" . _DB_PREFIX . "job` p "; $sql .= " WHERE p.date_renew != '0000-00-00'"; $sql .= " AND p.date_start != '0000-00-00'"; $sql .= " AND p.date_renew <= '" . date('Y-m-d') . "'"; $sql .= " AND (p.renew_job_id IS NULL OR p.renew_job_id = 0)"; $sql .= " AND (p.renew_auto = 1)"; $renew_jobs = qa($sql); foreach ($renew_jobs as $renew_job) { // time to automatically renew this job! woo! if ($debug) { echo "Automatically Renewing Job " . module_job::link_open($renew_job['job_id'], true) . "<br>\n"; } //$job_details = $this->get_job($renew_job['job_id']); $job_invoices = module_invoice::get_invoices(array('job_id' => $renew_job['job_id'])); $unpaid_invoice = false; foreach ($job_invoices as $job_invoice) { $job_invoice = module_invoice::get_invoice($job_invoice['invoice_id']); if ($job_invoice['total_amount_due'] > 0) { $unpaid_invoice = true; } } if (module_config::c('invoice_auto_renew_only_paid_invoices', 1) && $unpaid_invoice) { if ($debug) { echo "Not automatically renewing this job because it has unpaid invoices. <br>\n"; } } else { $new_job_id = $this->renew_job($renew_job['job_id'], true); if ($new_job_id) { //module_cache::clear_cache(); if ($debug) { echo "Job Automatically Renewed: " . module_job::link_open($new_job_id, true) . "<br>\n"; } if ($renew_job['renew_invoice']) { // we want to tick all these tasks off and invoice this job, then send this invoice to the customer. $job_tasks = module_job::get_tasks($new_job_id); foreach ($job_tasks as $job_task_id => $job_task) { $job_tasks[$job_task_id]['fully_completed_t'] = 1; $job_tasks[$job_task_id]['fully_completed'] = 1; } $this->save_job_tasks($new_job_id, array('job_task' => $job_tasks)); //module_cache::clear_cache(); // generate an invoice for this job. $_REQUEST['job_id'] = $new_job_id; $new_invoice = module_invoice::get_invoice('new'); $new_invoice['date_create'] = $renew_job['date_renew']; $new_invoice['invoice_invoice_item'] = module_invoice::get_invoice_items('new', $new_invoice); $new_invoice_id = module_invoice::save_invoice('new', $new_invoice); //module_cache::clear_cache(); if ($debug) { echo "Generated new invoice for renewed job: " . module_invoice::link_open($new_invoice_id, true) . "<br/>"; } if ($debug) { echo "Emailing invoice to customer..."; } if (module_invoice::email_invoice_to_customer($new_invoice_id)) { if ($debug) { echo "send successfully"; } } else { if ($debug) { echo "send failed"; } } if ($debug) { echo "<br>\n"; } } } } } }