function service_periods_add($id_service_customer, $billing_mode)
{
    log_debug("inc_services_invoicegen", "Executing service_periods_add({$id_service_customer}, {$billing_mode})");
    /*
    	Fetch required information from services_customers (service-customer assignment table)
    */
    $sql_custserv_obj = new sql_query();
    $sql_custserv_obj->string = "SELECT serviceid, date_period_first, date_period_next, date_period_last FROM services_customers WHERE id='{$id_service_customer}' LIMIT 1";
    $sql_custserv_obj->execute();
    $sql_custserv_obj->fetch_array();
    $serviceid = $sql_custserv_obj->data[0]["serviceid"];
    $date_period_start = $sql_custserv_obj->data[0]["date_period_next"];
    $date_period_last = $sql_custserv_obj->data[0]["date_period_last"];
    if (empty($date_period_last) || $date_period_last == "0000-00-00") {
        $date_period_last = NULL;
    }
    /*
    	Has the service reached it's end date?
    */
    if ($date_period_last) {
        /*
        	Is deactivation required?
        */
        if (time_date_to_timestamp($date_period_last) <= time()) {
            log_write("debug", "inc_services_invoicegen", "Service {$id_service_customer} has reached deactivation date ({$date_period_last}), disabling service.");
            // disable the service
            $obj_service = new customer_services();
            $obj_service->id_service_customer = $id_service_customer;
            $obj_service->verify_id_service_customer();
            $obj_service->service_disable();
            unset($obj_service);
        }
        /*
        	Have we reached the end of the service with the current period?
        */
        if ($date_period_start == $date_period_last) {
            // start date the same as the last date
            log_write("debug", "inc_services_invoicegen", "Service {$id_service_customer} is due to be deactived on {$date_period_last}, new period due to start on {$date_period_start}, preventing new period generation and making no changes.");
            return 1;
        }
        /*
        	Catch any glitches, where the period start date is newer than the period last date, and correct.
        */
        if (time_date_to_timestamp($date_period_start) > time_date_to_timestamp($date_period_last)) {
            log_write("debug", "inc_services_invoicegen", "Service start date of {$date_period_start}, but last period date is for {$date_period_last} - adjusting start date to match last");
            $date_period_start = $date_period_last;
        }
    }
    /*
    	Handle new services
    
    	If the service has not been billed before, the date_period_first value will have been set, but not the date_period_next value.
    */
    if ($sql_custserv_obj->data[0]["date_period_next"] == "0000-00-00") {
        $date_period_start = $sql_custserv_obj->data[0]["date_period_first"];
    }
    /*
    	Fetch Dates
    */
    $billing_cycle = sql_get_singlevalue("SELECT billing_cycles.name as value FROM services LEFT JOIN billing_cycles ON billing_cycles.id = services.billing_cycle WHERE services.id='{$serviceid}'");
    $dates = service_period_dates_generate($date_period_start, $billing_cycle, $billing_mode);
    $date_period_start = $dates["start"];
    $date_period_end = $dates["end"];
    $date_period_next = $dates["next"];
    /*
    	Handle Last Date
    
    	If the service has reached the date_period_last, we need to flag the period as being the last - this means
    	if an end/last date is set half way during a period, the period will be changed into a partial period.
    */
    if ($date_period_last) {
        if (time_date_to_timestamp($date_period_last) <= time_date_to_timestamp($date_period_end)) {
            /*
            	Period ending date is later than the last period date - adjust the end date to align.
            */
            $date_period_end = $date_period_last;
            $date_period_next = "0000-00-00";
        }
        if ($date_period_last == $date_period_end) {
            /*
            	Period end date same as the service last date.
            */
            $date_period_next = "0000-00-00";
        }
    }
    /*
    	Calculate date to bill the period on
    */
    switch ($billing_mode) {
        case "periodadvance":
        case "monthadvance":
            // PERIODADVANCE / MONTHADVANCE
            //
            // Billing date should be set to today, since the period will have just been generated in advance today and
            // we don't need to bother regenerating the billing period.
            //
            $date_period_billing = date("Y-m-d");
            break;
        case "periodtelco":
        case "monthtelco":
            // PERIODTELCO / MONTHTELCO
            //
            // With Telco periods, we need to bill on the first day of the new period.
            $date_period_billing = $date_period_start;
            break;
        case "periodend":
        case "monthend":
            // PERIODEND /  MONTHEND
            //
            // We can't bill for this period until it's end, so we set the billing date to the start of the next period,
            // so that the period has completely finished before we invoice.
            $date_period_billing = $date_period_next;
            break;
    }
    log_write("debug", "inc_customers", "Calculated billing date of \"" . $date_period_billing . "\" for service billing mode of \"" . $billing_mode . "\"");
    /*
    	Start Transaction
    */
    $sql_obj = new sql_query();
    $sql_obj->trans_begin();
    /*
    	Add a new period
    */
    $sql_obj->string = "INSERT INTO services_customers_periods (id_service_customer, date_start, date_end, date_billed) VALUES ('{$id_service_customer}', '{$date_period_start}', '{$date_period_end}', '{$date_period_billing}')";
    $sql_obj->execute();
    /*
    	Update services_customers
    */
    $sql_obj->string = "UPDATE services_customers SET date_period_next='{$date_period_next}' WHERE id='{$id_service_customer}' LIMIT 1";
    $sql_obj->execute();
    /*
    	If the period is ending, we need to create a special 0-day period - this is used
    	to account for usage on services, by having a final period with no service charge
    	but with usage for the previous (final) period.
    */
    if ($date_period_last && $date_period_next == "0000-00-00") {
        /*
        	This period is for one day after the service terminates - it will force an invoice to be generated for the
        	terminated service, with $0 plan charges and any usage charges that apply.
        
        	Depending on configuration, the customer may or may not recieve a copy of the invoice.
        */
        $sql_obj->string = "INSERT INTO services_customers_periods (id_service_customer, date_start, date_end, date_billed) VALUES ('{$id_service_customer}',  DATE_ADD('{$date_period_end}', INTERVAL 1 DAY), DATE_ADD('{$date_period_end}', INTERVAL 1 DAY), DATE_ADD('{$date_period_billing}', INTERVAL 1 DAY))";
        $sql_obj->execute();
    }
    /*
    	Commit
    */
    if (error_check()) {
        $sql_obj->trans_rollback();
        log_write("error", "process", "An error occured whilst attempting to add a new period to a service. No changes were made.");
        return 0;
    } else {
        $sql_obj->trans_commit();
    }
    return 1;
}
     }
 } else {
     /*
     				Adjust an existing service
     			"*/
     // enable/disable service if needed
     if ($obj_customer->service_get_status() != $data["active"]) {
         if ($data["active"]) {
             // service has been enabled
             $obj_customer->service_enable();
             // generate service period - this won't invoice, but allows us to get a date
             // for when the invoice will be generated
             service_periods_generate($obj_customer->id);
         } else {
             // service has been disabled
             $obj_customer->service_disable();
         }
     }
     // adjust dates if possible - only possible for services that have yet to be billed, any periods that currently
     // exist are uninvoiced and can be safely deleted.
     if ($data["date_period_first"]) {
         log_write("notification", "process", "Adjusted service start date to " . time_format_humandate($data["date_period_first"]) . "");
         // handle service information
         $obj_sql = new sql_query();
         $obj_sql->string = "UPDATE services_customers SET date_period_first='" . $data["date_period_first"] . "',  date_period_next='" . $data["date_period_next"] . "' WHERE id='" . $obj_customer->id_service_customer . "' LIMIT 1";
         $obj_sql->execute();
         unset($obj_sql);
         // delete service periods
         $obj_sql = new sql_query();
         $obj_sql->string = "DELETE FROM services_customers_periods WHERE id_service_customer='" . $obj_customer->id_service_customer . "'";
         $obj_sql->execute();