diff --git a/Layout/default/PreorderBilling/Index.php b/Layout/default/PreorderBilling/Index.php
new file mode 100644
index 000000000..40bb30097
--- /dev/null
+++ b/Layout/default/PreorderBilling/Index.php
@@ -0,0 +1,202 @@
+getUrl($Mod, "Index");
+$pagination_baseurl_params = ["filter" => $filter];
+$pagination_entity_name = "Billingrecords";
+?>
+
+
+
+
diff --git a/application/Api/v1/AddressdbApicontroller.php b/application/Api/v1/AddressdbApicontroller.php
index dbdfccecc..ce412aa2f 100644
--- a/application/Api/v1/AddressdbApicontroller.php
+++ b/application/Api/v1/AddressdbApicontroller.php
@@ -25,6 +25,7 @@ class AddressdbApicontroller extends mfBaseApicontroller {
$this->addRoute("/addressdb/findDistrict", "findDistrict", "GET");
$this->addRoute("/addressdb/findDistrict", "findDistrict", "POST");
$this->addRoute("/addressdb/fullexport", "exportAddresses", "GET");
+ $this->addRoute("/addressdb/:oaid/pricing", "getAddressPricing", "GET");
$this->allowMissingOrigin = true;
}
@@ -884,6 +885,74 @@ class AddressdbApicontroller extends mfBaseApicontroller {
return mfResponse::Ok(['addresses' => $addresses]);
}
+ protected function getAddressPricing($oaid) {
+ if(!$oaid) {
+ return mfResponse::BadRequest(['message' => "OAID missing"]);
+ }
+
+ $unit = ADBWohneinheitModel::getFirst(["oaid" => $oaid]);
+ if($unit) {
+ $hausnummer = $unit->hausnummer;
+ } else {
+ $hausnummer = ADBHausnummerModel::getFirst(["oaid" => $oaid]);
+ }
+
+ if(!$hausnummer) {
+ return mfResponse::NotFound(['message' => "Address not found"]);
+ }
+
+ $network = NetworkModel::getFirst(["adb_netzgebiet_id" => $hausnummer->netzgebiet_id]);
+ $netowner_id = $network->owner_id;
+
+ $campaign = PreordercampaignModel::getFirst(["network_id" => $network->id]);
+ $netop = PreordercampaignOperatorModel::getFirst(["isp_id" => $this->me->address_id, "preordercampaign_id" => $campaign->id]);
+
+ if(!$netop) {
+ $netop = PreordercampaignOperatorModel::getFirst(["operator_id" => $this->me->address_id, "preordercampaign_id" => $campaign->id]);
+ }
+ if(!$netop) {
+ return mfResponse::Unauthorized();
+ }
+
+ $netoperator = $netop->operator;
+
+ $prices = [];
+ $enduser_setup_product_id = false;
+ foreach(PreorderProduct::getWithTypes() as $product) {
+ if($product->type == "enduser_setup") {
+ $enduser_setup_product_id = $product->id;
+ }
+ $product->setNetownerId($netowner_id);
+ $product->setNetoperatorId($netoperator->id);
+
+ $prices[$product->type] = $product->getCampaignPrice($campaign->id);
+ }
+
+ $prices_return = [
+ "price_inet" => (float)$prices["operator_usage"]->price_inet,
+ "price_inet_tv" => (float)$prices["operator_usage"]->price_inet_tv,
+ "price_catv" => (float)$prices["operator_usage"]->price_catv,
+
+ "operator_setup_price" => (float)$prices["operator_setup"]->price_setup,
+ "operator_setup_info" => $prices["operator_setup"]->description,
+ "operator_setup_valid_until" => $prices["operator_setup"]->end_date,
+
+ "enduser_setup_price" => (float)$prices["enduser_setup"]->price_setup,
+ "enduser_setup_info" => $prices["enduser_setup"]->description,
+ "enduser_setup_valid_until" => $prices["enduser_setup"]->end_date,
+
+ "vatrate" => 20,
+ ];
+
+ if(PreorderBilling::getFirst(["adb_wohneinheit_id" => $unit->id, "product_id" => $enduser_setup_product_id])) {
+ $prices_return["enduser_setup_price"] = 0;
+ $prices_return["enduser_setup_info"] = "paid";
+ $prices_return["enduser_setup_valid_until"] = null;
+ }
+
+ return mfResponse::Ok(['oaid' => $oaid, 'prices' => $prices_return]);
+ }
+
protected function exportAddresses() {
//if($this->me->username != 'r.eschner@rmlinfrastruktur.at') {
// return mfResponse::Forbidden();
diff --git a/application/Preorder/PreorderModel.php b/application/Preorder/PreorderModel.php
index 900cb0b4d..3576f6ffb 100644
--- a/application/Preorder/PreorderModel.php
+++ b/application/Preorder/PreorderModel.php
@@ -658,6 +658,20 @@ class PreorderModel
}
}
+ if (array_key_exists("<=status_code", $filter)) {
+ $status_code = $filter['<=status_code'];
+ if (is_numeric($status_code)) {
+ $where .= " AND tt_preorderstatus.code <= $status_code";
+ }
+ }
+
+ if (array_key_exists(">=status_code", $filter)) {
+ $status_code = $filter['>=status_code'];
+ if (is_numeric($status_code)) {
+ $where .= " AND tt_preorderstatus.code >= $status_code";
+ }
+ }
+
if (array_key_exists("preordercampaign_id", $filter)) {
$preordercampaign_id = $filter['preordercampaign_id'];
diff --git a/application/PreorderBilling/PreorderBilling.php b/application/PreorderBilling/PreorderBilling.php
new file mode 100644
index 000000000..f9957b798
--- /dev/null
+++ b/application/PreorderBilling/PreorderBilling.php
@@ -0,0 +1,411 @@
+$name == null) {
+
+ if($name == "invoice") {
+ if(!$this->invoice_id) return null;
+ $invoice = new PreorderInvoice($this->invoice_id);
+ if($invoice->id) {
+ $this->invoice = $invoice;
+ return $this->invoice;
+ }
+ return null;
+ }
+
+ if($name == "creator") {
+ $creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by);
+ if($creator) {
+ $this->creator = $creator;
+ return $this->creator;
+ }
+ $this->creator = new User($this->create_by);
+
+ if(!$this->creator->id) {
+ return null;
+ }
+ mfValuecache::singleton()->set("Worker-id-".$this->create_by, $this->creator);
+ return $this->creator;
+ }
+
+ if($name == "editor") {
+ $editor = mfValuecache::singleton()->get("Worker-id-".$this->edit_by);
+ if($editor) {
+ $this->editor = $editor;
+ return $this->editor;
+ }
+ $this->editor = new User($this->edit_by);
+ if(!$this->editor->id) {
+ return null;
+ }
+ mfValuecache::singleton()->set("Worker-id-".$this->edit_by, $this->editor);
+ return $this->editor;
+ }
+
+ $classname = ucfirst($name);
+ $idfield = $name . "_id";
+ $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-" . $this->$idfield);
+ if(!$this->$name) {
+ $this->$name = new $classname($this->$idfield);
+ }
+
+ if($this->$name->id) {
+ mfValuecache::singleton()->set("mfObjectmodel-$name-" . $this->$name->id, $this->$name);
+ return $this->$name;
+ } else {
+ return null;
+ }
+ }
+
+ return $this->$name;
+
+ }
+
+ /********************************
+ * Begin static Model functions
+ */
+
+ public static function create(Array $data) {
+ $model = new PreorderBilling();
+
+ $table_fields = [
+ "invoice_id", "preorder_id", "adb_wohneinheit_id", "order_date", "start_date", "end_date", "preorderbillingcustomer_id", "owner_id", "billingaddress_id",
+ "fibu_account_number", "company", "firstname", "lastname", "street", "zip", "city", "country", "email", "uid", "billing_delivery",
+ "product_id", "product_name", "product_info", "article_number", "amount", "unit", "price", "price_setup", "vatrate", "billing_period",
+ "create_by","edit_by","create","edit"
+ ];
+
+ foreach($data as $field => $value) {
+ if(in_array($field, $table_fields)) {
+ $model->$field = $value;
+ }
+ }
+
+ $me = new User();
+ $me->loadMe();
+
+ if($model->create_by === null) {
+ $model->create_by = $me->id;
+ }
+ if($model->edit_by === null) {
+ $model->edit_by = $me->id;
+ }
+
+ return $model;
+ }
+
+ public static function getAll() {
+ $items = [];
+
+ $db = FronkDB::singleton();
+
+ $res = $db->select("PreorderBilling", "*", "1 = 1 ORDER BY preorder_id");
+ if($db->num_rows($res)) {
+ while($data = $db->fetch_object($res)) {
+ $items[] = new PreorderBilling($data);
+ }
+ }
+ return $items;
+
+ }
+
+ public static function getFirst($filter) {
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT * FROM PreorderBilling
+ WHERE $where
+ ORDER BY preorder_id LIMIT 1";
+ //var_dump($sql);exit;
+ //mfLoghandler::singleton()->debug($sql);
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ $item = new PreorderBilling($data);
+ if($item->id) {
+ return $item;
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static function count($filter) {
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT COUNT(*) as cnt FROM PreorderBilling
+ WHERE $where";
+
+ //mfLoghandler::singleton()->debug($sql);
+
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ return $data->cnt;
+ }
+ return 0;
+ }
+
+ public static function search($filter, $limit = false, $order = false) {
+ //var_dump($filter);exit;
+ $items = [];
+
+ if(!$order) {
+ $order = "preorder_id ASC";
+ }
+
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT * FROM PreorderBilling
+ WHERE $where
+ ORDER BY $order";
+
+ if(is_array($limit) && count($limit)) {
+ if(is_numeric($limit['start']) && is_numeric($limit['count'])) {
+ $sql .= " LIMIT ".$limit['start'].", ".$limit['count'];
+ } elseif(is_numeric($limit['count'])) {
+ $sql .= " LIMIT ".$limit['count'];
+ }
+ }
+
+ //mfLoghandler::singleton()->debug($sql);
+
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ while($data = $db->fetch_object($res)) {
+ $items[$data->id] = new PreorderBilling($data);
+ }
+ }
+
+ return $items;
+ }
+
+ private static function getSqlFilter($filter) {
+ $where = "1=1 ";
+
+ if(array_key_exists("invoice_id", $filter)) {
+ $invoice_id = $filter['invoice_id'];
+ if(is_numeric($invoice_id)) {
+ $where .= " AND PreorderBilling.invoice_id=$invoice_id";
+ } elseif($invoice_id === null || $invoice_id === false) {
+ $where .= " AND (PreorderBilling.invoice_id IS NULL OR PreorderBilling.invoice_id=0)";
+ } elseif($invoice_id === true) {
+ $where .= " AND (PreorderBilling.invoice_id IS NOT NULL AND PreorderBilling.invoice_id > 0)";
+ }
+ }
+
+ if(array_key_exists("preorder_id", $filter)) {
+ $preorder_id = $filter['preorder_id'];
+ if(is_numeric($preorder_id)) {
+ $where .= " AND PreorderBilling.preorder_id=$preorder_id";
+ }
+ }
+
+ if(array_key_exists("adb_wohneinheit_id", $filter)) {
+ $adb_wohneinheit_id = $filter['adb_wohneinheit_id'];
+ if(is_numeric($adb_wohneinheit_id)) {
+ $where .= " AND PreorderBilling.adb_wohneinheit_id=$adb_wohneinheit_id";
+ }
+ }
+
+ if(array_key_exists("order_date", $filter)) {
+ $order_date = FronkDB::singleton()->escape($filter['order_date']);
+ if($order_date) {
+ $where .= " AND PreorderBilling.order_date='$order_date'";
+ }
+ }
+
+ if(array_key_exists("start_date", $filter)) {
+ $start_date = FronkDB::singleton()->escape($filter['start_date']);
+ if($start_date) {
+ $where .= " AND PreorderBilling.start_date='$start_date'";
+ }
+ }
+
+ if(array_key_exists("start_date>", $filter)) {
+ $start_date = FronkDB::singleton()->escape($filter['start_date>']);
+ if($start_date) {
+ $where .= " AND PreorderBilling.start_date > '$start_date'";
+ }
+ }
+
+ if(array_key_exists("start_date<", $filter)) {
+ $start_date = FronkDB::singleton()->escape($filter['start_date<']);
+ if($start_date) {
+ $where .= " AND PreorderBilling.start_date < '$start_date'";
+ }
+ }
+
+ if(array_key_exists("start_date>=", $filter)) {
+ $start_date = FronkDB::singleton()->escape($filter['start_date>=']);
+ if($start_date) {
+ $where .= " AND PreorderBilling.start_date >= '$start_date'";
+ }
+ }
+
+ if(array_key_exists("start_date<=", $filter)) {
+ $start_date = FronkDB::singleton()->escape($filter['start_date<=']);
+ if($start_date) {
+ $where .= " AND PreorderBilling.start_date <= '$start_date'";
+ }
+ }
+
+ if(array_key_exists("owner_id", $filter)) {
+ $owner_id = $filter['owner_id'];
+ if(is_numeric($owner_id)) {
+ $where .= " AND PreorderBilling.owner_id=$owner_id";
+ }
+ }
+
+ if(array_key_exists("billingaddress_id", $filter)) {
+ $billingaddress_id = $filter['billingaddress_id'];
+ if(is_numeric($billingaddress_id)) {
+ $where .= " AND PreorderBilling.billingaddress_id=$billingaddress_id";
+ }
+ }
+
+ if (array_key_exists("company", $filter)) {
+ $company = FronkDB::singleton()->escape($filter["company"]);
+ if ($company) {
+ $where .= " AND company like '%$company%'";
+ }
+ }
+
+ if (array_key_exists("firstname", $filter)) {
+ $firstname = FronkDB::singleton()->escape($filter["firstname"]);
+ if ($firstname) {
+ $where .= " AND firstname like '%$firstname%'";
+ }
+ }
+
+ if (array_key_exists("lastname", $filter)) {
+ $lastname = FronkDB::singleton()->escape($filter["lastname"]);
+ if ($lastname) {
+ $where .= " AND lastname like '%$lastname%'";
+ }
+ }
+
+ if (array_key_exists("mergedName", $filter)) {
+ $name = FronkDB::singleton()->escape($filter["mergedName"]);
+ if ($name) {
+ $where .= " AND (CONCAT(firstname, ' ', lastname) like '%$name%' OR CONCAT(lastname, ' ', firstname) like '%$name%' )";
+ }
+ }
+
+ if (array_key_exists("street", $filter)) {
+ $street = FronkDB::singleton()->escape($filter["street"]);
+ if ($street) {
+ $where .= " AND street like '%$street%'";
+ }
+ }
+
+ if (array_key_exists("zip", $filter)) {
+ $zip = FronkDB::singleton()->escape($filter["zip"]);
+ if ($zip) {
+ $where .= " AND zip like '%$zip%'";
+ }
+ }
+
+ if (array_key_exists("city", $filter)) {
+ $city = FronkDB::singleton()->escape($filter["city"]);
+ if ($city) {
+ $where .= " AND city like '%$city%'";
+ }
+ }
+
+ if (array_key_exists("country", $filter)) {
+ $country = FronkDB::singleton()->escape($filter["country"]);
+ if ($country) {
+ $where .= " AND country like '%$country%'";
+ }
+ }
+
+ if (array_key_exists("email", $filter)) {
+ $email = FronkDB::singleton()->escape($filter["email"]);
+ if ($email) {
+ $where .= " AND email like '%$email%'";
+ }
+ }
+
+ if(array_key_exists("product_id", $filter)) {
+ $product_id = $filter['product_id'];
+ if(is_numeric($product_id)) {
+ $where .= " AND PreorderBilling.product_id=$product_id";
+ }
+ }
+
+ if(array_key_exists("product_name", $filter)) {
+ $product_name = FronkDB::singleton()->escape($filter['product_name']);
+ if($product_name) {
+ $where .= " AND product_name like '%$product_name%')";
+ }
+ }
+
+ if(array_key_exists("price<", $filter)) {
+ $price = $filter['price<'];
+ if(is_numeric($price)) {
+ $where .= " AND PreorderBilling.price < $price";
+ }
+ }
+ if(array_key_exists("price<=", $filter)) {
+ $price = $filter['price<='];
+ if(is_numeric($price)) {
+ $where .= " AND PreorderBilling.price <= $price";
+ }
+ }
+
+ if(array_key_exists("price>", $filter)) {
+ $price = $filter['price>'];
+ if(is_numeric($price)) {
+ $where .= " AND PreorderBilling.price > $price";
+ }
+ }
+ if(array_key_exists("price>=", $filter)) {
+ $price = $filter['price>='];
+ if(is_numeric($price)) {
+ $where .= " AND PreorderBilling.price >= $price";
+ }
+ }
+
+ if(array_key_exists("billing_delivery", $filter)) {
+ $billing_delivery = FronkDB::singleton()->escape($filter['billing_delivery']);
+ if($billing_delivery) {
+ $where .= " AND PreorderBilling.billing_delivery = '$billing_delivery'";
+ }
+ }
+
+ if(array_key_exists("vatgroup_id", $filter)) {
+ $vatgroup_id = $filter['vatgroup_id'];
+ if(is_numeric($vatgroup_id)) {
+ $where .= " AND PreorderBilling.vatgroup_id = $vatgroup_id";
+ }
+ }
+
+ if(array_key_exists("!vatgroup_id", $filter)) {
+ $vatgroup_id = $filter['!vatgroup_id'];
+ if(is_numeric($vatgroup_id)) {
+ $where .= " AND PreorderBilling.vatgroup_id <> $vatgroup_id";
+ }
+ }
+
+
+
+ if(array_key_exists("add-where", $filter)) {
+ $where .= " ".$filter['add-where'];
+ }
+
+ //var_dump($filter, $where);exit;
+ return $where;
+ }
+
+}
\ No newline at end of file
diff --git a/application/PreorderBilling/PreorderBillingController.php b/application/PreorderBilling/PreorderBillingController.php
new file mode 100644
index 000000000..9da60d31a
--- /dev/null
+++ b/application/PreorderBilling/PreorderBillingController.php
@@ -0,0 +1,413 @@
+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);
+ }
+}
\ No newline at end of file
diff --git a/application/PreorderBillingCustomer/PreorderBillingCustomer.php b/application/PreorderBillingCustomer/PreorderBillingCustomer.php
new file mode 100644
index 000000000..b05aca065
--- /dev/null
+++ b/application/PreorderBillingCustomer/PreorderBillingCustomer.php
@@ -0,0 +1,288 @@
+loadMe();
+ $data["edit_by"] = $me->id;
+ }
+
+ return $data;
+ }
+
+ public function createFibuAccountNumber($netowner_id) {
+ if($this->fibu_account_number) return true;
+
+ // get last FibuAccountNumber
+ $last_fibu_account_number_row = PreorderBillingCustomer::getLast(["netowner_id" => $netowner_id, "fibu_account_number" => true], "fibu_account_number DESC");
+ if($last_fibu_account_number_row) {
+ $new_num = $last_fibu_account_number_row->fibu_account_number + 1;
+ } else {
+ $new_num = 250001;
+ }
+
+ $this->fibu_account_number = $new_num;
+
+
+ }
+
+ public function getProperty($name) {
+ if($this->$name == null) {
+
+
+
+ $classname = ucfirst($name);
+ $idfield = $name."_id";
+ $this->$name = mfValuecache::singleton()->getMfObject($classname, $this->$idfield);
+ if(!$this->$name) {
+ return null;
+ }
+ }
+
+ return $this->$name;
+ }
+
+ /********************************
+ * Begin static Model functions
+ */
+
+ public static function create(Array $data) {
+ $model = new PreorderBillingCustomer();
+
+ $table_fields = [
+ "fibu_account_number", "company", "firstname", "lastname", "street", "zip", "city", "country", "phone", "email", "uid",
+ "create_by","edit_by","create","edit"
+ ];
+
+ foreach($data as $field => $value) {
+ if(in_array($field, $table_fields)) {
+ $model->$field = $value;
+ }
+ }
+
+ $me = new User();
+ $me->loadMe();
+
+ if($model->create_by === null) {
+ $model->create_by = $me->id;
+ }
+ if($model->edit_by === null) {
+ $model->edit_by = $me->id;
+ }
+
+ return $model;
+ }
+
+ public static function getAll() {
+ $items = [];
+
+ $db = FronkDB::singleton();
+
+ $res = $db->select("PreorderBillingCustomer", "*", "1 = 1 ORDER BY id");
+ if($db->num_rows($res)) {
+ while($data = $db->fetch_object($res)) {
+ $items[] = new PreorderBillingCustomer($data);
+ }
+ }
+ return $items;
+
+ }
+
+ public static function getFirst($filter) {
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT * FROM PreorderBillingCustomer
+ WHERE $where
+ ORDER BY id LIMIT 1";
+ //var_dump($sql);exit;
+ //mfLoghandler::singleton()->debug($sql);
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ $item = new PreorderBillingCustomer($data);
+ if($item->id) {
+ return $item;
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static function getLast($filter, $order = false) {
+ $db = FronkDB::singleton();
+
+ if(!$order) {
+ $order = "id DESC";
+ }
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT * FROM PreorderBillingCustomer
+ WHERE $where
+ ORDER BY $order LIMIT 1";
+ //var_dump($sql);exit;
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ $item = new PreorderBillingCustomer($data);
+ if($item->id) {
+ return $item;
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static function count($filter) {
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT COUNT(*) as cnt FROM PreorderBillingCustomer
+ WHERE $where";
+
+ //mfLoghandler::singleton()->debug($sql);
+
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ return $data->cnt;
+ }
+ return 0;
+ }
+
+ public static function search($filter, $limit = false, $order = false) {
+ //var_dump($filter);exit;
+ $items = [];
+
+ if(!$order) {
+ $order = "id ASC";
+ }
+
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $sql = "SELECT * FROM PreorderBillingCustomer
+ WHERE $where
+ ORDER BY $order";
+
+ if(is_array($limit) && count($limit)) {
+ if(is_numeric($limit['start']) && is_numeric($limit['count'])) {
+ $sql .= " LIMIT ".$limit['start'].", ".$limit['count'];
+ } elseif(is_numeric($limit['count'])) {
+ $sql .= " LIMIT ".$limit['count'];
+ }
+ }
+
+ mfLoghandler::singleton()->debug($sql);
+
+ $res = $db->query($sql);
+ if($db->num_rows($res)) {
+ while($data = $db->fetch_object($res)) {
+ $items[$data->id] = new PreorderBillingCustomer($data);
+ }
+ }
+
+ return $items;
+ }
+
+ private static function getSqlFilter($filter) {
+ $where = "1=1 ";
+
+ if(array_key_exists("fibu_account_number", $filter)) {
+ $fibu_account_number = $filter["fibu_account_number"];
+ if($fibu_account_number === true) {
+ $where .= " AND (fibu_account_number IS NOT NULL AND fibu_account_number <> '')";
+ } elseif($fibu_account_number === false || $fibu_account_number === null) {
+ $where .= " AND (fibu_account_number IS NULL OR fibu_account_number = '' || fibu_account_number = '0')";
+ } elseif($fibu_account_number) {
+ $fibu_account_number = FronkDB::singleton()->escape($filter["fibu_account_number"]);
+ $where .= " AND fibu_account_number='$fibu_account_number'";
+ }
+ }
+
+ if(array_key_exists("company", $filter)) {
+ $company = FronkDB::singleton()->escape($filter["company"]);
+ if($company) {
+ $where .= " AND company='$company'";
+ }
+ }
+
+ if(array_key_exists("firstname", $filter)) {
+ $firstname = FronkDB::singleton()->escape($filter["firstname"]);
+ if($firstname) {
+ $where .= " AND firstname='$firstname'";
+ }
+ }
+
+ if(array_key_exists("lastname", $filter)) {
+ $lastname = FronkDB::singleton()->escape($filter["lastname"]);
+ if($lastname) {
+ $where .= " AND lastname='$lastname'";
+ }
+ }
+
+ if(array_key_exists("street", $filter)) {
+ $street = FronkDB::singleton()->escape($filter["street"]);
+ if($street) {
+ $where .= " AND street='$street'";
+ }
+ }
+
+ if(array_key_exists("zip", $filter)) {
+ $zip = FronkDB::singleton()->escape($filter["zip"]);
+ if($zip) {
+ $where .= " AND zip='$zip'";
+ }
+ }
+
+ if(array_key_exists("city", $filter)) {
+ $city = FronkDB::singleton()->escape($filter["city"]);
+ if($city) {
+ $where .= " AND city='$city'";
+ }
+ }
+
+ if(array_key_exists("country", $filter)) {
+ $country = FronkDB::singleton()->escape($filter["country"]);
+ if($country) {
+ $where .= " AND country='$country'";
+ }
+ }
+
+ if(array_key_exists("phone", $filter)) {
+ $phone = FronkDB::singleton()->escape($filter["phone"]);
+ if($phone) {
+ $where .= " AND phone='$phone'";
+ }
+ }
+
+ if(array_key_exists("email", $filter)) {
+ $email = FronkDB::singleton()->escape($filter["email"]);
+ if($email) {
+ $where .= " AND email='$email'";
+ }
+ }
+
+ if(array_key_exists("uid", $filter)) {
+ $uid = FronkDB::singleton()->escape($filter["uid"]);
+ if($uid) {
+ $where .= " AND uid='$uid'";
+ }
+ }
+
+
+ if(array_key_exists("add-where", $filter)) {
+ $where .= " ".$filter['add-where'];
+ }
+
+ //var_dump($filter, $where);exit;
+ return $where;
+ }
+
+}
\ No newline at end of file
diff --git a/application/PreorderHistory/PreorderHistory.php b/application/PreorderHistory/PreorderHistory.php
index 2cc9f59dd..fb6c13409 100644
--- a/application/PreorderHistory/PreorderHistory.php
+++ b/application/PreorderHistory/PreorderHistory.php
@@ -69,6 +69,10 @@ class PreorderHistory extends mfBaseModel {
}
}
+ if($this->key == "order_date" && $value) {
+ return date("d.m.Y", $value);
+ }
+
if(!is_object($value)) {
return $value;
}
@@ -88,6 +92,8 @@ class PreorderHistory extends mfBaseModel {
if(get_class($value) == "Preordercampaign") {
return $value->name;
}
+
+ return "";
}
public function getProperty($name) {
diff --git a/application/PreorderHistory/PreorderHistoryModel.php b/application/PreorderHistory/PreorderHistoryModel.php
index 97575a27d..4e86eeb1f 100644
--- a/application/PreorderHistory/PreorderHistoryModel.php
+++ b/application/PreorderHistory/PreorderHistoryModel.php
@@ -37,6 +37,58 @@ class PreorderHistoryModel {
return $model;
}
+
+ public static function getStatusChange($type = "first", $preorder_id, $status_code) {
+ $status = PreorderstatusModel::getFirst(["code" => $status_code]);
+ if(!$status) {
+ return false;
+ }
+
+ $status_id = $status->id;
+ $sql = "SELECT * FROM PreorderHistory WHERE preorder_id = $preorder_id AND `key` = 'status_id' AND new_value = $status_id";
+ if($type == "first") {
+ $sql .= " ORDER BY id ASC LIMIT 1";
+ } else {
+ $sql .= " ORDER BY id DESC LIMIT 1";
+ }
+ //mfLoghandler::singleton()->debug($sql);
+ $res = FronkDB::singleton()->query($sql);
+ if(FronkDB::singleton()->num_rows($res)) {
+ $data = FronkDB::singleton()->fetch_object($res);
+ return new PreorderHistory($data);
+ }
+ return false;
+ }
+ public static function getFirstStatusChangeTo($preorder_id, $status_code) {
+ return self::getStatusChange("first", $preorder_id, $status_code);
+ }
+
+ public static function getLastStatusChangeTo($preorder_id, $status_code) {
+ return self::getStatusChange("last", $preorder_id, $status_code);
+ }
+
+ public static function getFirstStatusChangeToOrHigher($preorder_id, $status_code) {
+ foreach(PreorderstatusModel::getAll() as $status) {
+ if($status->code < $status_code) continue;
+
+ $change = self::getStatusChange("first", $preorder_id, $status_code);
+ if($change) return $change;
+ }
+
+ return false;
+ }
+
+ public static function getLastStatusChangeToOrHigher($preorder_id, $status_code) {
+ foreach(PreorderstatusModel::getAll() as $status) {
+ if($status->code < $status_code) continue;
+
+ $change = self::getStatusChange("last", $preorder_id, $status_code);
+ if($change) return $change;
+ }
+
+ return false;
+ }
+
public static function getFirst($filter = []) {
$db = FronkDB::singleton();
diff --git a/application/PreorderProduct/PreorderProduct.php b/application/PreorderProduct/PreorderProduct.php
index 432126f5b..a235b7ddf 100644
--- a/application/PreorderProduct/PreorderProduct.php
+++ b/application/PreorderProduct/PreorderProduct.php
@@ -53,6 +53,29 @@ class PreorderProduct extends mfBaseModel {
return $this->today_date;
}
+ public function getDefaultArticlenumber() {
+ $prices = PreorderProductPrice::search([
+ "article_number" => true,
+ "netowner_id" => $this->filter_netowner_id,
+ "netoperator_id" => $this->filter_netoperator_id,
+ "preorderproduct_id" => $this->id
+ ]);
+ foreach($prices as $price) {
+ if($price->article_number) return $price->article_number;
+ }
+
+ $prices = PreorderProductPrice::search([
+ "article_number" => true,
+ "netowner_id" => $this->filter_netowner_id,
+ "preorderproduct_id" => $this->id
+ ]);
+ foreach($prices as $price) {
+ if($price->article_number) return $price->article_number;
+ }
+
+ return "";
+ }
+
public function getCampaignFirstPrice($campaign_id, $date = null) {
if(!$date) $date = date("Y-m-d");
@@ -90,7 +113,7 @@ class PreorderProduct extends mfBaseModel {
return $price;
//return $this->current_campaign_regular_price;
} else {
- $this->log->debug(__METHOD__.": TRY FIRST PRICE");
+ //$this->log->debug(__METHOD__.": TRY FIRST PRICE");
return $this->getCampaignFirstPrice($campaign_id, $date);
}
return null;
@@ -130,23 +153,23 @@ class PreorderProduct extends mfBaseModel {
$this->log->debug("=== in ".__METHOD__);
if(!$date) $date = date("Y-m-d");
- $this->log->debug(__METHOD__.": TRY CURRENT PRICE");
+ //$this->log->debug(__METHOD__.": TRY CURRENT PRICE");
$price = $this->getCampaignCurrentPrice($campaign_id, $date);
if(!$price) {
- $this->log->debug(__METHOD__.": TRY CURRENT REGULAR PRICE");
+ //$this->log->debug(__METHOD__.": TRY CURRENT REGULAR PRICE");
$price = $this->getCampaignCurrentRegularPrice($campaign_id, $date);
}
if(!$price) {
- $this->log->debug(__METHOD__.": TRY FIRST PRICE");
+ //$this->log->debug(__METHOD__.": TRY FIRST PRICE");
$price = $this->getCampaignFirstPrice($campaign_id, $date);
}
if(!$price) {
- $this->log->debug(__METHOD__.": No Campaign price found. GET NETOP CURRENT PRICE");
+ //$this->log->debug(__METHOD__.": No Campaign price found. GET NETOP CURRENT PRICE");
$price = $this->getPrice();
}
if($price) {
- $this->log->debug("=== done in ".__METHOD__);
+ //$this->log->debug("=== done in ".__METHOD__);
return $price;
}
return null;
@@ -191,7 +214,7 @@ class PreorderProduct extends mfBaseModel {
], "start_date DESC, `create` DESC");
if(!$price && $allowCascading) {
- $this->log->debug(__METHOD__.": Cascading to getFirstPrice()");
+ //$this->log->debug(__METHOD__.": Cascading to getFirstPrice()");
return $this->getFirstPrice($date, true);
}
return $price;
@@ -230,7 +253,7 @@ class PreorderProduct extends mfBaseModel {
}
if(!$price && $allowCascading) {
- $this->log->debug(__METHOD__.": Cascading to getCurrentRegularPrice()");
+ //$this->log->debug(__METHOD__.": Cascading to getCurrentRegularPrice()");
return $this->getCurrentRegularPrice($date, true);
}
return $price;
@@ -239,23 +262,23 @@ class PreorderProduct extends mfBaseModel {
public function getPrice($date = null) {
if(!$date) $date = date("Y-m-d");
- $this->log->debug("=== in ".__METHOD__);
- $this->log->debug(__METHOD__.": TRY CURRENT PRICE");
+ //$this->log->debug("=== in ".__METHOD__);
+ //$this->log->debug(__METHOD__.": TRY CURRENT PRICE");
$price = $this->getCurrentPrice($date);
if(!$price) {
- $this->log->debug(__METHOD__.": TRY CURRENT REGULAR PRICE");
+ //$this->log->debug(__METHOD__.": TRY CURRENT REGULAR PRICE");
$price = $this->getCurrentRegularPrice($date);
}
if(!$price) {
- $this->log->debug(__METHOD__.": TRY FIRST PRICE");
+ //$this->log->debug(__METHOD__.": TRY FIRST PRICE");
$price = $this->getFirstPrice($date);
}
if(!$price) {
- $this->log->error(__METHOD__.": Unable to find price! netowner_id: ".$this->filter_netowner_id, " netoperator_id: ".$this->filter_netoperator_id." date: $date");
+ //$this->log->error(__METHOD__.": Unable to find price! netowner_id: ".$this->filter_netowner_id, " netoperator_id: ".$this->filter_netoperator_id." date: $date");
return null;
}
- $this->log->debug("=== done in ".__METHOD__);
+ //$this->log->debug("=== done in ".__METHOD__);
return $price;
}
@@ -608,7 +631,7 @@ class PreorderProduct extends mfBaseModel {
}
}
- mfLoghandler::singleton()->debug($sql);
+ //mfLoghandler::singleton()->debug($sql);
$res = $db->query($sql);
if($db->num_rows($res)) {
@@ -623,101 +646,11 @@ class PreorderProduct extends mfBaseModel {
private static function getSqlFilter($filter) {
$where = "1=1 ";
- if(array_key_exists("project_id", $filter)) {
- $project_id = $filter['project_id'];
- if(is_numeric($project_id)) {
- $where .= " AND PreorderProduct.preorderProductproject_id=$project_id";
- }
- }
- if(array_key_exists("preorderProductproject_id", $filter)) {
- $preorderProductproject_id = $filter['preorderProductproject_id'];
- if(is_numeric($preorderProductproject_id)) {
- $where .= " AND PreorderProduct.preorderProductproject_id=$preorderProductproject_id";
- }
- }
-
- if(array_key_exists("adb_wohneinheit_id", $filter)) {
- $adb_wohneinheit_id = $filter['adb_wohneinheit_id'];
- if(is_numeric($adb_wohneinheit_id)) {
- $where .= " AND PreorderProduct.adb_wohneinheit_id=$adb_wohneinheit_id";
- }
- }
-
- if(array_key_exists("termination_id", $filter)) {
- $termination_id = $filter['termination_id'];
- if(is_numeric($termination_id)) {
- $where .= " AND PreorderProduct.termination_id=$termination_id";
- }
- }
-
- if(array_key_exists("object_type", $filter)) {
- $object_type = FronkDB::singleton()->escape($filter["object_type"]);
- if($object_type) {
- $where .= " AND object_type='$object_type'";
- }
- }
-
- if(array_key_exists("ez", $filter)) {
- $ez = FronkDB::singleton()->escape($filter["ez"]);
- if($ez) {
- $where .= " AND ez='$ez'";
- }
- }
-
- if(array_key_exists("status", $filter)) {
- $status = FronkDB::singleton()->escape($filter["status"]);
- if($status) {
- $where .= " AND status='$status'";
- }
- }
-
- if(array_key_exists("result", $filter)) {
- $result = FronkDB::singleton()->escape($filter["result"]);
- if($result) {
- $where .= " AND result='$result'";
- }
- }
-
- if(array_key_exists("owner_name", $filter)) {
- $owner_name = FronkDB::singleton()->escape($filter["owner_name"]);
- if($owner_name) {
- $where .= " AND owner_name like '%$owner_name%'";
- }
- }
-
- if(array_key_exists("owner_street", $filter)) {
- $owner_street = FronkDB::singleton()->escape($filter["owner_street"]);
- if($owner_street) {
- $where .= " AND owner_street like '%$owner_street%'";
- }
- }
-
- if(array_key_exists("owner_zip", $filter)) {
- $owner_zip = FronkDB::singleton()->escape($filter["owner_zip"]);
- if($owner_zip) {
- $where .= " AND owner_zip like '%$owner_zip%'";
- }
- }
-
- if(array_key_exists("owner_city", $filter)) {
- $owner_city = FronkDB::singleton()->escape($filter["owner_city"]);
- if($owner_city) {
- $where .= " AND owner_city like '%$owner_city%'";
- }
- }
-
- if(array_key_exists("owner_country", $filter)) {
- $owner_country = FronkDB::singleton()->escape($filter["owner_country"]);
- if($owner_country) {
- $where .= " AND owner_country like '%$owner_country%'";
- }
- }
-
- if(array_key_exists("network", $filter)) {
- $network = FronkDB::singleton()->escape($filter["network"]);
- if($network) {
- $where .= " AND view_hausnummer.netzgebiet_id=$network";
+ if(array_key_exists("type", $filter)) {
+ $type = FronkDB::singleton()->escape($filter["type"]);
+ if($type) {
+ $where .= " AND type='$type'";
}
}
diff --git a/application/PreorderProduct/PreorderProductController.php b/application/PreorderProduct/PreorderProductController.php
index b91695625..f30037f22 100644
--- a/application/PreorderProduct/PreorderProductController.php
+++ b/application/PreorderProduct/PreorderProductController.php
@@ -9,7 +9,7 @@ class PreorderProductController extends mfBaseController {
$this->me = $me;
$this->layout()->set("me",$me);
- if(!$me->is(["Admin", "netowner", "salespartner"]) && !$me->can("Preorder")) {
+ if(!$me->can(["preorderpricing", "preorderpricingReadonly", "preorderbilling", "preorderbillingReadonly"])) {
$this->redirect("Dashboard");
}
}
@@ -17,7 +17,7 @@ class PreorderProductController extends mfBaseController {
protected function indexAction() {
$this->layout()->setTemplate("PreorderProduct/Index");
- $netowner_id = 4807; // $this->me->address_id;
+ $netowner_id = $this->me->address_id; // 4807 == rml
$netowner = new Address($netowner_id);
$products = PreorderProduct::getWithTypes($netowner_id);
@@ -62,7 +62,7 @@ class PreorderProductController extends mfBaseController {
$r = $this->request;
//var_dump($r->get());exit;
- $netowner_id = 4807; // $this->me->address_id;
+ $netowner_id = $this->me->address_id; // 4807 == rml
foreach($r->netoperators as $netoperator_id => $product_data) {
$netoperator = new Address($netoperator_id);
@@ -83,6 +83,7 @@ class PreorderProductController extends mfBaseController {
"netowner_id" => $netowner_id,
"preorderproduct_id" => $product->id,
"netoperator_id" => $netoperator_id,
+ "article_number" => $price_data["article_number"],
]);
if($price_data["description"]) $price->description = trim($price_data["description"]);
@@ -127,7 +128,9 @@ class PreorderProductController extends mfBaseController {
if(array_key_exists("marketshareprice", $price_data) && is_array($price_data["marketshareprice"])) {
foreach($price_data["marketshareprice"] as $msbracket => $msprice) {
if(!is_numeric($msbracket)) continue;
- if(!$msbracket) continue; // dont save 0
+ if(!$msbracket) continue; // dont save bracket 0 - 15%
+
+ if(empty(trim($msprice["inet"])) && empty(trim($msprice["inet_tv"])) && empty(trim($msprice["catv"])) && empty(trim($msprice["passive"]))) continue;
$msp = PreorderProductMarketshareDiscount::create([
"preorderproductprice_id" => $price->id,
diff --git a/application/PreorderProductPrice/PreorderProductPrice.php b/application/PreorderProductPrice/PreorderProductPrice.php
index a7e1a0e4c..d41609483 100644
--- a/application/PreorderProductPrice/PreorderProductPrice.php
+++ b/application/PreorderProductPrice/PreorderProductPrice.php
@@ -117,7 +117,7 @@ class PreorderProductPrice extends mfBaseModel {
$model = new PreorderProductPrice();
$table_fields = [
- "preorderproduct_id", "netowner_id", "netoperator_id", "preordercampaign_id", "description",
+ "preorderproduct_id", "netowner_id", "netoperator_id", "article_number", "description",
"start_date", "end_date", "price_inet", "price_inet_tv", "price_catv", "price_passive",
"billing_delay", "billing_period", "contract_term", "description", "note",
"create_by","edit_by","create","edit"
@@ -235,7 +235,7 @@ class PreorderProductPrice extends mfBaseModel {
}
}
- mfLoghandler::singleton()->debug($sql);
+ //mfLoghandler::singleton()->debug($sql);
$res = $db->query($sql);
if($db->num_rows($res)) {
@@ -291,7 +291,21 @@ class PreorderProductPrice extends mfBaseModel {
}
}
-
+ if(array_key_exists("article_number", $filter)) {
+ $article_number = $filter['article_number'];
+ if($article_number === null || $article_number === false) {
+ $where .= " AND (article_number IS NULL OR article_number = '')";
+ } elseif($article_number === true) {
+ $where .= " AND (article_number IS NOT NULL AND article_number <> '')";
+ } elseif(is_numeric($article_number)) {
+ $article_number = FronkDB::singleton()->escape($filter['article_number']);
+ $where .= " AND article_number='$article_number'";
+ }
+ }
+
+
+
+
if(array_key_exists("start_date", $filter)) {
$start_date = $filter["start_date"];
if($start_date === null || $start_date === false) {
diff --git a/application/PreordercampaignOperator/PreordercampaignOperator.php b/application/PreordercampaignOperator/PreordercampaignOperator.php
index ba1c58344..8a8cbcc47 100644
--- a/application/PreordercampaignOperator/PreordercampaignOperator.php
+++ b/application/PreordercampaignOperator/PreordercampaignOperator.php
@@ -40,8 +40,8 @@ class PreordercampaignOperator extends mfBaseModel
}
if($name == "operator") {
- $operator = mfValuecache::singleton()->getMfObject("Address", $this->operator_id);
- if(!$operator) {
+ $operator = new Address($this->operator_id);
+ if(!$operator->id) {
return null;
}
diff --git a/application/PreordercampaignOperator/PreordercampaignOperatorModel.php b/application/PreordercampaignOperator/PreordercampaignOperatorModel.php
index 68056e83f..e2e110dd0 100644
--- a/application/PreordercampaignOperator/PreordercampaignOperatorModel.php
+++ b/application/PreordercampaignOperator/PreordercampaignOperatorModel.php
@@ -52,8 +52,13 @@ class PreordercampaignOperatorModel {
$db = FronkDB::singleton();
$where = self::getSqlFilter($filter);
- mfLoghandler::singleton()->debug($where);
- $res = $db->select("PreordercampaignOperator", "*", "$where ORDER BY id");
+ $sql = "SELECT PreordercampaignOperator.* FROM PreordercampaignOperator
+ LEFT JOIN PreordercampaignOperatorIsp ON (PreordercampaignOperator.id = PreordercampaignOperatorIsp.campaignoperator_id)
+ WHERE $where
+ ORDER BY id
+ LIMIT 1";
+ //mfLoghandler::singleton()->debug($sql);
+ $res = $db->query($sql);
if($db->num_rows($res)) {
$data = $db->fetch_object($res);
$item = new PreordercampaignOperator($data);
@@ -66,32 +71,14 @@ class PreordercampaignOperatorModel {
return null;
}
- public static function getFirstOaid($oaid) {
- $db = FronkDB::singleton();
-
- if(!$oaid) return null;
-
- $where = self::getSqlFilter(["oaid" => $oaid]);
- //mfLoghandler::singleton()->debug($where);
- $res = $db->select("PreordercampaignOperator", "*", "$where ORDER BY id");
- if($db->num_rows($res)) {
- $data = $db->fetch_object($res);
- $item = new PreordercampaignOperator($data);
- if($item->id) {
- return $item;
- } else {
- return null;
- }
- }
- return null;
- }
public static function count($filter) {
$db = FronkDB::singleton();
$where = self::getSqlFilter($filter);
$sql = "SELECT COUNT(*) as cnt FROM PreordercampaignOperator
- WHERE $where
+ LEFT JOIN PreordercampaignOperatorIsp ON (PreordercampaignOperator.id = PreordercampaignOperatorIsp.campaignoperator_id)
+ WHERE $where
";
$res = $db->query($sql);
@@ -107,9 +94,10 @@ class PreordercampaignOperatorModel {
$db = FronkDB::singleton();
$where = self::getSqlFilter($filter);
- $sql = "SELECT * FROM PreordercampaignOperator
- WHERE $where
- ORDER BY id";
+ $sql = "SELECT PreordercampaignOperator.* FROM PreordercampaignOperator
+ LEFT JOIN PreordercampaignOperatorIsp ON (PreordercampaignOperator.id = PreordercampaignOperatorIsp.campaignoperator_id)
+ WHERE $where
+ ORDER BY id";
if(is_array($limit) && count($limit)) {
if(is_numeric($limit['start']) && is_numeric($limit['count'])) {
@@ -142,14 +130,21 @@ class PreordercampaignOperatorModel {
if(array_key_exists("preordercampaign_id", $filter)) {
$preordercampaign_id = $filter['preordercampaign_id'];
if(is_numeric($preordercampaign_id)) {
- $where .= " AND preordercampaign_id = $preordercampaign_id";
+ $where .= " AND PreordercampaignOperator.preordercampaign_id = $preordercampaign_id";
}
}
if(array_key_exists("operator_id", $filter)) {
$operator_id = $filter['operator_id'];
if(is_numeric($operator_id)) {
- $where .= " AND operator_id = $operator_id";
+ $where .= " AND PreordercampaignOperator.operator_id = $operator_id";
+ }
+ }
+
+ if(array_key_exists("isp_id", $filter)) {
+ $isp_id = $filter['isp_id'];
+ if(is_numeric($isp_id)) {
+ $where .= " AND PreordercampaignOperatorIsp.isp_id = $isp_id";
}
}
diff --git a/db/migrations/20250311131722_create_preorder_billing.php b/db/migrations/20250311131722_create_preorder_billing.php
new file mode 100644
index 000000000..faab3a963
--- /dev/null
+++ b/db/migrations/20250311131722_create_preorder_billing.php
@@ -0,0 +1,65 @@
+getEnvironment() == "thetool") {
+ $billing = $this->table('PreorderBilling');
+ $billing->addColumn("invoice_id", "integer", ["null" => true]);
+ $billing->addColumn("preorder_id", "integer", ["null" => false]);
+ $billing->addColumn("order_date", "date", ["null" => false]);
+ $billing->addColumn("start_date", "date", ["null" => false]);
+ $billing->addColumn("end_date", "date", ["null" => false]);
+ $billing->addColumn("owner_id", "integer", ["null" => false]);
+ $billing->addColumn("billingaddress_id", "integer", ["null" => false]);
+ $billing->addColumn("fibu_account_number", "integer", ["null" => false]);
+ $billing->addColumn("company", "string", ["null" => true, "default" => null, "length" => 1024]);
+ $billing->addColumn("firstname", "string", ["null" => true, "default" => null, "length" => 1024]);
+ $billing->addColumn("lastname", "string", ["null" => true, "default" => null, "length" => 1024]);
+ $billing->addColumn("street", "string", ["null" => false, "length" => 1024]);
+ $billing->addColumn("zip", "string", ["null" => false, "length" => 1024]);
+ $billing->addColumn("city", "string", ["null" => false, "length" => 1024]);
+ $billing->addColumn("country", "string", ["null" => true, "default" => null, "length" => 1024]);
+ $billing->addColumn("email", "string", ["null" => true, "default" => null, "length" => 1024]);
+ $billing->addColumn("uid", "string", ["null" => true, "default" => null, "length" => 1024]);
+ $billing->addColumn("billing_delivery", "enum", ["null" => false, "values" => "email,paper"]);
+ $billing->addColumn("product_id", "integer", ["null" => false]);
+ $billing->addColumn("product_name", "string", ["null" => false, "length" => 255]);
+ $billing->addColumn("product_info", "text", ["null" => true, "default" => null]);
+ $billing->addColumn("article_number", "string", ["null" => false, "length" => 32]);
+ $billing->addColumn("amount", "decimal", ["null" => false, "precision" => 9, "scale" => 6]);
+ $billing->addColumn("unit", "string", ["null" => false, "length" => 64]);
+ $billing->addColumn("price", "decimal", ["null" => false, "precision" => 14, "scale" => 4]);
+ $billing->addColumn("price_setup", "decimal", ["null" => false, "default" => 0, "precision" => 14, "scale" => 4]);
+ $billing->addColumn("vatrate", "decimal", ["null" => false, "precision" => 14, "scale" => 4]);
+ $billing->addColumn("billing_period", "integer", ["null" => false, "default" => 0]);
+ $billing->addColumn("create_by", "integer", ["null" => false]);
+ $billing->addColumn("edit_by", "integer", ["null" => false]);
+ $billing->addColumn("create", "integer", ["null" => false]);
+ $billing->addColumn("edit", "integer", ["null" => false]);
+ $billing->create();
+
+
+
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+
+ public function down(): void
+ {
+ if($this->getEnvironment() == "thetool") {
+ $this->table("PreorderBilling")->drop()->save();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+}
diff --git a/db/migrations/20250312124757_preorder_product_price_add_articlenumber.php b/db/migrations/20250312124757_preorder_product_price_add_articlenumber.php
new file mode 100644
index 000000000..ef1629eb7
--- /dev/null
+++ b/db/migrations/20250312124757_preorder_product_price_add_articlenumber.php
@@ -0,0 +1,33 @@
+getEnvironment() == "thetool") {
+ $table = $this->table("PreorderProductPrice");
+ $table->addColumn("article_number", "string", ["limit" => 255, "null" => true, "after" => "netoperator_id"]);
+ $table->update();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+
+ public function down(): void
+ {
+ if($this->getEnvironment() == "thetool") {
+ $table = $this->table("PreorderProductPrice");
+ $table->removeColumn("article_number");
+ $table->update();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+}
diff --git a/db/migrations/20250312143819_create_preorder_billing_customer.php b/db/migrations/20250312143819_create_preorder_billing_customer.php
new file mode 100644
index 000000000..3bc0c6166
--- /dev/null
+++ b/db/migrations/20250312143819_create_preorder_billing_customer.php
@@ -0,0 +1,46 @@
+getEnvironment() == "thetool") {
+ $table = $this->table('PreorderBillingCustomer');
+ $table->addColumn("netowner_id", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("fibu_account_number", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("company", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("firstname", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("lastname", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("street", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("zip", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("city", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("country", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("phone", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("email", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("uid", "string", ["limit" => 255, "null" => true, "default" => null]);
+ $table->addColumn("create_by", "integer", ["null" => false]);
+ $table->addColumn("edit_by", "integer", ["null" => false]);
+ $table->addColumn("create", "integer", ["null" => false]);
+ $table->addColumn("edit", "integer", ["null" => false]);
+ $table->create();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+
+ public function down(): void
+ {
+ if($this->getEnvironment() == "thetool") {
+ $this->table('PreorderBillingCustomer')->drop()->save();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+}
diff --git a/db/migrations/20250312152751_preorder_billing_add_customer_id.php b/db/migrations/20250312152751_preorder_billing_add_customer_id.php
new file mode 100644
index 000000000..a81d0fc05
--- /dev/null
+++ b/db/migrations/20250312152751_preorder_billing_add_customer_id.php
@@ -0,0 +1,35 @@
+getEnvironment() == "thetool") {
+ $table = $this->table('PreorderBilling');
+ $table->addColumn("preorderbillingcustomer_id", "integer", ["null" => true, "default" => null, "after" => "end_date"]);
+ $table->changeColumn("owner_id", "integer", ["null" => true, "default" => null]);
+ $table->changeColumn("billingaddress_id", "integer", ["null" => true, "default" => null]);
+ $table->update();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+
+ public function down(): void
+ {
+ if($this->getEnvironment() == "thetool") {
+ $table = $this->table('PreorderBilling');
+ $table->removeColumn("preorderbillingcustomer_id");
+ $table->update();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+}
diff --git a/db/migrations/20250313135536_preorder_billing_add_adb_hausnummer_id.php b/db/migrations/20250313135536_preorder_billing_add_adb_hausnummer_id.php
new file mode 100644
index 000000000..c7d98ce51
--- /dev/null
+++ b/db/migrations/20250313135536_preorder_billing_add_adb_hausnummer_id.php
@@ -0,0 +1,33 @@
+getEnvironment() == "thetool") {
+ $table = $this->table("PreorderBilling");
+ $table->addColumn("adb_wohneinheit_id", "integer", ["null" => false, "after" => "preorder_id"]);
+ $table->update();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+
+ public function down(): void
+ {
+ if($this->getEnvironment() == "thetool") {
+ $table = $this->table("PreorderBilling");
+ $table->removeColumn("adb_wohneinheit_id");
+ $table->update();
+ }
+
+ if($this->getEnvironment() == "addressdb") {
+
+ }
+ }
+}