Files
thetool/application/PreorderBilling/PreorderBillingController.php
2025-03-17 12:22:03 +01:00

413 lines
15 KiB
PHP

<?php
class PreorderBillingController extends mfBaseController {
private $billing_minimum_date = "2025-03-01";
protected function init() : void
{
$this->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);
}
//var_dump($filter);exit;
$pagination['maxItems'] = PreorderBilling::count($filter);
$projects = PreorderBilling::getAll();
$this->layout()->set("billings", $projects);
$this->layout()->set("pagination", $pagination);
}
private function getPreparedFilter($filter) {
$new_filter = [];
if (is_array($filter) && count($filter)) {
foreach ($filter as $name => $value) {
$new_filter[$name] = $value;
}
}
return $new_filter;
}
protected function importPreorders() {
$today = new DateTime("now");
$today->setTime(0,0,0);
$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-02-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");
$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" => 241
];
$billing_records = [];
foreach(PreorderModel::search($preorder_search) as $preorder) {
//$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") < "2025-01-01") {
// start billing from 2025-01-01
continue;
}
$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);
}
$bill_params = [
"netowner" => new Address($this->me->address_id),
"netoperator" => $netoperator,
"order_date" => $order_date,
"today" => $today,
"bill_date" => $bill_date,
];
if($preorder->status->code >= 241) {
$this->billSetup($preorder, "enduser_setup", $bill_params);
}
if($preorder->status->code >= 500) {
$this->billSetup($preorder, "operator_setup", $bill_params);
$this->billEnduserPeriodic($preorder, $bill_params);
//exit;
}
}
$this->Layout()->setFlash("Billing records erstellt", "success");
$this->redirect("PreorderBilling");
}
private function billSetup($preorder, $type, $options) {
$netowner = $options['netowner'];
$netoperator = $options['netoperator'];
$order_date = $options['order_date'];
$today = $options['today'];
$bill_date = $options['bill_date'];
// get price_setup
$product = PreorderProduct::getFirst(["type" => $type]);
if(!$product) {
die("operator_setup price not found!");
}
$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 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<br />";
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) {
$this->log->debug(__METHOD__.": No status change found for preorder ".$preorder->id." so using creation date");
$status_change = $preorder;
}
$status_change_date = new DateTime("@".$status_change->create);
$billing_data = [
"preorder_id" => $preorder->id,
"adb_wohneinheit_id" => $preorder->adb_wohneinheit_id,
"order_date" => $order_date->format("Y-m-d"),
"start_date" => $status_change_date->format("Y-m-d"),
"end_date" => $status_change_date->format("Y-m-d"),
"billing_delivery" => "email",
"product_id" => $product->id,
"product_info" => "",
"article_number" => $article_number,
"amount" => 1,
"unit" => "Stk.",
"price" => "0",
"price_setup" => $price->price_setup,
"vatrate" => 20,
"billing_period" => 0,
];
if($type == "enduser_setup") {
// Endkunde Setup Gebühr
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;
}
$billing_data["preorderbillingcustomer_id"] = $customer->id;
$billing_data["fibu_account_number"] = $customer->fibu_account_number;
$billing_data["product_name"] = "Bereitstellungsentgelt Glasfaseranschluss";
$billing_data["product_info"] = "Bestellung vom ".$order_date->format("d.m.Y");
} elseif($type == "operator_setup") {
// Netzbetreiber Setup Gebühr
$billing_data["product_name"] = "Brereitstellungsentgelt ".$bill_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["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->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);
return true;
}
private function billEnduserPeriodic($preorder, $options) {
$netowner = $options['netowner'];
$netoperator = $options['netoperator'];
$order_date = $options['order_date'];
$today = $options['today'];
$bill_date = $options['bill_date'];
// 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, $order_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::getFirstStatusChangeToOrHigher($preorder->id, 500);
if(!$status_change) {
$this->log->debug(__METHOD__.": No status change to 500 found for preorder ".$preorder->id." so using creation date");
$status_change = $preorder;
}
$status_change_date = new DateTime("@".$status_change->create);
$first_bill_day = clone $status_change_date;
$first_day = clone $today;
$first_day->modify("first day of this month");
$last_day = clone $today;
$last_day->modify("last day of this month");
//var_dump($first_bill_day);
//var_dump($first_day);
if($first_bill_day->format("Ymd") > $first_day->format("Ymd")) {
$first_day = clone $first_bill_day;
}
$start_date = clone($first_day);
$end_date = clone($last_day);
$to_bill_dates = [];
$sday = $start_date->format("d");
$eday = $end_date->format("d");
$bill_price = $price->price_inet;
if($price->price_inet && ($sday > 1)) {
// 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($price->price_inet / 100 * $pc, 4);
}
$article_number = $product->article_number;
if(!$article_number) {
$article_number = $product->getDefaultArticlenumber();
}
$billing_data = [
"preorder_id" => $preorder->id,
"adb_wohneinheit_id" => $preorder->adb_wohneinheit_id,
"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_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,
"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->email),
"uid" => trim($netoperator->uid),
];
$billing = PreorderBilling::create($billing_data);
//var_dump($billing);exit;
if(!$billing->save()) {
die("Billing record could not be saved!");
}
//var_dump($billing);
}
}