642 lines
30 KiB
PHP
642 lines
30 KiB
PHP
<?php
|
|
|
|
class CpeprovisioningController extends mfBaseController {
|
|
protected function init() {
|
|
if (defined('TT_CPE_PROV_ALLOW_COUNTS_IP') &&
|
|
in_array($_SERVER['REMOTE_ADDR'], TT_CPE_PROV_ALLOW_COUNTS_IP) &&
|
|
!mfLoginController::isLoggedIn()) {
|
|
if ($this->action !== 'CountOpenProvisionings') {
|
|
http_response_code(403);
|
|
die('Forbidden');
|
|
} else {
|
|
header("Access-Control-Allow-Origin: https://noc.xinon.at");
|
|
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
|
|
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
|
return;
|
|
}
|
|
}
|
|
|
|
$this->needlogin = true;
|
|
$this->me = new User();
|
|
$this->me->loadMe();
|
|
$this->layout()->set("me", $this->me);
|
|
|
|
if (!$this->me->is(["Admin"])) $this->redirect("Dashboard");
|
|
}
|
|
|
|
protected function indexAction() {
|
|
$cpecounter = 0;
|
|
$r = $this->request;
|
|
$page = $r->s;
|
|
|
|
$this->layout()->setTemplate("Cpeprovisioning/Index");
|
|
$cpeproducts = [];
|
|
|
|
$this->layout->set("filter", $this->request->filter);
|
|
$filter = $this->getPreparedFilter($this->request->filter);
|
|
// pagination defaults
|
|
$pagination = [];
|
|
$pagination['start'] = $page;
|
|
$pagination['count'] = 25;
|
|
$pagination['maxItems'] = 0;
|
|
|
|
$order_filter = $filter;
|
|
//var_dump($filter);exit;
|
|
/*
|
|
* Get orderproducts in need of sending a CPE
|
|
*/
|
|
//var_dump($order_filter);exit;
|
|
$orders = OrderModel::search($order_filter);
|
|
$orderproductsprefetch = OrderProductModel::precache();
|
|
|
|
|
|
foreach ($orders as $order) {
|
|
if ($order_filter["hide_delayed_finish"] && $order->finish_after) {
|
|
|
|
// show at most 4 weeks before finish_after date
|
|
//$after_ts = Layout::dateToInt($order->finish_after);
|
|
if ($order->finish_after > date("U") + (31 * 86400)) {
|
|
//$this->log->debug("Before 4 weeks before finish_after oid " . $order->id);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
if (is_array($orderproductsprefetch['terminations'][$order->id]) && count($orderproductsprefetch['terminations'][$order->id])) {
|
|
|
|
if (!$order->cpeprovisioning_enabled && $orderproductsprefetch['terminations'][$order->id][0]['statuscode'] < TT_TERMSTATUS_CONNECTED) {
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(array_key_exists($order->id, $orderproductsprefetch)) {
|
|
foreach ($orderproductsprefetch[$order->id] as $orderproduct) {
|
|
if(!$orderproduct) continue;
|
|
if(!is_array($orderproduct)) continue;
|
|
|
|
if ($orderproduct['routerconfig_finished'] == 1) {
|
|
if (!$filter['routerconfig_finished']) continue;
|
|
} else {
|
|
if ($filter['routerconfig_finished']) continue;
|
|
}
|
|
|
|
|
|
$productattributes = $orderproduct['attributes'];
|
|
|
|
|
|
if (is_array($productattributes) && count($productattributes)) {
|
|
// filter out products without bras_type
|
|
|
|
if (array_key_exists("bras_type", $productattributes) && $productattributes) {
|
|
$pagination['maxItems']++;
|
|
if ($pagination['maxItems'] >= $pagination['start']+1 && $pagination['maxItems'] <= $pagination['start'] + $pagination['count']) {
|
|
$cpeproducts[] = OrderProductModel::getOne($orderproduct['id']);
|
|
}
|
|
|
|
} else {
|
|
//$this->log->debug("no bras_type oid " . $order->id);
|
|
continue;
|
|
}
|
|
} else {
|
|
// ignore products without attributes
|
|
//$this->log->debug("no attributes oid " . $order->id);
|
|
continue;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
$this->layout()->set("pagination", $pagination);
|
|
$this->layout()->set("products", $cpeproducts);
|
|
}
|
|
|
|
private function getPreparedFilter($filter) {
|
|
$new_filter = [];
|
|
|
|
if (!is_array($filter)) $filter = [];
|
|
|
|
if (array_key_exists("hide_delayed_finish", $filter)) {
|
|
if ($filter["hide_delayed_finish"] == "1") {
|
|
$new_filter["hide_delayed_finish"] = true;
|
|
} else {
|
|
$new_filter["hide_delayed_finish"] = false;
|
|
}
|
|
unset($filter["hide_delayed_finish"]);
|
|
} else {
|
|
$new_filter["hide_delayed_finish"] = true;
|
|
}
|
|
|
|
if (array_key_exists("routerconfig_finished", $filter)) {
|
|
if ($filter["routerconfig_finished"] == "1") {
|
|
$new_filter["routerconfig_finished"] = true;
|
|
$new_filter["hide_delayed_finish"] = false;
|
|
} else {
|
|
$new_filter["routerconfig_finished"] = false;
|
|
$order_filter["finish_date"] = null;
|
|
}
|
|
unset($filter["routerconfig_finished"]);
|
|
} else {
|
|
$new_filter["routerconfig_finished"] = false;
|
|
$order_filter["finish_date"] = null;
|
|
}
|
|
|
|
$new_filter['upgrade'] = 0;
|
|
|
|
|
|
foreach ($filter as $name => $value) {
|
|
$new_filter[$name] = $value;
|
|
}
|
|
//var_dump($new_filter);exit;
|
|
return $new_filter;
|
|
}
|
|
|
|
protected function saveAction() {
|
|
$r = $this->request;
|
|
$id = $r->id;
|
|
//var_dump($r);exit;
|
|
if (is_numeric($id) && $id > 0) {
|
|
$mode = "edit";
|
|
$cpeprovisioning = new Cpeprovisioning($id);
|
|
if (!$cpeprovisioning->id) {
|
|
$this->layout()->setFlash("Eintrag nicht gefunden", "error");
|
|
$this->redirect("Cpeprovisioning");
|
|
}
|
|
} else {
|
|
$mode = "add";
|
|
}
|
|
|
|
$order_id = $r->order_id;
|
|
$termination_id = $r->termination_id;
|
|
if (!(is_numeric($termination_id) && $termination_id > 0) && !(is_numeric($order_id) && $order_id > 0)) {
|
|
$this->layout()->setFlash("Anschluss oder Bestellung nicht gefunden", "error");
|
|
$this->redirect("Cpeprovisioning");
|
|
}
|
|
|
|
$orderproduct = OrderProductModel::getFirst(["order_id" => $order_id, "termination_id" => $termination_id]);
|
|
if (!$orderproduct) {
|
|
$this->layout()->setFlash("Anschluss gehört nicht zur Bestellung", "error");
|
|
$this->redirect("Cpeprovisioning");
|
|
}
|
|
|
|
$prov_data = [];
|
|
$prov_data["termination_id"] = ($r->termination_id) ? $r->termination_id : null;
|
|
$prov_data["order_id"] = $r->order_id;
|
|
$prov_data["orderproduct_id"] = $r->orderproduct_id;
|
|
$prov_data["routerconfig_finished"] = ($r->routerconfig_finished) ? 1 : 0;
|
|
$prov_data["routertype"] = $r->routertype;
|
|
$prov_data["shipping"] = ($r->shipping) ? 1 : 0;
|
|
$prov_data["wifi_ssid"] = $r->wifi_ssid;
|
|
$prov_data["wifi_pass"] = $r->wifi_pass;
|
|
$prov_data["mac"] = $r->mac;
|
|
$prov_data["vlan_public"] = (strlen($r->vlan_public)) ? $r->vlan_public : null;
|
|
$prov_data["vlan_nat"] = (strlen($r->vlan_nat)) ? $r->vlan_nat : null;
|
|
$prov_data["vlan_ipv6"] = (strlen($r->vlan_ipv6)) ? $r->vlan_ipv6 : null;
|
|
$prov_data["ship_weight"] = (strlen($r->ship_weight)) ? $r->ship_weight : null;
|
|
$prov_data["ship_length"] = (strlen($r->ship_length)) ? $r->ship_length : null;
|
|
$prov_data["ship_width"] = (strlen($r->ship_width)) ? $r->ship_width : null;
|
|
$prov_data["ship_height"] = (strlen($r->ship_height)) ? $r->ship_height : null;
|
|
$prov_data["note"] = $r->note;
|
|
|
|
$prov_data["edit_by"] = $this->me->id;
|
|
|
|
if ($mode == "add") {
|
|
$prov_data["create_by"] = $this->me->id;
|
|
$cpeprovisioning = CpeprovisioningModel::create($prov_data);
|
|
} else {
|
|
$cpeprovisioning->update($prov_data);
|
|
}
|
|
|
|
//var_dump($prov_data);exit;
|
|
$new_id = $cpeprovisioning->save();
|
|
if (!$new_id) {
|
|
$this->layout()->setFlash("Fehler beim Speichern", "error");
|
|
$this->redirect("Cpeprovisioning");
|
|
}
|
|
|
|
// saved successfully, if routerconfig_finished make Journal entry in Order
|
|
|
|
if ($cpeprovisioning->routerconfig_finished) {
|
|
$order_product = new OrderProduct($r->orderproduct_id);
|
|
|
|
if ($cpeprovisioning->shipping) {
|
|
$text = "CPE zu Produkt \"" . $order_product->product->name . "\" zum Versand vorbereitet.\n\n";
|
|
} else {
|
|
$text = "CPE zu Produkt \"" . $order_product->product->name . "\" vorbereitet für Techniker zur Vorortinstallation.\n\n";
|
|
}
|
|
$text .= "Router: " . $cpeprovisioning->routertype . "\n";
|
|
$text .= "Zugangstyp: " . $order_product->product->attributes['bras_type']->value . "\n";
|
|
if ($cpeprovisioning->vlan_public) {
|
|
$text .= "Vlan Public: " . $cpeprovisioning->vlan_public . "\n";
|
|
}
|
|
if ($cpeprovisioning->vlan_nat) {
|
|
$text .= "Vlan NAT: " . $cpeprovisioning->vlan_nat . "\n";
|
|
}
|
|
if ($cpeprovisioning->vlan_ipv6) {
|
|
$text .= "Vlan IPv6: " . $cpeprovisioning->vlan_ipv6 . "\n";
|
|
}
|
|
|
|
$journal = new OrderJournal();
|
|
$journal->order_id = $order_id;
|
|
$journal->text = $text;
|
|
$journal->create_by = $this->me->id;
|
|
$journal->edit_by = $this->me->id;
|
|
|
|
$journal_id = $journal->save();
|
|
if (!$journal_id) {
|
|
$this->layout()->setFlash("Konnte nicht ins Bestelljournal schreiben!", "warning");
|
|
} else {
|
|
$cpeprovisioning->order_journal_id = $journal_id;
|
|
$cpeprovisioning->save();
|
|
}
|
|
}
|
|
|
|
// save ONT sn
|
|
if ($r->ont_sn) {
|
|
$termination = new Termination($termination_id);
|
|
$orig_sn = $termination->getWorkflowvalue("ont_sn", "string");
|
|
|
|
if ($orig_sn === null) {
|
|
|
|
$sn_item = WorkflowitemModel::getFirst(["name" => "ont_sn", "object_type" => "termination"]);
|
|
//var_dump($sn_item);exit;
|
|
//var_dump(mfValuecache::singleton()->get("wfItemvalue-item-".$sn_item->id."-object-".$termination_id));exit;
|
|
if (!$sn_item->id) {
|
|
$this->log->error("ont_sn workflow item not found");
|
|
} else {
|
|
$sn_item->setObjectId($termination_id);
|
|
$termination->workflowitems["ont_sn"] = $sn_item;
|
|
//$sn_item->value->setValue($r->ont_sn);
|
|
|
|
//$sn_item->value->save();
|
|
}
|
|
|
|
}
|
|
|
|
if ($r->ont_sn != $orig_sn) {
|
|
$termination->workflowitems["ont_sn"]->value->setValue($r->ont_sn);
|
|
$termination->workflowitems["ont_sn"]->value->save();
|
|
}
|
|
}
|
|
|
|
|
|
$query = [];
|
|
if (is_numeric($this->request->s) && $this->request->s > 0) {
|
|
$query["s"] = $this->request->s;
|
|
}
|
|
if (is_array($this->request->filter)) {
|
|
$query["filter"] = $this->request->filter;
|
|
}
|
|
|
|
$this->layout()->setFlash("Eintrag erfolgreich gespeichert.", "success");
|
|
$this->redirect("Cpeprovisioning", "Index", http_build_query($query));
|
|
}
|
|
|
|
protected function apiSaveAction() {
|
|
try {
|
|
$p = json_decode(file_get_contents('php://input'), true);
|
|
|
|
$id = $p['id'] ?? null;
|
|
$mode = $id ? "edit" : "add";
|
|
|
|
if ($mode === 'edit') {
|
|
$cpe = new Cpeprovisioning($id);
|
|
if (!$cpe->id) throw new Exception("Eintrag nicht gefunden");
|
|
}
|
|
|
|
if (empty($p['termination_id']) && empty($p['order_id'])) throw new Exception("Anschluss oder Bestellung nicht gefunden");
|
|
if (!OrderProductModel::getFirst(["order_id" => $p['order_id'], "termination_id" => $p['termination_id']])) throw new Exception("Anschluss gehört nicht zur Bestellung");
|
|
|
|
if (!empty($p['ont_sn'])) {
|
|
$termination = new Termination($p['termination_id']);
|
|
$orig_sn = $termination->getWorkflowvalue("ont_sn", "string");
|
|
|
|
if ($orig_sn === null) {
|
|
if ($sn_item = WorkflowitemModel::getFirst(["name" => "ont_sn", "object_type" => "termination"])) {
|
|
$sn_item->setObjectId($p['termination_id']);
|
|
$termination->workflowitems["ont_sn"] = $sn_item;
|
|
} else {
|
|
$this->log->error("ont_sn workflow item not found");
|
|
}
|
|
}
|
|
|
|
if ($p['ont_sn'] !== $orig_sn && isset($termination->workflowitems["ont_sn"])) {
|
|
$termination->workflowitems["ont_sn"]->value->setValue($p['ont_sn']);
|
|
$termination->workflowitems["ont_sn"]->value->save();
|
|
}
|
|
}
|
|
|
|
$data = [
|
|
"termination_id" => $p['termination_id'] ?: null,
|
|
"order_id" => $p['order_id'],
|
|
"orderproduct_id" => $p['orderproduct_id'],
|
|
"routerconfig_finished" => (int)($p['routerconfig_finished'] ?? 0),
|
|
"shipping" => (int)($p['shipping'] ?? 0),
|
|
"routertype" => $p['routertype'] ?? null,
|
|
"wifi_ssid" => $p['wifi_ssid'] ?? null,
|
|
"wifi_pass" => $p['wifi_pass'] ?? null,
|
|
"mac" => $p['mac'] ?? null,
|
|
"note" => $p['note'] ?? null,
|
|
"edit_by" => $this->me->id,
|
|
];
|
|
|
|
foreach (['ship_weight', 'ship_length', 'ship_width', 'ship_height'] as $key) $data[$key] = empty($p[$key]) ? null : $p[$key];
|
|
foreach (['public', 'nat', 'ipv6'] as $type) $data["vlan_{$type}"] = !empty($p['vlans'][$type]['checked']) ? ($p['vlans'][$type]['tag'] ?? null) : null;
|
|
|
|
if ($mode === 'add') {
|
|
$data["create_by"] = $this->me->id;
|
|
$cpe = CpeprovisioningModel::create($data);
|
|
} else $cpe->update($data);
|
|
|
|
if (!$cpe->save()) throw new Exception("Fehler beim Speichern");
|
|
|
|
if ($cpe->routerconfig_finished) {
|
|
$order_product = new OrderProduct($p['orderproduct_id']);
|
|
|
|
$shipping_text = $cpe->shipping
|
|
? "zum Versand vorbereitet"
|
|
: "vorbereitet für Techniker zur Vorortinstallation";
|
|
|
|
$text = "CPE zu Produkt \"{$order_product->product->name}\" {$shipping_text}.\n\n"
|
|
. "Router: {$cpe->routertype}\n"
|
|
. "Zugangstyp: {$order_product->product->attributes['bras_type']->value}\n";
|
|
|
|
if ($cpe->vlan_public) $text .= "Vlan Public: {$cpe->vlan_public}\n";
|
|
if ($cpe->vlan_nat) $text .= "Vlan NAT: {$cpe->vlan_nat}\n";
|
|
if ($cpe->vlan_ipv6) $text .= "Vlan IPv6: {$cpe->vlan_ipv6}\n";
|
|
|
|
$journal = new OrderJournal();
|
|
$journal->order_id = $p['order_id'];
|
|
$journal->text = $text;
|
|
$journal->create_by = $this->me->id;
|
|
$journal->edit_by = $this->me->id;
|
|
|
|
if (!($journal_id = $journal->save())) {
|
|
$this->layout()->setFlash("Konnte nicht ins Bestelljournal schreiben!", "warning");
|
|
} else {
|
|
$cpe->order_journal_id = $journal_id;
|
|
$cpe->save();
|
|
}
|
|
}
|
|
|
|
self::returnJson(['success' => true, 'message' => 'Eintrag erfolgreich gespeichert.']);
|
|
|
|
} catch (Exception $e) {
|
|
http_response_code(400);
|
|
self::returnJson(['success' => false, 'message' => $e->getMessage()]);
|
|
}
|
|
}
|
|
protected function apiGetAction(){
|
|
$p = json_decode(file_get_contents('php://input'), true) ?? [];
|
|
|
|
// --- Pagination and Sorting setup ---
|
|
$page = (int)($p['pagination']['page'] ?? 1);
|
|
$perPage = (int)($p['pagination']['per_page'] ?? 25);
|
|
$orderBy = $p['order']['key'] ?? null;
|
|
$orderDir = $p['order']['order'] ?? 'asc';
|
|
|
|
// Calculate start and end indexes for manual pagination, just like in the old indexAction
|
|
$start = ($page - 1) * $perPage;
|
|
$end = $start + $perPage;
|
|
|
|
// --- Data Fetching (same as before) ---
|
|
$searchFilter = $this->getPreparedFilter($p['filters'] ?? []);
|
|
// if routerconfig_finished === 0 then we can add key add-where to searchFilter and only show orders withing the last 180 days either by create or edit (caution this is unix timestamp)
|
|
if (isset($searchFilter['routerconfig_finished']) && !$searchFilter['routerconfig_finished']) {
|
|
$searchFilter['add-where'] = "`Order`.create > " . (time() - 365 * 86400) . " OR `Order`.edit > " . (time() - 365 * 86400);
|
|
}
|
|
|
|
$orders = OrderModel::search($searchFilter); // cpeprovisioning_enabled
|
|
// Use the same uncached precache from indexAction to get all potential products
|
|
// $prefetched = OrderProductModel::precache("`Terminationstatus`.`code` < " . TT_TERMSTATUS_CONNECTED . " AND `ProducttechAttribute`.`name` = 'bras_type'");
|
|
$sqlWhere = "`ProducttechAttribute`.`name` = 'bras_type'";
|
|
// if filter routerconfig_finished === 0 then we can filter the precache by routerconfig_finished = 0 or is null
|
|
if (isset($searchFilter['routerconfig_finished']) && !$searchFilter['routerconfig_finished']) {
|
|
// $sqlWhere .= " AND (`Cpeprovisioning`.`routerconfig_finished` = 0 OR `Cpeprovisioning`.`routerconfig_finished` IS NULL)";
|
|
}
|
|
|
|
$prefetched = OrderProductModel::precache($sqlWhere);
|
|
|
|
$paginatedRows = [];
|
|
$totalRows = 0;
|
|
$orderInfoCache = []; // Cache for order-level info to avoid repeated calculations
|
|
|
|
foreach ($orders as $order) {
|
|
// --- Apply the same initial filters as the old and new methods ---
|
|
if (($searchFilter["hide_delayed_finish"] ?? false) && $order->finish_after && $order->finish_after > strtotime('+31 days')) continue;
|
|
if (isset($prefetched['terminations'][$order->id][0]) && !$order->cpeprovisioning_enabled && $prefetched['terminations'][$order->id][0]['statuscode'] < TT_TERMSTATUS_CONNECTED) continue;
|
|
if (empty($prefetched[$order->id])) continue;
|
|
|
|
// Loop through the prefetched raw data, similar to indexAction
|
|
foreach ($prefetched[$order->id] as $opData) {
|
|
// --- Apply the same product-level filters ---
|
|
if (!is_array($opData) || ($opData['routerconfig_finished'] xor ($searchFilter['routerconfig_finished'] ?? false)) || empty($opData['attributes']['bras_type'])) continue;
|
|
|
|
// This item is a valid candidate for the list.
|
|
$totalRows++;
|
|
|
|
// *** THE CORE PERFORMANCE IMPROVEMENT ***
|
|
// If the current item is not on the page we want, skip the expensive processing below.
|
|
if ($totalRows <= $start || $totalRows > $end) {
|
|
continue;
|
|
}
|
|
|
|
// --- Now, do the expensive processing ONLY for the items on the current page ---
|
|
|
|
// Calculate and cache order-level info only when it's first needed for a visible item
|
|
if (!isset($orderInfoCache[$order->id])) {
|
|
$orderInfo = ['vot' => false, 'hw' => [], 'voip' => false];
|
|
foreach ($order->products as $prod) {
|
|
$attrs = $prod->product->attributes ?? [];
|
|
if (empty($attrs) || !is_array($attrs)) continue;
|
|
|
|
if ($attrs['hw_only']->value ?? false) $orderInfo['hw'][] = (int)$prod->amount . "x " . $prod->product->name;
|
|
if ($attrs['addon']->value ?? false) $orderInfo['hw'][] = $prod->product->name;
|
|
if ($attrs['voip_chan']->value ?? false) $orderInfo['voip'] = true;
|
|
if ($attrs['vot']->value ?? false) $orderInfo['vot'] = true;
|
|
}
|
|
$orderInfoCache[$order->id] = $orderInfo;
|
|
}
|
|
$orderInfo = $orderInfoCache[$order->id];
|
|
|
|
// Hydrate the full model object, but only for this one item
|
|
$product = OrderProductModel::getOne($opData['id']);
|
|
$term = $product->termination;
|
|
$attrs = $product->product->attributes;
|
|
$cpe = $product->cpeprovisioning;
|
|
|
|
$vlanPublicDefault = $term ? $term->getPop()->vlan_public : ($attrs['vlan_default_public']->value ?? null);
|
|
$vlanNatDefault = $term ? $term->getPop()->vlan_nat : ($attrs['vlan_default_nat']->value ?? null);
|
|
$vlanIpv6Default = $term ? $term->getPop()->vlan_ipv6 : ($attrs['vlan_default_ipv6']->value ?? null);
|
|
|
|
/** @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection */
|
|
$paginatedRows[] = [
|
|
'id' => $product->id, 'order_id' => $product->order_id, 'termination_id' => $product->termination_id, 'orderproduct_id' => $product->id,
|
|
'network' => $term->building->network->name ?? "{$order->owner->zip} {$order->owner->city}",
|
|
'spin' => $order->owner->spin, 'customer' => $order->owner->getCompanyOrName(),
|
|
'owner_email' => $order->owner->email,
|
|
'owner_phone' => $order->owner->phone,
|
|
'owner_customer_number' => $order->owner->customer_number,
|
|
'owner_full_address' => $order->owner->street . ", " . $order->owner->zip . " " . $order->owner->city,
|
|
'product_name' => $product->product->name, 'product_code' => $term->code ?? '',
|
|
'access_type' => $attrs['bras_type']->value,
|
|
'access_type_down' => $attrs["bw_down"]->value,
|
|
'access_type_up' => $attrs["bw_up"]->value,
|
|
'ont_deployed' => $term ? $term->getWorkflowValue("ont_deployed", "int") : 0,
|
|
'ont_sn' => $term ? $term->getWorkflowValue("ont_sn", "string") : null,
|
|
'vot' => $orderInfo['vot'] || $order->install_date,
|
|
'hw' => !empty($orderInfo['hw']) ? implode("<br />", $orderInfo['hw']) : null,
|
|
'voip' => $orderInfo['voip'],
|
|
'note' => $order->note,
|
|
'show_snopp_button' => ($attrs['hostnetwork_order']->value ?? 0) == 1 && !str_contains($product->product->name, 'XDSL'),
|
|
'snopp_url' => 'https://snopp.breitband-steiermark.at/Termination/index?filter[status][]=connected&filter[address]=' . urlencode($order->owner->street),
|
|
'vlans' => [
|
|
'public' => ['tag' => ($cpe ? $cpe->vlan_public : null) ?? $vlanPublicDefault, 'checked' => ($cpe ? $cpe->vlan_public : null)],
|
|
'nat' => ['tag' => ($cpe ? $cpe->vlan_nat : null) ?? $vlanNatDefault, 'checked' => ($cpe ? $cpe->vlan_nat : null)],
|
|
'ipv6' => ['tag' => ($cpe ? $cpe->vlan_ipv6 : null) ?? $vlanIpv6Default, 'checked' => ($cpe ? $cpe->vlan_ipv6 : null)],
|
|
],
|
|
'cpe_id' => $cpe->id ?? null,
|
|
'cpe_data' => $this->fixCpeData($cpe->data ?? null),
|
|
];
|
|
}
|
|
}
|
|
|
|
// Sort the final (small) array of results for the current page
|
|
if ($orderBy) {
|
|
usort($paginatedRows, fn($a, $b) => ($orderDir === 'asc' ? 1 : -1) * strnatcasecmp($a[$orderBy] ?? '', $b[$orderBy] ?? ''));
|
|
}
|
|
|
|
// No need for array_slice, we already built the paginated list manually
|
|
self::returnJson([
|
|
'rows' => $paginatedRows,
|
|
'pagination' => [
|
|
'page' => $page, 'per_page' => $perPage, 'total_rows' => $totalRows,
|
|
'filtered_available' => $totalRows, 'total_pages' => ceil($totalRows / $perPage)
|
|
]
|
|
]);
|
|
}
|
|
|
|
protected function newIndexAction() {
|
|
$this->layout()->set('additionalJS', ['js/pages/Cpeprovisioning/Cpeprovisioning.js']);
|
|
$this->layout()->set('additionalHead', ['<link rel="stylesheet" href="/js/pages/Cpeprovisioning/Cpeprovisioning.css">']);
|
|
|
|
Helper::renderVue(
|
|
$this,
|
|
"Cpeprovisioning", // The root Vue component name
|
|
"CPE Provisioning", // The page title
|
|
[
|
|
// Pass API URLs and initial data to the frontend
|
|
"CPE_PROV_API_GET_URL" => $this->getUrl("Cpeprovisioning", "apiGet"),
|
|
"CPE_PROV_API_SAVE_URL" => $this->getUrl("Cpeprovisioning", "apiSave"),
|
|
"CPE_PROV_PRINT_PDF_URL" => $this->getUrl("Cpeprovisioning", "printPDF"),
|
|
"ORDER_URL" => $this->getUrl("Order"),
|
|
"NETWORKS" => NetworkModel::getAll(),
|
|
"ROUTER_OPTIONS" => [
|
|
// General Options
|
|
['value' => 'eigener Router', 'text' => 'Eigener Router'],
|
|
['value' => 'anderes CPE', 'text' => 'Anderes CPE'],
|
|
// PPPoE/DHCP Routers
|
|
['value' => 'TP-Link Archer C80', 'text' => 'TP-Link Archer C80 (Inet, IPTV)'],
|
|
['value' => 'FritzBox 4040', 'text' => 'FritzBox 4040 (Inet, IPTV)'],
|
|
['value' => 'FritzBox 4050', 'text' => 'FritzBox 4050 (Inet, Phone IPTV)'],
|
|
['value' => 'FritzBox 5530', 'text' => 'FritzBox 5530 (Inet FiberP2P, Phone, IPTV)'],
|
|
['value' => 'FritzBox 7530', 'text' => 'FritzBox 7530 (Inet, Phone, IPTV)'],
|
|
['value' => 'FritzBox 7590', 'text' => 'FritzBox 7590 (Inet, Phone, IPTV)'],
|
|
['value' => 'FritzBox 7690', 'text' => 'FritzBox 7690 (Inet, Phone, IPTV)'],
|
|
// Static Routers
|
|
['value' => 'Mikrotik HAP AC', 'text' => 'Mikrotik HAP AC (Inet, IPTV)'],
|
|
['value' => 'Mikrotik HEX S', 'text' => 'Mikrotik HEX S (Inet, IPTV)'],
|
|
['value' => 'Mikrotik RB3011', 'text' => 'Mikrotik RB3011 (Inet, IPTV)'],
|
|
// CMTS Routers
|
|
['value' => 'FritzBox 6490 Cable', 'text' => 'FritzBox 6490 Cable (Inet, Phone, IPTV)'],
|
|
],
|
|
"ROUTER_SHIPPING_DATA" => [
|
|
"TP-Link Archer C80" => ["weight" => 1, "length" => 35, "width" => 24, "height" => 8],
|
|
"FritzBox 5530" => ["weight" => 1, "length" => 27, "width" => 19, "height" => 7],
|
|
"FritzBox 4050" => ["weight" => 1, "length" => 27, "width" => 19, "height" => 7],
|
|
"FritzBox 7690" => ["weight" => 1, "length" => 27, "width" => 19, "height" => 7],
|
|
"FritzBox 4040" => ["weight" => 1, "length" => 30, "width" => 24, "height" => 7],
|
|
"FritzBox 7530" => ["weight" => 1, "length" => 27, "width" => 19, "height" => 7],
|
|
"FritzBox 7590" => ["weight" => 1, "length" => 27, "width" => 19, "height" => 7],
|
|
"FritzBox 6490 Cable" => ["weight" => 1, "length" => 30, "width" => 26, "height" => 8]
|
|
]
|
|
]
|
|
);
|
|
}
|
|
|
|
private function fixCpeData($data) {
|
|
if (!$data) return [];
|
|
$data->shipping = (bool)$data->shipping;
|
|
$data->routerconfig_finished = (bool)$data->routerconfig_finished;
|
|
return $data;
|
|
}
|
|
|
|
protected function printPDFAction() {
|
|
$order_id = $this->request->order_id;
|
|
|
|
$order = OrderModel::getOne($order_id);
|
|
if (!$order) self::sendError("Order not found", 404);
|
|
|
|
$pdf_vars = [
|
|
'firstline' => $order->owner->getCompanyOrName(),
|
|
'secondline' => $order->owner->street,
|
|
'thirdline' => $order->owner->zip . " " . $order->owner->city,
|
|
'fourthline' => $order->owner->customer_number ?? $order->partner_number
|
|
];
|
|
|
|
$pdf = new PdfForm("Cpeprovisioning/PDF_MAIN", $pdf_vars);
|
|
$wkhtmltopdfArgs = "--page-height 32.5mm --page-width 57.5mm --margin-top 1mm --margin-bottom 0 --margin-left 0 --margin-right 0 --disable-smart-shrinking --encoding utf-8";
|
|
$filename = $pdf->render($wkhtmltopdfArgs);
|
|
|
|
header('Content-Type: application/pdf');
|
|
header('Content-Disposition: inline; filename="' . $filename . '"');
|
|
readfile($filename);
|
|
die();
|
|
}
|
|
|
|
protected function countOpenProvisioningsAction() {
|
|
$r = $this->request;
|
|
$filter = $this->getPreparedFilter($r->filter ?? []);
|
|
$filter['routerconfig_finished'] = 0; // only open ones
|
|
|
|
$orders = OrderModel::search($filter);
|
|
$orderproductsprefetch = OrderProductModel::precache();
|
|
|
|
$openCount = 0;
|
|
|
|
foreach ($orders as $order) {
|
|
if ($filter["hide_delayed_finish"] && $order->finish_after) {
|
|
if ($order->finish_after > date("U") + (31 * 86400)) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (isset($orderproductsprefetch['terminations'][$order->id]) && is_array($orderproductsprefetch['terminations'][$order->id]) && count($orderproductsprefetch['terminations'][$order->id])) {
|
|
if (!$order->cpeprovisioning_enabled && $orderproductsprefetch['terminations'][$order->id][0]['statuscode'] < TT_TERMSTATUS_CONNECTED) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (array_key_exists($order->id, $orderproductsprefetch)) {
|
|
foreach ($orderproductsprefetch[$order->id] as $orderproduct) {
|
|
if (!$orderproduct || !is_array($orderproduct)) continue;
|
|
|
|
if ($orderproduct['routerconfig_finished'] == 1) {
|
|
continue;
|
|
}
|
|
|
|
$productattributes = $orderproduct['attributes'];
|
|
if (is_array($productattributes) && count($productattributes)) {
|
|
if (array_key_exists("bras_type", $productattributes) && $productattributes) {
|
|
$openCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self::returnJson(['open_count' => $openCount]);
|
|
}
|
|
}
|