needlogin = true; $me = new User(); $me->loadMe(); $this->me = $me; $this->layout()->set("me", $me); if(!$me->can(["preorderbilling", "preorderbillingReadonly"])) { $this->redirect("Dashboard"); } } protected function indexAction() : void { $this->layout()->setTemplate("PreorderBilling/Index"); if ($this->request->resetFilter) { unset($_SESSION[MFAPPNAME . '-PreorderBilling-filter']); } $filter = []; if (is_array($this->request->filter)) { $filter = $this->request->filter; $_SESSION[MFAPPNAME . '-PreorderBilling-filter'] = $filter; } else { if (array_key_exists(MFAPPNAME . '-PreorderBilling-filter', $_SESSION) && count($_SESSION[MFAPPNAME . '-PreorderBilling-filter'])) { $filter = $_SESSION[MFAPPNAME . '-PreorderBilling-filter']; } } $this->layout->set("filter", $filter); $filter = $this->getPreparedFilter($filter); // pagination defaults $pagination = []; $pagination['start'] = 0; $pagination['count'] = 25; $pagination['maxItems'] = 0; if (is_numeric($this->request->s)) { $pagination['start'] = intval($this->request->s); } $my_campaigns = PreordercampaignModel::search(["owner_id" => $this->me->address_id]); //var_dump($my_network_ids,$my_campaign_ids);exit; $this->layout()->set("my_campaigns", $my_campaigns); $netoperators = []; foreach(PreordercampaignModel::search(["owner_id" => $this->me->address_id]) as $campaign) { foreach($campaign->active_operators as $op) { if(!array_key_exists($op->operator_id, $netoperators)) { $nop = new Address($op->operator_id); if($nop->id) { $netoperators[$nop->id] = $nop; } } } foreach($campaign->passive_operators as $op) { if(!array_key_exists($op->operator_id, $netoperators)) { $nop = new Address($op->operator_id); if($nop->id) { $netoperators[$nop->id] = $nop; } } } } $this->layout()->set("netoperators", $netoperators); //var_dump($filter);exit; $pagination['maxItems'] = PreorderBilling::count($filter); $billings = PreorderBilling::search($filter, $pagination); $this->layout()->set("billings", $billings); $this->layout()->set("pagination", $pagination); } private function getPreparedFilter($filter) { $new_filter = []; if(array_key_exists("status", $filter)) { if($filter["status"] == "billed") { $new_filter["invoice_id"] = true; } else { $new_filter["invoice_id"] = null; } } else { $new_filter["invoice_id"] = null; } if(array_key_exists("start_date_from", $filter)) { if($filter["start_date_from"]) { try { $from = DateTime::createFromFormat("d.m.Y", $filter["start_date_from"]); } catch (Exception $e) {} $new_filter["start_date>="] = $from->format("Y-m-d"); } unset($filter["start_date_from"]); } if(array_key_exists("start_date_to", $filter)) { if($filter["start_date_to"]) { try { $to = DateTime::createFromFormat("d.m.Y", $filter["start_date_to"]); } catch (Exception $e) {} $new_filter["start_date<="] = $to->format("Y-m-d"); } unset($filter["start_date_to"]); } if (is_array($filter) && count($filter)) { foreach ($filter as $name => $value) { $new_filter[$name] = $value; } } return $new_filter; } protected function importPreorders() { $netowner_id = $this->me->address_id; $netowner = new Address($netowner_id); if(!defined("TT_PREORDER_BILLING") || !is_array(TT_PREORDER_BILLING)) { die("Config Variable 'TT_PREORDER_BILLING' not found!"); } $netowner_config = TT_PREORDER_BILLING[$netowner_id]; $earliest_bill_date = new DateTime(PreorderBilling::$earliest_bill_date); $now_year = date("Y"); $now_month = date("m"); $now_day = date("d"); $today = new DateTime("$now_year-$now_month-$now_day"); //$today = new DateTime("2025-03-13"); $today->setTime(2,0,0); $today->setTimezone(new DateTimeZone("Europe/Vienna")); $bill_date = clone $today; $bill_date->modify("first day of this month"); $bill_date->modify("-1 month"); $latest_bill_date = clone $bill_date; $latest_bill_date->modify("last day of this month"); $this_quarter_start = clone $today; $this_quarter_start->modify("first day of this month"); $q_subtractor = ($this_quarter_start->format("m") - 1) % 3; $this_quarter_start->modify("- $q_subtractor months"); $this_quarter_end = clone $this_quarter_start; $this_quarter_end->modify("+ 3 months"); $this_quarter_end->modify("last day of this month"); $latest_quarter_bill_date = clone $this_quarter_start; $latest_quarter_bill_date->modify("-1 day"); $del = 0; // first delete all non-invoiced billing records foreach(PreorderBilling::search(["invoice_id" => null]) as $bill) { $bill->delete(); $del++; } $this->log->notice(__METHOD__.": $del Billing records deleted"); $campaign_ids = []; foreach(PreordercampaignModel::search(["owner_id" => $this->me->address_id]) as $campaign) { $campaign_ids[] = $campaign->id; } $preorder_search = [ "preordercampaign_id" => $campaign_ids, ">=status_code" => 244, //"oaid" => "AT-8943-a1116acf.001", ]; $billing_records = []; foreach(PreorderModel::search($preorder_search) as $preorder) { $bill_enduser_setup = true; $bill_operator_setup = true; $bill_usage = true; if($preorder->deleted) continue; if(!$preorder->adb_wohneinheit_id) { $this->log->info(__METHOD__.": Ignoring Preorder ".$preorder->id." without adb_wohneinheit_id"); continue; } //$order_date = false; if($preorder->order_date) { $order_date = new DateTime('@'.$preorder->order_date); } else { $order_date = new DateTime('@'.$preorder->create); } $order_date->setTime(4,0,0); $order_date->setTimezone(new DateTimeZone("Europe/Vienna")); if($order_date->format("Ymd") < $earliest_bill_date->format("Ymd")) { // start billing from 2025-01-01 $this->log->debug(__METHOD__.": Preorder ".$preorder->id." ordered before 2025-01-01, so billing no enduser setup"); $bill_enduser_setup = false; } $operator_id = false; $po = PreordercampaignOperatorModel::getFirst(["preordercampaign_id" => $preorder->preordercampaign_id, "isp_id" => $preorder->partner_id]); if(!$po) { $po = PreordercampaignOperatorModel::getFirst(["preordercampaign_id" => $preorder->preordercampaign_id, "operator_id" => $preorder->partner_id]); } if(!$po) { die("No operator found for preorder ".$preorder->id); } $netoperator = new Address($po->operator_id); if(!$netoperator) { die("No netoperator found for preorder ".$preorder->id); } if(!is_array($netowner_config["netoperators"]) || !array_key_exists($netoperator->id, $netowner_config["netoperators"])) { die("netoperator config missing for ".$netoperator->id); } $netoperator_config = $netowner_config["netoperators"][$netoperator->id]; $fibu_cost_code = TT_PREORDER_BILLING[$netowner_id]["fibu-cost-code"]; if($fibu_cost_code == "=from-campaign") { $campaign_cost_code = $preorder->campaign->netowner_fibu_cost_code; if(!$campaign_cost_code) { die("campaign cost_code not found for preorder ".$preorder->id." campaign ".$preorder->campaign->id); } $fibu_cost_code = $campaign_cost_code; } //var_dump($fibu_cost_code);exit; if(!$fibu_cost_code) { die("fibu_cost_code not found for preorder ".$preorder->id); } $bill_params = [ "netowner" => $netowner, "netowner_config" => $netowner_config, "netoperator" => $netoperator, "netoperator_config" => $netoperator_config, "order_date" => $order_date, "today" => $today, "bill_date" => $bill_date, "earliest_bill_date" => $earliest_bill_date, "latest_bill_date" => $latest_bill_date, "latest_quarter_bill_date" => $latest_quarter_bill_date, "fibu_cost_code" => $fibu_cost_code, ]; if($preorder->status->code >= 241) { if($bill_enduser_setup) $this->billSetup($preorder, "enduser_setup", $bill_params); } if($preorder->status->code >= 500) { if($bill_operator_setup) $this->billSetup($preorder, "operator_setup", $bill_params); if($bill_usage) $this->billOperatorPeriodic($preorder, $bill_params); //exit; } } //echo "
".print_r($this->marketshare, true)."
";exit; $this->Layout()->setFlash("Billing records erstellt", "success"); $this->redirect("PreorderBilling"); } /********************************* * Enduser Setup & Netoperator Setup Billing */ private function billSetup($preorder, $type, $options) { $netowner = $options['netowner']; $netowner_config = $options['netowner_config']; $netoperator = $options['netoperator']; $netoperator_config = $options['netoperator_config']; $order_date = $options['order_date']; $today = $options['today']; $bill_date = $options['bill_date']; $latest_bill_date = $options['latest_bill_date']; $earliest_bill_date = $options['earliest_bill_date']; $latest_quarter_bill_date = $options["latest_quarter_bill_date"]; $fibu_cost_code = $options['fibu_cost_code']; $this->log->debug(__METHOD__.": bill $type Preorder ".$preorder->id); // get price_setup $product = PreorderProduct::getFirst(["type" => $type]); if(!$product) { die("operator_setup price not found!"); } if($preorder->status->code >= 899) { // TODO is canceled, need to determine if setup still needs to be billed $this->log->debug(__METHOD__.": Preorder ".$preorder->id." / ".$preorder->oaid." already cancelled"); return true; } $product->setNetownerId($netowner->id); $product->setNetoperatorId($netoperator->id); $price = $product->getCampaignPrice($preorder->preordercampaign_id, $order_date->format("Y-m-d")); if(!$price) { die("operator_setup price not found for netoperator ".$netoperator->id.", campaign ".$preorder->preordercampaign_id." and date ".$order_date->format("Y-m-d")); } // check for existing billing record //var_dump($product); if(PreorderBilling::getFirst(["preorder_id" => $preorder->id, "product_id" => $product->id])) { //echo "billing record exists\n
"; $this->log->debug(__METHOD__.": billing record exists"); return true; // already billed } $article_number = $product->article_number; if(!$article_number) { $article_number = $product->getDefaultArticlenumber(); } // get change to 241/244/245 $status_change = PreorderHistoryModel::getFirstStatusChangeTo($preorder->id, 245); if(!$status_change) { $status_change = PreorderHistoryModel::getFirstStatusChangeTo($preorder->id, 244); } if(!$status_change) { $status_change = PreorderHistoryModel::getFirstStatusChangeToOrHigher($preorder->id, 241); } if($status_change) { $status_244_change_date = new DateTime("@".$status_change->changed); } else { $this->log->debug(__METHOD__.": No status change found for preorder ".$preorder->id." so using creation date"); $status_244_change_date = new DateTime("@".$preorder->create); } /*if($status_change_date < $earliest_bill_date) { $this->log->debug(__METHOD__.": Not billing setups for preorder ".$preorder->id." because status change date ".$status_change_date->format("Y-m-d")." is before earliest_bill_date ".$earliest_bill_date->format("Y-m-d")); return true; }*/ if($status_244_change_date->format("Ymd") > $latest_bill_date->format("Ymd")) { $this->log->debug(__METHOD__.": Skipping setup for preorder ".$preorder->id." because billing date (status change date) ".$status_244_change_date->format("Y-m-d")." is after latest_bill_date ".$latest_bill_date->format("Y-m-d")); return true; } $billing_data = [ "netowner_id" => $netowner->id, "preorder_id" => $preorder->id, "oaid" => $preorder->oaid, "adb_wohneinheit_id" => $preorder->adb_wohneinheit_id, "extref" => ($preorder->extref) ?: null, "order_date" => $order_date->format("Y-m-d"), "start_date" => $status_244_change_date->format("Y-m-d"), "end_date" => $status_244_change_date->format("Y-m-d"), "billing_delivery" => "email", "product_id" => $product->id, "product_type" => $product->type, "product_info" => "", "article_number" => $article_number, "amount" => 1, "unit" => "Stk.", "price" => "0", "price_setup" => round($price->price_setup, 2), "vatrate" => 20, "billing_period" => 0, "fibu_cost_account" => $fibu_cost_code, ]; $fibu_revenue_code = ""; if($type == "enduser_setup") { // Endkunde Setup Gebühr if($status_244_change_date < $earliest_bill_date) { $this->log->debug(__METHOD__.": Not billing enduser_setup for preorder ".$preorder->id." because status 244 change date ".$status_244_change_date->format("Y-m-d")." is before earliest_bill_date ".$earliest_bill_date->format("Y-m-d")); return true; } $fibu_revenue_code = $netowner_config["fibu-revenue-code"]; if(!$fibu_revenue_code) { die("fibu_revenue_code not found for preorder ".$preorder->id); } if($order_date->format("Ymd") < $earliest_bill_date->format("Ymd")) { return true; } if(PreorderBilling::getFirst(["adb_wohneinheit_id" => $preorder->adb_wohneinheit_id, "product_id" => $product->id])) { $this->log->debug(__METHOD__.": billing record for enduser setup for wohneinheit ".$preorder->adb_wohneinheit_id." exists"); return true; // already billed } // search for customer $customer_data = [ "company" => trim($preorder->company), "firstname" => trim($preorder->firstname), "lastname" => trim($preorder->lastname), "street" => trim($preorder->street) . (trim($preorder->housenumber) ? " " . trim($preorder->housenumber) : ""), "zip" => trim($preorder->zip), "city" => trim($preorder->city), "country" => trim($preorder->country), "phone" => trim($preorder->phone), "email" => trim($preorder->email), "uid" => trim($preorder->uid) ]; $customer = PreorderBillingCustomer::getFirst($customer_data); if(!$customer) { // create customer $customer = PreorderBillingCustomer::create($customer_data); if(!$customer->save()) { die("Customer record could not be saved!"); } $customer->createFibuAccountNumber($netowner->id); $customer->save(); } foreach($customer_data as $key => $value) { $billing_data[$key] = $value; } $address = $preorder->adb_hausnummer->strasse->name." ".$preorder->adb_hausnummer->hausnummer.($preorder->adb_hausnummer->stiege ? " /".$preorder->adb_hausnummer->stiege : "").", ".$preorder->adb_hausnummer->plz->plz." ".$preorder->adb_hausnummer->ortschaft->name; $billing_data["preorderbillingcustomer_id"] = $customer->id; $billing_data["fibu_account_number"] = $customer->fibu_account_number; $billing_data["fibu_revenue_account"] = $fibu_revenue_code; $billing_data["product_name"] = "Herstellungsentgelt Glasfaser-Internetanschluss"; $billing_data["product_info"] = $address; } elseif($type == "operator_setup") { if(array_key_exists("fibu-revenue-code", $netoperator_config) && $netoperator_config["fibu-revenue-code"]) { $fibu_revenue_code = $netoperator_config["fibu-revenue-code"]; } if(!$fibu_revenue_code) { die("fibu_revenue code not found for preorder ".$preorder->id); } $change_to_active = PreorderHistoryModel::getFirstStatusChangeTo($preorder->id, 500); if($change_to_active) { $status_change_date = new DateTime("@".$change_to_active->changed); $billing_data["start_date"] = $status_change_date->format("Y-m-d"); $billing_data["end_date"] = $status_change_date->format("Y-m-d"); } if(!$change_to_active) { $status_change_date = $status_244_change_date; } if($netoperator_config["billing-period"] == "quarterly" && $status_change_date->format("Ymd") > $latest_quarter_bill_date->format("Ymd")) { $this->log->debug(__METHOD__.": Skipping operator_setup for preorder ".$preorder->id." because Billing date ".$status_change_date->format("Y-m-d")." is after latest_quarter_bill_date ".$latest_quarter_bill_date->format("Y-m-d")); return true; } if($status_change_date->format("Ymd") > $latest_bill_date->format("Ymd")) { $this->log->debug(__METHOD__.": Skipping setup for preorder ".$preorder->id." because billing date (status change date) ".$status_change_date->format("Y-m-d")." is after latest_bill_date ".$latest_bill_date->format("Y-m-d")); return true; } // Netzbetreiber Setup Gebühr $billing_data["product_name"] = "Brereitstellungsentgelt ".$status_change_date->format("m/Y"); $billing_data["owner_id"] = $netoperator->id; $billing_data["billingaddress_id"] = $netoperator->id; $billing_data["fibu_account_number"] = $netoperator->attributes['rml-fibu-account']->value; $billing_data["fibu_revenue_account"] = $fibu_revenue_code; $billing_data["company"] = trim($netoperator->company); $billing_data["firstname"] = trim($netoperator->firstname); $billing_data["lastname"] = trim($netoperator->lastname); $billing_data["street"] = trim($netoperator->street); $billing_data["zip"] = trim($netoperator->zip); $billing_data["city"] = trim($netoperator->city); $billing_data["country"] = trim($netoperator->country->name); $billing_data["email"] = trim($netoperator_config["email"]); $billing_data["uid"] = trim($netoperator->uid); } else { die("Unknown billing type $type"); } $billing = PreorderBilling::create($billing_data); if(!$billing->save()) { die("Billing record could not be saved!"); } //var_dump($billing); $this->log->debug(__METHOD__.": Billed"); return true; } /********************************* * Usage Billing */ private function billOperatorPeriodic($preorder, $options) { $netowner = $options['netowner']; $netowner_config = $options['netowner_config']; $netoperator = $options['netoperator']; $netoperator_config = $options['netoperator_config']; $order_date = $options['order_date']; $today = $options['today']; $bill_date = $options['bill_date']; $latest_bill_date = $options['latest_bill_date']; $earliest_bill_date = $options['earliest_bill_date']; $latest_quarter_bill_date = $options["latest_quarter_bill_date"]; $fibu_cost_code = $options['fibu_cost_code']; $cancel_date = false; $campaign = new PreorderCampaign($preorder->preordercampaign_id); if(!$campaign) { die("Campaign ".$preorder->preordercampaign_id." not found!"); } $fibu_revenue_code = ""; if(array_key_exists("fibu-revenue-code", $netoperator_config) && $netoperator_config["fibu-revenue-code"]) { $fibu_revenue_code = $netoperator_config["fibu-revenue-code"]; } if(!$fibu_revenue_code) { die("fibu_revenue code not found for preorder ".$preorder->id); } if(!array_key_exists($campaign->id, $this->marketshare)) { $this->marketshare[$campaign->id] = []; $this->marketshare[$campaign->id]["max"] = $campaign->getUnitCount(); $this->marketshare[$campaign->id]["netops"] = []; } if(!array_key_exists($netoperator->id, $this->marketshare[$campaign->id]["netops"])) { $this->marketshare[$campaign->id]["netops"][$netoperator->id] = []; $this->marketshare[$campaign->id]["netops"][$netoperator->id]["bracket_price"] = []; } // get price_setup $product = PreorderProduct::getFirst(["type" => "operator_usage"]); if(!$product) { die("operator_setup price not found!"); } $product->setNetownerId($netowner->id); $product->setNetoperatorId($netoperator->id); $price = $product->getCampaignPrice($preorder->preordercampaign_id, $bill_date->format("Y-m-d")); if(!$price) { die("operator_setup price not found for campaign ".$preorder->preordercampaign_id." and date ".$order_date->format("Y-m-d")); } //var_dump($product, $price);exit; $status_change = PreorderHistoryModel::getLastStatusChangeTo($preorder->id, 500); if($status_change) { $status_change_date = new DateTime("@".$status_change->changed); } else { $this->log->debug(__METHOD__.": No status change to 500 found for preorder ".$preorder->id." so using creation date"); $status_change_date = new DateTime("@".$preorder->create); } if($status_change_date->format("Ymd") > $earliest_bill_date->format("Ymd")) { $earliest_bill_date = $status_change_date; } if($status_change_date->format("Ymd") > $latest_bill_date->format("Ymd")) { $this->log->debug(__METHOD__.": Skipping usage for preorder ".$preorder->id." because billing date (status change date) ".$status_change_date->format("Y-m-d")." is after latest_bill_date ".$latest_bill_date->format("Y-m-d")); return true; } if($preorder->status->code >= 899) { $this->log->debug(__METHOD__.": Preorder ".$preorder->id." / ".$preorder->oaid." is cancelled"); // get cancel date if(!$status_change) { $this->log->debug(__METHOD__.": But was never 500, so skipping"); return true; } $cancel_change = PreorderHistoryModel::getLastStatusChangeToOrHigher($preorder->id, 899); if(!$cancel_change) { die("Preorder ".$preorder->oaid." gekündigt (Status ".$preorder->status->code."), aber kein Cancel date gefunden"); } $cancel_date = new DateTime("@".$cancel_change->changed); } $first_bill_date = clone $status_change_date; // get earlier missing billing records and bill them too $create_date = clone $bill_date; $create_date->modify("first day of this month"); $create_date->setTime(0,0,0); $last_create_date = false; $to_bill_dates = []; /*var_dump($today); var_dump($bill_date); var_dump($earliest_bill_date); var_dump($status_change_date);exit; */ $earliest_bill_year = $status_change_date->format('Y'); $earliest_bill_month = $status_change_date->format('m'); $earliest_bill_day = $status_change_date->format('d'); // earliest bill date is before this month //echo "\$create_date ".$create_date->format("Y-m-d H:i:s")."
\n"; //echo "\$earliest_bill_date ".$earliest_bill_date->format("Y-m-d H:i:s")."

\n"; while($create_date->format("Ym") >= $earliest_bill_date->format("Ym")) { if($last_create_date) { //var_dump($create_dates); // just for safety / shouldn't happen break; //die("need-date ran out of dates"); } //echo " - \$create_date ".$create_date->format("Y-m-d H:i:s")."
\n"; //echo " - \$earliest_bill_date ".$earliest_bill_date->format("Y-m-d H:i:s")."

\n"; if($create_date->format("Y") == $earliest_bill_date->format("Y") && $create_date->format("m") == $earliest_bill_date->format("m")) { // this is the finish month, so set day back to day of finish_date $create_date->setDate($earliest_bill_date->format("Y"), $earliest_bill_date->format("m"), $earliest_bill_date->format("d")); $last_create_date = true; } $existing_bill = PreorderBilling::getFirst(["product_id" => $product->id, "preorder_id" => $preorder->id, "start_date" => $create_date->format("Y-m-d")]); //var_dump($existing_bill); if(!$existing_bill) { if($netoperator_config["billing-period"] == "quarterly" && $create_date->format("Ymd") > $latest_quarter_bill_date->format("Ymd")) { $this->log->debug(__METHOD__.": Skipping operator_usage ".$create_date->format("m/Y")." for preorder ".$preorder->id." because Billing date ".$create_date->format("Y-m-d")." is after latest_quarter_bill_date ".$latest_quarter_bill_date->format("Y-m-d")); return true; } $new_create_date = clone $create_date; $to_bill_dates[] = $new_create_date; $create_date->modify("-1 months"); continue; } break; } //var_dump($to_bill_dates); //exit; foreach($to_bill_dates as $start_date) { $end_date = clone $start_date; $end_date->modify("first day of this month"); $end_date->modify("+1 months"); $end_date->modify("-1 day"); if($cancel_date && $cancel_date->format("Ym") == $start_date->format("Ym")) { $end_date = clone $cancel_date; } $sday = $start_date->format("d"); $eday = $end_date->format("d"); $price_id = $price->id; $base_price = $price->price_inet; if($netoperator_config["marketshare-discount"]) { // get current percentage of billed homes $ms_bill_month = $start_date->format("Ym"); if(!array_key_exists("billed-$ms_bill_month", $this->marketshare[$campaign->id]["netops"][$netoperator->id])) { $this->marketshare[$campaign->id]["netops"][$netoperator->id]["billed-$ms_bill_month"] = 0; } $max_homes = $this->marketshare[$campaign->id]["max"]; $billed_homes = $this->marketshare[$campaign->id]["netops"][$netoperator->id]["billed-$ms_bill_month"]; if($billed_homes) { $billed_pct = (100 * $billed_homes) / $max_homes; foreach([15,20,25,30,35,40,45,50] as $bracket) { if ($billed_pct >= $bracket) { if(array_key_exists("$bracket-$price_id", $this->marketshare[$campaign->id]["netops"][$netoperator->id]["bracket_price"])) { $base_price = $this->marketshare[$campaign->id]["netops"][$netoperator->id]["bracket_price"]["$bracket-$price_id"]->price_inet; } else { $bracket_price = $price->getMarketshareBracket($bracket); if ($bracket_price) { $this->marketshare[$campaign->id]["netops"][$netoperator->id]["bracket_price"]["$bracket-$price_id"] = $bracket_price; $base_price = $bracket_price->price_inet; } } } } } $this->log->debug(__METHOD__.": ".$netoperator->getCompanyOrName()." (month: $ms_bill_month; campaign: ".$campaign->name.") Marketshare Price: $base_price (max: $max_homes | billed: $billed_homes | billed% $billed_pct "); } $bill_price = $base_price; if ($base_price && ($sday > 1 || $cancel_date)) { // Aliquoten Preis errechnen $first_of_period = clone $start_date; $first_of_period->modify("first day of this month"); $last_of_period = clone $start_date; $last_of_period->modify("last day of this month"); $total_days = $last_of_period->diff($first_of_period)->format("%a") + 1; $period_days = ($end_date->diff($start_date)->format("%a")) + 1; if ($period_days < 0) return true; // don't bill for negative time range $pc = $period_days / $total_days * 100; $bill_price = round($base_price / 100 * $pc, 2); } $article_number = $product->article_number; if (!$article_number) { $article_number = $product->getDefaultArticlenumber(); } $billing_data = [ "netowner_id" => $netowner->id, "preorder_id" => $preorder->id, "oaid" => $preorder->oaid, "adb_wohneinheit_id" => $preorder->adb_wohneinheit_id, "extref" => ($preorder->extref) ?: null, "order_date" => $order_date->format("Y-m-d"), "start_date" => $start_date->format("Y-m-d"), "end_date" => $end_date->format("Y-m-d"), "billing_delivery" => "email", "product_id" => $product->id, "product_type" => $product->type, "product_info" => "", "article_number" => $article_number, "amount" => 1, "unit" => "Stk.", "price" => $bill_price, "price_setup" => 0, "vatrate" => 20, "billing_period" => 0, "product_name" => "Nutzungsentgelt " . $start_date->format("m/Y"), "owner_id" => $netoperator->id, "billingaddress_id" => $netoperator->id, "fibu_account_number" => $netoperator->attributes['rml-fibu-account']->value, "fibu_cost_account" => $fibu_cost_code, "fibu_revenue_account" => $fibu_revenue_code, "company" => trim($netoperator->company), "firstname" => trim($netoperator->firstname), "lastname" => trim($netoperator->lastname), "street" => trim($netoperator->street), "zip" => trim($netoperator->zip), "city" => trim($netoperator->city), "country" => trim($netoperator->country->name), "email" => trim($netoperator_config["email"]), "uid" => trim($netoperator->uid), ]; $billing = PreorderBilling::create($billing_data); //var_dump($billing);exit; if (!$billing->save()) { die("Billing record could not be saved!"); } $ms_bill_month = $start_date->format("Ym"); if(!array_key_exists("billed-$ms_bill_month", $this->marketshare[$campaign->id]["netops"][$netoperator->id])) { $this->marketshare[$campaign->id]["netops"][$netoperator->id]["billed-$ms_bill_month"] = 0; } $this->marketshare[$campaign->id]["netops"][$netoperator->id]["billed-$ms_bill_month"]++; //$this->marketshare[$campaign->id]["netops"][$netoperator->id]["billed-$ms_bill_month"] } //var_dump($this->marketshare);exit; //var_dump($billing); } }