<td>
                        <?php 
        $c = array();
        $quotes = module_quote::get_quotes(array('customer_id' => $job['customer_id']));
        foreach ($quotes as $quote) {
            $c[$quote['quote_id']] = $quote['name'];
        }
        echo print_select_box($c, 'quote_id', $job['quote_id']);
        ?>

                        <?php 
        if ($job['quote_id'] && module_quote::can_i('view', 'Quotes')) {
            ?>

                        <a href="<?php 
            echo module_quote::link_open($job['quote_id'], false);
            ?>
"><?php 
            _e('Open');
            ?>
</a>
                        <?php 
        }
        ?>

                    </td>
                </tr>
                <?php 
    }
    ?>
						    </tr>
						    </thead>
						    <tbody>
						    <?php 
                foreach ($quotes as $quote) {
                    $quote = module_quote::get_quote($quote['quote_id']);
                    ?>

							    <tr class="<?php 
                    echo $c++ % 2 ? "odd" : "even";
                    ?>
">
								    <td class="row_action">
									    <?php 
                    echo module_quote::link_open($quote['quote_id'], true);
                    ?>

								    </td>
								    <td>
									    <?php 
                    echo print_date($quote['date_create']);
                    ?>

								    </td>
								    <td>
									    <?php 
                    echo print_date($quote['date_approved']);
                    ?>

								    </td>
Exemple #3
0
 public static function get_job($job_id, $full = true, $skip_permissions = false)
 {
     $job_id = (int) $job_id;
     if ($job_id <= 0) {
         $job = array();
     } else {
         $cache_key = self::_job_cache_key($job_id, array($job_id, $full, $skip_permissions));
         if ($cached_item = module_cache::get('job', $cache_key)) {
             return $cached_item;
         }
         $cache_key_full = self::_job_cache_key($job_id, array($job_id, true, $skip_permissions));
         if ($cache_key_full != $cache_key && ($cached_item = module_cache::get('job', $cache_key_full))) {
             return $cached_item;
         }
         $cache_timeout = module_config::c('cache_objects', 60);
         $job = get_single("job", "job_id", $job_id);
     }
     // check permissions
     if ($job && isset($job['job_id']) && $job['job_id'] == $job_id) {
         switch (self::get_job_access_permissions()) {
             case _JOB_ACCESS_ALL:
                 break;
             case _JOB_ACCESS_ASSIGNED:
                 // only assigned jobs!
                 $has_job_access = false;
                 if ($job['user_id'] == module_security::get_loggedin_id()) {
                     $has_job_access = true;
                     break;
                 }
                 $tasks = module_job::get_tasks($job['job_id']);
                 foreach ($tasks as $task) {
                     if ($task['user_id'] == module_security::get_loggedin_id()) {
                         $has_job_access = true;
                         break;
                     }
                 }
                 unset($tasks);
                 if (!$has_job_access) {
                     if ($skip_permissions) {
                         $job['_no_access'] = true;
                         // set a flag for custom processing. we check for this when calling get_customer with the skip permissions argument. (eg: in the ticket file listing link)
                     } else {
                         $job = false;
                     }
                 }
                 break;
             case _JOB_ACCESS_CUSTOMER:
                 // tie in with customer permissions to only get jobs from customers we can access.
                 $customers = module_customer::get_customers();
                 $has_job_access = false;
                 if (isset($customers[$job['customer_id']])) {
                     $has_job_access = true;
                 }
                 /*foreach($customers as $customer){
                       // todo, if($job['customer_id'] == 0) // ignore this permission
                       if($customer['customer_id']==$job['customer_id']){
                           $has_job_access = true;
                           break;
                       }
                   }*/
                 unset($customers);
                 if (!$has_job_access) {
                     if ($skip_permissions) {
                         $job['_no_access'] = true;
                         // set a flag for custom processing. we check for this when calling get_customer with the skip permissions argument. (eg: in the ticket file listing link)
                     } else {
                         $job = false;
                     }
                 }
                 break;
         }
         if ($job) {
             $job['taxes'] = get_multiple('job_tax', array('job_id' => $job_id), 'job_tax_id', 'exact', 'order');
         }
     }
     if (!$full) {
         // unserialize our cached staff_total_grouped key (and other cache keys?)
         // this is used in finance.php line 1053
         $job['staff_total_grouped'] = array();
         if (isset($job['c_staff_total_grouped']) && strlen($job['c_staff_total_grouped'])) {
             $job['staff_total_grouped'] = @unserialize($job['c_staff_total_grouped']);
         }
         if (isset($cache_key)) {
             module_cache::put('job', $cache_key, $job, $cache_timeout);
         }
         return $job;
     }
     if (!$job) {
         $customer_id = 0;
         if (isset($_REQUEST['customer_id']) && $_REQUEST['customer_id']) {
             //
             $customer_id = (int) $_REQUEST['customer_id'];
             // find default website id to use.
             if (isset($_REQUEST['website_id'])) {
                 $website_id = (int) $_REQUEST['website_id'];
             } else {
             }
         }
         $default_job_name = module_config::c('job_default_new_name', '');
         if (module_config::c('job_name_incrementing', 0)) {
             $job_number = module_config::c('job_name_incrementing_next', 1);
             // see if there is an job number matching this one.
             $this_job_number = $job_number;
             do {
                 $jobs = get_multiple('job', array('name' => $this_job_number));
                 //'customer_id'=>$customer_id,
                 if (!count($jobs)) {
                     $job_number = $this_job_number;
                 } else {
                     $this_job_number++;
                 }
             } while (count($jobs));
             module_config::save_config('job_name_incrementing_next', $job_number);
             $default_job_name = $job_number . $default_job_name;
         }
         $job = array('job_id' => 'new', 'customer_id' => $customer_id, 'website_id' => isset($_REQUEST['website_id']) ? $_REQUEST['website_id'] : 0, 'hourly_rate' => module_config::c('hourly_rate', 60), 'name' => $default_job_name, 'date_quote' => date('Y-m-d'), 'date_start' => module_config::c('job_allow_quotes', 0) ? '' : date('Y-m-d'), 'date_due' => '', 'date_completed' => '', 'date_renew' => '', 'user_id' => module_security::get_loggedin_id(), 'renew_job_id' => '', 'status' => module_config::s('job_status_default', 'New'), 'type' => module_config::s('job_type_default', 'Website Design'), 'currency_id' => module_config::c('default_currency_id', 1), 'auto_task_numbers' => '0', 'default_task_type' => module_config::c('default_task_type', _TASK_TYPE_HOURS_AMOUNT), 'description' => '', 'quote_id' => 0, 'discount_description' => _l('Discount:'), 'discount_amount' => 0, 'discount_type' => module_config::c('invoice_discount_type', _DISCOUNT_TYPE_BEFORE_TAX));
         if (isset($_REQUEST['from_quote_id']) && (int) $_REQUEST['from_quote_id']) {
             $quote = module_quote::get_quote($_REQUEST['from_quote_id']);
             $job = array_merge($job, $quote);
             $job['date_quote'] = $quote['date_create'];
             $job['date_start'] = date('Y-m-d');
             $job['quote_id'] = (int) $_REQUEST['from_quote_id'];
         }
         // some defaults from the db.
         $job['total_tax_rate'] = module_config::c('tax_percent', 10);
         $job['total_tax_name'] = module_config::c('tax_name', 'TAX');
         if ($customer_id > 0) {
             $customer_data = module_customer::get_customer($customer_id, false, true);
             if ($customer_data && isset($customer_data['default_tax']) && $customer_data['default_tax'] >= 0) {
                 $job['total_tax_rate'] = $customer_data['default_tax'];
                 $job['total_tax_name'] = $customer_data['default_tax_name'];
             }
         }
     }
     // new support for multiple taxes
     if (!isset($job['taxes']) || !count($job['taxes']) && $job['total_tax_rate'] > 0) {
         $job['taxes'] = array();
         $tax_rates = explode(',', $job['total_tax_rate']);
         $tax_names = explode(',', $job['total_tax_name']);
         foreach ($tax_rates as $tax_rate_id => $tax_rate_amount) {
             if ($tax_rate_amount > 0) {
                 $job['taxes'][] = array('order' => 0, 'percent' => $tax_rate_amount, 'name' => isset($tax_names[$tax_rate_id]) ? $tax_names[$tax_rate_id] : $job['total_tax_name'], 'total' => 0, 'amount' => 0, 'discount' => 0, 'increment' => module_config::c('tax_multiple_increment', 0));
             }
         }
     }
     if ($job) {
         // work out total hours etc..
         $job['total_hours'] = 0;
         $job['total_hours_completed'] = 0;
         $job['total_hours_overworked'] = 0;
         $job['total_sub_amount'] = 0;
         $job['total_sub_amount_taxable'] = 0;
         $job['total_sub_amount_unbillable'] = 0;
         $job['total_sub_amount_invoicable'] = 0;
         $job['total_sub_amount_invoicable_taxable'] = 0;
         $job['total_amount_invoicable'] = 0;
         $job['total_tasks_remain'] = 0;
         $job['total_amount'] = 0;
         $job['total_amount_paid'] = 0;
         $job['total_amount_invoiced'] = 0;
         $job['total_amount_invoiced_deposit'] = 0;
         $job['total_amount_todo'] = 0;
         $job['total_amount_outstanding'] = 0;
         $job['total_amount_due'] = 0;
         $job['total_hours_remain'] = 0;
         $job['total_percent_complete'] = isset($job['total_percent_complete']) ? $job['total_percent_complete'] : 0;
         $job['total_tax'] = 0;
         $job['total_tax_invoicable'] = 0;
         $job['invoice_discount_amount'] = 0;
         $job['invoice_discount_amount_on_tax'] = 0;
         $job['total_amount_discounted'] = 0;
         // new feature to invoice incompleted tasks
         $job['uninvoiced_task_ids'] = array();
         // new staff expenses/totals
         $job['staff_hourly_rate'] = $job['hourly_rate'];
         $job['staff_total_hours'] = 0;
         $job['staff_total_hours_completed'] = 0;
         $job['staff_total_hours_overworked'] = 0;
         $job['staff_total_sub_amount'] = 0;
         $job['staff_total_sub_amount_unbillable'] = 0;
         $job['staff_total_amount'] = 0;
         $job['staff_total_grouped'] = array();
         // total staff expenses grouped by individual staff members.
         $job['total_net_amount'] = 0;
         // after the staff expense is taken away.
         if ($job_id > 0) {
             $non_hourly_job_count = $non_hourly_job_completed = 0;
             $tasks = self::get_tasks($job['job_id']);
             $job_percentage_complete_averages = array();
             foreach ($tasks as $task_id => $task) {
                 // new support for different task types
                 if (!isset($task['manual_task_type']) || $task['manual_task_type'] < 0) {
                     $task['manual_task_type'] = $job['default_task_type'];
                 }
                 if (module_config::c('job_task_log_all_hours', 1)) {
                     // jobs have to be marked fully_completd.
                     if (!$task['fully_completed']) {
                         $job['total_tasks_remain']++;
                     }
                 } else {
                     if ($task['amount'] != 0 && $task['completed'] <= 0) {
                         $job['total_tasks_remain']++;
                     } else {
                         if ($task['hours'] > 0 && $task['completed'] < $task['hours']) {
                             $job['total_tasks_remain']++;
                         }
                     }
                 }
                 $tasks[$task_id]['sum_amount'] = 0;
                 if ($task['amount'] != 0) {
                     // we have a custom amount for this task.
                     // do we multiply it by qty (stored in hours?)
                     if ($task['manual_task_type'] == _TASK_TYPE_QTY_AMOUNT) {
                         $tasks[$task_id]['sum_amount'] = $task['amount'] * $task['hours'];
                     } else {
                         $tasks[$task_id]['sum_amount'] = $task['amount'];
                     }
                 }
                 if ($task['manual_task_type'] == _TASK_TYPE_QTY_AMOUNT && $task['hours'] > 0 && $task['amount'] == 0) {
                     $tasks[$task_id]['sum_amount'] = $task['hours'] * $job['hourly_rate'];
                 }
                 if ($task['manual_task_type'] == _TASK_TYPE_HOURS_AMOUNT && $task['hours'] > 0) {
                     $job['total_hours'] += $task['hours'];
                     $task_completed_hours = min($task['hours'], $task['completed']);
                     if ($task['fully_completed']) {
                         // hack to record that we have worked 100% of this task.
                         $task_completed_hours = $task['hours'];
                     }
                     $job['total_hours_completed'] += $task_completed_hours;
                     if ($task['completed'] > $task['hours']) {
                         $job['total_hours_overworked'] += $task['completed'] - $task['hours'];
                     } else {
                         if ($task['completed'] > 0) {
                             // underworked hours
                             $job['total_hours_overworked'] += $task['completed'] - $task['hours'];
                         }
                     }
                     if ($task['amount'] <= 0) {
                         $tasks[$task_id]['sum_amount'] = $task['hours'] * $job['hourly_rate'];
                     }
                 } else {
                     // it's a non-hourly task.
                     // work out if it's completed or not.
                     $non_hourly_job_count++;
                     if ($task['fully_completed']) {
                         $non_hourly_job_completed++;
                     }
                 }
                 if (!$task['invoiced'] && $task['billable']) {
                     $job['uninvoiced_task_ids'][] = $task_id;
                 }
                 if (!$task['invoiced'] && $task['billable'] && (module_config::c('job_task_log_all_hours', 1) || $task['hours'] > 0 && $task['completed'] > 0 && $task['completed'] >= $task['hours'] || $task['hours'] <= 0 && $task['fully_completed'])) {
                     /*if(module_config::c('job_task_log_all_hours',1)){*/
                     // a task has to be marked "fully_completeD" before it will be invoiced.
                     if ($task['fully_completed']) {
                         $job['total_sub_amount_invoicable'] += $tasks[$task_id]['sum_amount'];
                         if ($task['taxable']) {
                             if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_INCREMENTAL) {
                                 foreach ($job['taxes'] as $job_tax_id => $job_tax) {
                                     $job['total_tax_invoicable'] += round($tasks[$task_id]['sum_amount'] * ($job_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                                 }
                             } else {
                                 $job['total_sub_amount_invoicable_taxable'] += $tasks[$task_id]['sum_amount'];
                             }
                         }
                     }
                     /*}else{
                           $job['total_sub_amount_invoicable'] += $tasks[$task_id]['sum_amount'];
                           if($task['taxable']){
                               if(module_config::c('tax_calculate_mode',_TAX_CALCULATE_AT_END)==_TAX_CALCULATE_INCREMENTAL){
                                   $job['total_tax_invoicable'] += round(($tasks[$task_id]['sum_amount'] * ($job['total_tax_rate'] / 100)),module_config::c('currency_decimal_places',2));
                               }else{
                                   $job['total_sub_amount_invoicable_taxable'] += $tasks[$task_id]['sum_amount'];
                               }
                           }
                           //(min($task['hours'],$task['completed']) * $job['hourly_rate']);
                       }*/
                 }
                 if ($task['taxable'] && $task['billable']) {
                     $job['total_sub_amount_taxable'] += $tasks[$task_id]['sum_amount'];
                     if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_INCREMENTAL) {
                         //$job['total_tax'] += round(($tasks[$task_id]['sum_amount'] * ($job['total_tax_rate'] / 100)),module_config::c('currency_decimal_places',2));
                         // todo - incremental multi-tax calculation
                         foreach ($job['taxes'] as $job_tax_id => $job_tax) {
                             if (!isset($job['taxes'][$job_tax_id]['total'])) {
                                 $job['taxes'][$job_tax_id]['total'] = 0;
                             }
                             $job['taxes'][$job_tax_id]['total'] += $tasks[$task_id]['sum_amount'];
                             $job['taxes'][$job_tax_id]['amount'] += round($tasks[$task_id]['sum_amount'] * ($job_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                         }
                     }
                 }
                 if ($task['billable']) {
                     $job['total_sub_amount'] += $tasks[$task_id]['sum_amount'];
                 } else {
                     $job['total_sub_amount_unbillable'] += $tasks[$task_id]['sum_amount'];
                 }
                 $job_percentage_complete_averages[] = self::get_percentage($tasks[$task_id]);
                 // new staff expenses calculations
                 if (self::job_task_has_split_hours($job_id, $job, $task_id, $task)) {
                     $tasks[$task_id]['staff_sum_amount'] = 0;
                     switch ($task['manual_task_type']) {
                         case _TASK_TYPE_QTY_AMOUNT:
                             $tasks[$task_id]['staff_sum_amount'] = $task['staff_amount'] * $task['staff_hours'];
                             break;
                         case _TASK_TYPE_AMOUNT_ONLY:
                             $tasks[$task_id]['staff_sum_amount'] = $task['staff_amount'];
                             break;
                         case _TASK_TYPE_HOURS_AMOUNT:
                             $tasks[$task_id]['staff_sum_amount'] = $task['staff_amount'] == 0 ? $task['staff_hours'] * $job['staff_hourly_rate'] : $task['staff_amount'] * $task['staff_hours'];
                             break;
                     }
                     if ($task['billable']) {
                         $job['staff_total_sub_amount'] += $tasks[$task_id]['staff_sum_amount'];
                         if (!isset($job['staff_total_grouped'][$task['user_id']])) {
                             $job['staff_total_grouped'][$task['user_id']] = 0;
                         }
                         $job['staff_total_grouped'][$task['user_id']] += $tasks[$task_id]['staff_sum_amount'];
                     } else {
                         $job['staff_total_sub_amount_unbillable'] += $tasks[$task_id]['staff_sum_amount'];
                     }
                 }
             }
             // end task loop
             $job['total_hours_remain'] = $job['total_hours'] - $job['total_hours_completed'];
             // add any discounts.
             if ($job['discount_amount'] != 0) {
                 if ($job['discount_type'] == _DISCOUNT_TYPE_AFTER_TAX) {
                     // after tax discount ::::::::::
                     // handled below.
                     //$job['final_modification'] = -$job['discount_amount'];
                 } else {
                     if ($job['discount_type'] == _DISCOUNT_TYPE_BEFORE_TAX) {
                         // before tax discount:::::
                         //$job['final_modification'] = -$job['discount_amount'];
                         // problem : this 'discount_amount_on_tax' calculation may not match the correct final discount calculation as per below
                         if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_INCREMENTAL) {
                             // tax calculated along the way.
                             // we have discounted the 'total amount taxable' so that means we need to reduce the tax amount by that much as well.
                             foreach ($job['taxes'] as $job_tax_id => $job_tax) {
                                 $this_tax_discount = round($job['discount_amount'] * ($job['taxes'][$job_tax_id]['percent'] / 100), module_config::c('currency_decimal_places', 2));
                                 $job['discount_amount_on_tax'] += $this_tax_discount;
                                 if (!isset($job['taxes'][$job_tax_id]['total'])) {
                                     $job['taxes'][$job_tax_id]['total'] = 0;
                                 }
                                 $job['taxes'][$job_tax_id]['total'] -= $job['discount_amount'];
                                 $job['taxes'][$job_tax_id]['amount'] -= $this_tax_discount;
                                 $job['taxes'][$job_tax_id]['discount'] = $this_tax_discount;
                             }
                         } else {
                             // we work out what the tax would have been if there was no applied discount
                             // this is used in job.php
                             $job['taxes_backup'] = $job['taxes'];
                             $job['total_sub_amount_taxable_backup'] = $job['total_sub_amount_taxable'];
                             $total_tax_before_discount = 0;
                             foreach ($job['taxes'] as $job_tax_id => $job_tax) {
                                 $job['taxes'][$job_tax_id]['total'] = $job['total_sub_amount_taxable'];
                                 $job['taxes'][$job_tax_id]['amount'] = round($job['total_sub_amount_taxable'] * ($job_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                                 // here we adjust the 'total_sub_amount_taxable' to include the value from the previous calculation.
                                 // this is for multiple taxes that addup as they go (eg: Canada)
                                 if (isset($job_tax['increment']) && $job_tax['increment']) {
                                     $job['total_sub_amount_taxable'] += $job['taxes'][$job_tax_id]['amount'];
                                 }
                                 $total_tax_before_discount += $job['taxes'][$job_tax_id]['amount'];
                             }
                             $job['taxes'] = $job['taxes_backup'];
                             $job['total_sub_amount_taxable'] = $job['total_sub_amount_taxable_backup'];
                         }
                         // remove the discount amount from the 'sub total' and the 'taxable total' but don't go negative on it.
                         // remove the discount from any non-taxable portion first.
                         $non_taxable_amount = $job['total_sub_amount'] - $job['total_sub_amount_taxable'];
                         $non_taxable_discount = min($job['discount_amount'], $non_taxable_amount);
                         $taxable_discount = $job['discount_amount'] - $non_taxable_discount;
                         //echo "non tax $non_taxable_amount \n nontax discount: $non_taxable_discount \n tax discount: $taxable_discount \n";print_r($job);exit;
                         $job['total_sub_amount'] -= $job['discount_amount'];
                         $job['total_sub_amount_taxable'] -= $taxable_discount;
                     }
                 }
             }
             if (count($job_percentage_complete_averages) > 0) {
                 if (!isset($job['total_percent_complete_manual']) || !$job['total_percent_complete_manual']) {
                     $job['total_percent_complete'] = round(array_sum($job_percentage_complete_averages) / count($job_percentage_complete_averages), 2);
                 } else {
                     $job['total_percent_complete_calculated'] = round(array_sum($job_percentage_complete_averages) / count($job_percentage_complete_averages), 2);
                 }
             }
             /*if($job['total_hours'] > 0){
                   // total hours completed. work out job task based on hours completed.
                   $job['total_percent_complete'] = round($job['total_hours_completed'] / $job['total_hours'],2);
               }else if($non_hourly_job_count>0){
                   // work out job completed rate based on $non_hourly_job_completed and $non_hourly_job_count
                   $job['total_percent_complete'] = round($non_hourly_job_completed/$non_hourly_job_count,2);
               }*/
             // find any invoices
             $invoices = module_invoice::get_invoices(array('job_id' => $job_id));
             foreach ($invoices as $invoice) {
                 $invoice = module_invoice::get_invoice($invoice['invoice_id']);
                 if (!$invoice) {
                     continue;
                 }
                 //print_r($invoice);
                 // we only ad up the invoiced tasks that are from this job
                 // an invoice could have added manually more items to it, so this would throw the price out.
                 $this_invoice = 0;
                 $this_invoice_taxable = 0;
                 $invoice_items = module_invoice::get_invoice_items($invoice['invoice_id']);
                 // first loop will find out of this is a merged invoice or not.
                 $merged_invoice = false;
                 foreach ($invoice_items as $invoice_item) {
                     if ($invoice_item['task_id'] && !isset($tasks[$invoice_item['task_id']])) {
                         $merged_invoice = true;
                     }
                 }
                 // if it's a merged invoice we don't add non-task-id items to the total.
                 // if its a normal non-merged invoice then we can add the non-task linked items to the total.
                 if (!$merged_invoice) {
                     $this_invoice = $invoice['total_amount'];
                 } else {
                     foreach ($invoice_items as $invoice_item) {
                         if ($invoice_item['task_id'] && isset($tasks[$invoice_item['task_id']]) && $tasks[$invoice_item['task_id']]['billable']) {
                             $this_invoice += $tasks[$invoice_item['task_id']]['sum_amount'];
                             if ($invoice_item['taxable']) {
                                 $this_invoice_taxable += $tasks[$invoice_item['task_id']]['sum_amount'];
                                 if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_INCREMENTAL) {
                                     foreach ($invoice_item['taxes'] as $invoice_item_tax) {
                                         $this_invoice += round($tasks[$invoice_item['task_id']]['sum_amount'] * ($invoice_item_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                                     }
                                 }
                             }
                         }
                     }
                 }
                 // any discounts ?
                 $job['invoice_discount_amount'] += $invoice['discount_amount'];
                 $job['invoice_discount_amount_on_tax'] += $invoice['discount_amount_on_tax'];
                 // todo - move all this tax calculation back to
                 if ($merged_invoice && module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_AT_END && $this_invoice_taxable > 0) {
                     $this_invoice_tax = 0;
                     foreach ($invoice['taxes'] as $invoice_tax) {
                         // todo - incremental or what not in here.
                         $this_invoice_tax = $this_invoice_tax + $this_invoice_taxable * ($invoice_tax['percent'] / 100);
                     }
                     $this_invoice += $this_invoice_tax;
                     //$this_invoice = ($this_invoice + ($this_invoice_taxable * ($invoice['total_tax_rate'] / 100)));
                 }
                 //print_r($invoice);
                 if ($invoice['deposit_job_id'] == $job_id) {
                     $job['total_amount_invoiced_deposit'] += $this_invoice;
                 } else {
                 }
                 $job['total_amount_invoiced'] += $this_invoice;
                 $job['total_amount_paid'] += min($invoice['total_amount_paid'], $this_invoice);
                 $job['total_amount_outstanding'] += min($invoice['total_amount_due'], $this_invoice);
             }
             // todo: save these two values in the database so that future changes do not affect them.
             if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_AT_END) {
                 $job['total_tax'] = 0;
                 $job['total_tax_invoicable'] = 0;
                 $previous_tax_id = false;
                 foreach ($job['taxes'] as $job_tax_id => $job_tax) {
                     if (!isset($job['taxes'][$job_tax_id]['total'])) {
                         $job['taxes'][$job_tax_id]['total'] = 0;
                     }
                     if (!isset($job['taxes'][$job_tax_id]['total_invoicable'])) {
                         $job['taxes'][$job_tax_id]['total_invoicable'] = 0;
                     }
                     if (!isset($job['taxes'][$job_tax_id]['amount_invoicable'])) {
                         $job['taxes'][$job_tax_id]['amount_invoicable'] = 0;
                     }
                     $job['taxes'][$job_tax_id]['total'] += $job['total_sub_amount_taxable'];
                     $job['taxes'][$job_tax_id]['total_invoicable'] += $job['total_sub_amount_invoicable_taxable'];
                     if (isset($job_tax['increment']) && $job_tax['increment'] && $previous_tax_id) {
                         $job['taxes'][$job_tax_id]['total'] += $job['taxes'][$previous_tax_id]['amount'];
                         $job['taxes'][$job_tax_id]['total_invoicable'] += $job['taxes'][$previous_tax_id]['amount_invoicable'];
                     }
                     $t = round($job['taxes'][$job_tax_id]['total'] * ($job_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                     $job['taxes'][$job_tax_id]['amount'] += $t;
                     $job['total_tax'] += $t;
                     $t = round($job['taxes'][$job_tax_id]['total_invoicable'] * ($job_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                     $job['taxes'][$job_tax_id]['amount_invoicable'] += $t;
                     $job['total_tax_invoicable'] += $t;
                     $previous_tax_id = $job_tax_id;
                 }
                 //$job['total_tax'] = ( ($job['total_sub_amount_taxable']) * ($job['total_tax_rate'] / 100));
                 //$job['total_tax_invoicable'] =$job['total_sub_amount_invoicable_taxable'] > 0 ? ($job['total_sub_amount_invoicable_taxable'] * ($job['total_tax_rate'] / 100)) : 0;
             }
             $job['total_amount'] = round($job['total_sub_amount'] + $job['total_tax'], module_config::c('currency_decimal_places', 2));
             if ($job['discount_type'] == _DISCOUNT_TYPE_AFTER_TAX) {
                 $job['total_amount'] -= $job['discount_amount'];
                 $job['total_sub_amount_invoicable'] -= $job['discount_amount'];
             }
             $job['total_amount_invoicable'] = $job['total_sub_amount_invoicable'] + $job['total_tax_invoicable'];
             // + ($job['total_sub_amount_invoicable'] * ($job['total_tax_rate'] / 100));
             $job['total_amount_due'] = $job['total_amount'] - $job['total_amount_paid'];
             //todo: chekc if this is wrong with non-invoicable tasks.
             //$job['total_amount_outstanding'] = $job['total_amount_invoiced'] - $job['total_amount_paid'];
             $job['total_amount_discounted'] = $job['total_amount'] - $job['invoice_discount_amount'] - $job['invoice_discount_amount_on_tax'];
             //$job['total_amount_invoicable'] = $job['total_amount_invoicable'] - $job['invoice_discounts']-$job['invoice_discounts_tax'];
             $job['total_amount_todo'] = $job['total_amount_discounted'] - $job['total_amount_invoiced'] - $job['total_amount_invoicable'];
             //$job['total_amount_paid'] -
             // staff calculations
             if ($job['staff_total_sub_amount'] > 0) {
                 // tax for staff??
                 $job['staff_total_amount'] = $job['staff_total_sub_amount'];
             }
             $job['total_net_amount'] = $job['total_amount'] - $job['staff_total_amount'];
         }
     }
     if (isset($cache_key)) {
         module_cache::put('job', $cache_key, $job, $cache_timeout);
     }
     self::save_job_cache($job_id, $job);
     return $job;
 }
// are we sending the paid one? or the dueone.
$template_name = isset($_REQUEST['template_name']) ? $_REQUEST['template_name'] : 'quote_staff_email';
$template = module_template::get_template_by_key($template_name);
$quote['quote_name'] = $quote['name'];
$quote['staff_name'] = $staff['name'];
$quote['quote_url'] = module_quote::link_open($quote_id);
$quote['quote_tasks'] = '<ul>';
$quote['task_count'] = 0;
foreach ($quote_tasks as $quote_task) {
    if ($quote_task['user_id'] != $staff_id) {
        continue;
    }
    $quote['quote_tasks'] .= '<li><strong>' . $quote_task['description'] . '</strong>';
    $quote['quote_tasks'] .= ' <br/>';
    if ($quote_task['long_description']) {
        $quote['quote_tasks'] .= _l('Notes:') . ' <em>' . $quote_task['long_description'] . '</em><br/>';
    }
    if ($quote_task['hours']) {
        $quote['quote_tasks'] .= _l('Hours:') . ' ' . $quote_task['hours'] . '<br/>';
    }
    $quote['quote_tasks'] .= '</li>';
    $quote['task_count']++;
}
$quote['quote_tasks'] .= '</ul>';
// find available "to" recipients.
// customer contacts.
$to = array();
$to[] = array('name' => $staff['name'], 'email' => $staff['email']);
$template->assign_values($quote);
module_email::print_compose(array('title' => _l('Email Quote: %s', $quote['name']), 'find_other_templates' => 'quote_staff_email', 'current_template' => $template_name, 'quote_id' => $quote['quote_id'], 'debug_message' => 'Sending quote to staff', 'to' => $to, 'bcc' => module_config::c('admin_email_address', ''), 'content' => $template->render('html'), 'subject' => $template->replace_description(), 'success_url' => module_quote::link_open($quote_id), 'cancel_url' => module_quote::link_open($quote_id)));
 * IP Address: 67.79.165.254
 */
if ($ticket_id > 0 && module_config::c('ticket_allow_billing', 1) && module_ticket::can_edit_tickets()) {
    $done_in_ticket_billing = true;
    $responsive_summary = array();
    $quotes = array();
    if (class_exists('module_quote', false) && module_quote::is_plugin_enabled()) {
        $quotes = module_quote::get_quotes(array('ticket_id' => $ticket_id));
        foreach ($quotes as $quote) {
            $responsive_summary[] = module_quote::link_open($quote['quote_id'], true, $quote);
        }
    }
    $fieldset_data = array('heading' => array('type' => 'h3', 'title' => 'Ticket Billing', 'responsive' => array('summary' => implode(', ', $responsive_summary))), 'class' => 'tableclass tableclass_form tableclass_full', 'elements' => array());
    $c = array();
    $res = module_customer::get_customers();
    while ($row = array_shift($res)) {
        $c[$row['customer_id']] = $row['customer_name'];
    }
    if ($ticket['customer_id'] < 0) {
        $ticket['customer_id'] = false;
    }
    $fieldset_data['elements'][] = array('title' => _l('Customer'), 'fields' => array(array('type' => 'select', 'name' => 'change_customer_id', 'value' => $ticket['customer_id'], 'options' => $c), array('type' => 'button', 'name' => 'new_customer', 'value' => _l('New'), 'onclick' => "window.location.href='" . module_customer::link_open('new', false) . "&move_user_id=" . $ticket['user_id'] . "';")));
    if (class_exists('module_quote', false) && module_quote::is_plugin_enabled()) {
        $quote_list = '';
        foreach ($quotes as $quote) {
            $quote_list .= module_quote::link_open($quote['quote_id'], true, $quote) . ' (<a href="#" onclick="ucm.ticket.add_to_message($(this).data(\'link\'));return false;" data-link="<a href=\'' . module_quote::link_public($quote['quote_id']) . '\'>View Quote</a>">insert link</a>) <br/>';
        }
        $fieldset_data['elements'][] = array('title' => _l('Quotes'), 'fields' => array($quote_list, array('type' => 'button', 'name' => 'new_quote', 'value' => _l('New'), 'onclick' => "window.location.href='" . module_quote::link_open('new', false) . "&ticket_id=" . $ticket_id . "';")));
    }
    echo module_form::generate_fieldset($fieldset_data);
}
Exemple #6
0
 public static function quote_html($quote_id, $quote_data, $mode = 'html')
 {
     if ($quote_id && $quote_data) {
         // spit out the quote html into a file, then pass it to the pdf converter
         // to convert it into a PDF.
         $quote = $quote_data;
         if (class_exists('module_company', false) && isset($quote_data['company_id']) && (int) $quote_data['company_id'] > 0) {
             module_company::set_current_company_id($quote_data['company_id']);
         }
         $quote_template = isset($quote_data['quote_template_print']) && strlen($quote_data['quote_template_print']) ? $quote_data['quote_template_print'] : module_config::c('quote_template_print_default', 'quote_pdf');
         $quote_template_suffix = '';
         if ($quote_template != 'quote_pdf') {
             $quote_template_suffix = str_replace('quote_pdf', '', $quote_template);
         }
         ob_start();
         include module_theme::include_ucm('includes/plugin_quote/template/quote_task_list.php');
         $task_list_html = ob_get_clean();
         $replace = self::get_replace_fields($quote_id, $quote_data);
         $replace['task_list'] = $task_list_html;
         $replace['quote_link'] = module_quote::link_public($quote_id);
         $replace['external_quote_template_html'] = '';
         $external_quote_template = module_template::get_template_by_key('quote_pdf');
         $external_quote_template->assign_values($replace);
         $replace['external_quote_template_html'] = $external_quote_template->replace_content();
         ob_start();
         $template = module_template::get_template_by_key($quote_template);
         $template->assign_values($replace);
         echo $template->render('html');
         $quote_html = ob_get_clean();
         return $quote_html;
     }
     return false;
 }
Exemple #7
0
<?php

/** 
 * Copyright: dtbaker 2012
 * Licence: Please check CodeCanyon.net for licence details. 
 * More licence clarification available here:  http://codecanyon.net/wiki/support/legal-terms/licensing-terms/ 
 * Deploy: 9809 f200f46c2a19bb98d112f2d32a8de0c4
 * Envato: 4ffca17e-861e-4921-86c3-8931978c40ca
 * Package Date: 2015-11-25 02:55:20 
 * IP Address: 67.79.165.254
 */
$quote_safe = true;
// stop including files directly.
if (!module_quote::can_i('view', 'Quotes')) {
    echo 'permission denied';
    return;
}
if (isset($_REQUEST['quote_id'])) {
    if (isset($_REQUEST['email_staff'])) {
        include module_theme::include_ucm("includes/plugin_quote/pages/quote_admin_email_staff.php");
    } else {
        if (isset($_REQUEST['email'])) {
            include module_theme::include_ucm("includes/plugin_quote/pages/quote_admin_email.php");
        } else {
            if ((int) $_REQUEST['quote_id'] > 0) {
                include module_theme::include_ucm("includes/plugin_quote/pages/quote_admin_edit.php");
                //include("quote_admin_edit.php");
            } else {
                include module_theme::include_ucm("includes/plugin_quote/pages/quote_admin_create.php");
                //include("quote_admin_create.php");
            }
include('quote_public.php');
$quote['quote_tasks'] = ob_get_clean();*/
// generate the PDF ready for sending.
$pdf = module_quote::generate_pdf($quote_id);
// find available "to" recipients.
// customer contacts.
$to_select = false;
if ($quote['customer_id']) {
    $customer = module_customer::get_customer($quote['customer_id']);
    $quote['customer_name'] = $customer['customer_name'];
    $to = module_user::get_contacts(array('customer_id' => $quote['customer_id']));
    if ($quote['contact_user_id']) {
        $primary = module_user::get_user($quote['contact_user_id']);
        if ($primary) {
            $to_select = $primary['email'];
        }
    } else {
        if ($customer['primary_user_id']) {
            $primary = module_user::get_user($customer['primary_user_id']);
            if ($primary) {
                $to_select = $primary['email'];
            }
        }
    }
} else {
    $to = array();
}
$template->assign_values($quote);
ob_start();
module_email::print_compose(array('title' => _l('Email Quote: %s', $quote['name']), 'find_other_templates' => 'quote_email', 'current_template' => $template_name, 'customer_id' => $quote['customer_id'], 'quote_id' => $quote['quote_id'], 'debug_message' => 'Sending quote as email', 'to' => $to, 'to_select' => $to_select, 'bcc' => module_config::c('admin_email_address', ''), 'content' => $template->render('html'), 'subject' => $template->replace_description(), 'success_url' => module_quote::link_open($quote_id), 'cancel_url' => module_quote::link_open($quote_id), 'attachments' => array(array('path' => $pdf, 'name' => basename($pdf), 'preview' => module_quote::link_public_print($quote_id)))));
if (function_exists('hook_handle_callback')) {
    hook_handle_callback('quote_task_after', $task_data['quote_id'], $task_data['quote_task_id'], $quote, $task_data);
}
?>
    </td>
    <td colspan="<?php 
echo $colspan;
?>
" valign="top">

        <div>
        <?php 
_e('Task Type:');
?>
 <?php 
$types = module_quote::get_task_types();
$types['-1'] = _l('Default (%s)', $types[$quote['default_task_type']]);
module_form::generate_form_element(array('type' => 'select', 'name' => 'quote_task[' . $quote_task_id . '][manual_task_type]', 'id' => 'manual_task_type_' . $quote_task_id, 'options' => $types, 'blank' => false, 'value' => $task_data['manual_task_type_real']));
?>
        </div>

    </td>
    <td class="edit_task_options">
        <div>
        <?php 
if ($task_editable) {
    ?>
            <input type="hidden" name="quote_task[<?php 
    echo $quote_task_id;
    ?>
][billable_t]" value="1">
Exemple #10
0
 public function delete_customer($customer_id, $remove_linked_data = true)
 {
     $customer_id = (int) $customer_id;
     if ($customer_id > 0) {
         if (_DEMO_MODE && $customer_id == 1) {
             set_error('Sorry this is a Demo Customer. It cannot be changed.');
             redirect_browser(self::link_open($customer_id));
         }
         $customer = self::get_customer($customer_id);
         if ($customer && $customer['customer_id'] == $customer_id) {
             // todo: Delete emails (wack these in this customer_deleted hook)
             hook_handle_callback('customer_deleted', $customer_id, $remove_linked_data);
             if (class_exists('module_group', false)) {
                 // remove the customer from his groups
                 module_group::delete_member($customer_id, 'customer');
             }
             if (class_exists('module_extra', false)) {
                 module_extra::delete_extras('customer', 'customer_id', $customer_id);
             }
             // remove the contacts from this customer
             foreach (module_user::get_contacts(array('customer_id' => $customer_id)) as $val) {
                 if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                     module_user::delete_user($val['user_id']);
                 }
             }
             // remove staff
             delete_from_db('customer_user_rel', 'customer_id', $customer_id);
             if (class_exists('module_note', false)) {
                 module_note::note_delete("customer", 'customer_id', $customer_id);
             }
             handle_hook("address_delete", $this, 'all', "customer", 'customer_id', $customer_id);
             // todo, check the 'delete' permission on each one of these 'delete' method calls
             // do that better when we remove each of these and put them into the customer delete hook
             if ($remove_linked_data) {
                 if (class_exists('module_website', false) && module_website::is_plugin_enabled()) {
                     foreach (module_website::get_websites(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             module_website::delete_website($val['website_id']);
                         }
                     }
                 }
                 if (class_exists('module_job', false) && module_job::is_plugin_enabled()) {
                     foreach (module_job::get_jobs(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             module_job::delete_job($val['job_id']);
                         }
                     }
                 }
                 if (class_exists('module_invoice', false) && module_invoice::is_plugin_enabled()) {
                     foreach (module_invoice::get_invoices(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             module_invoice::delete_invoice($val['invoice_id']);
                         }
                     }
                 }
                 if (class_exists('module_quote', false) && module_quote::is_plugin_enabled()) {
                     foreach (module_quote::get_quotes(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             module_quote::delete_quote($val['quote_id']);
                         }
                     }
                 }
                 //handle_hook("file_delete",$this,"customer",'customer_id',$customer_id);
             } else {
                 // instead of deleting these records we just update them to customer_id = 0
                 if (class_exists('module_website', false) && module_website::is_plugin_enabled()) {
                     foreach (module_website::get_websites(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             update_insert('website_id', $val['website_id'], 'website', array('customer_id' => 0));
                         }
                     }
                 }
                 if (class_exists('module_job', false) && module_job::is_plugin_enabled()) {
                     foreach (module_job::get_jobs(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             update_insert('job_id', $val['job_id'], 'job', array('customer_id' => 0));
                         }
                     }
                 }
                 if (class_exists('module_invoice', false) && module_invoice::is_plugin_enabled()) {
                     foreach (module_invoice::get_invoices(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             update_insert('invoice_id', $val['invoice_id'], 'invoice', array('customer_id' => 0));
                         }
                     }
                 }
                 if (class_exists('module_quote', false) && module_quote::is_plugin_enabled()) {
                     foreach (module_quote::get_quotes(array('customer_id' => $customer_id)) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             update_insert('quote_id', $val['quote_id'], 'quote', array('customer_id' => 0));
                         }
                     }
                 }
                 if (class_exists('module_file', false) && module_file::is_plugin_enabled()) {
                     foreach (module_file::get_files(array('owner_id' => $customer_id, 'owner_table' => 'customer')) as $val) {
                         if ($val['customer_id'] && $val['customer_id'] == $customer_id) {
                             update_insert('file_id', $val['file_id'], 'file', array('owner_id' => 0, 'owner_table' => ''));
                         }
                     }
                 }
             }
             // finally delete the main customer record
             // (this is so the above code works with its sql joins)
             $sql = "DELETE FROM " . _DB_PREFIX . "customer WHERE customer_id = '" . $customer_id . "' LIMIT 1";
             query($sql);
         }
     }
 }
        ?>
            <td><?php 
        foreach ($module->get_data_link_keys() as $key) {
            if (isset($data[$key]) && (int) $data[$key] > 0) {
                switch ($key) {
                    case 'customer_id':
                        echo module_customer::link_open($data[$key], true);
                        break;
                    case 'job_id':
                        echo module_job::link_open($data[$key], true);
                        break;
                    case 'invoice_id':
                        echo module_invoice::link_open($data[$key], true);
                        break;
                    case 'quote_id':
                        echo module_quote::link_open($data[$key], true);
                        break;
                    case 'file_id':
                        echo module_file::link_open($data[$key], true);
                        break;
                }
            }
        }
        ?>
</td>
            <?php 
    }
    /*<td><a href="<?php echo $module->link('',array("data_record_id"=>$data['data_record_id'],"customer_id"=>isset($_REQUEST['customer_id']) ? $_REQUEST['customer_id'] : false)); ?>"><?php echo $module->format_record_id($data['data_type_id'],$data['data_record_id']); ?></a></td>
      <td><?php echo $data['status']; ?></td>
      <td><?php echo print_date($data['date_updated']); ?></td>
      <?php */
        if (module_quote::can_i('edit', 'Quote Tasks') && $quote['date_approved'] == '0000-00-00') {
            $task_editable = true;
        } else {
            $task_editable = false;
        }
        echo module_quote::generate_task_preview($quote_id, $quote, $quote_task_id, $task_data, $task_editable);
    }
    ?>

                        </tbody>
                        </table>
                        <?php 
    if ((int) $quote_id > 0) {
        ?>
 <div id="quote_summary"> <?php 
        echo module_quote::generate_quote_summary($quote_id, $quote);
        ?>
 </div> <?php 
    }
    ?>

                            </div>


                <?php 
    $fieldset_data = array('heading' => $header, 'elements_before' => ob_get_clean());
    echo module_form::generate_fieldset($fieldset_data);
}
// end can i view quote tasks
hook_handle_callback('layout_column_half', 'end');
?>
Exemple #13
0
 public static function hook_filter_generate_fieldset_options($callback_name, $fieldset_options)
 {
     if (is_array($fieldset_options) && isset($fieldset_options['id']) && $fieldset_options['id'] == 'quote_advanced') {
         $ticket_quote_rel_data = array();
         $customer_id = 0;
         // which customer to bring related quotes in from.
         if (isset($_REQUEST['ticket_id']) && (int) $_REQUEST['ticket_id'] > 0) {
             $ticket_data = module_ticket::get_ticket($_REQUEST['ticket_id'], false);
             if ($ticket_data && $ticket_data['ticket_id'] == $_REQUEST['ticket_id']) {
                 // we're creating a new quote linked to this particular ticket
                 $ticket_quote_rel_data[] = $ticket_data['ticket_id'];
                 $customer_id = $ticket_data['customer_id'];
             }
         }
         if (isset($_REQUEST['quote_id']) && (int) $_REQUEST['quote_id'] > 0) {
             // we're opening an existing quote, find any matching linked tickets.
             $quote_data = module_quote::get_quote($_REQUEST['quote_id']);
             if ($quote_data && $quote_data['quote_id'] == $_REQUEST['quote_id']) {
                 if ($quote_data['customer_id']) {
                     $customer_id = $quote_data['customer_id'];
                 }
                 // any existing ones from within the database?
                 $existing = get_multiple('ticket_quote_rel', array('quote_id' => $quote_data['quote_id']));
                 foreach ($existing as $e) {
                     if ($e['ticket_id']) {
                         $ticket_quote_rel_data[] = $e['ticket_id'];
                     }
                 }
             }
         }
         $select_values = array();
         if ($customer_id > 0) {
             $tickets = module_ticket::get_tickets(array('customer_id' => $customer_id));
             while ($row = mysql_fetch_assoc($tickets)) {
                 $select_values[$row['ticket_id']] = module_ticket::ticket_number($row['ticket_id']) . ' ' . substr($row['subject'], 0, 20) . '...';
             }
         }
         if (!count($ticket_quote_rel_data)) {
             $ticket_quote_rel_data = array(false);
         }
         $ticket_links = array();
         foreach ($ticket_quote_rel_data as $ticket_id) {
             if ($ticket_id > 0) {
                 $ticket_links[] = module_ticket::link_open($ticket_id, true);
             }
         }
         $fieldset_options['elements']['ticket_rel_ids'] = array('title' => 'Linked Tickets', 'fields' => array('<div id="ticket_rel_ids_holder">', array('type' => 'select', 'name' => 'ticket_rel_ids[]', 'options' => $select_values, 'multiple' => 'ticket_rel_ids_holder', 'values' => $ticket_quote_rel_data), '</div>', '<div>' . implode(' ', $ticket_links) . '</div>'));
     }
     return $fieldset_options;
 }
            }
        });
    }
}
if (class_exists('module_group', false)) {
    $columns['group'] = array('title' => 'Group', 'callback' => function ($quote) {
        $groups = module_group::get_groups_search(array('owner_table' => 'quote', 'owner_id' => $quote['quote_id']));
        $g = array();
        foreach ($groups as $group) {
            $g[] = $group['name'];
        }
        echo implode(', ', $g);
    });
}
$table_manager->set_columns($columns);
$table_manager->row_callback = function ($row_data) {
    // load the full vendor data before displaying each row so we have access to more details
    return module_quote::get_quote($row_data['quote_id']);
};
$table_manager->set_rows($quotes);
if (class_exists('module_extra', false)) {
    $table_manager->display_extra('quote', function ($quote) {
        module_extra::print_table_data('quote', $quote['quote_id']);
    });
}
$table_manager->pagination = true;
$table_manager->print_table();
?>


</form>
}
$staff_members = module_user::get_staff_members();
$staff_member_rel = array();
foreach ($staff_members as $staff_member) {
    $staff_member_rel[$staff_member['user_id']] = $staff_member['name'];
}
if (!isset($file['staff_ids']) || !is_array($file['staff_ids']) || !count($file['staff_ids'])) {
    $file['staff_ids'] = array(false);
    if (count($staff_member_rel) == 1) {
        $file['staff_ids'] = array(key($staff_member_rel));
    }
}
$fieldset_data['elements'][] = array('title' => 'Staff', 'fields' => array(array('type' => 'hidden', 'name' => 'staff_ids_save', 'value' => 1), '<div id="staff_ids_holder" style="float:left;">', array('type' => 'select', 'name' => 'staff_ids[]', 'options' => $staff_member_rel, 'multiple' => 'staff_ids_holder', 'values' => $file['staff_ids']), '</div>', function () use(&$file) {
    if ($file['quote_id']) {
        echo ' ';
        echo '<a href="' . module_quote::link_open($file['quote_id'], false) . '">' . _l('Open Quote &raquo;') . '</a>';
    }
}, array('type' => 'html', 'value' => '', 'help' => 'Assign a staff member to this file. Staff members are users who have EDIT permissions on Job Tasks. Click the plus sign to add more staff members. You can apply the "Only Assigned Staff" permission in User Role settings to restrict staff members to these files.<br><br>If there are assigned staff members then those members will be the only ones to receive notifications when a change is made to the file. If no staff are assigned to this file then anyone with the "Receive Alerts" permission will receive file change/comment alerts.')));
echo module_form::generate_fieldset($fieldset_data);
unset($fieldset_data);
hook_handle_callback('layout_column_half', 2);
$fieldset_data = array('heading' => array('title' => _l('Bucket Description'), 'type' => 'h3'), 'elements' => array(array('field' => array('type' => 'wysiwyg', 'name' => 'description', 'value' => $file['description']))));
echo module_form::generate_fieldset($fieldset_data);
unset($fieldset_data);
if ((int) $file_id > 0) {
    if (module_file::can_i('edit', 'Files')) {
        module_email::display_emails(array('title' => 'File Emails', 'search' => array('file_id' => $file_id)));
    }
    ob_start();
    $search = array();
    $search['bucket_parent_file_id'] = $file_id;
Exemple #16
0
    public function external_hook($hook)
    {
        switch ($hook) {
            case 'view':
                $file_id = isset($_REQUEST['i']) ? (int) $_REQUEST['i'] : false;
                $hash = isset($_REQUEST['hash']) ? trim($_REQUEST['hash']) : false;
                if ($file_id && $hash) {
                    $correct_hash = $this->link_public($file_id, true);
                    if ($correct_hash == $hash) {
                        // all good to print a receipt for this payment.
                        $file_data = $this->get_file($file_id, false);
                        if ($file_data && $file_data['file_id'] == $file_id) {
                            if (isset($_POST['save_file_comments'])) {
                                if (isset($_POST['file_approve']) && isset($_POST['file_approve_go']) && isset($_POST['file_approve_name']) && strlen($_POST['file_approve_name']) > 0) {
                                    update_insert('file_id', $file_id, 'file', array('approved_time' => time(), 'approved_by' => $_POST['file_approve_name']));
                                    // send email, same 'updated' email as before.
                                    $this->send_file_changed_notice($file_id, false, true);
                                    //redirect_browser($this->link_public($file_id));
                                    $_REQUEST['new_comment_text'] = _l('File was approved at %s by %s', print_date(time(), true), htmlspecialchars($_POST['file_approve_name']));
                                }
                                if (isset($_POST['pointers'])) {
                                    update_insert('file_id', $file_id, 'file', array('pointers' => $_POST['pointers']));
                                }
                                $this->save_file_comments($file_id);
                                redirect_browser($this->link_public($file_id));
                            }
                            module_template::init_template('file_approval_view', '<h2>File Details</h2>
    File Name: <strong>{FILE_NAME}</strong> <br/>
    Download: <strong><a href="{FILE_DOWNLOAD_URL}">Click Here</a></strong> <br/>
    Status: <strong>{STATUS}</strong> <br/>
    Customer: <strong>{CUSTOMER_NAME}</strong> <br/>
    {if:JOB_NAME}Job: <strong>{JOB_NAME}</strong> <br/>{endif:JOB_NAME}
    {if:FILE_APPROVAL_PENDING}
    <h2>File Approval Pending</h2>
    <p>If you would like to approve this file please complete the form below:</p>
    <p>Your Name: <input type="text" name="file_approve_name"> </p>
    <p><input type="checkbox" name="file_approve_go" value="yes"> Yes, I approve this file. </p>
    <p><input type="submit" name="file_approve" value="Approve File" class="submit_button save_button"></p>
    {endif:FILE_APPROVAL_PENDING}
    {if:FILE_APPROVED}
    <h2>File Has Been Approved</h2>
    <p>Thank you, the file was approved by <strong>{APPROVED_BY}</strong> on <strong>{APPROVED_TIME}</strong>.</p>
    {endif:FILE_APPROVED}
    <h2>File Comments</h2>
    <p>Please feel free to add comments to this file using the form below.</p>
    {FILE_COMMENTS}
    {if:FILE_PREVIEW}
    <h2>File Preview</h2>
    <div style="overflow:scroll;">{FILE_PREVIEW}</div>
    {endif:FILE_PREVIEW}
    ', 'Used when displaying the file to a customer for approval.', 'code');
                            $template = module_template::get_template_by_key('file_approval_view');
                            // generate the html for the task output
                            $job_data = $file_data['job_id'] ? module_job::get_replace_fields($file_data['job_id']) : array();
                            if (class_exists('module_quote', false)) {
                                $quote_data = $file_data['quote_id'] ? module_quote::get_replace_fields($file_data['quote_id']) : array();
                            }
                            $customer_data = $file_data['customer_id'] ? module_customer::get_replace_fields($file_data['customer_id']) : array();
                            $file_data['file_preview'] = module_file::generate_preview($file_id, $file_data['file_name'], $file_data);
                            $file_data['FILE_DOWNLOAD_URL'] = module_file::link_public_view($file_id);
                            if (isset($file_data['approved_time'])) {
                                switch ($file_data['approved_time']) {
                                    case -1:
                                        $file_data['FILE_APPROVAL_PENDING'] = 1;
                                        break;
                                    case 0:
                                        break;
                                    default:
                                        $file_data['FILE_APPROVED'] = 1;
                                        $file_data['APPROVED_TIME'] = print_date($file_data['approved_time'], true);
                                }
                            }
                            if (class_exists('module_extra', false) && module_extra::is_plugin_enabled()) {
                                $all_extra_fields = module_extra::get_defaults('file');
                                foreach ($all_extra_fields as $e) {
                                    $file_data[$e['key']] = _l('N/A');
                                }
                                // and find the ones with values:
                                $extras = module_extra::get_extras(array('owner_table' => 'file', 'owner_id' => $file_id));
                                foreach ($extras as $e) {
                                    $file_data[$e['extra_key']] = $e['extra'];
                                }
                            }
                            ob_start();
                            ?>

                            <div id="file_notes">
                            <div style="border-top:1px dashed #CCCCCC; padding:3px; margin:3px 0;">
                                <textarea name="new_comment_text" style="width:100%;" class="no_permissions"></textarea>
                                <div style="text-align: right;">
                                <input type="submit" name="butt_save_note" id="butt_save_note" value="<?php 
                            echo _l('Add Comment');
                            ?>
" class="submit_button no_permissions">
                                    </div>
                            </div>
                            <?php 
                            foreach (module_file::get_file_comments($file_id) as $item) {
                                $note_text = forum_text($item['comment']);
                                if (preg_match_all('/#(\\d+)/', $note_text, $matches)) {
                                    //
                                    foreach ($matches[1] as $digit) {
                                        $note_text = preg_replace('/#' . $digit . '([^\\d]*)/', '<span node_id=' . $digit . ' class="pointer-ids pointer-id-' . $digit . '">#' . $digit . '</span>$1', $note_text);
                                    }
                                }
                                ?>

                                <div style="border-top:1px dashed #CCCCCC; padding:3px; margin:3px 0;">
                                    <?php 
                                echo $note_text;
                                ?>

                                    <div style="font-size:10px; text-align:right; color:#CCCCCC;">From <?php 
                                echo $item['create_user_id'] ? module_user::link_open($item['create_user_id'], true) : _l('Customer');
                                ?>
 on <?php 
                                echo print_date($item['date_created'], true);
                                ?>

                                    </div>
                                </div>

                                <?php 
                            }
                            ?>

                            </div>
                            <?php 
                            $file_data['file_comments'] = ob_get_clean();
                            $template->assign_values($file_data);
                            $template->assign_values($customer_data);
                            $template->assign_values($job_data);
                            if (class_exists('module_quote', false)) {
                                $quote_data['quote_approved_by'] = $quote_data['approved_by'];
                                $quote_data['quote_date_approved'] = $quote_data['date_approved'];
                                unset($quote_data['approved_by']);
                                unset($quote_data['date_approved']);
                                $template->assign_values($quote_data);
                            }
                            $template->page_title = $file_data['file_name'];
                            $template->content = '<form action="" method="post"><input type="hidden" name="save_file_comments" value="1">' . $template->content . '</form>';
                            echo $template->render('pretty_html');
                        }
                    }
                }
                break;
            case 'download_bucket':
                @ob_end_clean();
                $file_id = isset($_REQUEST['i']) ? (int) $_REQUEST['i'] : false;
                $hash = isset($_REQUEST['hash']) ? trim($_REQUEST['hash']) : false;
                if ($file_id && $hash) {
                    $correct_hash = $this->link_public_download_bucket($file_id, true);
                    if ($correct_hash == $hash) {
                        // all good to print a receipt for this payment.
                        $file_data = $this->get_file($file_id, false);
                        @ignore_user_abort(true);
                        $search = array();
                        $search['bucket_parent_file_id'] = $file_id;
                        $files = module_file::get_files($search);
                        //Create ZIP
                        $zip = new ZipArchive();
                        $zipName = "bucket-" . $file_id . "-" . md5($file_id . _UCM_SECRET) . ".zip";
                        if ($zip->open(_FILE_UPLOAD_PATH . $zipName, ZIPARCHIVE::CREATE) !== TRUE) {
                            echo 'Failed to create bucket zip file';
                            exit;
                        }
                        foreach ($files as $file) {
                            if (is_file($file['file_path'])) {
                                $zip->addFromString($file['file_name'], file_get_contents($file['file_path']));
                            }
                        }
                        $zip->close();
                        //Set headers
                        header("Pragma: public");
                        header("Expires: 0");
                        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                        header("Cache-Control: public");
                        header("Content-Description: File Transfer");
                        header("Content-type: application/octet-stream");
                        //header("Content-Disposition: attachment; filename='" . $zipName . "'");
                        header("Content-Disposition: attachment; filename=\"" . preg_replace("#[^a-zA-Z0-9]+#", "-", $file_data['file_name']) . ".zip\";");
                        header("Content-Transfer-Encoding: binary");
                        header("Content-Length: " . filesize(_FILE_UPLOAD_PATH . $zipName));
                        @clearstatcache();
                        //Make sure the file size isn't cached
                        $size = @readfile(_FILE_UPLOAD_PATH . $zipName);
                        if (!$size) {
                            echo file_get_contents(_FILE_UPLOAD_PATH . $zipName);
                        }
                        @unlink(_FILE_UPLOAD_PATH . $zipName);
                    }
                }
                exit;
                break;
            case 'download':
                @ob_end_clean();
                $file_id = isset($_REQUEST['i']) ? (int) $_REQUEST['i'] : false;
                $hash = isset($_REQUEST['hash']) ? trim($_REQUEST['hash']) : false;
                if ($file_id && $hash) {
                    $correct_hash = $this->link_public_view($file_id, true);
                    if ($correct_hash == $hash) {
                        // all good to print a receipt for this payment.
                        $file_data = $this->get_file($file_id, false);
                        if (isset($file_data['file_url']) && strlen($file_data['file_url'])) {
                            redirect_browser($file_data['file_url']);
                        } else {
                            if (is_file($file_data['file_path'])) {
                                header("Pragma: public");
                                header("Expires: 0");
                                header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                                header("Cache-Control: private", false);
                                header("Content-type: " . dtbaker_mime_type($file_data['file_name'], $file_data['file_path']));
                                if (!isset($_REQUEST['embed'])) {
                                    header("Content-Disposition: attachment; filename=\"" . $file_data['file_name'] . "\";");
                                    header("Content-Transfer-Encoding: binary");
                                }
                                header("Content-Length: " . filesize($file_data['file_path']));
                                //readfile($file_data['file_path']);
                                $size = @readfile($file_data['file_path']);
                                if (!$size) {
                                    echo file_get_contents($file_data['file_path']);
                                }
                            } else {
                                echo 'Not found';
                            }
                        }
                    }
                }
                exit;
                break;
        }
    }
    </td>
</tr>
<?php 
}
$replace['quote_summary'] = ob_get_clean();
/* START QUOTE LINE ITEMS */
$task_decimal_places = module_config::c('task_amount_decimal_places', -1);
if ($task_decimal_places < 0) {
    $task_decimal_places = false;
    // use default currency dec places.
}
$task_decimal_places_trim = module_config::c('task_amount_decimal_places_trim', 0);
$all_item_row_html = '';
$item_count = 0;
// changed from 1
foreach (module_quote::get_quote_items($quote_id, $quote) as $quote_item_id => $quote_item_data) {
    $row_replace = array('item_odd_or_even' => $item_count++ % 2 ? 'odd' : 'even', 'item_number' => '', 'item_description' => '', 'item_tax' => 0, 'item_tax_rate' => '');
    if (isset($quote_item_data['task_order']) && $quote_item_data['task_order'] > 0) {
        $row_replace['item_number'] = $quote_item_data['task_order'];
    } else {
        $row_replace['item_number'] = $item_count;
    }
    $row_replace['item_description'] .= htmlspecialchars($quote_item_data['description']);
    if (module_config::c('quote_show_long_desc', 1)) {
        $long_description = $quote_item_data['long_description'];
        if ($long_description != '') {
            $row_replace['item_description'] .= '<br/><em>' . forum_text($long_description) . '</em>';
        }
    }
    /*if(isset($quote_item_data['date_done']) && $quote_item_data['date_done'] != '0000-00-00'){
          $row_replace['item_date'] .= print_date($quote_item_data['date_done']);
Exemple #18
0
 function handle_hook($hook, $calling_module = false, $owner_table = false, $key_name = false, $key_value = false, $rel_data = false)
 {
     switch ($hook) {
         case "home_alerts":
             $alerts = array();
             if (module_config::c('allow_note_reminders', 1)) {
                 // find any jobs that are past the due date and dont have a finished date.
                 $key = _l('Note Reminder');
                 if (class_exists('module_dashboard', false)) {
                     module_dashboard::register_group($key, array('columns' => array('name' => _l('Reminder'), 'type' => _l('Type'), 'full_link' => _l('Link'), 'date' => _l('Date'), 'days' => _l('Date'))));
                 }
                 $sql = "SELECT * FROM `" . _DB_PREFIX . "note` n ";
                 $sql .= " WHERE n.`reminder` = 1 AND n.note_time < " . (int) strtotime('+' . module_config::c('alert_days_in_future', 5) . ' days') . "";
                 $sql .= " AND ( n.`user_id` = 0 OR n.`user_id` = " . module_security::get_loggedin_id() . ")";
                 $sql .= " ORDER BY n.note_time ASC";
                 $tasks = qa($sql);
                 foreach ($tasks as $task) {
                     $alert_res = process_alert(date('Y-m-d', $task['note_time']), $key);
                     if ($alert_res) {
                         $alert_res['link'] = $task['rel_data'];
                         // fix for linking when changing folder.
                         $alert_res['type'] = _l(ucwords($task['owner_table']));
                         switch ($task['owner_table']) {
                             case 'user':
                                 $user = module_user::get_user($task['owner_id']);
                                 if ($user['customer_id'] || $user['vendor_id']) {
                                     $alert_res['link'] = module_user::link_open_contact($task['owner_id'], false, $user);
                                     $alert_res['full_link'] = module_user::link_open_contact($task['owner_id'], true, $user);
                                     $alert_res['type'] = _l('Contact');
                                 } else {
                                     $alert_res['link'] = module_user::link_open($task['owner_id'], false, $user);
                                     $alert_res['full_link'] = module_user::link_open($task['owner_id'], true, $user);
                                 }
                                 break;
                             case 'invoice':
                                 $invoice_data = module_invoice::get_invoice($task['owner_id'], true);
                                 if (!$invoice_data || !isset($invoice_data['invoice_id']) || $invoice_data['invoice_id'] != $task['owner_id']) {
                                     continue 2;
                                 }
                                 $alert_res['link'] = module_invoice::link_open($task['owner_id'], false, $invoice_data);
                                 $alert_res['full_link'] = module_invoice::link_open($task['owner_id'], true, $invoice_data);
                                 break;
                             case 'quote':
                                 $quote_data = module_quote::get_quote($task['owner_id'], true);
                                 if (!$quote_data || !isset($quote_data['quote_id']) || $quote_data['quote_id'] != $task['owner_id']) {
                                     continue 2;
                                 }
                                 $alert_res['link'] = module_quote::link_open($task['owner_id'], false, $quote_data);
                                 $alert_res['full_link'] = module_quote::link_open($task['owner_id'], true, $quote_data);
                                 break;
                             case 'website':
                                 $website_data = module_website::get_website($task['owner_id']);
                                 if (!$website_data || !isset($website_data['website_id']) || $website_data['website_id'] != $task['owner_id']) {
                                     continue 2;
                                 }
                                 $alert_res['link'] = module_website::link_open($task['owner_id'], false);
                                 $alert_res['full_link'] = module_website::link_open($task['owner_id'], true);
                                 break;
                             case 'customer':
                                 $customer_data = module_customer::get_customer($task['owner_id']);
                                 if (!$customer_data || !isset($customer_data['customer_id']) || $customer_data['customer_id'] != $task['owner_id']) {
                                     continue 2;
                                 }
                                 $alert_res['link'] = module_customer::link_open($task['owner_id'], false, $customer_data);
                                 $alert_res['full_link'] = module_customer::link_open($task['owner_id'], true, $customer_data);
                                 break;
                             case 'vendor':
                                 $vendor_data = module_vendor::get_vendor($task['owner_id']);
                                 if (!$vendor_data || !isset($vendor_data['vendor_id']) || $vendor_data['vendor_id'] != $task['owner_id']) {
                                     continue 2;
                                 }
                                 $alert_res['link'] = module_vendor::link_open($task['owner_id'], false, $vendor_data);
                                 $alert_res['full_link'] = module_vendor::link_open($task['owner_id'], true, $vendor_data);
                                 break;
                             case 'job':
                                 $job_data = module_job::get_job($task['owner_id']);
                                 if (!$job_data || !isset($job_data['job_id']) || $job_data['job_id'] != $task['owner_id']) {
                                     continue 2;
                                 }
                                 $alert_res['link'] = module_job::link_open($task['owner_id'], false, $job_data);
                                 $alert_res['full_link'] = module_job::link_open($task['owner_id'], true, $job_data);
                                 break;
                                 // todo - add others.
                         }
                         $alert_res['name'] = $task['note'];
                         $alert_res['date'] = print_date($alert_res['date']);
                         $alert_res['time'] = $task['note_time'];
                         $alerts[] = $alert_res;
                     }
                 }
             }
             return $alerts;
             break;
             /*case "note_list":
             				if($owner_id && $owner_id != 'new'){
             
             					$note_items = $this->get_notes(array("owner_table"=>$owner_table,"owner_id"=>$owner_id));
             					foreach($note_items as &$note_item){
             						// do it in loop here because of $this issues in static method below.
             						// instead of include file below.
             						$note_item['html'] = $this->print_note($note_item['note_id']);
             					}
             					include("pages/note_list.php");
             				}else{
             					echo 'Please save first before creating notes.';
             				}
             				break;*/
         /*case "note_list":
         				if($owner_id && $owner_id != 'new'){
         
         					$note_items = $this->get_notes(array("owner_table"=>$owner_table,"owner_id"=>$owner_id));
         					foreach($note_items as &$note_item){
         						// do it in loop here because of $this issues in static method below.
         						// instead of include file below.
         						$note_item['html'] = $this->print_note($note_item['note_id']);
         					}
         					include("pages/note_list.php");
         				}else{
         					echo 'Please save first before creating notes.';
         				}
         				break;*/
         case "note_delete":
             // find the key we are saving this address against.
             $owner_id = (int) $key_value;
             if (!$owner_id || $owner_id == 'new') {
                 // find one in the post data.
                 if (isset($_REQUEST[$key_name])) {
                     $owner_id = $_REQUEST[$key_name];
                 }
             }
             $note_hash = md5($owner_id . '|' . $owner_table);
             // just for posting unique arrays.
             if ($owner_table && $owner_id) {
                 $this->note_delete($owner_table, $owner_id);
             }
             break;
     }
 }
Exemple #19
0
 private function _handle_send_email()
 {
     $options = @unserialize(base64_decode($_REQUEST['options']));
     if (!$options) {
         $options = array();
     }
     $options = $this->get_email_compose_options($options);
     if (isset($_REQUEST['custom_to'])) {
         $custom_to = is_array($_REQUEST['custom_to']) ? $_REQUEST['custom_to'] : array($_REQUEST['custom_to']);
         $to = array();
         foreach ($custom_to as $ct) {
             $ct = explode('||', $ct);
             $ct['email'] = $ct[0];
             $ct['name'] = isset($ct[1]) ? $ct[1] : '';
             $ct['user_id'] = isset($ct[2]) ? (int) $ct[2] : 0;
             $to[] = $ct;
         }
     } else {
         $to = isset($options['to']) && is_array($options['to']) ? $options['to'] : array();
     }
     $email = $this->new_email();
     $email->subject = $options['subject'];
     foreach ($to as $t) {
         if (isset($t['user_id']) && $t['user_id'] > 0) {
             $email->set_to('user', $t['user_id'], $t['email'], $t['name'] . (isset($t['last_name']) && module_config::c('email_to_full_name', 1) ? ' ' . $t['last_name'] : ''));
         } else {
             $email->set_to_manual($t['email'], $t['name'] . (isset($t['last_name']) && module_config::c('email_to_full_name', 1) ? ' ' . $t['last_name'] : ''));
         }
     }
     // set from is the default from address.
     if (isset($options['from_email'])) {
         $email->set_from_manual($options['from_email'], isset($options['from_name']) ? $options['from_name'] : '');
         $email->set_bounce_address($options['from_email']);
     }
     if ($options['cc'] && is_array($options['cc'])) {
         foreach ($options['cc'] as $cc_details) {
             $bits = explode('||', $cc_details);
             if (count($bits) >= 2 && $bits[0]) {
                 $email->set_cc_manual($bits[0], $bits[1]);
             }
         }
     }
     if ($options['bcc']) {
         $bcc = explode(',', $options['bcc']);
         foreach ($bcc as $b) {
             $b = trim($b);
             if (strlen($b)) {
                 $email->set_bcc_manual($b, '');
             }
         }
     }
     if (isset($options['company_id'])) {
         $email->company_id = $options['company_id'];
     }
     if (isset($options['customer_id'])) {
         // todo: verify this is a legit customer id we can send emails to.
         $email->customer_id = $options['customer_id'];
         if ($options['customer_id'] > 0) {
             foreach (module_customer::get_replace_fields($options['customer_id']) as $key => $val) {
                 //echo "Replacing $key with $val <br>";
                 $email->replace($key, $val);
             }
         }
     }
     if (isset($options['newsletter_id'])) {
         $email->newsletter_id = $options['newsletter_id'];
     }
     if (isset($options['file_id'])) {
         $email->file_id = $options['file_id'];
     }
     if (isset($options['send_id'])) {
         $email->send_id = $options['send_id'];
     }
     if (isset($options['invoice_id'])) {
         $email->invoice_id = $options['invoice_id'];
         if ($options['invoice_id'] > 0) {
             foreach (module_invoice::get_replace_fields($options['invoice_id']) as $key => $val) {
                 $email->replace($key, $val);
             }
         }
     }
     if (isset($options['job_id'])) {
         $email->job_id = $options['job_id'];
         if ($options['job_id'] > 0) {
             foreach (module_job::get_replace_fields($options['job_id']) as $key => $val) {
                 $email->replace($key, $val);
             }
         }
     }
     if (isset($options['website_id'])) {
         $email->website_id = $options['website_id'];
         if ($options['website_id'] > 0) {
             foreach (module_website::get_replace_fields($options['website_id']) as $key => $val) {
                 $email->replace($key, $val);
             }
         }
     }
     if (isset($options['quote_id'])) {
         $email->quote_id = $options['quote_id'];
         if ($options['quote_id'] > 0) {
             foreach (module_quote::get_replace_fields($options['quote_id']) as $key => $val) {
                 $email->replace($key, $val);
             }
         }
     }
     // custom data integration
     if (class_exists('module_data', false) && module_config::c('custom_data_in_email', 1) && $options['customer_id'] > 0 && !empty($_REQUEST['custom_data_info']) && !empty($_REQUEST['custom_data_related'])) {
         global $plugins;
         // find all possible custom data entries
         $data_types = $plugins['data']->get_data_types();
         foreach ($data_types as $data_type) {
             switch ($data_type['data_type_menu']) {
                 case _CUSTOM_DATA_MENU_LOCATION_CUSTOMER:
                     if ($plugins['data']->can_i('view', $data_type['data_type_name'])) {
                         $search = array('customer_id' => $options['customer_id'], 'data_type_id' => $data_type['data_type_id']);
                         // we have to limit the data types to only those created by current user if they are not administration
                         $datas = $plugins['data']->get_datas($search);
                         if ($datas) {
                             // found some! does this exist in one of our inputs?
                             if (!empty($_REQUEST['custom_data_info'][$data_type['data_type_id']]) && !empty($_REQUEST['custom_data_related'][$data_type['data_type_id']])) {
                                 $data_record_id = $_REQUEST['custom_data_related'][$data_type['data_type_id']];
                                 $data_info = json_decode($_REQUEST['custom_data_info'][$data_type['data_type_id']], true);
                                 if (is_array($data_info) && isset($datas[$data_record_id])) {
                                     // we have a winner!
                                     $list_fields = array();
                                     $data_field_groups = $plugins['data']->get_data_field_groups($data_type['data_type_id']);
                                     foreach ($data_field_groups as $data_field_group) {
                                         $data_fields = $plugins['data']->get_data_fields($data_field_group['data_field_group_id']);
                                         foreach ($data_fields as $data_field) {
                                             if ($data_field['show_list']) {
                                                 $list_fields[$data_field['data_field_id']] = $data_field;
                                             }
                                         }
                                     }
                                     $list_data_items = $plugins['data']->get_data_items($data_record_id);
                                     foreach ($list_fields as $list_field) {
                                         $settings = @unserialize($list_data_items[$list_field['data_field_id']]['data_field_settings']);
                                         if (!isset($settings['field_type'])) {
                                             $settings['field_type'] = isset($list_field['field_type']) ? $list_field['field_type'] : false;
                                         }
                                         $value = false;
                                         if (isset($list_data_items[$list_field['data_field_id']])) {
                                             $value = $list_data_items[$list_field['data_field_id']]['data_text'];
                                         }
                                         if ($value) {
                                             $data_info['key'] = $value;
                                             break;
                                         }
                                     }
                                     $data_info['data_record_id'] = $data_record_id[$data_type['data_type_id']];
                                     $email->custom_data[$data_type['data_type_id']] = $data_info;
                                     $email->set_custom_data($data_type['data_type_id'], $data_record_id);
                                 }
                             }
                         }
                     }
             }
         }
     }
     // final override for first_name last_name if selected from the custom to drop down
     foreach ($to as $t) {
         if (isset($t['user_id']) && $t['user_id'] > 0) {
             $user = module_user::get_user($t['user_id']);
             if ($user) {
                 if (strpos($options['content'], '{AUTO_LOGIN_LINK}') !== false && $t['user_id'] != 1) {
                     $email->replace('AUTO_LOGIN_LINK', module_security::generate_auto_login_link($t['user_id']));
                 }
                 $email->replace('first_name', $user['name']);
                 $email->replace('last_name', $user['last_name']);
             }
         }
     }
     if (isset($options['note_id'])) {
         $email->note_id = $options['note_id'];
     }
     if (isset($options['debug_message'])) {
         $email->debug_message = $options['debug_message'];
     }
     $email->set_html($options['content']);
     foreach ($options['attachments'] as $attachment) {
         $email->AddAttachment($attachment['path'], $attachment['name']);
     }
     // new addition, manually added attachments.
     if (isset($_FILES['manual_attachment']) && isset($_FILES['manual_attachment']['tmp_name'])) {
         foreach ($_FILES['manual_attachment']['tmp_name'] as $key => $tmp_name) {
             if (is_uploaded_file($tmp_name) && isset($_FILES['manual_attachment']['name'][$key]) && strlen($_FILES['manual_attachment']['name'][$key])) {
                 $email->AddAttachment($tmp_name, $_FILES['manual_attachment']['name'][$key]);
             }
         }
     }
     if ($email->send()) {
         if (isset($options['success_callback_args']) && count($options['success_callback_args']) && $options['success_callback'] && is_callable($options['success_callback'])) {
             // new callback method using call_user_func_array
             $args = $options['success_callback_args'];
             $args['email_id'] = $email->email_id;
             if (preg_match('#module_\\w#', $options['success_callback'])) {
                 call_user_func($options['success_callback'], $args);
             }
         }
         /*else if($options['success_callback']){
               eval($options['success_callback']);
           }*/
         set_message('Email sent successfully');
         redirect_browser($options['complete_url']);
     } else {
         set_error('Sending email failed: ' . $email->error_text);
         redirect_browser($options['cancel_url']);
     }
 }