/** * This method adds taxrates to the invoice rows. * * @param array The array containing all invoice rows * * @return array The array containing (taxed) invoice rows * * @author Former03 GmbH :: Florian Lippert <*****@*****.**> */ public function applyTaxRate($invoice) { $invoice_new = array(); foreach ($invoice as $rowid => $invoice_row) { // If we don't have a valid taxclass, use the default one. if (!isset($invoice_row['taxclass']) || !isset($this->taxclasses[$invoice_row['taxclass']])) { $invoice_row['taxclass'] = $this->default_taxclass; } if (isset($invoice_row['taxclass']) && isset($this->taxclasses[$invoice_row['taxclass']])) { // Once-fees are quite easy, just get the valid taxrate and add it to the row. if (isset($invoice_row['service_occurence']) && $invoice_row['service_occurence'] == 'once') { $taxchanges = $this->getTaxChanges($invoice_row['taxclass'], $invoice_row['service_date']); $pricing = array('taxrate' => $taxchanges[0]['taxrate'], 'total_fee' => $invoice_row['setup_fee']); $invoice_new[] = array_merge($invoice_row, $pricing); } elseif (isset($invoice_row['service_occurence']) && $invoice_row['service_occurence'] == 'period') { // Get all tax changes in our service interval $taxchanges = $this->getTaxChanges($invoice_row['taxclass'], $invoice_row['service_date_begin'], manipulateDate($invoice_row['service_date_end'], '-', 1, 'd')); // In pricing we store all changes to our invoice row, will get merged lateron. $pricing = array('taxrate' => $taxchanges[0]['taxrate'], 'total_fee' => 0); // number_days will store the days we already processed... $number_days = 0; // ... whereas days_diff contains the whole number of days of our service interval. $days_diff = calculateDayDifference($invoice_row['service_date_begin'], $invoice_row['service_date_end']); $service_date_begin_array = transferDateToArray($invoice_row['service_date_begin']); // Now we walk through the interval, stepping is the interval length. while ($days_diff >= $number_days + $this->getDaysForInterval($invoice_row['interval_length'], $invoice_row['interval_type'], $service_date_begin_array)) { // Whenever we happen to meet a tax change, remaining will reduced by the number of days to that tax change. $remaining = $interval_days = $this->getDaysForInterval($invoice_row['interval_length'], $invoice_row['interval_type'], $service_date_begin_array); $interval_begin = manipulateDate($invoice_row['service_date_begin'], '+', $number_days, 'd'); $interval_end = manipulateDate($invoice_row['service_date_begin'], '+', $number_days + $interval_days, 'd'); // Now get tax changes in the current interval. $taxchanges = $this->getTaxChanges($invoice_row['taxclass'], $interval_begin, $interval_end); // Maybe taxrate already changed on the first day of our interval. if ($pricing['taxrate'] != $taxchanges[0]['taxrate']) { $pricing['service_date_end'] = $taxchanges[0]['valid_to']; $invoice_new[] = array_merge($invoice_row, $pricing); $pricing['taxrate'] = $taxchanges[0]['taxrate']; $pricing['total_fee'] = 0; } // Anyways, we don't need the current taxrate. unset($taxchanges[0]); // Walk through all taxchanges... foreach ($taxchanges as $valid_from => $taxchange) { $tax_days = calculateDayDifference($interval_begin, $valid_from); // Subtract the days we are going to tax from the remaining days in our interval $remaining -= $tax_days; // total_fee is a fraction of the interval fee $pricing['total_fee'] += $invoice_row['interval_fee'] * ($tax_days / $interval_days); // Set ending day of row to day when tax changed $pricing['service_date_end'] = $taxchange['valid_from']; // And add a new row to invoice $invoice_new[] = array_merge($invoice_row, $pricing); // Next line begins with the day when tax changed $interval_begin = $pricing['service_date_begin'] = $taxchange['valid_from']; $pricing['taxrate'] = $taxchange['taxrate']; $pricing['total_fee'] = 0; } // Incruse number_days (loop condition value) $number_days += $interval_days; // also update service_date_begin_array, so self::getDaysForInterval returns a correct value in our loop condition $service_date_begin_array[$invoice_row['interval_type']] += $invoice_row['interval_length']; // Finally add the remaining fraction to total_fee $pricing['total_fee'] += $invoice_row['interval_fee'] * ($remaining / $interval_days); } // Last element, so use our real service_date_end unset($pricing['service_date_end']); // If there are still have some days left (e.g. when service was terminated during an interval)... if ($days_diff > $number_days) { // ... calculate last total_fee... $pricing['total_fee'] += $invoice_row['interval_fee'] * (($days_diff - $number_days) / $this->getDaysForInterval($invoice_row['interval_length'], $invoice_row['interval_type'], $service_date_begin_array)); } // ... and finally add last line. $invoice_new[] = array_merge($invoice_row, $pricing); } } else { $invoice_new[] = $invoice_row; } } return $invoice_new; }
/** * Here we calculate the traffic usage, as we get the interval from the collector at this point. * All the rest is done in parent::buildInvoiceRowIntervalFee. * * @param array Service details * @param array Service description * @return array The invoice row * * @author Former03 GmbH :: Florian Lippert <*****@*****.**> */ function buildInvoiceRowIntervalFee($service_detail, $service_description) { $traffic_total = 0; if (isset($this->traffic_data[$service_detail[$this->toInvoiceTableData['keyfield']]]) && is_array($this->traffic_data[$service_detail[$this->toInvoiceTableData['keyfield']]]) && !empty($this->traffic_data[$service_detail[$this->toInvoiceTableData['keyfield']]])) { reset($this->traffic_data[$service_detail[$this->toInvoiceTableData['keyfield']]]); foreach ($this->traffic_data[$service_detail[$this->toInvoiceTableData['keyfield']]] as $date => $traffic) { if (calculateDayDifference($service_detail['service_date_begin'], $date) >= 0 && calculateDayDifference($date, $service_detail['service_date_end']) > 0) { $traffic_total += $traffic; } } } $service_description['traffic_included'] = round($service_detail['traffic'] / (1024 * 1024), 2); $service_description['traffic_total'] = round($traffic_total / (1024 * 1024), 2); if ($service_detail['traffic'] < $traffic_total && $service_description['traffic_included'] != '-1' && (int) $service_detail['additional_traffic_unit'] != 0) { $traffic_exceeded = $traffic_total - $service_detail['traffic']; // Wir casten auf int um die Dezimalstellen zu entfernen. Danach wird 1 addiert ("je angefangenes gb traffic") $service_detail['interval_fee'] = (int) ((int) ($traffic_exceeded / $service_detail['additional_traffic_unit']) + 1) * $service_detail['additional_traffic_fee']; } else { $service_detail['interval_fee'] = '0.00'; } if ($service_description['traffic_included'] == '-1') { $service_description['caption_class'] = 'unlimited'; } return parent::buildInvoiceRowIntervalFee($service_detail, $service_description); }
/** * This method selects a template which has been valid at the given time from the given templatekeys. * * @param date The date when the template should have been valid * @param array All appropriate template keys * * @return array The valid template * * @author Former03 GmbH :: Florian Lippert <*****@*****.**> */ public function findValidTemplate($date, $templatekeys) { $returnval = array(); if (!is_array($templatekeys)) { $templatekey = $templatekeys; unset($templatekeys); $templatekeys = array($templatekey); unset($templatekey); } foreach ($templatekeys as $templatekey) { if (isset($this->service_templates[$templatekey])) { reset($this->service_templates[$templatekey]); foreach ($this->service_templates[$templatekey] as $valid => $template) { list($valid_from, $valid_to) = explode(':', $valid, 2); if (calculateDayDifference($valid_from, $date) >= 0 && (calculateDayDifference($date, $valid_to) > 0 || (int) $valid_to == 0)) { $returnval = $template; } } } } return $returnval; }
if ($result['id'] == $id && $id != '0') { if (isset($_POST['send']) && $_POST['send'] == 'send') { $db->query('DELETE FROM `' . TABLE_BILLING_SERVICE_OTHER . '` WHERE `id` = \'' . $id . '\' '); redirectTo($filename, array('s' => $s)); } else { $result = $db->query_first('SELECT * FROM `' . TABLE_BILLING_SERVICE_OTHER . '` WHERE `id` = \'' . $id . '\' '); $result['valid_from'] = date('Y-m-d', $result['valid_from']); ask_yesno('billing_other_service_reallydelete', $filename, array('id' => $id, 'action' => $action)); } } } if ($action == 'edit') { $result = $db->query_first('SELECT * FROM `' . TABLE_BILLING_SERVICE_OTHER . '` WHERE `id` = \'' . $id . '\' '); if ($result['id'] == $id && $id != '0') { $override_billing_data_edit = isset($_GET['override_billing_data_edit']) && $_GET['override_billing_data_edit'] == '1' || isset($_POST['override_billing_data_edit']) && $_POST['override_billing_data_edit'] == '1'; $enable_billing_data_edit = $result['servicestart_date'] == '0000-00-00' || $result['interval_payment'] == CONST_BILLING_INTERVALPAYMENT_PREPAID && calculateDayDifference(time(), $result['lastinvoiced_date']) >= 0 || $override_billing_data_edit === true; if (isset($_POST['send']) && $_POST['send'] == 'send') { if ($enable_billing_data_edit === true) { if (isset($_POST['templateid']) && intval($_POST['templateid']) != 0 && isset($other_templates[$_POST['templateid']])) { $templateid = $_POST['templateid']; } else { $templateid = '0'; } if (isset($_POST['taxclass']) && intval($_POST['taxclass']) != 0 && isset($taxclasses[$_POST['taxclass']])) { $taxclass = $_POST['taxclass']; } else { $taxclass = '0'; } $quantity = doubleval(str_replace(',', '.', $_POST['quantity'])); $interval_fee = doubleval(str_replace(',', '.', $_POST['interval_fee'])); $interval_length = intval($_POST['interval_length']);
/** * This method returns a nice utf8-formatted XML file * with the data it got from self::exportArray. * * @param array Language array * @param string Invoice number * @return string Contains the XML data. * * @author Former03 GmbH :: Florian Lippert <*****@*****.**> */ function exportXml($lng = array(), $invoice_number = '') { if ($this->userId == 0 || !is_array($this->user) || empty($this->user) || $this->user[getModeDetails($this->mode, 'TABLE_PANEL_USERS', 'key')] != $this->userId) { return false; } $invoice = $this->exportArray($lng); $invoiceXml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><invoice></invoice>'); $invoiceXml->addChild('invoice_number', utf8_encode(htmlspecialchars($invoice_number))); $invoiceXml->addChild('invoice_date', makeNicePresentableDate(date('Y-m-d'), $lng['panel']['dateformat_function'])); $address = $invoiceXml->addChild('address'); $address->addChild('name', utf8_encode(htmlspecialchars($this->user['name']))); $address->addChild('firstname', utf8_encode(htmlspecialchars($this->user['firstname']))); $address->addChild('title', utf8_encode(htmlspecialchars($this->user['title']))); $address->addChild('company', utf8_encode(htmlspecialchars($this->user['company']))); $address->addChild('street', utf8_encode(htmlspecialchars($this->user['street']))); $address->addChild('zipcode', utf8_encode(htmlspecialchars($this->user['zipcode']))); $address->addChild('city', utf8_encode(htmlspecialchars($this->user['city']))); $address->addChild('country', utf8_encode(htmlspecialchars($this->user['country']))); $billing = $invoiceXml->addChild('billing'); $billing->addChild('contract_number', utf8_encode(htmlspecialchars($this->user['contract_number']))); $billing->addChild('contract_details', utf8_encode(htmlspecialchars(sprintf(html_entity_decode($lng['invoice']['contract_details_template']), makeNicePresentableDate($this->user['contract_date'], $lng['panel']['dateformat_function']), (int) $this->user['diskspace'] / 1024 == '-1' ? html_entity_decode($lng['customer']['unlimited']) : (string) round((int) $this->user['diskspace'] / 1024, 2), $this->user['additional_diskspace_fee'], (string) round((int) $this->user['additional_diskspace_unit'] / 1024, 4), (int) $this->user['traffic'] / (1024 * 1024) == '-1' ? html_entity_decode($lng['customer']['unlimited']) : (string) round((int) $this->user['traffic'] / (1024 * 1024), 4), $this->user['additional_traffic_fee'], (string) round((int) $this->user['additional_traffic_unit'] / (1024 * 1024), 4), $this->user['included_domains_qty'], $this->user['interval_fee'], str_replace('1 ' . $lng['panel']['intervalfee_type'][$this->user['interval_type']], $lng['panel']['intervalfee_type_one'][$this->user['interval_type']], $this->user['interval_length'] . ' ' . $lng['panel']['intervalfee_type'][$this->user['interval_type']]), str_replace('1 ' . $lng['panel']['intervalfee_type'][$this->user['interval_type']], '1 ' . $lng['panel']['intervalfee_type_one'][$this->user['interval_type']], (string) ((int) $this->user['interval_length'] * (int) $this->user['payment_every']) . ' ' . $lng['panel']['intervalfee_type'][$this->user['interval_type']]))))); $billing->addChild('payment_method', utf8_encode(htmlspecialchars($this->user['payment_method']))); $billing->addChild('term_of_payment', utf8_encode(htmlspecialchars($this->user['term_of_payment']))); $billing->addChild('bankaccount_holder', utf8_encode(htmlspecialchars($this->user['bankaccount_holder']))); $billing->addChild('bankaccount_number', utf8_encode(htmlspecialchars($this->user['bankaccount_number']))); $billing->addChild('bankaccount_blz', utf8_encode(htmlspecialchars($this->user['bankaccount_blz']))); $billing->addChild('bankaccount_bank', utf8_encode(htmlspecialchars($this->user['bankaccount_bank']))); $billing->addChild('taxid', utf8_encode(htmlspecialchars($this->user['taxid']))); $billing->addChild('calc_tax', utf8_encode(htmlspecialchars($this->user['calc_tax']))); $total_fee = 0; $total_fee_taxed = 0; $tax = array(); $allservices_begin = 0; $allservices_end = 0; foreach ($invoice as $service_type => $service_details) { $service_category = $invoiceXml->addChild('service_category'); $service_category->addAttribute('service_type', utf8_encode(htmlspecialchars($service_type))); $service_category->addChild('caption', utf8_encode(htmlspecialchars(html_entity_decode($service_details['caption'])))); $service_category->addChild('interval', utf8_encode(htmlspecialchars(html_entity_decode($service_details['interval'])))); if (calculateDayDifference($service_details['service_date_begin'], $service_details['service_date_end']) != 0) { $invoiceXml->addChild('service_date_begin', utf8_encode(htmlspecialchars($service_details['service_date_begin']))); $invoiceXml->addChild('service_date_end', utf8_encode(htmlspecialchars($service_details['service_date_end']))); } else { $invoiceXml->addChild('service_date', utf8_encode(htmlspecialchars($service_details['service_date_begin']))); } if (calculateDayDifference($service_details['service_date_begin'], $allservices_begin) > 0 || $allservices_begin == 0) { $allservices_begin = $service_details['service_date_begin']; } if (calculateDayDifference($allservices_end, $service_details['service_date_end']) > 0 || $allservices_end == 0) { $allservices_end = $service_details['service_date_end']; } foreach ($service_details['rows'] as $rowid => $row) { $invoice_row = $service_category->addChild('invoice_row'); $invoice_row->addAttribute('key', utf8_encode(htmlspecialchars($row['key']))); $invoice_row->addChild('service_occurence', utf8_encode(htmlspecialchars($row['service_occurence']))); switch ($row['service_occurence']) { case 'once': $invoice_row->addAttribute('date', utf8_encode(htmlspecialchars(makeNicePresentableDate($row['service_date'], 'Ymd')))); $invoice_row->addChild('service_date', utf8_encode(htmlspecialchars($row['service_date']))); break; case 'period': $invoice_row->addAttribute('date', utf8_encode(htmlspecialchars(makeNicePresentableDate($row['service_date_begin'], 'Ymd')))); $invoice_row->addChild('service_date_begin', utf8_encode(htmlspecialchars($row['service_date_begin']))); $invoice_row->addChild('service_date_end', utf8_encode(htmlspecialchars($row['service_date_end']))); break; } $invoice_row->addChild('caption', utf8_encode(htmlspecialchars(html_entity_decode($row['description']['caption'])))); $invoice_row->addChild('interval', utf8_encode(htmlspecialchars($row['interval']))); $invoice_row->addChild('quantity', utf8_encode(htmlspecialchars($row['quantity']))); $invoice_row->addChild('single_fee', utf8_encode(htmlspecialchars($row['single_fee']))); $invoice_row->addChild('total_fee', utf8_encode(htmlspecialchars($row['total_fee']))); $invoice_row->addChild('taxrate', utf8_encode(htmlspecialchars($row['taxrate']))); $invoice_row->addChild('tax', utf8_encode(htmlspecialchars($row['tax']))); $invoice_row->addChild('total_fee_taxed', utf8_encode(htmlspecialchars($row['total_fee_taxed']))); if (!isset($tax[$row['taxrate']])) { $tax[$row['taxrate']] = 0; } $tax[$row['taxrate']] += $row['tax']; $total_fee += $row['total_fee']; $total_fee_taxed += $row['total_fee_taxed']; } } if (calculateDayDifference($allservices_begin, $allservices_end) != 0) { $invoiceXml->addChild('invoice_period', utf8_encode(htmlspecialchars(makeNicePresentableDate($allservices_begin, $lng['panel']['dateformat_function']) . ' - ' . makeNicePresentableDate($allservices_end, $lng['panel']['dateformat_function'])))); } else { $invoiceXml->addChild('invoice_period', utf8_encode(htmlspecialchars(makeNicePresentableDate($allservices_begin, $lng['panel']['dateformat_function'])))); } $credit_note = $this->getCreditNote(); if ($credit_note != 0) { $invoiceXml->addChild('credit_note', utf8_encode(htmlspecialchars(sprintf("%01.2f", $credit_note)))); $total_fee_taxed -= $credit_note; } $invoiceXml->addChild('total_fee', utf8_encode(htmlspecialchars(sprintf("%01.2f", $total_fee)))); foreach ($tax as $taxrate => $taxamount) { $taxXml = $invoiceXml->AddChild('tax', utf8_encode(htmlspecialchars(sprintf("%01.2f", $taxamount)))); $taxXml->addAttribute('taxrate', utf8_encode(htmlspecialchars($taxrate))); } $invoiceXml->addChild('total_fee_taxed', utf8_encode(htmlspecialchars(sprintf("%01.2f", $total_fee_taxed)))); return $invoiceXml->asXML(); }