diff --git a/application/Cpeprovisioning/CpeprovisioningController.php b/application/Cpeprovisioning/CpeprovisioningController.php
index 7ef383c45..3ca148fe2 100644
--- a/application/Cpeprovisioning/CpeprovisioningController.php
+++ b/application/Cpeprovisioning/CpeprovisioningController.php
@@ -529,6 +529,7 @@ class CpeprovisioningController extends mfBaseController {
// 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_API_TEST_ACS_VLAN_URL" => $this->getUrl("Cpeprovisioning", "getAcsVlan"),
"CPE_PROV_PRINT_PDF_URL" => $this->getUrl("Cpeprovisioning", "printPDF"),
"ORDER_URL" => $this->getUrl("Order"),
"NETWORKS" => NetworkModel::getAll(),
@@ -565,6 +566,58 @@ class CpeprovisioningController extends mfBaseController {
);
}
+ protected function getAcsVlanAction() {
+ $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? null;
+ $isApiCall = defined('TT_CPE_PROV_ACS_API_KEY') && $apiKey && $apiKey === TT_CPE_PROV_ACS_API_KEY;
+ $isLoggedInUser = $this->me && $this->me->id;
+
+ if (!$isApiCall && !$isLoggedInUser) {
+ http_response_code(403);
+ self::returnJson(['success' => false, 'message' => 'Forbidden']);
+ return;
+ }
+
+ try {
+ $p = json_decode(file_get_contents('php://input'), true);
+ $mac = $p['mac'] ?? null;
+
+ if (empty($mac)) {
+ throw new Exception("MAC address is required.");
+ }
+
+ $cpe = CpeprovisioningModel::getFirst(['mac' => $mac]);
+ if (!$cpe || !$cpe->termination_id) {
+ throw new Exception("No active provisioning entry found for this MAC address.");
+ }
+
+ $term = new Termination($cpe->termination_id);
+ $product = $cpe->orderproduct;
+ if (!$term->id || !$product->id) {
+ throw new Exception("Could not load termination or product details.");
+ }
+
+ $attrs = $product->product->attributes;
+
+ $vlanPublicDefault = $term->getPop()->vlan_public ?? $attrs['vlan_default_public']->value ?? null;
+ $vlanNatDefault = $term->getPop()->vlan_nat ?? $attrs['vlan_default_nat']->value ?? null;
+ $vlanIpv6Default = $term->getPop()->vlan_ipv6 ?? $attrs['vlan_default_ipv6']->value ?? null;
+
+ // For the test, we just return the first available VLAN that would be assigned.
+ // The logic can be expanded if a specific type is requested.
+ $assignedVlan = $vlanPublicDefault ?? $vlanNatDefault ?? $vlanIpv6Default;
+
+ if ($assignedVlan) {
+ self::returnJson(['success' => true, 'vlan_id' => $assignedVlan]);
+ } else {
+ throw new Exception("No default VLAN could be determined for this product/POP combination.");
+ }
+
+ } catch (Exception $e) {
+ http_response_code(400);
+ self::returnJson(['success' => false, 'message' => $e->getMessage()]);
+ }
+ }
+
private function fixCpeData($data) {
if (!$data) return [];
$data->shipping = (bool)$data->shipping;
diff --git a/application/Cpeprovisioning/CpeprovisioningModel.php b/application/Cpeprovisioning/CpeprovisioningModel.php
index 19d17cfe6..fb79df3c3 100644
--- a/application/Cpeprovisioning/CpeprovisioningModel.php
+++ b/application/Cpeprovisioning/CpeprovisioningModel.php
@@ -181,6 +181,13 @@ class CpeprovisioningModel {
}
}
+ if(array_key_exists("mac", $filter)) {
+ $mac = FronkDB::singleton()->escape($filter['mac']);
+ if($mac) {
+ $where .= " AND mac='$mac'";
+ }
+ }
+
//var_dump($filter, $where);exit;
return $where;
}
diff --git a/public/js/pages/Cpeprovisioning/Cpeprovisioning.css b/public/js/pages/Cpeprovisioning/Cpeprovisioning.css
index 431fe7c92..0456872a3 100644
--- a/public/js/pages/Cpeprovisioning/Cpeprovisioning.css
+++ b/public/js/pages/Cpeprovisioning/Cpeprovisioning.css
@@ -83,7 +83,7 @@ body {
.cpe-card-content {
padding: 0.75rem 1rem;
display: grid;
- grid-template-columns: minmax(280px, 1.25fr) minmax(280px, 1.25fr) minmax(280px, 1.5fr);
+ grid-template-columns: repeat(4, minmax(280px, 1fr)); /* Changed to 4 columns */
gap: 1rem 1.5rem;
}
diff --git a/public/js/pages/Cpeprovisioning/Cpeprovisioning.js b/public/js/pages/Cpeprovisioning/Cpeprovisioning.js
index ec93ede76..ac3150a99 100644
--- a/public/js/pages/Cpeprovisioning/Cpeprovisioning.js
+++ b/public/js/pages/Cpeprovisioning/Cpeprovisioning.js
@@ -87,7 +87,7 @@ Vue.component('Cpeprovisioning', {
{{ item.product_name }} {{ item.product_code }}
@@ -103,6 +103,22 @@ Vue.component('Cpeprovisioning', {