Index: uc_recurring.ca.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uc_recurring/Attic/uc_recurring.ca.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 uc_recurring.ca.inc
--- uc_recurring.ca.inc	24 Sep 2009 04:26:22 -0000	1.1.2.2
+++ uc_recurring.ca.inc	8 Oct 2009 02:30:29 -0000
@@ -291,6 +291,15 @@ function uc_recurring_ca_trigger() {
     ),
   );
 
+  $triggers['uc_recurring_renewal_expired'] = array(
+    '#title' => t('Recurring order renewal expired'),
+    '#category' => t('Recurring Fees'),
+    '#arguments' => array(
+      'order' => $order,
+      'recurring_fee' => $recurring_fee,
+    ),
+  );
+
   return $triggers;
 }
 
Index: uc_recurring.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uc_recurring/uc_recurring.module,v
retrieving revision 1.1.4.46
diff -u -p -r1.1.4.46 uc_recurring.module
--- uc_recurring.module	4 Oct 2009 07:15:28 -0000	1.1.4.46
+++ uc_recurring.module	8 Oct 2009 02:30:29 -0000
@@ -266,6 +266,14 @@ function uc_recurring_cron() {
     }
     watchdog('uc_recurring', '@success recurring fees processed successfully; @fail failed.', array('@success' => $success, '@fail' => $fail));
   }
+
+  $fees = uc_recurring_get_fees_for_expiration();
+  if (!empty($fees)) {
+    foreach($fees as $fee) {
+      uc_recurring_expire($fee);
+    }
+    watchdog('uc_recurring', '@count recurring fees expired successfully.', array('@count' => count($fees)));
+  }
 }
 
 /**
@@ -585,6 +593,21 @@ function uc_recurring_renew($fee) {
 }
 
 /**
+ * Process a fee expiration.
+ * 
+ * @param #fee
+ *   The fee object.
+ */
+function uc_recurring_expire($fee) {
+  $order = uc_order_load($fee->order_id);
+
+  $fee->status = 'expired';
+  uc_recurring_fee_save($fee);
+
+  ca_pull_trigger('uc_recurring_renewal_expired', $order, $fee);
+}
+
+/**
  * Handle extensions when a recurring payment was unsuccessful.
  *
  * @param $fee
@@ -939,6 +962,20 @@ function uc_recurring_get_fees_for_renew
 }
 
 /**
+ * Get all pending fees that should be expired.
+ */
+function uc_recurring_get_fees_for_expiration() {
+  $fees= array();
+  $result = db_query("SELECT * FROM {uc_recurring_users} WHERE remaining_intervals = 0 AND next_charge <= %d AND own_handler = 0 AND status != 'expired' ORDER BY order_id DESC", time());
+  while ($fee = db_fetch_object($result)) {
+    $fee->data = unserialize($fee->data);
+    $fees[$fee->rfid] = $fee;
+  }
+  return $fees;
+}
+
+
+/**
  * Get all fees is the system.
  */
 function uc_recurring_get_all_fees() {
Index: uc_recurring.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uc_recurring/uc_recurring.install,v
retrieving revision 1.1.4.6
diff -u -p -r1.1.4.6 uc_recurring.install
--- uc_recurring.install	8 Sep 2009 06:13:50 -0000	1.1.4.6
+++ uc_recurring.install	8 Oct 2009 02:30:29 -0000
@@ -455,3 +455,14 @@ function uc_recurring_update_6006() {
 
   return $ret;
 }
+
+/**
+ * Add status field to recurring users table.
+ */
+function uc_recurring_update_6007() {
+  $ret = array();
+  
+  db_add_field($ret, 'uc_recurring_users', 'status', array('description' => 'The status of the recurring fee, e.g. "active" or "expired"', 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => 'active'));
+  
+  return $ret;
+}
