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
"; 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); } }