? issue_567558_project.patch
? storm_735694.patch
? storm_746410.patch
? storm_746410_2.patch
? storm_acm1.patch
? storminvoice/storminvoice_acm1.module
Index: stormattribute/stormattribute.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormattribute/stormattribute.install,v
retrieving revision 1.2.4.16
diff -u -p -r1.2.4.16 stormattribute.install
--- stormattribute/stormattribute.install	4 Apr 2010 22:10:50 -0000	1.2.4.16
+++ stormattribute/stormattribute.install	26 Apr 2010 10:00:50 -0000
@@ -16,6 +16,7 @@ function stormattribute_install() {
     'hourly' => 'Hourly',
     'daily' => 'Daily',
     'fixed_timetracking' => 'Fixed Timetracking',
+    'fixed_project' => 'Fixed Project',
   );
 
   $attributes['Project status'] = array(
@@ -961,3 +962,15 @@ function stormattribute_update_6111() {
 
   return $ret;
 }
+
+/**
+ * Added fixed_project attribute for issue 567558
+*/
+function stormattribute_update_6112() {
+  $ret = array();
+
+  $ret[] = update_sql("INSERT INTO {stormattribute} (domain, akey, avalue, weight, isactive) VALUES ('Price mode', 'fixed_project', 'Fixed Project', 0, 1)");
+
+  return $ret;
+}
+
Index: storminvoice/storminvoice.auto_add.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/storminvoice/storminvoice.auto_add.inc,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 storminvoice.auto_add.inc
--- storminvoice/storminvoice.auto_add.inc	22 Jul 2009 00:05:15 -0000	1.1.2.3
+++ storminvoice/storminvoice.auto_add.inc	26 Apr 2010 10:00:50 -0000
@@ -13,7 +13,7 @@ function storminvoice_auto_add($node, $i
       $invoice_nid = stormorganization_storminvoice_auto_add($node, $invoice);
       break;
     case 'stormproject':
-      $invoice_nid = stormorganization_storminvoice_auto_add($node, $invoice);
+      $invoice_nid = stormproject_storminvoice_auto_add($node, $invoice);
       break;
     case 'stormtask':
       $invoice_nid = stormorganization_storminvoice_auto_add($node, $invoice);
Index: storminvoice/storminvoice.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/storminvoice/storminvoice.module,v
retrieving revision 1.4.4.72
diff -u -p -r1.4.4.72 storminvoice.module
--- storminvoice/storminvoice.module	18 Jan 2010 22:01:41 -0000	1.4.4.72
+++ storminvoice/storminvoice.module	26 Apr 2010 10:00:50 -0000
@@ -315,10 +315,11 @@ function storminvoice_form(&$node) {
   if (arg(1)=='add') {
     $node->requestdate = time();
     $node->duedate = $node->requestdate + (variable_get('storminvoice_payment_days', 30) * 86400);
-    $s = "SELECT MAX(CAST(SUBSTRING_INDEX(sin.number, '/', 1) AS SIGNED)) FROM {node} n INNER JOIN {storminvoice} sin ON n.nid=sin.nid
-      WHERE n.type='storminvoice' AND YEAR(FROM_UNIXTIME(sin.requestdate))=YEAR(FROM_UNIXTIME(%d))";
-    $date = getdate($node->requestdate);
-    $node->number = (db_result(db_query($s, $node->requestdate)) + 1) .'/'. $date['year'];
+    //$s = "SELECT MAX(CAST(SUBSTRING_INDEX(sin.number, '/', 1) AS SIGNED)) FROM {node} n INNER JOIN {storminvoice} sin ON n.nid=sin.nid
+    //  WHERE n.type='storminvoice' AND YEAR(FROM_UNIXTIME(sin.requestdate))=YEAR(FROM_UNIXTIME(%d))";
+    //$date = getdate($node->requestdate);
+    //$node->number = (db_result(db_query($s, $node->requestdate)) + 1) .'/'. $date['year'];
+    $node->number = storminvoice_get_invoice_number($node->requestdate);
 
     if (array_key_exists('organization_nid', $_GET) && !$node->organization_nid) {
       $node->organization_nid = $_GET['organization_nid'];
@@ -868,3 +869,74 @@ function storminvoice_getitems($invoice_
   }
   return $items;
 }
+
+function storminvoice_get_invoice_number($requestdate) {
+  $s = "SELECT MAX(CAST(SUBSTRING_INDEX(sin.number, '/', 1) AS SIGNED)) FROM {node} n INNER JOIN {storminvoice} sin ON n.nid=sin.nid
+    WHERE n.type='storminvoice' AND YEAR(FROM_UNIXTIME(sin.requestdate))=YEAR(FROM_UNIXTIME(%d))";
+  $date = getdate($requestdate);
+  $new_invoice_number = (db_result(db_query($s, $requestdate)) + 1) .'/'. $date['year'];
+  
+  return $new_invoice_number;
+}
+
+function storminvoice_get_rate($node) {
+  $rate_array = array('pricemode_used' => '', 'rate_to_use' => 0);
+
+  $hours_per_day = 8;
+  $found = FALSE;
+
+  $node_list = array();
+  
+  switch ($node->type) {
+    case 'stormtimetracking':
+      $node_list = array('ticket' => $node->ticket_nid, 'task' => $node->task_nid, 'project' => $node->project_nid, 'organization' => $node->organization_nid);
+      break;
+    case 'stormproject':
+      $node_list = array('project' => $node->nid, 'organization' => $node->organization_nid);
+    }
+  
+//  foreach (array('ticket' => $node->ticket_nid, 'task' => $node->task_nid, 'project' => $node->project_nid, 'organization' => $node->organization_nid) as $type => $nid) {
+    foreach ($node_list as $type => $nid) {
+    if($nid) {
+      $parent_item = node_load($nid);
+      switch ($parent_item->pricemode) {
+        case 'hourly':
+          $found = TRUE;
+          $rate_array['rate_to_use'] = $parent_item->price;
+          break;
+
+        case 'daily':
+          $found = TRUE;
+          $rate_array['rate_to_use'] = $parent_item->price / $hours_per_day;
+          break;
+
+        case 'fixed':
+          $found = TRUE;
+          $rate_array['rate_to_use'] = 0;
+          break;
+
+        case 'fixed_timetracking':
+          $found = TRUE;
+          $rate_array['rate_to_use'] = $parent_item->price;
+          break;
+
+        case 'fixed_project':
+          $found = TRUE;
+          $rate_array['rate_to_use'] = $parent_item->price;
+          break;
+
+        default:
+          continue;
+      }
+    }
+  if ($found == TRUE) {
+    $rate_array['pricemode_used'] = $parent_item->pricemode;
+    break;
+    }
+  }
+  if($found == FALSE) {
+    drupal_set_message(t('Error whilst finding a rate from ticket, task, project and organization. Consider setting the pricemode and price for your client organizations to avoid this error.'), 'error');
+    }
+  return $rate_array;
+}
+
Index: stormproject/stormproject.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormproject/Attic/stormproject.admin.inc,v
retrieving revision 1.9.4.19
diff -u -p -r1.9.4.19 stormproject.admin.inc
--- stormproject/stormproject.admin.inc	23 Apr 2010 16:01:40 -0000	1.9.4.19
+++ stormproject/stormproject.admin.inc	26 Apr 2010 10:00:51 -0000
@@ -157,6 +157,12 @@ function stormproject_list() {
     }
   }
   
+  if ($_SESSION['stormproject_list_filter']['billable']!='-' && $_SESSION['stormproject_list_filter']['billable']!= NULL) {
+    $where[] = 'spr.billable=%d';
+    $args[] = $_SESSION['stormproject_list_filter']['billable'];
+    $filterfields[] = t('Billable');
+  }
+
   $itemsperpage = $_SESSION['stormproject_list_filter']['itemsperpage'];
   if (!$itemsperpage) {
     $itemsperpage = variable_get('storm_default_items_per_page', 10);
@@ -314,6 +320,13 @@ function stormproject_list_filter(&$form
     '#default_value' => $dateendto,
   );
 
+  $form['filter']['billable'] = array(
+    '#type' => 'select',
+    '#title' => 'Billable',
+    '#options' => array('-' => t('all'), '1' => t('billable'), '0' => t('not billable')),
+    '#default_value' => $_SESSION['stormproject_list_filter']['billable'],
+  );
+
   $form['filter']['group4'] = array(
     '#type' => 'markup',
     '#theme' => 'storm_form_group',
@@ -366,6 +379,7 @@ function stormproject_list_filter_filter
   $_SESSION['stormproject_list_filter']['datebeginto'] = $form_state['values']['datebeginto'];
   $_SESSION['stormproject_list_filter']['dateendfrom'] = $form_state['values']['dateendfrom'];
   $_SESSION['stormproject_list_filter']['dateendto'] = $form_state['values']['dateendto'];
+  $_SESSION['stormproject_list_filter']['billable'] = $form_state['values']['billable'];
   $_SESSION['stormproject_list_filter']['assigned_to'] = $form_state['values']['assigned_to'];
   $_SESSION['stormproject_list_filter']['itemsperpage'] = $form_state['values']['itemsperpage'];
 }
Index: stormproject/stormproject.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormproject/stormproject.install,v
retrieving revision 1.2.4.9
diff -u -p -r1.2.4.9 stormproject.install
--- stormproject/stormproject.install	23 Nov 2009 20:35:46 -0000	1.2.4.9
+++ stormproject/stormproject.install	26 Apr 2010 10:00:51 -0000
@@ -39,6 +39,8 @@ function stormproject_schema() {
       'manager_title'       => array('type' => 'varchar', 'length' => 100),
       'assigned_nid'        => array('type' => 'int'),
       'assigned_title'      => array('type' => 'varchar', 'length' => 100),
+      'billable'            => array('type' => 'int'),
+      'billed'              => array('type' => 'int'),
     ),
     'primary key' => array('vid', 'nid'),
   );
@@ -77,4 +79,12 @@ function stormproject_update_6104() {
   db_add_field($ret, 'stormproject', 'assigned_nid', array('type' => 'int'));
   db_add_field($ret, 'stormproject', 'assigned_title', array('type' => 'varchar', 'length' => 100));
   return $ret;
+}
+
+
+function stormproject_update_6105() {
+  $ret = array();
+  db_add_field($ret, 'stormproject', 'billable', array('type' => 'int'));
+  db_add_field($ret, 'stormproject', 'billed', array('type' => 'int'));
+  return $ret;
 }
\ No newline at end of file
Index: stormproject/stormproject.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormproject/stormproject.module,v
retrieving revision 1.8.4.57
diff -u -p -r1.8.4.57 stormproject.module
--- stormproject/stormproject.module	19 Jan 2010 18:27:29 -0000	1.8.4.57
+++ stormproject/stormproject.module	26 Apr 2010 10:00:51 -0000
@@ -285,6 +285,7 @@ function stormproject_content_extra_fiel
       'group3' => array('label' => 'Date/Duration Group', 'weight' => -18),
       'group4' => array('label' => 'Price Group', 'weight' => -17),
       'group5' => array('label' => 'Manager / Assigned to Group', 'weight' => -16),
+      'group6' => array('label' => 'Billable / Billed Group', 'weight' => -15),
     );
   }
 }
@@ -319,6 +320,9 @@ function stormproject_form(&$node) {
     }
     $s_org = "SELECT n.nid, n.title FROM {stormorganization} so INNER JOIN {node} n 
               ON so.nid=n.nid WHERE n.status=1 AND so.isactive=1 AND so.iscustomer=1 AND n.type='stormorganization' ORDER BY n.title";
+
+    $node->billable = variable_get('stormproject_billable_default', FALSE);
+
   }
   else {
     $s_org = "SELECT n.nid, n.title FROM {stormorganization} so INNER JOIN {node} n 
@@ -522,6 +526,26 @@ function stormproject_form(&$node) {
     '#default_value' => $node->assigned_nid,
   );
   
+  $form['group6'] = array(
+    '#type' => 'markup',
+    '#theme' => 'storm_form_group',
+    '#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group6') : -15,
+  );
+
+  $form['group6']['billable'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Billable'),
+    '#default_value' => $node->billable,
+    '#weight' => 1,
+  );
+  
+  $form['group6']['billed'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Billed'),
+    '#default_value' => $node->billed,
+    '#weight' => 2,
+  );
+
   if ($type->has_body) {
     $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
   }
@@ -587,10 +611,12 @@ function stormproject_update($node) {
       organization_nid=%d, organization_title='%s',
       projectcategory='%s', projectstatus='%s', projectpriority='%s', pricemode='%s', 
       price=%f, currency='%s', datebegin=%d, dateend=%d, durationunit='%s', duration=%f,
-      manager_nid=%d, manager_title='%s', assigned_nid=%d, assigned_title='%s' WHERE vid = %d",
+      manager_nid=%d, manager_title='%s', assigned_nid=%d, assigned_title='%s',
+      billable=%d, billed=%d WHERE vid = %d",
       $node->organization_nid, $organization->title, $node->projectcategory, $node->projectstatus, $node->projectpriority,
       $node->pricemode, $node->price, $node->currency, $node->datebegin, $node->dateend, $node->durationunit, $node->duration,
-      $node->manager_nid, $manager->title, $node->assigned_nid, $assigned->title, $node->vid
+      $node->manager_nid, $manager->title, $node->assigned_nid, $assigned->title, 
+      $node->billable, $node->billed, $node->vid
     );
     
     if ($node->title != $node->title_old) {
@@ -675,3 +701,101 @@ function stormproject_views_api() {
     'path' => drupal_get_path('module', 'stormproject'),
   );
 }
+
+// INVOICE AUTO ADD HANDLER
+function stormproject_storminvoice_auto_add($node, $invoice_nid = NULL) {
+  if (!module_exists('storminvoice')) {
+    drupal_set_message(t('This function should only be called from within Storm Invoice'));
+    return;
+  } elseif ($node->billed) {
+    drupal_set_message(t('This timetracking has already been billed!'));
+    return;
+  } elseif (!$node->billable) {
+    drupal_set_message(t('This timetracking is marked unbillable!'));
+    return;
+  } else {
+    global $user;
+    
+    if (!$invoice_nid) {
+    
+      $new_invoice = new StdClass;
+      
+      //Code copied with edits from node form
+      $new_invoice->requestdate = time();
+      $new_invoice->duedate = $new_invoice->requestdate + (variable_get('storminvoice_payment_days', 30) * 86400);
+      //$s = "SELECT MAX(CAST(SUBSTRING_INDEX(sin.number, '/', 1) AS SIGNED)) FROM {node} n INNER JOIN {storminvoice} sin ON n.nid=sin.nid
+      //  WHERE n.type='storminvoice' AND YEAR(FROM_UNIXTIME(sin.requestdate))=YEAR(FROM_UNIXTIME(%d))";
+      //$date = getdate($new_invoice->requestdate);
+      //$new_invoice->number = (db_result(db_query($s, $new_invoice->requestdate)) + 1) .'/'. $date['year'];
+      $new_invoice->number = storminvoice_get_invoice_number($new_invoice->requestdate);
+
+      $new_invoice->title = $node->title;
+      $new_invoice->uid = $user->uid;
+      $new_invoice->type = 'storminvoice';
+      //$new_invoice->reference
+      $new_invoice->organization_nid = $node->organization_nid;
+      $new_invoice->organization_title = $node->organization_title;
+      $new_invoice->project_nid = $node->project_nid;
+      $new_invoice->project_title = $node->project_title;
+      //$new_invoice->amount
+      //$new_invoice->tax
+      //$new_invoice->total
+      //$new_invoice->totalcustomercurr
+      //$new_invoice->taxexempt
+      $new_invoice->src_nid = $node->nid;
+      $new_invoice->src_vid = $node->vid;
+      
+      node_save($new_invoice);
+      $invoice_nid = $new_invoice->nid;
+    } else {
+      $new_invoice = node_load($invoice_nid);
+    }
+
+    $rate_array = array('pricemode_used' => '', 'rate_to_use' => 0);
+    
+    $rate_array = storminvoice_get_rate($node);
+    
+    $count = count($new_invoice->items);
+    
+    $new_invoice->items[$count]->description  = date('d M y', $node->trackingdate) . ': ';
+    
+    switch ($rate_array['pricemode_used']) {
+      case 'hourly':
+        $new_invoice->items[$count]->description .= t('@dur hours work at @rate per hour on @desc', array('@dur' => $node->billing_duration, '@rate' => $rate_array['rate_to_use'], '@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $node->billing_duration * $rate_array['rate_to_use'];
+        break;
+      case 'daily':
+        $new_invoice->items[$count]->description .= t('@dur hours work at @rate per day on @desc', array('@dur' => $node->billing_duration, '@rate' => $rate_array['rate_to_use'], '@desc' => $node->title));
+        break;
+      case 'daily':
+        $new_invoice->items[$count]->description .= t('@dur hours work at @rate per day on @desc', array('@dur' => $node->billing_duration, '@rate' => $rate_array['rate_to_use'], '@desc' => $node->title));
+        break;
+      case 'fixed':
+        $new_invoice->items[$count]->description .= t('@dur hours unbilled work on @desc', array('@dur' => $node->billing_duration, '@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
+        break;
+      case 'fixed_timetracking':
+        $new_invoice->items[$count]->description .= t('work billed for @desc', array('@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
+        break;
+      case 'fixed_project':
+        $new_invoice->items[$count]->description .= t('Project billed for @desc', array('@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
+        break;
+    }
+
+
+    // Tax percent simply uses default at the moment
+    $new_invoice->items[$count]->tax1percent = variable_get('storm_tax1_percent', 20);
+    //$new_invoice_item->items[$count]->tax1
+    //$new_invoice_item->items[$count]->total
+    
+    storm_taxation($new_invoice->items[$count]);
+    storminvoice_update($new_invoice);
+  }
+  
+  // Mark timetracking as billed.
+  db_query("UPDATE {stormproject} SET billed=%d WHERE vid=%d", 1, $node->vid);
+  
+  return $invoice_nid;
+}
\ No newline at end of file
Index: stormproject/stormproject.theme.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormproject/stormproject.theme.inc,v
retrieving revision 1.2.4.17
diff -u -p -r1.2.4.17 stormproject.theme.inc
--- stormproject/stormproject.theme.inc	17 Jan 2010 14:38:15 -0000	1.2.4.17
+++ stormproject/stormproject.theme.inc	26 Apr 2010 10:00:51 -0000
@@ -36,13 +36,41 @@ function theme_stormproject_view($node, 
     '#suffix' => '</dl></div>',
     '#weight' => -25,
   );
-  
+
   $node->content['links']['expenses'] = theme('storm_link', 'stormproject', 'stormexpense', $node->nid, 1);
   $node->content['links']['notes'] = theme('storm_link', 'stormproject', 'stormnote', $node->nid, 2);
   $node->content['links']['tasks'] = theme('storm_link', 'stormproject', 'stormtask', $node->nid, 3);
   $node->content['links']['tickets'] = theme('storm_link', 'stormproject', 'stormticket', $node->nid, 4);  
   $node->content['links']['timetrackings'] = theme('storm_link', 'stormproject', 'stormtimetracking', $node->nid, 5);
   
+  // Code to create invoice auto_add link
+  if (module_exists('storminvoice') && user_access('Storm invoice: add')) {
+    if ($node->billable && !$node->billed) {
+      $v = '';
+      $v = '<strong>'. t('Invoice this item:') .'</strong>';
+      $v .= '<ul>';
+      $v .= '<li>'. l('Add to new invoice', 'storm/invoice/auto_add/new/'. $node->nid) .'</li>';
+      $v .= '<li>'. l('Add to existing invoice', 'storm/invoice/auto_add/existing/'. $node->nid) .'</li>';
+      $v .= '</ul>';
+    }
+    elseif ($node->billed) {
+      $v = '';
+      $v .= '<strong>'. t('Item already billed.') .'</strong>';
+    }
+    else {
+      $v = '';
+      $v .= '<strong>'. t('Item marked unbillable.') .'</strong>';
+    }
+    
+    $node->content['links']['auto_invoice'] = array(
+      '#prefix' => variable_get('storm_icons_display', TRUE) ? '<dt id="storminvoices" class="stormcomponent">' : '<dt class="stormcomponent">',
+      '#suffix' => '</dt>',
+      '#value' => $v,
+      '#weight' => 6,
+    );
+  }
+
+
   $node->content['group1'] = array(
     '#prefix' => '<div class="stormfields">',
     '#suffix' => '</div>',
Index: stormproject/stormproject.views.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormproject/Attic/stormproject.views.inc,v
retrieving revision 1.1.2.7
diff -u -p -r1.1.2.7 stormproject.views.inc
--- stormproject/stormproject.views.inc	12 Dec 2009 21:38:39 -0000	1.1.2.7
+++ stormproject/stormproject.views.inc	26 Apr 2010 10:00:51 -0000
@@ -278,6 +278,34 @@ function stormproject_views_data() {
     ),
   );
   
+  $data['stormproject']['billable'] = array(
+    'title' => t('Project Billable'),
+    'help' => 'Storm Project Billable',
+    'field' => array(
+      'click sortable' => TRUE,
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+    ),
+  );
+  
+  $data['stormproject']['billed'] = array(
+    'title' => t('Project Billed'),
+    'help' => 'Storm Project Billed',
+    'field' => array(
+      'click sortable' => TRUE,
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+    ),
+  );
+
   return $data;
 }
 
Index: stormtimetracking/stormtimetracking.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/storm/stormtimetracking/stormtimetracking.module,v
retrieving revision 1.10.4.50
diff -u -p -r1.10.4.50 stormtimetracking.module
--- stormtimetracking/stormtimetracking.module	4 Apr 2010 22:10:50 -0000	1.10.4.50
+++ stormtimetracking/stormtimetracking.module	26 Apr 2010 10:00:51 -0000
@@ -666,10 +666,11 @@ function stormtimetracking_storminvoice_
       //Code copied with edits from node form
       $new_invoice->requestdate = time();
       $new_invoice->duedate = $new_invoice->requestdate + (variable_get('storminvoice_payment_days', 30) * 86400);
-      $s = "SELECT MAX(CAST(SUBSTRING_INDEX(sin.number, '/', 1) AS SIGNED)) FROM {node} n INNER JOIN {storminvoice} sin ON n.nid=sin.nid
-        WHERE n.type='storminvoice' AND YEAR(FROM_UNIXTIME(sin.requestdate))=YEAR(FROM_UNIXTIME(%d))";
-      $date = getdate($new_invoice->requestdate);
-      $new_invoice->number = (db_result(db_query($s, $new_invoice->requestdate)) + 1) .'/'. $date['year'];
+      //$s = "SELECT MAX(CAST(SUBSTRING_INDEX(sin.number, '/', 1) AS SIGNED)) FROM {node} n INNER JOIN {storminvoice} sin ON n.nid=sin.nid
+      //  WHERE n.type='storminvoice' AND YEAR(FROM_UNIXTIME(sin.requestdate))=YEAR(FROM_UNIXTIME(%d))";
+      //$date = getdate($new_invoice->requestdate);
+      //$new_invoice->number = (db_result(db_query($s, $new_invoice->requestdate)) + 1) .'/'. $date['year'];
+      $new_invoice->number = storminvoice_get_invoice_number($new_invoice->requestdate);
 
       $new_invoice->title = $node->title;
       $new_invoice->uid = $user->uid;
@@ -693,9 +694,9 @@ function stormtimetracking_storminvoice_
       $new_invoice = node_load($invoice_nid);
     }
 
-    $rate_array = array('pricemode_used' => '', 'use_fixed' => FALSE, 'use_hourly' => FALSE, 'use_fixed_timetracking' => FALSE, 'rate_to_use' => 0);
+    $rate_array = array('pricemode_used' => '', 'rate_to_use' => 0);
     
-    $rate_array = stormtimetracking_timetracking_get_rate($node);
+    $rate_array = storminvoice_get_rate($node);
     
     $count = count($new_invoice->items);
     
@@ -704,6 +705,7 @@ function stormtimetracking_storminvoice_
     switch ($rate_array['pricemode_used']) {
       case 'hourly':
         $new_invoice->items[$count]->description .= t('@dur hours work at @rate per hour on @desc', array('@dur' => $node->billing_duration, '@rate' => $rate_array['rate_to_use'], '@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $node->billing_duration * $rate_array['rate_to_use'];
         break;
       case 'daily':
         $new_invoice->items[$count]->description .= t('@dur hours work at @rate per day on @desc', array('@dur' => $node->billing_duration, '@rate' => $rate_array['rate_to_use'], '@desc' => $node->title));
@@ -713,24 +715,15 @@ function stormtimetracking_storminvoice_
         break;
       case 'fixed':
         $new_invoice->items[$count]->description .= t('@dur hours unbilled work on @desc', array('@dur' => $node->billing_duration, '@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
         break;
       case 'fixed_timetracking':
         $new_invoice->items[$count]->description .= t('work billed for @desc', array('@desc' => $node->title));
+        $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
         break;
     }
 
-    if ($rate_array['use_hourly'] == TRUE) {
-      $new_invoice->items[$count]->amount = $node->billing_duration * $rate_array['rate_to_use'];
-      }
-
-    if ($rate_array['use_fixed'] == TRUE) {
-      $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
-      }
-    
-    if ($rate_array['use_fixed_timetracking'] == TRUE) {
-      $new_invoice->items[$count]->amount = $rate_array['rate_to_use'];
-      }
-      
+
     // Tax percent simply uses default at the moment
     $new_invoice->items[$count]->tax1percent = variable_get('storm_tax1_percent', 20);
     //$new_invoice_item->items[$count]->tax1
@@ -767,51 +760,3 @@ function stormtimetracking_views_api() {
  * @return
  *   Variables in an array.
  */
-function stormtimetracking_timetracking_get_rate($node) {
-  $rate_array = array('pricemode_used' => '', 'use_fixed' => FALSE, 'use_hourly' => FALSE, 'use_fixed_timetracking' => FALSE, 'rate_to_use' => 0);
-
-  $hours_per_day = 8;
-  $found = FALSE;
-  
-  foreach (array('ticket' => $node->ticket_nid, 'task' => $node->task_nid, 'project' => $node->project_nid, 'organization' => $node->organization_nid) as $type => $nid) {
-    if($nid) {
-      $parent_item = node_load($nid);
-      switch ($parent_item->pricemode) {
-        case 'hourly':
-          $rate_array['use_hourly'] = TRUE;
-          $found = TRUE;
-          $rate_array['rate_to_use'] = $parent_item->price;
-          break;
-
-        case 'daily':
-          $rate_array['use_hourly'] = TRUE;
-          $found = TRUE;
-          $rate_array['rate_to_use'] = $parent_item->price / $hours_per_day;
-          break;
-
-        case 'fixed':
-          $rate_array['use_fixed'] = TRUE;
-          $found = TRUE;
-          $rate_array['rate_to_use'] = 0;
-          break;
-
-        case 'fixed_timetracking':
-          $rate_array['use_fixed_timetracking'] = TRUE;
-          $found = TRUE;
-          $rate_array['rate_to_use'] = $parent_item->price;
-          break;
-
-        default:
-          continue;
-      }
-    }
-  if ($found == TRUE) {
-  	$rate_array['pricemode_used'] = $parent_item->pricemode;
-    break;
-    }
-  }
-  if($found == FALSE) {
-    drupal_set_message(t('Error whilst finding a rate from ticket, task, project and organization. Consider setting the pricemode and price for your client organizations to avoid this error.'), 'error');
-    }
-  return $rate_array;
-}
