/**
 * Calculates the number of days between first and second parameter
 *
 * @param  int Date 1
 * @param  int Date 2
 * @return int Number of days
 *
 * @author Former03 GmbH :: Florian Lippert <*****@*****.**>
 */
function calculateDayDifference($begin, $end)
{
    $daycount = 0;
    $begin = transferDateToArray($begin);
    $end = transferDateToArray($end);
    $direction = 1;
    // Sanity check, if our given array is in the right format
    if (checkDateArray($begin) === true && checkDateArray($end) === true) {
        if (strtotime($end['y'] . '-' . $end['m'] . '-' . $end['d']) < strtotime($begin['y'] . '-' . $begin['m'] . '-' . $begin['d'])) {
            $tmp = $end;
            $end = $begin;
            $begin = $tmp;
            unset($tmp);
            $direction = -1;
        }
        $yeardiff = (int) $end['y'] - (int) $begin['y'];
        $monthdiff = (int) $end['m'] + 12 * $yeardiff - (int) $begin['m'];
        for ($i = 0; $i < abs($monthdiff); $i++) {
            $daycount += getDaysForMonth($begin['m'] + $i, $begin['y']);
        }
        $daycount += $end['d'] - $begin['d'];
        $daycount *= $direction;
    }
    return $daycount;
}
Example #2
0
 /**
  * This method is a wrapper for parent::collect. Before launching it,
  * we will gather information about traffic usage for all given userids.
  *
  * @param bool   Should we fix invoice (means we call self::setLastInvoiced to latest invoiced date).
  * @param bool   Should we include the setup fee?
  * @param bool   Should we include the interval fees?
  * @return array All invoice rows
  *
  * @author Former03 GmbH :: Florian Lippert <*****@*****.**>
  */
 function collect($fixInvoice = false, $include_setup_fee = false, $include_interval_fee = false)
 {
     $traffic_result = $this->db->query('SELECT `' . getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key') . '`, `year`, `month`, `day`, SUM(`http`+`ftp_down`+`ftp_up`+`mail`) as traffic FROM `' . getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'table') . '` WHERE `' . getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key') . '` IN ( ' . implode(', ', $this->userIds) . ' ) GROUP BY `' . getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key') . '`, `year`, `month`, `day`');
     while ($traffic_row = $this->db->fetch_array($traffic_result)) {
         if (!isset($this->traffic_data[$traffic_row[getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key')]]) || !is_array($this->traffic_data[$traffic_row[getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key')]])) {
             $this->traffic_data[$traffic_row[getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key')]] = array();
         }
         $date = $traffic_row['year'] . '-' . $traffic_row['month'] . '-' . $traffic_row['day'];
         if (!isset($this->traffic_data[$traffic_row[getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key')]][$date]) && checkDateArray(transferDateToArray($date))) {
             $this->traffic_data[$traffic_row[getModeDetails($this->mode, 'TABLE_PANEL_TRAFFIC', 'key')]][$date] = (int) $traffic_row['traffic'];
         }
     }
     reset($this->userIds);
     foreach ($this->userIds as $userId) {
         // Using fixed values here, because those settings are always the same. interval_fee will be calculated lateron, when traffic consumption is calculated
         $this->service_details[$userId]['service_active'] = '1';
         $this->service_details[$userId]['interval_fee'] = '0.00';
         $this->service_details[$userId]['interval_length'] = '1';
         $this->service_details[$userId]['interval_type'] = 'm';
         $this->service_details[$userId]['interval_payment'] = '1';
         // Always postpaid, we can't invoice this month/payment_term's traffic, if it hasn't finished yet
         $this->service_details[$userId]['setup_fee'] = '0.00';
         $this->service_details[$userId]['payment_every'] = '1';
         $this->service_details[$userId]['lastinvoiced_date'] = $this->service_details[$userId]['lastinvoiced_date_traffic'];
         // We still want to be able to calculate traffic usage in case of no service information
         if (($this->service_details[$userId]['lastinvoiced_date'] == '0' || $this->service_details[$userId]['lastinvoiced_date'] == '') && ($this->service_details[$userId]['servicestart_date'] == '0' || $this->service_details[$userId]['servicestart_date'] == '') && isset($this->traffic_data[$userId]) && is_array($this->traffic_data[$userId]) && !empty($this->traffic_data[$userId])) {
             // Get the date of first appereance of traffic
             ksort($this->traffic_data[$userId]);
             $dates = array_keys($this->traffic_data[$userId]);
             $this->service_details[$userId]['servicestart_date'] = $dates[0];
         }
     }
     return parent::collect($fixInvoice, $include_setup_fee, $include_interval_fee);
 }
/**
 * Manipulates a date, like adding a month or so and correcting it afterwards
 * (2008-01-33 -> 2008-02-02)
 *
 * @param  array  The date array
 * @param  string The operation, may be '+', 'add', 'sum' or '-', 'subtract', 'subduct'
 * @param  int    Number if days/month/years
 * @param  string Either 'y', 'm', 'd', depending on what part to change.
 * @param  array  A valid date array with original date, mandatory for more than one manipulation on same date.
 * @return date   The manipulated date array
 *
 * @author Former03 GmbH :: Florian Lippert <*****@*****.**>
 */
function manipulateDate($date, $operation, $count, $type, $original_date = null)
{
    $newdate = $date;
    $date = transferDateToArray($date);
    if (checkDateArray($date) === true && isset($date[$type])) {
        switch ($operation) {
            case '+':
            case 'add':
            case 'sum':
                $date[$type] += (int) $count;
                break;
            case '-':
            case 'subtract':
            case 'subduct':
                $date[$type] -= (int) $count;
                break;
        }
        if ($original_date !== null && ($original_date = transferDateToArray($original_date)) !== false && $type == 'm') {
            if ($original_date['d'] > getDaysForMonth($date['m'], $date['y'])) {
                $date['d'] = getDaysForMonth($date['m'], $date['y']) - (getDaysForMonth($original_date['m'], $original_date['y']) - $original_date['d']);
            } else {
                $date['d'] = $original_date['d'];
            }
        }
        while (checkDateArray($date) === false) {
            if ($date['d'] > getDaysForMonth($date['m'], $date['y'])) {
                $date['d'] -= getDaysForMonth($date['m'], $date['y']);
                $date['m']++;
            }
            if ($date['d'] < 1) {
                $date['m']--;
                $date['d'] += getDaysForMonth($date['m'], $date['y']);
                // Adding here, because date[d] is negative
            }
            if ($date['m'] > 12) {
                $date['m'] -= 12;
                $date['y']++;
            }
            if ($date['m'] < 1) {
                $date['y']--;
                $date['m'] += 12;
            }
        }
        $newdate = $date['y'] . '-' . $date['m'] . '-' . $date['d'];
    }
    return $newdate;
}
Example #4
0
 /**
  * This method collects the invoice rows.
  *
  * @param bool   Should we fix invoice (means we call self::setLastInvoiced to latest invoiced date).
  * @param bool   Should we include the setup fee?
  * @param bool   Should we include the interval fees?
  *
  * @return array All invoice rows
  *
  * @author Former03 GmbH :: Florian Lippert <*****@*****.**>
  */
 public function collect($fixInvoice = false, $include_setup_fee = false, $include_interval_fee = false)
 {
     $invoice = array();
     reset($this->service_details);
     foreach ($this->service_details as $serviceId => $service_detail) {
         if (checkDateArray(transferDateToArray($service_detail['servicestart_date'])) === true) {
             // Load template which is valid through our setup date
             $template = $this->findValidTemplate($service_detail['servicestart_date'], $this->selectAppropriateTemplateKey($service_detail));
             foreach ($this->defaultvalues as $field => $value) {
                 // We are using $this->service_details[$serviceId] instead of $service_detail so we can see the original values, as the "working copy" ($service_detail) could have been changed...
                 if ((!isset($this->service_details[$serviceId][$field]) || isset($this->service_details[$serviceId][$field]) && $this->service_details[$serviceId][$field] == $value) && isset($template[$field]) && $template[$field] != $value) {
                     $service_detail[$field] = $template[$field];
                 }
             }
             // If quantity is not set, we do need a value 1, otherwise this doesn't make sense...
             if (!isset($service_detail['quantity'])) {
                 $service_detail['quantity'] = 1;
             }
             // Add setup fee to invoice
             if (checkDateArray(transferDateToArray($service_detail['lastinvoiced_date'])) !== true || $this->allowLastInvoicedDatePastServiceStart === false && calculateDayDifference($service_detail['lastinvoiced_date'], $service_detail['servicestart_date']) > 0) {
                 if ($include_setup_fee === true) {
                     $invoice[] = $this->buildInvoiceRowSetupFee($service_detail, $this->getServiceDescription($service_detail, 'setup'));
                 }
                 $service_detail['lastinvoiced_date'] = $service_detail['servicestart_date'];
             }
             // If payment_every is not set, we do need a value 1, otherwise nextinvoiced_date wouldn't be calculated correctly and we'll get stuck in an infinite loop
             if (!isset($service_detail['payment_every'])) {
                 $service_detail['payment_every'] = 1;
             }
             if ((int) $service_detail['interval_length'] != 0 && (int) $service_detail['payment_every'] != 0 && in_array($service_detail['interval_type'], getIntervalTypes('array'))) {
                 $original_date = $service_detail['lastinvoiced_date'];
                 $service_detail['nextinvoiced_date'] = manipulateDate($service_detail['lastinvoiced_date'], '+', (int) $service_detail['interval_length'] * (int) $service_detail['payment_every'], $service_detail['interval_type'], $original_date);
                 while ($service_detail['interval_payment'] == CONST_BILLING_INTERVALPAYMENT_PREPAID && calculateDayDifference($service_detail['lastinvoiced_date'], time()) >= 0 && !($service_detail['service_active'] == '0' && calculateDayDifference($service_detail['lastinvoiced_date'], $service_detail['serviceend_date']) <= 0) || $service_detail['interval_payment'] == CONST_BILLING_INTERVALPAYMENT_POSTPAID && (calculateDayDifference($service_detail['nextinvoiced_date'], time()) >= 0 || $this->endServiceImmediately === true && $service_detail['service_active'] == '0' && calculateDayDifference($service_detail['lastinvoiced_date'], $service_detail['serviceend_date']) > 0 && calculateDayDifference($service_detail['serviceend_date'], $service_detail['nextinvoiced_date']) >= 0 && calculateDayDifference($service_detail['lastinvoiced_date'], time()) >= 0 && calculateDayDifference($service_detail['serviceend_date'], time()) >= 0)) {
                     // Reload template which is valid through our current invoice period
                     reset($this->defaultvalues);
                     $template = $this->findValidTemplate($service_detail['lastinvoiced_date'], $this->selectAppropriateTemplateKey($service_detail));
                     foreach ($this->defaultvalues as $field => $value) {
                         // We are using $this->service_details[$serviceId] instead of $service_detail so we can see the original values, as the "working copy" ($service_detail) could have been changed...
                         if ((!isset($this->service_details[$serviceId][$field]) || isset($this->service_details[$serviceId][$field]) && $this->service_details[$serviceId][$field] == $value) && isset($template[$field]) && $template[$field] != $value) {
                             $service_detail[$field] = $template[$field];
                         }
                     }
                     if ($this->endServiceImmediately === true && $service_detail['service_active'] == '0' && calculateDayDifference($service_detail['lastinvoiced_date'], $service_detail['serviceend_date']) > 0 && calculateDayDifference($service_detail['serviceend_date'], $service_detail['nextinvoiced_date']) >= 0 && calculateDayDifference($service_detail['lastinvoiced_date'], time()) >= 0 && calculateDayDifference($service_detail['serviceend_date'], time()) >= 0) {
                         $service_detail['nextinvoiced_date'] = $service_detail['serviceend_date'];
                     }
                     // Sanity check, shouldn't be needed...
                     if (calculateDayDifference($service_detail['lastinvoiced_date'], $service_detail['nextinvoiced_date']) >= 0) {
                         $service_detail['service_date_begin'] = $service_detail['lastinvoiced_date'];
                         $service_detail['service_date_end'] = $service_detail['nextinvoiced_date'];
                         if ($include_interval_fee === true) {
                             $invoice[] = $this->buildInvoiceRowIntervalFee($service_detail, $this->getServiceDescription($service_detail, 'interval'));
                         }
                     }
                     // Go on in loop, set lastinvoiced_date to nextinvoiced_date ...
                     $service_detail['lastinvoiced_date'] = $service_detail['nextinvoiced_date'];
                     // ... and recalculate nextinvoiced_date.
                     $service_detail['nextinvoiced_date'] = manipulateDate($service_detail['lastinvoiced_date'], '+', (int) $service_detail['interval_length'] * (int) $service_detail['payment_every'], $service_detail['interval_type'], $original_date);
                 }
             }
             if ($fixInvoice === true) {
                 $this->setLastInvoiced($serviceId, $service_detail);
             }
         }
     }
     return $invoice;
 }