* Deploy: 9809 f200f46c2a19bb98d112f2d32a8de0c4
 * Envato: 4ffca17e-861e-4921-86c3-8931978c40ca
 * Package Date: 2015-11-25 02:55:20 
 * IP Address: 67.79.165.254
 */
if (!$quote_safe) {
    die('failed');
}
if (!module_quote::can_i('edit', 'Quotes')) {
    die('no perms');
}
$quote_id = (int) $_REQUEST['quote_id'];
$staff_id = (int) $_REQUEST['staff_id'];
$staff = module_user::get_user($staff_id);
$quote = module_quote::get_quote($quote_id);
$quote_tasks = module_quote::get_tasks($quote_id);
// template for sending emails.
// 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/>';
示例#2
0
 public static function get_quote($quote_id, $full = true, $skip_permissions = false)
 {
     $quote_id = (int) $quote_id;
     if ($quote_id <= 0) {
         $quote = array();
     } else {
         $cache_key = self::_quote_cache_key($quote_id, array($quote_id, $full, $skip_permissions));
         if ($cached_item = module_cache::get('quote', $cache_key)) {
             if (function_exists('hook_filter_var')) {
                 $cached_item = hook_filter_var('get_quote', $cached_item, $quote_id);
             }
             return $cached_item;
         }
         $cache_key_full = self::_quote_cache_key($quote_id, array($quote_id, true, $skip_permissions));
         if ($cache_key_full != $cache_key && ($cached_item = module_cache::get('quote', $cache_key_full))) {
             if (function_exists('hook_filter_var')) {
                 $cached_item = hook_filter_var('get_quote', $cached_item, $quote_id);
             }
             return $cached_item;
         }
         $cache_timeout = module_config::c('cache_objects', 60);
         $quote = get_single("quote", "quote_id", $quote_id);
     }
     // check permissions
     if ($quote && isset($quote['quote_id']) && $quote['quote_id'] == $quote_id) {
         switch (self::get_quote_access_permissions()) {
             case _QUOTE_ACCESS_ALL:
                 break;
             case _QUOTE_ACCESS_ASSIGNED:
                 // only assigned quotes!
                 $has_quote_access = false;
                 if ($quote['user_id'] == module_security::get_loggedin_id()) {
                     $has_quote_access = true;
                     break;
                 }
                 $tasks = module_quote::get_tasks($quote['quote_id']);
                 foreach ($tasks as $task) {
                     if ($task['user_id'] == module_security::get_loggedin_id()) {
                         $has_quote_access = true;
                         break;
                     }
                 }
                 unset($tasks);
                 if (!$has_quote_access) {
                     if ($skip_permissions) {
                         $quote['_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 {
                         $quote = false;
                     }
                 }
                 break;
             case _QUOTE_ACCESS_CUSTOMER:
                 // tie in with customer permissions to only get quotes from customers we can access.
                 $customers = module_customer::get_customers();
                 $has_quote_access = false;
                 if (isset($customers[$quote['customer_id']])) {
                     $has_quote_access = true;
                 }
                 /*foreach($customers as $customer){
                       // todo, if($quote['customer_id'] == 0) // ignore this permission
                       if($customer['customer_id']==$quote['customer_id']){
                           $has_quote_access = true;
                           break;
                       }
                   }*/
                 unset($customers);
                 if (!$has_quote_access) {
                     if ($skip_permissions) {
                         $quote['_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 {
                         $quote = false;
                     }
                 }
                 break;
         }
         if (!$quote) {
             $quote = array();
             if (function_exists('hook_filter_var')) {
                 $quote = hook_filter_var('get_quote', $quote, $quote_id);
             }
             return $quote;
         }
         $quote['taxes'] = get_multiple('quote_tax', array('quote_id' => $quote_id), 'quote_tax_id', 'exact', 'order');
     }
     if (!$full) {
         if (isset($cache_key)) {
             module_cache::put('quote', $cache_key, $quote, $cache_timeout);
         }
         if (function_exists('hook_filter_var')) {
             $quote = hook_filter_var('get_quote', $quote, $quote_id);
         }
         return $quote;
     }
     if (!$quote) {
         $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_quote_name = module_config::c('quote_default_new_name', '');
         if (module_config::c('quote_name_incrementing', 0)) {
             $quote_number = module_config::c('quote_name_incrementing_next', 1);
             // see if there is an quote number matching this one.
             $this_quote_number = $quote_number;
             do {
                 $quotes = get_multiple('quote', array('name' => $this_quote_number));
                 //'customer_id'=>$customer_id,
                 if (!count($quotes)) {
                     $quote_number = $this_quote_number;
                 } else {
                     $this_quote_number++;
                 }
             } while (count($quotes));
             module_config::save_config('quote_name_incrementing_next', $quote_number);
             $default_quote_name = $quote_number . $default_quote_name;
         }
         $quote = array('quote_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_quote_name, 'date_create' => date('Y-m-d'), 'date_approved' => '0000-00-00', 'approved_by' => '', 'user_id' => module_security::get_loggedin_id(), 'contact_user_id' => -1, 'status' => module_config::s('quote_status_default', 'New'), 'tax_type' => module_config::c('invoice_tax_type', 0), 'type' => module_config::s('quote_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' => '', 'discount_description' => _l('Discount:'), 'discount_amount' => 0, 'discount_type' => module_config::c('invoice_discount_type', _DISCOUNT_TYPE_BEFORE_TAX));
         // some defaults from the db.
         $quote['total_tax_rate'] = module_config::c('tax_percent', 10);
         $quote['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) {
                 $quote['total_tax_rate'] = $customer_data['default_tax'];
                 $quote['total_tax_name'] = $customer_data['default_tax_name'];
             }
         }
     }
     // new support for multiple taxes
     if (!isset($quote['taxes']) || !count($quote['taxes']) && $quote['total_tax_rate'] > 0) {
         $quote['taxes'] = array();
         $tax_rates = explode(',', $quote['total_tax_rate']);
         $tax_names = explode(',', $quote['total_tax_name']);
         foreach ($tax_rates as $tax_rate_id => $tax_rate_amount) {
             if ($tax_rate_amount > 0) {
                 $quote['taxes'][] = array('order' => 0, 'percent' => $tax_rate_amount, 'name' => isset($tax_names[$tax_rate_id]) ? $tax_names[$tax_rate_id] : $quote['total_tax_name'], 'total' => 0, 'amount' => 0, 'discount' => 0, 'increment' => module_config::c('tax_multiple_increment', 0));
             }
         }
     }
     if ($quote) {
         // work out total hours etc..
         $quote['total_hours'] = 0;
         $quote['total_hours_completed'] = 0;
         $quote['total_hours_overworked'] = 0;
         $quote['total_sub_amount'] = 0;
         $quote['total_sub_amount_taxable'] = 0;
         $quote['total_sub_amount_unbillable'] = 0;
         $quote['total_sub_amount_invoicable'] = 0;
         $quote['total_sub_amount_invoicable_taxable'] = 0;
         $quote['total_amount_invoicable'] = 0;
         $quote['total_tasks_remain'] = 0;
         $quote['total_amount'] = 0;
         $quote['total_amount_paid'] = 0;
         $quote['total_amount_invoiced'] = 0;
         $quote['total_amount_invoiced_deposit'] = 0;
         $quote['total_amount_todo'] = 0;
         $quote['total_amount_outstanding'] = 0;
         $quote['total_amount_due'] = 0;
         $quote['total_hours_remain'] = 0;
         $quote['total_percent_complete'] = 0;
         $quote['total_tax'] = 0;
         $quote['total_tax_invoicable'] = 0;
         //            $quote['invoice_discount_amount'] = 0;
         //            $quote['invoice_discount_amount_on_tax'] = 0;
         //            $quote['total_amount_discounted'] = 0;
         // new feature to invoice incompleted tasks
         $quote['uninvoiced_quote_task_ids'] = array();
         $quote_items = self::get_quote_items((int) $quote['quote_id'], $quote);
         foreach ($quote_items as $quote_item) {
             if ($quote_item['quote_item_amount'] != 0) {
                 // we have a custom amount for this quote_item
                 if ($quote_item['billable']) {
                     $quote['total_sub_amount'] += $quote_item['quote_item_amount'];
                     if ($quote_item['taxable']) {
                         $quote['total_sub_amount_taxable'] += $quote_item['quote_item_amount'];
                         if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_INCREMENTAL) {
                             // tax calculated along the way (this isn't the recommended way, but was included as a feature request)
                             // we add tax to each of the tax array items
                             //$quote['total_tax'] += round(($quote_item['quote_item_amount'] * ($quote['total_tax_rate'] / 100)),module_config::c('currency_decimal_places',2));
                             foreach ($quote['taxes'] as $quote_tax_id => $quote_tax) {
                                 if (!isset($quote['taxes'][$quote_tax_id]['total'])) {
                                     $quote['taxes'][$quote_tax_id]['total'] = 0;
                                 }
                                 $quote['taxes'][$quote_tax_id]['total'] += $quote_item['quote_item_amount'];
                                 $quote['taxes'][$quote_tax_id]['amount'] += round($quote_item['quote_item_amount'] * ($quote_tax['percent'] / 100), module_config::c('currency_decimal_places', 2));
                             }
                         }
                     }
                 } else {
                     $quote['total_sub_amount_unbillable'] += $quote_item['quote_item_amount'];
                 }
             }
         }
         // add any discounts.
         if ($quote['discount_amount'] != 0) {
             if ($quote['discount_type'] == _DISCOUNT_TYPE_AFTER_TAX) {
                 // after tax discount ::::::::::
                 // handled below.
                 //$quote['final_modification'] = -$quote['discount_amount'];
             } else {
                 if ($quote['discount_type'] == _DISCOUNT_TYPE_BEFORE_TAX) {
                     // before tax discount:::::
                     //$quote['final_modification'] = -$quote['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 ($quote['taxes'] as $quote_tax_id => $quote_tax) {
                             $this_tax_discount = round($quote['discount_amount'] * ($quote['taxes'][$quote_tax_id]['percent'] / 100), module_config::c('currency_decimal_places', 2));
                             $quote['discount_amount_on_tax'] += $this_tax_discount;
                             if (!isset($quote['taxes'][$quote_tax_id]['total'])) {
                                 $quote['taxes'][$quote_tax_id]['total'] = 0;
                             }
                             $quote['taxes'][$quote_tax_id]['total'] -= $quote['discount_amount'];
                             $quote['taxes'][$quote_tax_id]['amount'] -= $this_tax_discount;
                             $quote['taxes'][$quote_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
                         $quote['taxes_backup'] = $quote['taxes'];
                         $quote['total_sub_amount_taxable_backup'] = $quote['total_sub_amount_taxable'];
                         $total_tax_before_discount = 0;
                         foreach ($quote['taxes'] as $quote_tax_id => $quote_tax) {
                             $quote['taxes'][$quote_tax_id]['total'] = $quote['total_sub_amount_taxable'];
                             $quote['taxes'][$quote_tax_id]['amount'] = round($quote['total_sub_amount_taxable'] * ($quote_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($quote_tax['increment']) && $quote_tax['increment']) {
                                 $quote['total_sub_amount_taxable'] += $quote['taxes'][$quote_tax_id]['amount'];
                             }
                             $total_tax_before_discount += $quote['taxes'][$quote_tax_id]['amount'];
                         }
                         $quote['taxes'] = $quote['taxes_backup'];
                         $quote['total_sub_amount_taxable'] = $quote['total_sub_amount_taxable_backup'];
                     }
                     $quote['total_sub_amount'] -= $quote['discount_amount'];
                     $quote['total_sub_amount_taxable'] -= $quote['discount_amount'];
                 }
             }
         }
         if (module_config::c('tax_calculate_mode', _TAX_CALCULATE_AT_END) == _TAX_CALCULATE_AT_END) {
             // tax needs to be calculated based on the total_sub_amount_taxable
             $previous_quote_tax_id = false;
             foreach ($quote['taxes'] as $quote_tax_id => $quote_tax) {
                 $quote['taxes'][$quote_tax_id]['total'] = $quote['total_sub_amount_taxable'];
                 if (isset($quote_tax['increment']) && $quote_tax['increment'] && $previous_quote_tax_id) {
                     $quote['taxes'][$quote_tax_id]['total'] += $quote['taxes'][$previous_quote_tax_id]['amount'];
                 }
                 $quote['taxes'][$quote_tax_id]['amount'] = round($quote['taxes'][$quote_tax_id]['total'] * ($quote_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)
                 $previous_quote_tax_id = $quote_tax_id;
             }
             //$quote['total_tax'] = round(($quote['total_sub_amount_taxable'] * ($quote['total_tax_rate'] / 100)),module_config::c('currency_decimal_places',2));
         } else {
             //$quote['total_tax'] = 0;
         }
         if (isset($quote['tax_type']) && $quote['tax_type'] == 1) {
             // hack! not completely correct, oh well.
             // todo - make this work with more than 1 tax rate.
             // $amount / 1.05  ( this is 1 + tax %)
             // this will only work if a single tax has been included.
             if (is_array($quote['taxes']) && count($quote['taxes']) > 1) {
                 set_error('Included tax calculation only works with 1 tax rate');
             } else {
                 if (is_array($quote['taxes']) && count($quote['taxes'])) {
                     reset($quote['taxes']);
                     $quote_tax_id = key($quote['taxes']);
                     if (isset($quote['taxes'][$quote_tax_id])) {
                         $taxable_amount = $quote['total_sub_amount_taxable'] / (1 + $quote['taxes'][$quote_tax_id]['percent'] / 100);
                         $quote['taxes'][$quote_tax_id]['amount'] = $quote['total_sub_amount_taxable'] - $taxable_amount;
                         $quote['total_sub_amount'] = $quote['total_sub_amount'] - $quote['taxes'][$quote_tax_id]['amount'];
                     }
                 }
             }
         }
         $quote['total_tax'] = 0;
         foreach ($quote['taxes'] as $quote_tax_id => $quote_tax) {
             $quote['total_tax'] += $quote_tax['amount'];
         }
         $quote['total_amount'] = $quote['total_sub_amount'] + $quote['total_tax'];
         if ($quote['discount_type'] == _DISCOUNT_TYPE_AFTER_TAX) {
             $quote['total_amount'] -= $quote['discount_amount'];
         }
         $quote['total_amount'] = round($quote['total_amount'], module_config::c('currency_decimal_places', 2));
     }
     if (isset($cache_key)) {
         module_cache::put('quote', $cache_key, $quote, $cache_timeout);
     }
     if (function_exists('hook_filter_var')) {
         $quote = hook_filter_var('get_quote', $quote, $quote_id);
     }
     return $quote;
 }