From 76be480f7b3022079a9aa01870343ba2ab99c340 Mon Sep 17 00:00:00 2001 From: Frank Schubert Date: Thu, 15 Jan 2026 14:16:22 +0100 Subject: [PATCH] Changed Citycom order flow to new estmk activation workflow --- .../Preorder/include/preorder-detail.php | 2 + .../Modules/Operationaldata/SnoppCitycom.php | 34 ++++++-- application/Preorder/Preorder.php | 14 +++- application/PreorderCtag/PreorderCtag.php | 10 +-- ...60115121818_preorder_ctag_add_ext_name.php | 35 +++++++++ lib/Citycom/OanApiClient.php | 19 ++++- lib/Citycom/OanApiHelper.php | 77 ++++++++++++++++--- scripts/adb-rimo-import/importer/citycom.php | 8 +- .../preorder/citycom/order-mgmt-services.php | 29 +++++-- 9 files changed, 195 insertions(+), 33 deletions(-) create mode 100644 db/migrations/20260115121818_preorder_ctag_add_ext_name.php diff --git a/Layout/default/Preorder/include/preorder-detail.php b/Layout/default/Preorder/include/preorder-detail.php index 31849a571..6329d86f8 100644 --- a/Layout/default/Preorder/include/preorder-detail.php +++ b/Layout/default/Preorder/include/preorder-detail.php @@ -697,6 +697,7 @@ ctag Typ External ID + External Name External State ctags) && count($preorder->ctags)): ?> @@ -706,6 +707,7 @@ ctag?> service_type?> ext_id)?> + ext_name)?> ext_status)?> diff --git a/application/Api/v1/Modules/Operationaldata/SnoppCitycom.php b/application/Api/v1/Modules/Operationaldata/SnoppCitycom.php index 75bdbade4..f5d51a2bb 100644 --- a/application/Api/v1/Modules/Operationaldata/SnoppCitycom.php +++ b/application/Api/v1/Modules/Operationaldata/SnoppCitycom.php @@ -85,13 +85,13 @@ class SnoppCitycom extends Modules\ApiControllerModule $bb_down = $this->post["bb_down"]; $execution_date = false; - if($this->post["execution_date"]) { + /*if($this->post["execution_date"]) { try { $execution_date = new \DateTime($this->post["execution_date"]); } catch(\Exception $e) { return \mfResponse::BadRequest(["message" => "Invalid Timestamp format"]); } - } + }*/ if(!is_numeric($bb_down) || !$bb_down || !is_numeric($bb_up) || !$bb_up || !$bb_down > 10000 || $bb_up > 10000) { @@ -118,6 +118,10 @@ class SnoppCitycom extends Modules\ApiControllerModule // if all services are ordered and active, finish order and return active $ctag = PreorderCtag::getFirstActive(["preorder_id" => $preorder->id, "service_type" => "inet"]); + if(!$ctag) { + return \mfResponse::NotFound(["message" => "Home not found"]); + } + if($ctag->ext_id && $ctag->ext_status == "finished") { if($preorder->status->code < 500) { $preorder->setNewStatusCode(500); @@ -132,7 +136,7 @@ class SnoppCitycom extends Modules\ApiControllerModule return \mfResponse::Ok(["message" => "ONT not yet installed. Deferred", "activation_status" => "deferred"]); } - + /* $cc_home_id = \Citycom_OanApiHelper::hausnummerExtrefToCitycomId($wohneinheit->extref); $data["up"] = $bb_up; $data["down"] = $bb_down; @@ -159,10 +163,30 @@ class SnoppCitycom extends Modules\ApiControllerModule // order Service at Citycom and set Preorder to 500 Finished if(!$cc_api->orderServices($preorder, $cc_home_id, $data)) { return \mfResponse::InternalServerError(["message" => "Error activating service"]); + }*/ + + // update product at citycom + //$cc_home_id = \Citycom_OanApiHelper::hausnummerExtrefToCitycomId($wohneinheit->extref); + $data["up"] = $bb_up; + $data["down"] = $bb_down; + $data["product_name"] = false; + + if($preorder->campaign->fulfillment == "citycom_oan") { + $data["product_name"] = "Estmk Greenstream OAN $bb_down/$bb_up"; } - // live check if service is active, if not return deferred - $ctag = PreorderCtag::getFirstActive(["preorder_id" => $preorder->id, "service_type" => "inet"]); + $cc_api_client = new \Citycom_OanApiClient(CITYCOM_OAN_API_USER, CITYCOM_OAN_API_PASS); + $cc_api = new \Citycom_OanApiHelper($cc_api_client); + + // try to update product with bandwidth provided by snopp. + // updateService() only updates if values are changed. + if(!$cc_api->updateService($ctag->ext_id, $data)) { + $this->log->error(__METHOD__.": Error updating service {$ctag->ext_id} for preorder {$preorder->id}"); + //return \mfResponse::InternalServerError(["message" => "Error activating service"]); + } + + // check if service is active, if not return deferred + //$ctag = PreorderCtag::getFirstActive(["preorder_id" => $preorder->id, "service_type" => "inet"]); if($ctag->ext_id && $ctag->ext_status == "finished") { if($preorder->status->code < 500) { $preorder->setNewStatusCode(500); diff --git a/application/Preorder/Preorder.php b/application/Preorder/Preorder.php index fffeb2fbe..af01ffe27 100644 --- a/application/Preorder/Preorder.php +++ b/application/Preorder/Preorder.php @@ -736,19 +736,27 @@ class Preorder extends mfBaseModel { $first_ctag = $search_ctag - ($search_ctag % $ctags_per_home); $last_ctag = $first_ctag + $ctags_per_home - 1; + $mgmt_ctag_exists = false; + $mgmt_ctag = null; $ctag_range = []; for($i = $first_ctag; $i <= $last_ctag; $i++) { - if(!PreorderCtag::getFirstActive(["stag" => $stag, "ctag" => $i, "network" => $network_name])) { - if($i == $last_ctag) { + $ctag = PreorderCtag::getFirstActive(["stag" => $stag, "ctag" => $i, "network" => $network_name]); + if(!$ctag) { + if($i == $last_ctag && !$mgmt_ctag_exists) { // mgmt ctag should be the last in range $mgmt_ctag = $i; continue; } $ctag_range[] = $i; - + } else { + if($ctag->service_type == "mgmt") { + $this->log->debug(__METHOD__.": mgmt ctag ($i / stag $stag) exists already\n"); + $mgmt_ctag_exists = true; + } } } + return [$ctag_range, $mgmt_ctag]; } diff --git a/application/PreorderCtag/PreorderCtag.php b/application/PreorderCtag/PreorderCtag.php index db3f194f0..85f589cda 100644 --- a/application/PreorderCtag/PreorderCtag.php +++ b/application/PreorderCtag/PreorderCtag.php @@ -1,10 +1,8 @@ debug($sql); $res = $db->query($sql); @@ -230,7 +228,7 @@ class PreorderCtag extends mfBaseModel { $where = self::getSqlFilter($filter); $sql = "SELECT PreorderCtag.* FROM PreorderCtag WHERE $where - ORDER BY preorder_id DESC,stag DESC,ctag DESC LIMIT 1"; + ORDER BY ctag DESC LIMIT 1"; //var_dump($sql);exit; mfLoghandler::singleton()->debug($sql); $res = $db->query($sql); diff --git a/db/migrations/20260115121818_preorder_ctag_add_ext_name.php b/db/migrations/20260115121818_preorder_ctag_add_ext_name.php new file mode 100644 index 000000000..d225a7036 --- /dev/null +++ b/db/migrations/20260115121818_preorder_ctag_add_ext_name.php @@ -0,0 +1,35 @@ +getEnvironment() == "thetool") { + $table = $this->table("PreorderCtag"); + $table->renameColumn("ext_id", "ext_name"); + $table->addColumn("ext_id", "string", ["null" => true, "default" => null, "length" => 255, "after" => "service_type"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $table = $this->table("PreorderCtag"); + $table->removeColumn("ext_id"); + $table->renameColumn("ext_name", "ext_id"); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/lib/Citycom/OanApiClient.php b/lib/Citycom/OanApiClient.php index c5f61c546..7d61e91f7 100644 --- a/lib/Citycom/OanApiClient.php +++ b/lib/Citycom/OanApiClient.php @@ -219,6 +219,21 @@ class Citycom_OanApiClient { $url = str_replace("{service_id}", $service_id, $this->baseurl.CITYCOM_OAN_API_EP_UPDATE_SERVICES); + $ctx_options = [ + "http" => [ + "ignore_errors" => true, + "method" => "PUT", + "content" => json_encode($data), + "header" => [ + "Accept: application/json", + "Content-type: application/json", + "Authorization: Bearer ".$this->token, + ], + ] + ]; + + $result = $this->runApiRequest($url, $ctx_options); + return $result; } public function cancelService($service_id, $data) { @@ -449,7 +464,7 @@ class Citycom_OanApiClient { $output = file_get_contents($final_url, false, $ctx); $resp = json_decode($output); - //var_dump($resp); + //var_dump($resp);exit; if(!is_object($resp) || (property_exists($resp, "success") && !$resp->success)) { $this->lastError = $output; return false; @@ -459,6 +474,8 @@ class Citycom_OanApiClient { if(is_array($response)) { $return_data = $response; + } elseif(is_object($response) && (!property_exists($response, "data") || !is_array($response->data))) { + $return_data = $response; } elseif(is_object($response) && property_exists($response, "data") && is_array($response->data)) { $return_data = $response->data; diff --git a/lib/Citycom/OanApiHelper.php b/lib/Citycom/OanApiHelper.php index ccd3bacc7..46e345e1e 100644 --- a/lib/Citycom/OanApiHelper.php +++ b/lib/Citycom/OanApiHelper.php @@ -94,7 +94,7 @@ class Citycom_OanApiHelper { $execution_date = date("Y-m-d"); } - + $ctag_range_search = false; if(array_key_exists("ctag_range_search", $data) && $data["ctag_range_search"]) { $ctag_range_search = $data["ctag_range_search"]; @@ -116,21 +116,21 @@ class Citycom_OanApiHelper { // order all services and save ctags $cc_service_types = $this->api->getServiceTypes(); - $this->log->debug(print_r($want_services, true)); + $this->log->debug(__METHOD__.": Want services: ".print_r($want_services, true)); $allowed_service_types = array_merge(CITYCOM_OAN_API_SERVICES_FOR_ORDER, CITYCOM_OAN_API_SERVICES_FOR_RESERVATION); // check if we have these services already foreach($cc_service_types as $stype) { if(!in_array($stype->name, $allowed_service_types)) continue; - $ctag_service_type = array_flip($allowed_service_types)[$stype->name]; + $ctag_service_type = (array_flip($allowed_service_types))[$stype->name]; if(PreorderCtag::getFirstActive(["preorder_id" => $preorder->id, "service_type" => $ctag_service_type])) { // service was ordered already, remove from want_services unset($want_services[$ctag_service_type]); } } - $this->log->debug(print_r($want_services, true)); + $this->log->debug(__METHOD__.": Want services after filtering: ".print_r($want_services, true)); $new_services = []; @@ -140,26 +140,32 @@ class Citycom_OanApiHelper { list($ctags, $mgmt_ctag) = $preorder->getNextFreeCtags(); } - $this->log->debug(print_r($ctags, true)); + //var_dump($ctags); + //var_dump($mgmt_ctag); + + $this->log->debug(__METHOD__.": ctags: ".print_r($ctags, true)); + $this->log->debug(__METHOD__.": mgmt ctag: ".print_r($mgmt_ctag, true)); if(!is_array($ctags)) { $this->log->error(__METHOD__.": No Free Ctags (Preorder ".$preorder->id.")"); return false; } - if(count($ctags) < count($want_services)) { + $ctag_count = count($ctags); + if($mgmt_ctag) $ctag_count++; + if($ctag_count < count($want_services)) { $this->log->error(__METHOD__.": Not enough New Free CTags for Preorder ".$preorder->id); return false; } - $preorder_ctag_data = [ "preorder_id" => $preorder->id, "network" => "citycom-oan", "stag" => $preorder->adb_hausnummer->vlan_stag, ]; + $service_count = 0; foreach($cc_service_types as $stype) { // was this service type requested @@ -169,7 +175,7 @@ class Citycom_OanApiHelper { if($mgmt_ctag && $stype->name == $allowed_service_types["mgmt"]) { $ctag = $mgmt_ctag; } else { - $ctag = $ctags[$service_count]; + $ctag = array_shift($ctags); } $ctag_service_type = array_flip($allowed_service_types)[$stype->name]; if(!$ctag_service_type) { @@ -185,6 +191,7 @@ class Citycom_OanApiHelper { "ctag" => $ctag, ]; + //echo "Creating Service ".$stype->name." on sublocation $sublocation_id with product_id $product_id and ctag $ctag\n"; $this->log->info(__METHOD__.": Creating Service ".$stype->name." on sublocation $sublocation_id with product_id $product_id and ctag $ctag"); //continue; @@ -247,11 +254,61 @@ class Citycom_OanApiHelper { } - - return true; } + /** + * Updates service values if nesseccary + * + * @param $service_ext_num + * @param $data + * @return bool + */ + public function updateService($service_ext_id, $data) { + // get service and compare data + $services = $this->api->getServices(); + if(!$services) { + $this->log->error(__METHOD__.": Error getting services."); + return false; + } + + $service = false; + foreach($services as $cc_service) { + if($cc_service->id == $service_ext_id) { + $service = $cc_service; + break; + } + } + + if(!$service) { + $this->log->error(__METHOD__.": Service not available."); + return false; + } + + $service_data = []; + + // update service if nesseccary + if(array_key_exists("product_name", $data) && $data["product_name"] && $service->product->name != $data["product_name"]) { + $product_data["up"] = $data["up"]; + $product_data["down"] = $data["down"]; + $product_data["name"] = $data["product_name"]; + $product_id = $this->findOrCreateProduct($product_data); + if(!$product_id) { + $this->log->error(__METHOD__.": Cannot find or create product ".$product_data["name"]); + return false; + } + + $service_data["product_id"] = $product_id; + } + + if(!count($service_data)) return true; + $result = $this->api->updateService($service, $service_data); + + if($result) return true; + return false; + + } + public static function citycomIdToHausnummerExtref($id) { diff --git a/scripts/adb-rimo-import/importer/citycom.php b/scripts/adb-rimo-import/importer/citycom.php index 42c39f12c..fe39a1013 100644 --- a/scripts/adb-rimo-import/importer/citycom.php +++ b/scripts/adb-rimo-import/importer/citycom.php @@ -254,8 +254,12 @@ class CitycomImporter { $ctag = \PreorderCtag::getFirstActive(["preorder_id" => $preorder->id, "stag" => $stag, "service_type" => $stypes[$service->service_type]]); //echo "====\n"; //echo $preorder->id." - ".$service->service_number." - ".$service->location->sublocation->id." - ".$service->service_type." - $stag\n"; - if($ctag && $ctag->ext_id != $service->service_number) { - $ctag->ext_id = $service->service_number; + if($ctag && $ctag->ext_id != $service->id) { + $ctag->ext_id = $service->id; + $ctag->save(); + } + if($ctag && $ctag->ext_name != $service->service_number) { + $ctag->ext_name = $service->service_number; $ctag->save(); } if($ctag && $ctag->ext_status != $service->state) { diff --git a/scripts/preorder/citycom/order-mgmt-services.php b/scripts/preorder/citycom/order-mgmt-services.php index 3d0515fbb..df6140f8a 100644 --- a/scripts/preorder/citycom/order-mgmt-services.php +++ b/scripts/preorder/citycom/order-mgmt-services.php @@ -1,5 +1,9 @@ #!/usr/bin/php "citycom_oan"]) as $camp } } - if($has_inet_service || $has_mgmt_service) continue; + if($has_inet_service) continue; $sublocation_id = \Citycom_OanApiHelper::hausnummerExtrefToCitycomId($preorder->adb_wohneinheit->extref); $data = [ "down" => 100, "up" => 100, - "product_name" => "Estmk Greenstream OAN Mgmt", + "product_name" => "Estmk Greenstream OAN Default", "execution_date" => false, - "services" => CITYCOM_OAN_API_SERVICES_FOR_RESERVATION, - ]; - $log->info(__METHOD__.": Ordering mgmt service for preorder ".$preorder->id); + $services_to_order = array_merge(CITYCOM_OAN_API_SERVICES_FOR_RESERVATION, CITYCOM_OAN_API_SERVICES_FOR_ORDER); + if($has_mgmt_service) { + $services_to_order = CITYCOM_OAN_API_SERVICES_FOR_ORDER; + } + $data["services"] = $services_to_order; + + $existing_ctag = \PreorderCtag::getFirstActive(["preorder_id" => $preorder->id]); + if($existing_ctag) { + $data["ctag_range_search"] = $existing_ctag->ctag; + } + + //echo "{$preorder->id}\n"; + //var_dump($data);exit; + + $log->info(__FILE__.": Ordering Citycom services for preorder ".$preorder->id); if(!$cc_helper->orderServices($preorder, $sublocation_id, $data)) { - $log->error(__METHOD__.": Error ordering mgmt service for preorder ".$preorder->id); + $log->error(__FILE__.": Error ordering Citycom services for preorder ".$preorder->id); continue; } + //continue; // TODO check for new service @ citycom -> 230 $cc_services = $cc->getServices();