Align 2G CIQ output with final schema
Browse files- queries/ciq_2g_final_schema.json +743 -0
- queries/ciq_2g_schema_loader.py +32 -0
- queries/process_ciq_2g.py +191 -30
- tests/test_process_ciq_2g_final_schema.py +303 -0
queries/ciq_2g_final_schema.json
ADDED
|
@@ -0,0 +1,743 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"BTS": {
|
| 3 |
+
"columns": [
|
| 4 |
+
"site",
|
| 5 |
+
"bscid",
|
| 6 |
+
"cellId",
|
| 7 |
+
"bcfId",
|
| 8 |
+
"btsId",
|
| 9 |
+
"Check",
|
| 10 |
+
"bsIdentityCodeNCC",
|
| 11 |
+
"bsIdentityCodeBCC",
|
| 12 |
+
"locationAreaIdLAC",
|
| 13 |
+
"locationAreaIdMCC",
|
| 14 |
+
"locationAreaIdMNC",
|
| 15 |
+
"usedMobileAllocation",
|
| 16 |
+
"malId",
|
| 17 |
+
"name",
|
| 18 |
+
"template_name",
|
| 19 |
+
"sectorId",
|
| 20 |
+
"masterBCF",
|
| 21 |
+
"allowIMSIAttachDetach",
|
| 22 |
+
"amhLowerLoadThreshold",
|
| 23 |
+
"amhMaxLoadOfTgtCell",
|
| 24 |
+
"amhTrhoGuardTime",
|
| 25 |
+
"amhUpperLoadThreshold",
|
| 26 |
+
"btsIsHopping",
|
| 27 |
+
"btsLoadInSeg",
|
| 28 |
+
"btsLoadThreshold",
|
| 29 |
+
"btsMeasAver",
|
| 30 |
+
"callReestablishmentAllowed",
|
| 31 |
+
"cellBarQualify",
|
| 32 |
+
"cellBarred",
|
| 33 |
+
"cellLoadForChannelSearch",
|
| 34 |
+
"cellNumberInBtsHw",
|
| 35 |
+
"cellReselectHysteresis",
|
| 36 |
+
"cellReselectOffset",
|
| 37 |
+
"cellReselectParamInd",
|
| 38 |
+
"cnThreshold",
|
| 39 |
+
"diversityUsed",
|
| 40 |
+
"dlNoiseLevel",
|
| 41 |
+
"drInUse",
|
| 42 |
+
"drMethod",
|
| 43 |
+
"dtxMode",
|
| 44 |
+
"earlySendingIndication",
|
| 45 |
+
"emergencyCallRestricted",
|
| 46 |
+
"fddQMin",
|
| 47 |
+
"fddQOffset",
|
| 48 |
+
"frequencyBandInUse",
|
| 49 |
+
"hoppingMode",
|
| 50 |
+
"hoppingSequenceNumber1",
|
| 51 |
+
"hoppingSequenceNumber2",
|
| 52 |
+
"idleStateBcchAllocListId",
|
| 53 |
+
"idrCellType",
|
| 54 |
+
"idrUsed",
|
| 55 |
+
"interferenceAveragingProcessAverPeriod",
|
| 56 |
+
"interferenceAveragingProcessBoundary0",
|
| 57 |
+
"interferenceAveragingProcessBoundary1",
|
| 58 |
+
"interferenceAveragingProcessBoundary2",
|
| 59 |
+
"interferenceAveragingProcessBoundary3",
|
| 60 |
+
"interferenceAveragingProcessBoundary4",
|
| 61 |
+
"interferenceAveragingProcessBoundary5",
|
| 62 |
+
"lowPriorityThr",
|
| 63 |
+
"maioOffset",
|
| 64 |
+
"maxNumberOfRepetition",
|
| 65 |
+
"maxNumberRetransmission",
|
| 66 |
+
"maxQueueLength",
|
| 67 |
+
"maxTimeLimitDirectedRetry",
|
| 68 |
+
"measListUsedDuringMeas",
|
| 69 |
+
"measurementBCCHAllocation",
|
| 70 |
+
"minMsTxPower",
|
| 71 |
+
"minTimeLimitDirectedRetry",
|
| 72 |
+
"msMaxDistInCallSetup",
|
| 73 |
+
"msPriorityUsedInQueueing",
|
| 74 |
+
"msTxPwrMaxCCH",
|
| 75 |
+
"msTxPwrMaxCCH1x00",
|
| 76 |
+
"msTxPwrMaxGSM",
|
| 77 |
+
"msTxPwrMaxGSM1x00",
|
| 78 |
+
"multiBandCell",
|
| 79 |
+
"multiBandCellReporting",
|
| 80 |
+
"nbrOfSlotsSpreadTrans",
|
| 81 |
+
"newEstabCausesSupport",
|
| 82 |
+
"noOfBlocksForAccessGrant",
|
| 83 |
+
"noOfMFramesBetweenPaging",
|
| 84 |
+
"penaltyTime",
|
| 85 |
+
"powerOffset",
|
| 86 |
+
"prioritySearchThr",
|
| 87 |
+
"qSearchI",
|
| 88 |
+
"qSearchP",
|
| 89 |
+
"queuePriorityNonUrgentHo",
|
| 90 |
+
"queuePriorityUsed",
|
| 91 |
+
"queueingPriorityCall",
|
| 92 |
+
"queueingPriorityHandover",
|
| 93 |
+
"radioLinkTimeout",
|
| 94 |
+
"radioLinkTimeoutUlIncreaseStep",
|
| 95 |
+
"reselectionAlgorithmHysteresis",
|
| 96 |
+
"rxLevAccessMin",
|
| 97 |
+
"segmentId",
|
| 98 |
+
"smsCbUsed",
|
| 99 |
+
"stircEnabled",
|
| 100 |
+
"temporaryOffset",
|
| 101 |
+
"timeHysteresis",
|
| 102 |
+
"timeLimitCall",
|
| 103 |
+
"timeLimitHandover",
|
| 104 |
+
"timerPeriodicUpdateMs",
|
| 105 |
+
"trxPriorityInTchAlloc",
|
| 106 |
+
"ulNoiseLevel",
|
| 107 |
+
"utranQualRxLevelMargin",
|
| 108 |
+
"utranThresholdReselection",
|
| 109 |
+
"wcdmaPriority",
|
| 110 |
+
"gprsCapacityThroughputFactor",
|
| 111 |
+
"fddRscpMin",
|
| 112 |
+
"fddQMinOffset"
|
| 113 |
+
],
|
| 114 |
+
"defaults": {
|
| 115 |
+
"locationAreaIdMCC": 610,
|
| 116 |
+
"locationAreaIdMNC": 2,
|
| 117 |
+
"masterBCF": 1,
|
| 118 |
+
"allowIMSIAttachDetach": 1,
|
| 119 |
+
"amhLowerLoadThreshold": -1,
|
| 120 |
+
"amhMaxLoadOfTgtCell": 85,
|
| 121 |
+
"amhTrhoGuardTime": 30,
|
| 122 |
+
"amhUpperLoadThreshold": 30,
|
| 123 |
+
"btsIsHopping": 1,
|
| 124 |
+
"btsLoadInSeg": 70,
|
| 125 |
+
"btsLoadThreshold": 85,
|
| 126 |
+
"btsMeasAver": 2,
|
| 127 |
+
"callReestablishmentAllowed": 1,
|
| 128 |
+
"cellBarQualify": 0,
|
| 129 |
+
"cellBarred": 0,
|
| 130 |
+
"cellLoadForChannelSearch": 0,
|
| 131 |
+
"cellNumberInBtsHw": 255,
|
| 132 |
+
"cellReselectHysteresis": 7,
|
| 133 |
+
"cellReselectOffset": 0,
|
| 134 |
+
"cellReselectParamInd": 1,
|
| 135 |
+
"cnThreshold": 0,
|
| 136 |
+
"diversityUsed": 1,
|
| 137 |
+
"dlNoiseLevel": 3,
|
| 138 |
+
"drInUse": 1,
|
| 139 |
+
"drMethod": 0,
|
| 140 |
+
"dtxMode": 1,
|
| 141 |
+
"earlySendingIndication": 1,
|
| 142 |
+
"emergencyCallRestricted": 0,
|
| 143 |
+
"fddQMin": 7,
|
| 144 |
+
"fddQOffset": 8,
|
| 145 |
+
"hoppingMode": 2,
|
| 146 |
+
"hoppingSequenceNumber2": 0,
|
| 147 |
+
"idleStateBcchAllocListId": 0,
|
| 148 |
+
"idrCellType": 0,
|
| 149 |
+
"idrUsed": 0,
|
| 150 |
+
"interferenceAveragingProcessAverPeriod": 10,
|
| 151 |
+
"interferenceAveragingProcessBoundary0": 0,
|
| 152 |
+
"interferenceAveragingProcessBoundary1": 5,
|
| 153 |
+
"interferenceAveragingProcessBoundary2": 10,
|
| 154 |
+
"interferenceAveragingProcessBoundary3": 15,
|
| 155 |
+
"interferenceAveragingProcessBoundary4": 20,
|
| 156 |
+
"interferenceAveragingProcessBoundary5": 63,
|
| 157 |
+
"lowPriorityThr": 15,
|
| 158 |
+
"maioOffset": 0,
|
| 159 |
+
"maxNumberOfRepetition": 35,
|
| 160 |
+
"maxNumberRetransmission": 2,
|
| 161 |
+
"maxQueueLength": 50,
|
| 162 |
+
"maxTimeLimitDirectedRetry": 5,
|
| 163 |
+
"measListUsedDuringMeas": 1,
|
| 164 |
+
"measurementBCCHAllocation": 1,
|
| 165 |
+
"minMsTxPower": 13,
|
| 166 |
+
"minTimeLimitDirectedRetry": 0,
|
| 167 |
+
"msMaxDistInCallSetup": 64,
|
| 168 |
+
"msPriorityUsedInQueueing": 0,
|
| 169 |
+
"msTxPwrMaxCCH": 2,
|
| 170 |
+
"msTxPwrMaxCCH1x00": 0,
|
| 171 |
+
"msTxPwrMaxGSM": 2,
|
| 172 |
+
"msTxPwrMaxGSM1x00": 0,
|
| 173 |
+
"multiBandCell": 1,
|
| 174 |
+
"multiBandCellReporting": 3,
|
| 175 |
+
"nbrOfSlotsSpreadTrans": 10,
|
| 176 |
+
"newEstabCausesSupport": 0,
|
| 177 |
+
"noOfBlocksForAccessGrant": 2,
|
| 178 |
+
"noOfMFramesBetweenPaging": 3,
|
| 179 |
+
"penaltyTime": 0,
|
| 180 |
+
"powerOffset": 0,
|
| 181 |
+
"prioritySearchThr": 15,
|
| 182 |
+
"qSearchI": 7,
|
| 183 |
+
"qSearchP": 7,
|
| 184 |
+
"queuePriorityNonUrgentHo": 9,
|
| 185 |
+
"queuePriorityUsed": 1,
|
| 186 |
+
"queueingPriorityCall": 10,
|
| 187 |
+
"queueingPriorityHandover": 9,
|
| 188 |
+
"radioLinkTimeout": 7,
|
| 189 |
+
"radioLinkTimeoutUlIncreaseStep": 2,
|
| 190 |
+
"reselectionAlgorithmHysteresis": 0,
|
| 191 |
+
"rxLevAccessMin": 8,
|
| 192 |
+
"smsCbUsed": 1,
|
| 193 |
+
"stircEnabled": 1,
|
| 194 |
+
"temporaryOffset": 0,
|
| 195 |
+
"timeHysteresis": 0,
|
| 196 |
+
"timeLimitCall": 6,
|
| 197 |
+
"timeLimitHandover": 3,
|
| 198 |
+
"timerPeriodicUpdateMs": 60,
|
| 199 |
+
"trxPriorityInTchAlloc": 0,
|
| 200 |
+
"ulNoiseLevel": 3,
|
| 201 |
+
"utranQualRxLevelMargin": 2,
|
| 202 |
+
"utranThresholdReselection": 3,
|
| 203 |
+
"wcdmaPriority": 4,
|
| 204 |
+
"gprsCapacityThroughputFactor": 80,
|
| 205 |
+
"fddRscpMin": 4,
|
| 206 |
+
"fddQMinOffset": 0
|
| 207 |
+
},
|
| 208 |
+
"formulas": {
|
| 209 |
+
"segmentId": {
|
| 210 |
+
"kind": "same_row_ref",
|
| 211 |
+
"source_column": "btsId"
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
},
|
| 215 |
+
"BTS_GPRS": {
|
| 216 |
+
"columns": [
|
| 217 |
+
"Site",
|
| 218 |
+
"bscid",
|
| 219 |
+
"cellId",
|
| 220 |
+
"bcfId",
|
| 221 |
+
"btsId",
|
| 222 |
+
"template_name",
|
| 223 |
+
"dedicatedGPRScapacity",
|
| 224 |
+
"egprsEnabled",
|
| 225 |
+
"egprsLinkAdaptEnabled",
|
| 226 |
+
"gprsEnabled",
|
| 227 |
+
"gprsMsTxPwrMaxCCH1x00",
|
| 228 |
+
"gprsMsTxpwrMaxCCH",
|
| 229 |
+
"gprsRxlevAccessMin",
|
| 230 |
+
"csAckDl",
|
| 231 |
+
"csAckUl",
|
| 232 |
+
"csUnackDl",
|
| 233 |
+
"csUnackUl",
|
| 234 |
+
"preferBCCHfreqGPRS2",
|
| 235 |
+
"raReselectHysteresis",
|
| 236 |
+
"egprsInitMcsAckMode",
|
| 237 |
+
"egprsInitMcsUnAckMode",
|
| 238 |
+
"maxGPRSCapacity",
|
| 239 |
+
"adaptiveLaAlgorithm",
|
| 240 |
+
"cs3Cs4Enabled",
|
| 241 |
+
"defaultGPRScapacity",
|
| 242 |
+
"directGPRSAccessBts",
|
| 243 |
+
"egprsMaxBlerAckMode",
|
| 244 |
+
"egprsMaxBlerUnAckMode",
|
| 245 |
+
"egprsMeanBepOffset8psk",
|
| 246 |
+
"egprsMeanBepOffsetGmsk",
|
| 247 |
+
"gprsDlPcEnabled",
|
| 248 |
+
"gprsNonBCCHRxlevLower",
|
| 249 |
+
"gprsNonBCCHRxlevUpper",
|
| 250 |
+
"hcsPriorityClass",
|
| 251 |
+
"hcsThreshold",
|
| 252 |
+
"pcuCsHopping",
|
| 253 |
+
"pcuCsNonHopping",
|
| 254 |
+
"pcuDlBlerCpHopping",
|
| 255 |
+
"pcuDlBlerCpNonHop",
|
| 256 |
+
"pcuDlLaRiskLevel",
|
| 257 |
+
"pcuUlBlerCpHopping",
|
| 258 |
+
"pcuUlBlerCpNonHop",
|
| 259 |
+
"pcuUlLaRiskLevel",
|
| 260 |
+
"throughputFactor_cs1cs4dlcs",
|
| 261 |
+
"throughputFactor_cs1cs4ulcs",
|
| 262 |
+
"throughputFactor_mcs1mcs4ulcs",
|
| 263 |
+
"throughputFactor_mcs1mcs9dlcs",
|
| 264 |
+
"throughputFactor_mcs1mcs9ulcs",
|
| 265 |
+
"inactEndTimeHour",
|
| 266 |
+
"inactEndTimeMinute",
|
| 267 |
+
"inactStartTimeHour",
|
| 268 |
+
"inactStartTimeMinute",
|
| 269 |
+
"inactWeekDays",
|
| 270 |
+
"nsei",
|
| 271 |
+
"psei",
|
| 272 |
+
"rac"
|
| 273 |
+
],
|
| 274 |
+
"defaults": {
|
| 275 |
+
"template_name": "All",
|
| 276 |
+
"dedicatedGPRScapacity": 15,
|
| 277 |
+
"egprsEnabled": 1,
|
| 278 |
+
"egprsLinkAdaptEnabled": 2,
|
| 279 |
+
"gprsEnabled": 1,
|
| 280 |
+
"gprsMsTxPwrMaxCCH1x00": 2,
|
| 281 |
+
"gprsMsTxpwrMaxCCH": 2,
|
| 282 |
+
"gprsRxlevAccessMin": 10,
|
| 283 |
+
"csAckDl": 5,
|
| 284 |
+
"csAckUl": 5,
|
| 285 |
+
"csUnackDl": 5,
|
| 286 |
+
"csUnackUl": 5,
|
| 287 |
+
"preferBCCHfreqGPRS2": 1,
|
| 288 |
+
"raReselectHysteresis": 2,
|
| 289 |
+
"egprsInitMcsAckMode": 2,
|
| 290 |
+
"egprsInitMcsUnAckMode": 2,
|
| 291 |
+
"maxGPRSCapacity": 100,
|
| 292 |
+
"adaptiveLaAlgorithm": 0,
|
| 293 |
+
"cs3Cs4Enabled": 1,
|
| 294 |
+
"defaultGPRScapacity": 50,
|
| 295 |
+
"directGPRSAccessBts": 0,
|
| 296 |
+
"egprsMaxBlerAckMode": 90,
|
| 297 |
+
"egprsMaxBlerUnAckMode": 10,
|
| 298 |
+
"egprsMeanBepOffset8psk": 31,
|
| 299 |
+
"egprsMeanBepOffsetGmsk": 31,
|
| 300 |
+
"gprsDlPcEnabled": 1,
|
| 301 |
+
"gprsNonBCCHRxlevLower": 10,
|
| 302 |
+
"gprsNonBCCHRxlevUpper": 15,
|
| 303 |
+
"hcsPriorityClass": 0,
|
| 304 |
+
"hcsThreshold": 255,
|
| 305 |
+
"pcuCsHopping": 0,
|
| 306 |
+
"pcuCsNonHopping": 0,
|
| 307 |
+
"pcuDlBlerCpHopping": 20,
|
| 308 |
+
"pcuDlBlerCpNonHop": 90,
|
| 309 |
+
"pcuDlLaRiskLevel": 20,
|
| 310 |
+
"pcuUlBlerCpHopping": 24,
|
| 311 |
+
"pcuUlBlerCpNonHop": 90,
|
| 312 |
+
"pcuUlLaRiskLevel": 10,
|
| 313 |
+
"throughputFactor_cs1cs4dlcs": 12,
|
| 314 |
+
"throughputFactor_cs1cs4ulcs": 12,
|
| 315 |
+
"throughputFactor_mcs1mcs4ulcs": 16,
|
| 316 |
+
"throughputFactor_mcs1mcs9dlcs": 30,
|
| 317 |
+
"throughputFactor_mcs1mcs9ulcs": 30,
|
| 318 |
+
"inactEndTimeHour": 18,
|
| 319 |
+
"inactEndTimeMinute": 0,
|
| 320 |
+
"inactStartTimeHour": 8,
|
| 321 |
+
"inactStartTimeMinute": 0,
|
| 322 |
+
"inactWeekDays": 0,
|
| 323 |
+
"nsei": "",
|
| 324 |
+
"psei": 0,
|
| 325 |
+
"rac": 1
|
| 326 |
+
},
|
| 327 |
+
"formulas": {}
|
| 328 |
+
},
|
| 329 |
+
"BTS_AMR": {
|
| 330 |
+
"columns": [
|
| 331 |
+
"Site",
|
| 332 |
+
"bscId",
|
| 333 |
+
"cellId",
|
| 334 |
+
"bcfId",
|
| 335 |
+
"btsId",
|
| 336 |
+
"template_name",
|
| 337 |
+
"amrConfFrCodecModeSet",
|
| 338 |
+
"amrConfFrDlThreshold1",
|
| 339 |
+
"amrConfFrDlThreshold2",
|
| 340 |
+
"amrConfFrDlThreshold3",
|
| 341 |
+
"amrConfFrHysteresis1",
|
| 342 |
+
"amrConfFrHysteresis2",
|
| 343 |
+
"amrConfFrHysteresis3",
|
| 344 |
+
"amrConfFrInitCodecMode",
|
| 345 |
+
"amrConfFrStartMode",
|
| 346 |
+
"amrConfFrUlThreshold1",
|
| 347 |
+
"amrConfFrUlThreshold2",
|
| 348 |
+
"amrConfFrUlThreshold3",
|
| 349 |
+
"amrConfHrCodecModeSet",
|
| 350 |
+
"amrConfHrDlThreshold1",
|
| 351 |
+
"amrConfHrDlThreshold2",
|
| 352 |
+
"amrConfHrDlThreshold3",
|
| 353 |
+
"amrConfHrHysteresis1",
|
| 354 |
+
"amrConfHrHysteresis2",
|
| 355 |
+
"amrConfHrHysteresis3",
|
| 356 |
+
"amrConfHrInitCodecMode",
|
| 357 |
+
"amrConfHrStartMode",
|
| 358 |
+
"amrConfHrUlThreshold1",
|
| 359 |
+
"amrConfHrUlThreshold2",
|
| 360 |
+
"amrConfHrUlThreshold3",
|
| 361 |
+
"amrHoFrInHoThrDlRxQual",
|
| 362 |
+
"amrHoFrThrDlRxQual",
|
| 363 |
+
"amrHoFrThrUlRxQual",
|
| 364 |
+
"amrHoHrInHoThrDlRxQual",
|
| 365 |
+
"amrHoHrThrDlRxQual",
|
| 366 |
+
"amrHoHrThrUlRxQual",
|
| 367 |
+
"amrPocFrPcLThrDlRxQual",
|
| 368 |
+
"amrPocFrPcLThrUlRxQual",
|
| 369 |
+
"amrPocFrPcUThrDlRxQual",
|
| 370 |
+
"amrPocFrPcUThrUlRxQual",
|
| 371 |
+
"amrPocHrPcLThrDlRxQual",
|
| 372 |
+
"amrPocHrPcLThrUlRxQual",
|
| 373 |
+
"amrPocHrPcUThrDlRxQual",
|
| 374 |
+
"amrPocHrPcUThrUlRxQual",
|
| 375 |
+
"amrSegLoadDepTchRateLower",
|
| 376 |
+
"amrSegLoadDepTchRateUpper",
|
| 377 |
+
"radioLinkTimeoutAmrHr",
|
| 378 |
+
"radioLinkTimeoutAmr",
|
| 379 |
+
"btsSpLoadDepTchRateLower",
|
| 380 |
+
"btsSpLoadDepTchRateUpper",
|
| 381 |
+
"radioLinkTimeoutAmrHrUlIncreaseStep",
|
| 382 |
+
"radioLinkTimeoutAmrUlIncreaseStep",
|
| 383 |
+
"tchRateIntraCellHo"
|
| 384 |
+
],
|
| 385 |
+
"defaults": {
|
| 386 |
+
"template_name": "All",
|
| 387 |
+
"amrConfFrCodecModeSet": 149,
|
| 388 |
+
"amrConfFrDlThreshold1": 14,
|
| 389 |
+
"amrConfFrDlThreshold2": 26,
|
| 390 |
+
"amrConfFrDlThreshold3": 52,
|
| 391 |
+
"amrConfFrHysteresis1": 8,
|
| 392 |
+
"amrConfFrHysteresis2": 8,
|
| 393 |
+
"amrConfFrHysteresis3": 8,
|
| 394 |
+
"amrConfFrInitCodecMode": 1,
|
| 395 |
+
"amrConfFrStartMode": 0,
|
| 396 |
+
"amrConfFrUlThreshold1": 18,
|
| 397 |
+
"amrConfFrUlThreshold2": 28,
|
| 398 |
+
"amrConfFrUlThreshold3": 46,
|
| 399 |
+
"amrConfHrCodecModeSet": 21,
|
| 400 |
+
"amrConfHrDlThreshold1": 40,
|
| 401 |
+
"amrConfHrDlThreshold2": 52,
|
| 402 |
+
"amrConfHrDlThreshold3": 52,
|
| 403 |
+
"amrConfHrHysteresis1": 8,
|
| 404 |
+
"amrConfHrHysteresis2": 8,
|
| 405 |
+
"amrConfHrHysteresis3": 8,
|
| 406 |
+
"amrConfHrInitCodecMode": 1,
|
| 407 |
+
"amrConfHrStartMode": 0,
|
| 408 |
+
"amrConfHrUlThreshold1": 40,
|
| 409 |
+
"amrConfHrUlThreshold2": 52,
|
| 410 |
+
"amrConfHrUlThreshold3": 52,
|
| 411 |
+
"amrHoFrInHoThrDlRxQual": 0,
|
| 412 |
+
"amrHoFrThrDlRxQual": 5,
|
| 413 |
+
"amrHoFrThrUlRxQual": 5,
|
| 414 |
+
"amrHoHrInHoThrDlRxQual": 5,
|
| 415 |
+
"amrHoHrThrDlRxQual": 5,
|
| 416 |
+
"amrHoHrThrUlRxQual": 5,
|
| 417 |
+
"amrPocFrPcLThrDlRxQual": 3,
|
| 418 |
+
"amrPocFrPcLThrUlRxQual": 3,
|
| 419 |
+
"amrPocFrPcUThrDlRxQual": 1,
|
| 420 |
+
"amrPocFrPcUThrUlRxQual": 1,
|
| 421 |
+
"amrPocHrPcLThrDlRxQual": 3,
|
| 422 |
+
"amrPocHrPcLThrUlRxQual": 3,
|
| 423 |
+
"amrPocHrPcUThrDlRxQual": 1,
|
| 424 |
+
"amrPocHrPcUThrUlRxQual": 1,
|
| 425 |
+
"amrSegLoadDepTchRateLower": 100,
|
| 426 |
+
"amrSegLoadDepTchRateUpper": 0,
|
| 427 |
+
"radioLinkTimeoutAmrHr": 7,
|
| 428 |
+
"radioLinkTimeoutAmr": 7,
|
| 429 |
+
"btsSpLoadDepTchRateLower": 100,
|
| 430 |
+
"btsSpLoadDepTchRateUpper": 0,
|
| 431 |
+
"radioLinkTimeoutAmrHrUlIncreaseStep": 2,
|
| 432 |
+
"radioLinkTimeoutAmrUlIncreaseStep": 2,
|
| 433 |
+
"tchRateIntraCellHo": 0
|
| 434 |
+
},
|
| 435 |
+
"formulas": {}
|
| 436 |
+
},
|
| 437 |
+
"HOC": {
|
| 438 |
+
"columns": [
|
| 439 |
+
"Site",
|
| 440 |
+
"bscid",
|
| 441 |
+
"cellId",
|
| 442 |
+
"bcfId",
|
| 443 |
+
"btsId",
|
| 444 |
+
"hocId",
|
| 445 |
+
"template_name",
|
| 446 |
+
"averagingWindowSizeAdjCell",
|
| 447 |
+
"ddeThresholdsLevRxLevel",
|
| 448 |
+
"enableIntraHoDl",
|
| 449 |
+
"enableIntraHoUl",
|
| 450 |
+
"enableMsDistance",
|
| 451 |
+
"enablePowerBudgetHo",
|
| 452 |
+
"enableSddchHandover",
|
| 453 |
+
"hoAvaragingLevDLWeighting",
|
| 454 |
+
"hoAvaragingLevDlWindowSize",
|
| 455 |
+
"hoAveragingLevUlWeighting",
|
| 456 |
+
"hoAveragingLevUlWindowSize",
|
| 457 |
+
"hoAveragingQualDlWeighting",
|
| 458 |
+
"hoAveragingQualDlWindowSize",
|
| 459 |
+
"hoAveragingQualUl",
|
| 460 |
+
"hoAveragingQualUlWindowSize",
|
| 461 |
+
"hoPeriodPbgt",
|
| 462 |
+
"hoTLDlRxLevel",
|
| 463 |
+
"hoTLUlRxLevel",
|
| 464 |
+
"hoTQDlRxQual",
|
| 465 |
+
"hoTQUlRxQual",
|
| 466 |
+
"hoThresholdsInterferenceDlRxLevel",
|
| 467 |
+
"hoThresholdsInterferenceULRxLevel",
|
| 468 |
+
"minIntBetweenUnsuccHoAttempt",
|
| 469 |
+
"msDistanceAveragingParamHreqave",
|
| 470 |
+
"msDistanceHoThresholdParamMsRangeMax",
|
| 471 |
+
"qSearchC",
|
| 472 |
+
"allAdjacentCellsAveraged",
|
| 473 |
+
"allUtranAdjAver",
|
| 474 |
+
"amhTrafficControlIUO",
|
| 475 |
+
"amhTrafficControlMCN",
|
| 476 |
+
"amhTrhoPbgtMargin",
|
| 477 |
+
"ddeThresholdsLevNx",
|
| 478 |
+
"ddeThresholdsLevPx",
|
| 479 |
+
"ddeWindow",
|
| 480 |
+
"enaFastAveCallSetup",
|
| 481 |
+
"enaFastAveHo",
|
| 482 |
+
"enaFastAvePc",
|
| 483 |
+
"enaHierCellHo",
|
| 484 |
+
"erfdEnabled",
|
| 485 |
+
"erfdOver",
|
| 486 |
+
"failMoveThreshold",
|
| 487 |
+
"gsmPlmnPriorisation",
|
| 488 |
+
"hoPeriodUmbrella",
|
| 489 |
+
"hoTLDlPx",
|
| 490 |
+
"hoTLUlNx",
|
| 491 |
+
"hoTLUlPx",
|
| 492 |
+
"hoTQDlNx",
|
| 493 |
+
"hoTQDlPx",
|
| 494 |
+
"hoTQUlNx",
|
| 495 |
+
"hoTQUlPx",
|
| 496 |
+
"hoThrInterferenceDlNx",
|
| 497 |
+
"hoThrInterferenceDlPx",
|
| 498 |
+
"hoThresholdsInterferenceULNx",
|
| 499 |
+
"hoThresholdsInterferenceULPx",
|
| 500 |
+
"hoThresholdsLevDLNx",
|
| 501 |
+
"hoThresholdsRapidLevUl",
|
| 502 |
+
"hoThresholdsRapidLevUlN",
|
| 503 |
+
"interSystemDa",
|
| 504 |
+
"intraHoLoRxLevLimAmrHr",
|
| 505 |
+
"intraHoLoRxQualLimAmr",
|
| 506 |
+
"intraHoUpRxLevLimAmrHr",
|
| 507 |
+
"lowerSpeedLimit",
|
| 508 |
+
"minIntBetweenHoReq",
|
| 509 |
+
"minIntUnsuccIsHo",
|
| 510 |
+
"modifiedAveWinNCell",
|
| 511 |
+
"modifiedNoz",
|
| 512 |
+
"msDHoThrParamN8",
|
| 513 |
+
"msDistanceHoThresholdParamP8",
|
| 514 |
+
"msSpeedAveraging",
|
| 515 |
+
"msSpeedDetectionState",
|
| 516 |
+
"msSpeedThresholdNx",
|
| 517 |
+
"msSpeedThresholdPx",
|
| 518 |
+
"multiratRep",
|
| 519 |
+
"noOfZeroResUtran",
|
| 520 |
+
"numberOfZeroResults",
|
| 521 |
+
"upperSpeedLimit",
|
| 522 |
+
"utranAveragingNumber",
|
| 523 |
+
"utranHoThScTpdc",
|
| 524 |
+
"wcdmaRanCellPenalty",
|
| 525 |
+
"enableUmbrellaHo"
|
| 526 |
+
],
|
| 527 |
+
"defaults": {
|
| 528 |
+
"hocId": 1,
|
| 529 |
+
"averagingWindowSizeAdjCell": 10,
|
| 530 |
+
"ddeThresholdsLevRxLevel": 10,
|
| 531 |
+
"enableIntraHoDl": 0,
|
| 532 |
+
"enableIntraHoUl": 0,
|
| 533 |
+
"enableMsDistance": 0,
|
| 534 |
+
"enablePowerBudgetHo": 1,
|
| 535 |
+
"enableSddchHandover": "",
|
| 536 |
+
"hoAvaragingLevDLWeighting": 2,
|
| 537 |
+
"hoAvaragingLevDlWindowSize": 5,
|
| 538 |
+
"hoAveragingLevUlWeighting": 2,
|
| 539 |
+
"hoAveragingLevUlWindowSize": 5,
|
| 540 |
+
"hoAveragingQualDlWeighting": 3,
|
| 541 |
+
"hoAveragingQualDlWindowSize": 5,
|
| 542 |
+
"hoAveragingQualUl": "",
|
| 543 |
+
"hoAveragingQualUlWindowSize": 5,
|
| 544 |
+
"hoPeriodPbgt": 6,
|
| 545 |
+
"hoTLDlRxLevel": 15,
|
| 546 |
+
"hoTLUlRxLevel": 15,
|
| 547 |
+
"hoTQDlRxQual": 4,
|
| 548 |
+
"hoTQUlRxQual": 4,
|
| 549 |
+
"hoThresholdsInterferenceDlRxLevel": 12,
|
| 550 |
+
"hoThresholdsInterferenceULRxLevel": 3,
|
| 551 |
+
"minIntBetweenUnsuccHoAttempt": 20,
|
| 552 |
+
"msDistanceAveragingParamHreqave": 4,
|
| 553 |
+
"msDistanceHoThresholdParamMsRangeMax": 63,
|
| 554 |
+
"qSearchC": 15,
|
| 555 |
+
"allAdjacentCellsAveraged": 0,
|
| 556 |
+
"allUtranAdjAver": 0,
|
| 557 |
+
"amhTrafficControlIUO": 0,
|
| 558 |
+
"amhTrafficControlMCN": 0,
|
| 559 |
+
"amhTrhoPbgtMargin": -2,
|
| 560 |
+
"ddeThresholdsLevNx": 3,
|
| 561 |
+
"ddeThresholdsLevPx": 2,
|
| 562 |
+
"ddeWindow": 2,
|
| 563 |
+
"enaFastAveCallSetup": 0,
|
| 564 |
+
"enaFastAveHo": 1,
|
| 565 |
+
"enaFastAvePc": 1,
|
| 566 |
+
"enaHierCellHo": 0,
|
| 567 |
+
"erfdEnabled": 0,
|
| 568 |
+
"erfdOver": 10,
|
| 569 |
+
"failMoveThreshold": 50,
|
| 570 |
+
"gsmPlmnPriorisation": 0,
|
| 571 |
+
"hoPeriodUmbrella": 0,
|
| 572 |
+
"hoTLDlPx": 1,
|
| 573 |
+
"hoTLUlNx": 1,
|
| 574 |
+
"hoTLUlPx": 1,
|
| 575 |
+
"hoTQDlNx": 6,
|
| 576 |
+
"hoTQDlPx": 4,
|
| 577 |
+
"hoTQUlNx": 6,
|
| 578 |
+
"hoTQUlPx": 4,
|
| 579 |
+
"hoThrInterferenceDlNx": 1,
|
| 580 |
+
"hoThrInterferenceDlPx": 1,
|
| 581 |
+
"hoThresholdsInterferenceULNx": 1,
|
| 582 |
+
"hoThresholdsInterferenceULPx": 1,
|
| 583 |
+
"hoThresholdsLevDLNx": 1,
|
| 584 |
+
"hoThresholdsRapidLevUl": 0,
|
| 585 |
+
"hoThresholdsRapidLevUlN": 0,
|
| 586 |
+
"interSystemDa": 0,
|
| 587 |
+
"intraHoLoRxLevLimAmrHr": 63,
|
| 588 |
+
"intraHoLoRxQualLimAmr": 0,
|
| 589 |
+
"intraHoUpRxLevLimAmrHr": 0,
|
| 590 |
+
"lowerSpeedLimit": 0,
|
| 591 |
+
"minIntBetweenHoReq": 5,
|
| 592 |
+
"minIntUnsuccIsHo": 3,
|
| 593 |
+
"modifiedAveWinNCell": 2,
|
| 594 |
+
"modifiedNoz": 1,
|
| 595 |
+
"msDHoThrParamN8": 1,
|
| 596 |
+
"msDistanceHoThresholdParamP8": 1,
|
| 597 |
+
"msSpeedAveraging": 4,
|
| 598 |
+
"msSpeedDetectionState": 0,
|
| 599 |
+
"msSpeedThresholdNx": 6,
|
| 600 |
+
"msSpeedThresholdPx": 3,
|
| 601 |
+
"multiratRep": 2,
|
| 602 |
+
"noOfZeroResUtran": 5,
|
| 603 |
+
"numberOfZeroResults": 2,
|
| 604 |
+
"upperSpeedLimit": 0,
|
| 605 |
+
"utranAveragingNumber": 6,
|
| 606 |
+
"utranHoThScTpdc": 80,
|
| 607 |
+
"wcdmaRanCellPenalty": 127,
|
| 608 |
+
"enableUmbrellaHo": 1
|
| 609 |
+
},
|
| 610 |
+
"formulas": {}
|
| 611 |
+
},
|
| 612 |
+
"POC": {
|
| 613 |
+
"columns": [
|
| 614 |
+
"Site",
|
| 615 |
+
"bscid",
|
| 616 |
+
"cellId",
|
| 617 |
+
"bcfId",
|
| 618 |
+
"btsId",
|
| 619 |
+
"hocId",
|
| 620 |
+
"template_name",
|
| 621 |
+
"alpha",
|
| 622 |
+
"bepPeriod",
|
| 623 |
+
"bsTxPwrMax",
|
| 624 |
+
"bsTxPwrMax1x00",
|
| 625 |
+
"bsTxPwrMin",
|
| 626 |
+
"gamma",
|
| 627 |
+
"pcALDlWeighting",
|
| 628 |
+
"pcALDlWindowSize",
|
| 629 |
+
"pcALUlWeighting",
|
| 630 |
+
"pcALUlWindowSize",
|
| 631 |
+
"pcAQLDlWeighting",
|
| 632 |
+
"pcAQLDlWindowSize",
|
| 633 |
+
"pcAQLUlWeighting",
|
| 634 |
+
"pcAQLUlWindowSize",
|
| 635 |
+
"pcControlEnabled",
|
| 636 |
+
"pcControlInterval",
|
| 637 |
+
"pcIncrStepSize",
|
| 638 |
+
"pcLowerThresholdsLevDLRxLevel",
|
| 639 |
+
"pcLowerThresholsLevULRxLevel",
|
| 640 |
+
"pcRedStepSize",
|
| 641 |
+
"pcUpperThresholdsLevDLRxLevel",
|
| 642 |
+
"pcUpperThresholdsLevULRxLevel",
|
| 643 |
+
"tAvgT",
|
| 644 |
+
"tAvgW",
|
| 645 |
+
"pcLTQualDlRxQual",
|
| 646 |
+
"pcLTQualUlRxQual",
|
| 647 |
+
"pcUTQualDlRxQual",
|
| 648 |
+
"pcUTQualUlRxQual",
|
| 649 |
+
"dlPcPowerReduction",
|
| 650 |
+
"dlPcWindowSize",
|
| 651 |
+
"enableAla",
|
| 652 |
+
"maxPwrCompensation",
|
| 653 |
+
"minIntBetweenAla",
|
| 654 |
+
"pcLTLevDlNx",
|
| 655 |
+
"pcLTLevDlPx",
|
| 656 |
+
"pcLTLevUlNx",
|
| 657 |
+
"pcLTLevUlPx",
|
| 658 |
+
"pcLTQual144Nx",
|
| 659 |
+
"pcLTQual144Px",
|
| 660 |
+
"pcLTQual144RxQual",
|
| 661 |
+
"pcLTQualDlNx",
|
| 662 |
+
"pcLTQualDlPx",
|
| 663 |
+
"pcLTQualUlNx",
|
| 664 |
+
"pcLTQualUlPx",
|
| 665 |
+
"pcUTLevDlNx",
|
| 666 |
+
"pcUTLevDlPx",
|
| 667 |
+
"pcUTLevUlNx",
|
| 668 |
+
"pcUTLevUlPx",
|
| 669 |
+
"pcUTQualDlNx",
|
| 670 |
+
"pcUTQualDlPx",
|
| 671 |
+
"pcUTQualUlNx",
|
| 672 |
+
"pcUTQualUlPx",
|
| 673 |
+
"powerDecrQualFactor",
|
| 674 |
+
"powerLimitAla",
|
| 675 |
+
"pwrDecrLimitBand0",
|
| 676 |
+
"pwrDecrLimitBand1",
|
| 677 |
+
"pwrDecrLimitBand2",
|
| 678 |
+
"transmitPowerReduction"
|
| 679 |
+
],
|
| 680 |
+
"defaults": {
|
| 681 |
+
"hocId": 1,
|
| 682 |
+
"alpha": 10,
|
| 683 |
+
"bepPeriod": 6,
|
| 684 |
+
"bsTxPwrMax": 0,
|
| 685 |
+
"bsTxPwrMax1x00": 0,
|
| 686 |
+
"bsTxPwrMin": 15,
|
| 687 |
+
"gamma": 15,
|
| 688 |
+
"pcALDlWeighting": 1,
|
| 689 |
+
"pcALDlWindowSize": 1,
|
| 690 |
+
"pcALUlWeighting": 1,
|
| 691 |
+
"pcALUlWindowSize": 4,
|
| 692 |
+
"pcAQLDlWeighting": 1,
|
| 693 |
+
"pcAQLDlWindowSize": 1,
|
| 694 |
+
"pcAQLUlWeighting": 1,
|
| 695 |
+
"pcAQLUlWindowSize": 4,
|
| 696 |
+
"pcControlEnabled": 1,
|
| 697 |
+
"pcControlInterval": 1,
|
| 698 |
+
"pcIncrStepSize": 1,
|
| 699 |
+
"pcLowerThresholdsLevDLRxLevel": 25,
|
| 700 |
+
"pcLowerThresholsLevULRxLevel": 20,
|
| 701 |
+
"pcRedStepSize": 1,
|
| 702 |
+
"pcUpperThresholdsLevDLRxLevel": 35,
|
| 703 |
+
"pcUpperThresholdsLevULRxLevel": 30,
|
| 704 |
+
"tAvgT": 10,
|
| 705 |
+
"tAvgW": 20,
|
| 706 |
+
"pcLTQualDlRxQual": 3,
|
| 707 |
+
"pcLTQualUlRxQual": 3,
|
| 708 |
+
"pcUTQualDlRxQual": 1,
|
| 709 |
+
"pcUTQualUlRxQual": 0,
|
| 710 |
+
"dlPcPowerReduction": 4,
|
| 711 |
+
"dlPcWindowSize": 8,
|
| 712 |
+
"enableAla": 0,
|
| 713 |
+
"maxPwrCompensation": 10,
|
| 714 |
+
"minIntBetweenAla": 10,
|
| 715 |
+
"pcLTLevDlNx": 1,
|
| 716 |
+
"pcLTLevDlPx": 1,
|
| 717 |
+
"pcLTLevUlNx": 1,
|
| 718 |
+
"pcLTLevUlPx": 1,
|
| 719 |
+
"pcLTQual144Nx": 4,
|
| 720 |
+
"pcLTQual144Px": 3,
|
| 721 |
+
"pcLTQual144RxQual": 2,
|
| 722 |
+
"pcLTQualDlNx": 1,
|
| 723 |
+
"pcLTQualDlPx": 1,
|
| 724 |
+
"pcLTQualUlNx": 4,
|
| 725 |
+
"pcLTQualUlPx": 3,
|
| 726 |
+
"pcUTLevDlNx": 1,
|
| 727 |
+
"pcUTLevDlPx": 1,
|
| 728 |
+
"pcUTLevUlNx": 1,
|
| 729 |
+
"pcUTLevUlPx": 1,
|
| 730 |
+
"pcUTQualDlNx": 1,
|
| 731 |
+
"pcUTQualDlPx": 1,
|
| 732 |
+
"pcUTQualUlNx": 1,
|
| 733 |
+
"pcUTQualUlPx": 1,
|
| 734 |
+
"powerDecrQualFactor": 1,
|
| 735 |
+
"powerLimitAla": 3,
|
| 736 |
+
"pwrDecrLimitBand0": 0,
|
| 737 |
+
"pwrDecrLimitBand1": 19,
|
| 738 |
+
"pwrDecrLimitBand2": 19,
|
| 739 |
+
"transmitPowerReduction": 4
|
| 740 |
+
},
|
| 741 |
+
"formulas": {}
|
| 742 |
+
}
|
| 743 |
+
}
|
queries/ciq_2g_schema_loader.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
_SCHEMA_PATH = Path(__file__).with_name("ciq_2g_final_schema.json")
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def _load_schema() -> dict[str, dict[str, object]]:
|
| 9 |
+
return json.loads(_SCHEMA_PATH.read_text(encoding="utf-8"))
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
_SCHEMA = _load_schema()
|
| 13 |
+
|
| 14 |
+
BTS_FINAL_COLUMNS = _SCHEMA["BTS"]["columns"]
|
| 15 |
+
BTS_FINAL_DEFAULTS = _SCHEMA["BTS"]["defaults"]
|
| 16 |
+
BTS_FINAL_FORMULAS = _SCHEMA["BTS"]["formulas"]
|
| 17 |
+
|
| 18 |
+
BTS_GPRS_FINAL_COLUMNS = _SCHEMA["BTS_GPRS"]["columns"]
|
| 19 |
+
BTS_GPRS_FINAL_DEFAULTS = _SCHEMA["BTS_GPRS"]["defaults"]
|
| 20 |
+
BTS_GPRS_FINAL_FORMULAS = _SCHEMA["BTS_GPRS"]["formulas"]
|
| 21 |
+
|
| 22 |
+
BTS_AMR_FINAL_COLUMNS = _SCHEMA["BTS_AMR"]["columns"]
|
| 23 |
+
BTS_AMR_FINAL_DEFAULTS = _SCHEMA["BTS_AMR"]["defaults"]
|
| 24 |
+
BTS_AMR_FINAL_FORMULAS = _SCHEMA["BTS_AMR"]["formulas"]
|
| 25 |
+
|
| 26 |
+
HOC_FINAL_COLUMNS = _SCHEMA["HOC"]["columns"]
|
| 27 |
+
HOC_FINAL_DEFAULTS = _SCHEMA["HOC"]["defaults"]
|
| 28 |
+
HOC_FINAL_FORMULAS = _SCHEMA["HOC"]["formulas"]
|
| 29 |
+
|
| 30 |
+
POC_FINAL_COLUMNS = _SCHEMA["POC"]["columns"]
|
| 31 |
+
POC_FINAL_DEFAULTS = _SCHEMA["POC"]["defaults"]
|
| 32 |
+
POC_FINAL_FORMULAS = _SCHEMA["POC"]["formulas"]
|
queries/process_ciq_2g.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import io
|
| 2 |
import re
|
| 3 |
from dataclasses import dataclass
|
|
@@ -5,6 +6,23 @@ from typing import Optional
|
|
| 5 |
|
| 6 |
import pandas as pd
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
from utils.ciq_excel import read_ciq_excel
|
| 9 |
from utils.dump_excel import detect_dump_header_row
|
| 10 |
from utils.utils_vars import UtilsVars
|
|
@@ -28,6 +46,8 @@ BTS_EXPORT_COLUMNS = [
|
|
| 28 |
"name",
|
| 29 |
"template_name",
|
| 30 |
"sectorId",
|
|
|
|
|
|
|
| 31 |
]
|
| 32 |
|
| 33 |
|
|
@@ -87,6 +107,22 @@ TRX_STATIC_DEFAULTS = {
|
|
| 87 |
"trxRfPower": 20000,
|
| 88 |
}
|
| 89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
def _normalize_col(col: object) -> str:
|
| 92 |
return re.sub(r"[^0-9A-Za-z]", "", str(col))
|
|
@@ -98,6 +134,79 @@ def _clean_columns(df: pd.DataFrame) -> pd.DataFrame:
|
|
| 98 |
return df
|
| 99 |
|
| 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
def _read_dump_bts_required_columns(dump_file) -> pd.DataFrame:
|
| 102 |
if hasattr(dump_file, "seek"):
|
| 103 |
dump_file.seek(0)
|
|
@@ -734,6 +843,66 @@ def _build_trx_sheet_from_assigned_sites(
|
|
| 734 |
return df_trx
|
| 735 |
|
| 736 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 737 |
def build_bts_sheet(
|
| 738 |
dump_file, ciq_file, mcc: int = 610, mnc: int = 2, forbidden_file=None
|
| 739 |
) -> pd.DataFrame:
|
|
@@ -755,6 +924,9 @@ def _build_bts_sheet_from_assigned_sites(
|
|
| 755 |
) -> pd.DataFrame:
|
| 756 |
assigned_by_site = {s.site_name: s for s in assigned_sites}
|
| 757 |
|
|
|
|
|
|
|
|
|
|
| 758 |
required = [
|
| 759 |
"Sites",
|
| 760 |
"NOM_CELLULE",
|
|
@@ -785,6 +957,7 @@ def _build_bts_sheet_from_assigned_sites(
|
|
| 785 |
lac = pd.to_numeric(r.get("LAC"), errors="coerce")
|
| 786 |
ncc = pd.to_numeric(r.get("NCC"), errors="coerce")
|
| 787 |
bcc = pd.to_numeric(r.get("BCC"), errors="coerce")
|
|
|
|
| 788 |
|
| 789 |
rows.append(
|
| 790 |
{
|
|
@@ -804,6 +977,8 @@ def _build_bts_sheet_from_assigned_sites(
|
|
| 804 |
"name": f"{str(r.get('NOM_CELLULE'))}_NA",
|
| 805 |
"template_name": _template_name_from_band(r.get("band")),
|
| 806 |
"sectorId": int(sector_id),
|
|
|
|
|
|
|
| 807 |
}
|
| 808 |
)
|
| 809 |
|
|
@@ -904,6 +1079,8 @@ def generate_ciq_2g_excel(
|
|
| 904 |
) -> tuple[dict[str, pd.DataFrame], bytes]:
|
| 905 |
dump_bts = _read_dump_bts_required_columns(dump_file)
|
| 906 |
ciq_df = _read_ciq_df(ciq_file, ciq_sheet_name=ciq_sheet_name)
|
|
|
|
|
|
|
| 907 |
planned_sites = _parse_ciq_sites(ciq_df)
|
| 908 |
forbidden_by_bsc, forbidden_df = _read_forbidden_bcfs(forbidden_file)
|
| 909 |
assigned_sites = _assign_bcfs(
|
|
@@ -912,40 +1089,23 @@ def generate_ciq_2g_excel(
|
|
| 912 |
|
| 913 |
df_bcf = _build_bcf_sheet_from_assigned_sites(assigned_sites)
|
| 914 |
df_bcf_free = _build_free_bcf_sheet(dump_bts, forbidden_by_bsc=forbidden_by_bsc)
|
| 915 |
-
|
| 916 |
ciq_df, assigned_sites, mcc=mcc, mnc=mnc
|
| 917 |
)
|
|
|
|
| 918 |
df_mal = _build_mal_sheet_from_assigned_sites(ciq_df, assigned_sites)
|
| 919 |
df_trx = _build_trx_sheet_from_assigned_sites(ciq_df, assigned_sites)
|
| 920 |
|
| 921 |
-
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
df_hoc = pd.DataFrame()
|
| 928 |
-
df_poc = pd.DataFrame()
|
| 929 |
-
if not df_bts.empty:
|
| 930 |
-
base = df_bts[
|
| 931 |
-
["site", "bscid", "cellId", "bcfId", "btsId", "template_name"]
|
| 932 |
-
].rename(columns={"site": "Site"})
|
| 933 |
-
|
| 934 |
-
df_hoc = base.copy()
|
| 935 |
-
df_hoc.insert(5, "hocId", 1)
|
| 936 |
-
df_hoc = df_hoc[
|
| 937 |
-
["Site", "bscid", "cellId", "bcfId", "btsId", "hocId", "template_name"]
|
| 938 |
-
]
|
| 939 |
-
|
| 940 |
-
df_poc = base.copy()
|
| 941 |
-
df_poc.insert(5, "pocId", 1)
|
| 942 |
-
df_poc = df_poc[
|
| 943 |
-
["Site", "bscid", "cellId", "bcfId", "btsId", "pocId", "template_name"]
|
| 944 |
-
]
|
| 945 |
|
| 946 |
df_plmn_permitted = pd.DataFrame()
|
| 947 |
-
if not
|
| 948 |
-
base_plmn =
|
| 949 |
columns={"bscid": "BSCId"}
|
| 950 |
)
|
| 951 |
df_plmn_permitted = base_plmn.loc[base_plmn.index.repeat(8)].reset_index(
|
|
@@ -961,8 +1121,8 @@ def generate_ciq_2g_excel(
|
|
| 961 |
"BCF": df_bcf,
|
| 962 |
"BCF_LIBRE": df_bcf_free,
|
| 963 |
"BTS": df_bts,
|
| 964 |
-
"BTS_GPRS":
|
| 965 |
-
"BTS_AMR":
|
| 966 |
"HOC": df_hoc,
|
| 967 |
"POC": df_poc,
|
| 968 |
"MAL": df_mal,
|
|
@@ -973,8 +1133,9 @@ def generate_ciq_2g_excel(
|
|
| 973 |
if not forbidden_df.empty:
|
| 974 |
sheets["BCF_FORBIDDEN"] = forbidden_df
|
| 975 |
|
|
|
|
| 976 |
bytes_io = io.BytesIO()
|
| 977 |
-
with pd.ExcelWriter(bytes_io, engine=
|
| 978 |
for sheet_name, df in sheets.items():
|
| 979 |
df.to_excel(writer, sheet_name=sheet_name, index=False)
|
| 980 |
|
|
|
|
| 1 |
+
import importlib.util
|
| 2 |
import io
|
| 3 |
import re
|
| 4 |
from dataclasses import dataclass
|
|
|
|
| 6 |
|
| 7 |
import pandas as pd
|
| 8 |
|
| 9 |
+
from queries.ciq_2g_schema_loader import (
|
| 10 |
+
BTS_AMR_FINAL_COLUMNS,
|
| 11 |
+
BTS_AMR_FINAL_DEFAULTS,
|
| 12 |
+
BTS_AMR_FINAL_FORMULAS,
|
| 13 |
+
BTS_FINAL_COLUMNS,
|
| 14 |
+
BTS_FINAL_DEFAULTS,
|
| 15 |
+
BTS_FINAL_FORMULAS,
|
| 16 |
+
BTS_GPRS_FINAL_COLUMNS,
|
| 17 |
+
BTS_GPRS_FINAL_DEFAULTS,
|
| 18 |
+
BTS_GPRS_FINAL_FORMULAS,
|
| 19 |
+
HOC_FINAL_COLUMNS,
|
| 20 |
+
HOC_FINAL_DEFAULTS,
|
| 21 |
+
HOC_FINAL_FORMULAS,
|
| 22 |
+
POC_FINAL_COLUMNS,
|
| 23 |
+
POC_FINAL_DEFAULTS,
|
| 24 |
+
POC_FINAL_FORMULAS,
|
| 25 |
+
)
|
| 26 |
from utils.ciq_excel import read_ciq_excel
|
| 27 |
from utils.dump_excel import detect_dump_header_row
|
| 28 |
from utils.utils_vars import UtilsVars
|
|
|
|
| 46 |
"name",
|
| 47 |
"template_name",
|
| 48 |
"sectorId",
|
| 49 |
+
"frequencyBandInUse",
|
| 50 |
+
"hoppingSequenceNumber1",
|
| 51 |
]
|
| 52 |
|
| 53 |
|
|
|
|
| 107 |
"trxRfPower": 20000,
|
| 108 |
}
|
| 109 |
|
| 110 |
+
FINAL_SCHEMA = {
|
| 111 |
+
"BTS": (BTS_FINAL_COLUMNS, BTS_FINAL_DEFAULTS, BTS_FINAL_FORMULAS),
|
| 112 |
+
"BTS_GPRS": (
|
| 113 |
+
BTS_GPRS_FINAL_COLUMNS,
|
| 114 |
+
BTS_GPRS_FINAL_DEFAULTS,
|
| 115 |
+
BTS_GPRS_FINAL_FORMULAS,
|
| 116 |
+
),
|
| 117 |
+
"BTS_AMR": (
|
| 118 |
+
BTS_AMR_FINAL_COLUMNS,
|
| 119 |
+
BTS_AMR_FINAL_DEFAULTS,
|
| 120 |
+
BTS_AMR_FINAL_FORMULAS,
|
| 121 |
+
),
|
| 122 |
+
"HOC": (HOC_FINAL_COLUMNS, HOC_FINAL_DEFAULTS, HOC_FINAL_FORMULAS),
|
| 123 |
+
"POC": (POC_FINAL_COLUMNS, POC_FINAL_DEFAULTS, POC_FINAL_FORMULAS),
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
|
| 127 |
def _normalize_col(col: object) -> str:
|
| 128 |
return re.sub(r"[^0-9A-Za-z]", "", str(col))
|
|
|
|
| 134 |
return df
|
| 135 |
|
| 136 |
|
| 137 |
+
def _raise_missing_hsn_error() -> None:
|
| 138 |
+
raise ValueError(
|
| 139 |
+
"CIQ brut is missing required column: HSN. "
|
| 140 |
+
"The 2G final export uses HSN to populate BTS.hoppingSequenceNumber1."
|
| 141 |
+
)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def _get_excel_writer_engine() -> str:
|
| 145 |
+
for engine_name in ("xlsxwriter", "openpyxl"):
|
| 146 |
+
if importlib.util.find_spec(engine_name) is not None:
|
| 147 |
+
return engine_name
|
| 148 |
+
raise RuntimeError(
|
| 149 |
+
"Excel export requires 'xlsxwriter' or 'openpyxl' to be installed."
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def _excel_column_name(index: int) -> str:
|
| 154 |
+
if index < 1:
|
| 155 |
+
raise ValueError("Excel column index must be >= 1")
|
| 156 |
+
|
| 157 |
+
result = ""
|
| 158 |
+
while index > 0:
|
| 159 |
+
index, remainder = divmod(index - 1, 26)
|
| 160 |
+
result = chr(65 + remainder) + result
|
| 161 |
+
return result
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def apply_final_schema(df: pd.DataFrame, sheet_name: str) -> pd.DataFrame:
|
| 165 |
+
if sheet_name not in FINAL_SCHEMA:
|
| 166 |
+
raise ValueError(f"Unsupported 2G CIQ sheet '{sheet_name}'")
|
| 167 |
+
|
| 168 |
+
final_columns, default_values, formula_specs = FINAL_SCHEMA[sheet_name]
|
| 169 |
+
final_df = df.copy()
|
| 170 |
+
missing_columns = [column for column in final_columns if column not in final_df.columns]
|
| 171 |
+
|
| 172 |
+
if missing_columns:
|
| 173 |
+
if final_df.empty:
|
| 174 |
+
additions = pd.DataFrame(
|
| 175 |
+
{column: pd.Series(dtype="object") for column in missing_columns}
|
| 176 |
+
)
|
| 177 |
+
else:
|
| 178 |
+
additions = pd.DataFrame(
|
| 179 |
+
{
|
| 180 |
+
column: [default_values.get(column, "")] * len(final_df)
|
| 181 |
+
for column in missing_columns
|
| 182 |
+
},
|
| 183 |
+
index=final_df.index,
|
| 184 |
+
)
|
| 185 |
+
final_df = pd.concat([final_df, additions], axis=1)
|
| 186 |
+
|
| 187 |
+
final_df = final_df.loc[:, final_columns]
|
| 188 |
+
|
| 189 |
+
if final_df.empty or not formula_specs:
|
| 190 |
+
return final_df
|
| 191 |
+
|
| 192 |
+
for formula_column, spec in formula_specs.items():
|
| 193 |
+
kind = spec.get("kind")
|
| 194 |
+
if kind != "same_row_ref":
|
| 195 |
+
raise ValueError(
|
| 196 |
+
f"Unsupported formula kind '{kind}' for 2G sheet '{sheet_name}'"
|
| 197 |
+
)
|
| 198 |
+
|
| 199 |
+
source_column = spec["source_column"]
|
| 200 |
+
source_col_idx = final_columns.index(source_column) + 1
|
| 201 |
+
source_col_letter = _excel_column_name(source_col_idx)
|
| 202 |
+
final_df[formula_column] = [
|
| 203 |
+
f"={source_col_letter}{row_number}"
|
| 204 |
+
for row_number in range(2, len(final_df) + 2)
|
| 205 |
+
]
|
| 206 |
+
|
| 207 |
+
return final_df
|
| 208 |
+
|
| 209 |
+
|
| 210 |
def _read_dump_bts_required_columns(dump_file) -> pd.DataFrame:
|
| 211 |
if hasattr(dump_file, "seek"):
|
| 212 |
dump_file.seek(0)
|
|
|
|
| 843 |
return df_trx
|
| 844 |
|
| 845 |
|
| 846 |
+
def _build_bts_gprs_sheet_from_bts(df_bts: pd.DataFrame) -> pd.DataFrame:
|
| 847 |
+
if df_bts.empty:
|
| 848 |
+
return pd.DataFrame(
|
| 849 |
+
columns=["Site", "bscid", "cellId", "bcfId", "btsId", "template_name"]
|
| 850 |
+
)
|
| 851 |
+
|
| 852 |
+
df_bts_gprs = df_bts[["site", "bscid", "cellId", "bcfId", "btsId"]].rename(
|
| 853 |
+
columns={"site": "Site"}
|
| 854 |
+
)
|
| 855 |
+
df_bts_gprs["template_name"] = "All"
|
| 856 |
+
return df_bts_gprs[
|
| 857 |
+
["Site", "bscid", "cellId", "bcfId", "btsId", "template_name"]
|
| 858 |
+
]
|
| 859 |
+
|
| 860 |
+
|
| 861 |
+
def _build_bts_amr_sheet_from_bts(df_bts: pd.DataFrame) -> pd.DataFrame:
|
| 862 |
+
if df_bts.empty:
|
| 863 |
+
return pd.DataFrame(
|
| 864 |
+
columns=["Site", "bscId", "cellId", "bcfId", "btsId", "template_name"]
|
| 865 |
+
)
|
| 866 |
+
|
| 867 |
+
df_bts_amr = df_bts[["site", "bscid", "cellId", "bcfId", "btsId"]].rename(
|
| 868 |
+
columns={"site": "Site", "bscid": "bscId"}
|
| 869 |
+
)
|
| 870 |
+
df_bts_amr["template_name"] = "All"
|
| 871 |
+
return df_bts_amr[
|
| 872 |
+
["Site", "bscId", "cellId", "bcfId", "btsId", "template_name"]
|
| 873 |
+
]
|
| 874 |
+
|
| 875 |
+
|
| 876 |
+
def _build_hoc_sheet_from_bts(df_bts: pd.DataFrame) -> pd.DataFrame:
|
| 877 |
+
if df_bts.empty:
|
| 878 |
+
return pd.DataFrame(
|
| 879 |
+
columns=["Site", "bscid", "cellId", "bcfId", "btsId", "hocId", "template_name"]
|
| 880 |
+
)
|
| 881 |
+
|
| 882 |
+
df_hoc = df_bts[
|
| 883 |
+
["site", "bscid", "cellId", "bcfId", "btsId", "template_name"]
|
| 884 |
+
].rename(columns={"site": "Site"})
|
| 885 |
+
df_hoc.insert(5, "hocId", 1)
|
| 886 |
+
return df_hoc[
|
| 887 |
+
["Site", "bscid", "cellId", "bcfId", "btsId", "hocId", "template_name"]
|
| 888 |
+
]
|
| 889 |
+
|
| 890 |
+
|
| 891 |
+
def _build_poc_sheet_from_bts(df_bts: pd.DataFrame) -> pd.DataFrame:
|
| 892 |
+
if df_bts.empty:
|
| 893 |
+
return pd.DataFrame(
|
| 894 |
+
columns=["Site", "bscid", "cellId", "bcfId", "btsId", "hocId", "template_name"]
|
| 895 |
+
)
|
| 896 |
+
|
| 897 |
+
df_poc = df_bts[
|
| 898 |
+
["site", "bscid", "cellId", "bcfId", "btsId", "template_name"]
|
| 899 |
+
].rename(columns={"site": "Site"})
|
| 900 |
+
df_poc.insert(5, "hocId", 1)
|
| 901 |
+
return df_poc[
|
| 902 |
+
["Site", "bscid", "cellId", "bcfId", "btsId", "hocId", "template_name"]
|
| 903 |
+
]
|
| 904 |
+
|
| 905 |
+
|
| 906 |
def build_bts_sheet(
|
| 907 |
dump_file, ciq_file, mcc: int = 610, mnc: int = 2, forbidden_file=None
|
| 908 |
) -> pd.DataFrame:
|
|
|
|
| 924 |
) -> pd.DataFrame:
|
| 925 |
assigned_by_site = {s.site_name: s for s in assigned_sites}
|
| 926 |
|
| 927 |
+
if "HSN" not in ciq_df.columns:
|
| 928 |
+
_raise_missing_hsn_error()
|
| 929 |
+
|
| 930 |
required = [
|
| 931 |
"Sites",
|
| 932 |
"NOM_CELLULE",
|
|
|
|
| 957 |
lac = pd.to_numeric(r.get("LAC"), errors="coerce")
|
| 958 |
ncc = pd.to_numeric(r.get("NCC"), errors="coerce")
|
| 959 |
bcc = pd.to_numeric(r.get("BCC"), errors="coerce")
|
| 960 |
+
hsn = pd.to_numeric(r.get("HSN"), errors="coerce")
|
| 961 |
|
| 962 |
rows.append(
|
| 963 |
{
|
|
|
|
| 977 |
"name": f"{str(r.get('NOM_CELLULE'))}_NA",
|
| 978 |
"template_name": _template_name_from_band(r.get("band")),
|
| 979 |
"sectorId": int(sector_id),
|
| 980 |
+
"frequencyBandInUse": _frequency_band_in_use_from_band(r.get("band")),
|
| 981 |
+
"hoppingSequenceNumber1": int(hsn) if not pd.isna(hsn) else None,
|
| 982 |
}
|
| 983 |
)
|
| 984 |
|
|
|
|
| 1079 |
) -> tuple[dict[str, pd.DataFrame], bytes]:
|
| 1080 |
dump_bts = _read_dump_bts_required_columns(dump_file)
|
| 1081 |
ciq_df = _read_ciq_df(ciq_file, ciq_sheet_name=ciq_sheet_name)
|
| 1082 |
+
if "HSN" not in ciq_df.columns:
|
| 1083 |
+
_raise_missing_hsn_error()
|
| 1084 |
planned_sites = _parse_ciq_sites(ciq_df)
|
| 1085 |
forbidden_by_bsc, forbidden_df = _read_forbidden_bcfs(forbidden_file)
|
| 1086 |
assigned_sites = _assign_bcfs(
|
|
|
|
| 1089 |
|
| 1090 |
df_bcf = _build_bcf_sheet_from_assigned_sites(assigned_sites)
|
| 1091 |
df_bcf_free = _build_free_bcf_sheet(dump_bts, forbidden_by_bsc=forbidden_by_bsc)
|
| 1092 |
+
df_bts_base = _build_bts_sheet_from_assigned_sites(
|
| 1093 |
ciq_df, assigned_sites, mcc=mcc, mnc=mnc
|
| 1094 |
)
|
| 1095 |
+
df_bts = apply_final_schema(df_bts_base, "BTS")
|
| 1096 |
df_mal = _build_mal_sheet_from_assigned_sites(ciq_df, assigned_sites)
|
| 1097 |
df_trx = _build_trx_sheet_from_assigned_sites(ciq_df, assigned_sites)
|
| 1098 |
|
| 1099 |
+
df_bts_gprs = apply_final_schema(
|
| 1100 |
+
_build_bts_gprs_sheet_from_bts(df_bts_base), "BTS_GPRS"
|
| 1101 |
+
)
|
| 1102 |
+
df_bts_amr = apply_final_schema(_build_bts_amr_sheet_from_bts(df_bts_base), "BTS_AMR")
|
| 1103 |
+
df_hoc = apply_final_schema(_build_hoc_sheet_from_bts(df_bts_base), "HOC")
|
| 1104 |
+
df_poc = apply_final_schema(_build_poc_sheet_from_bts(df_bts_base), "POC")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1105 |
|
| 1106 |
df_plmn_permitted = pd.DataFrame()
|
| 1107 |
+
if not df_bts_base.empty:
|
| 1108 |
+
base_plmn = df_bts_base[["bscid", "cellId", "bcfId", "btsId"]].rename(
|
| 1109 |
columns={"bscid": "BSCId"}
|
| 1110 |
)
|
| 1111 |
df_plmn_permitted = base_plmn.loc[base_plmn.index.repeat(8)].reset_index(
|
|
|
|
| 1121 |
"BCF": df_bcf,
|
| 1122 |
"BCF_LIBRE": df_bcf_free,
|
| 1123 |
"BTS": df_bts,
|
| 1124 |
+
"BTS_GPRS": df_bts_gprs,
|
| 1125 |
+
"BTS_AMR": df_bts_amr,
|
| 1126 |
"HOC": df_hoc,
|
| 1127 |
"POC": df_poc,
|
| 1128 |
"MAL": df_mal,
|
|
|
|
| 1133 |
if not forbidden_df.empty:
|
| 1134 |
sheets["BCF_FORBIDDEN"] = forbidden_df
|
| 1135 |
|
| 1136 |
+
engine_name = _get_excel_writer_engine()
|
| 1137 |
bytes_io = io.BytesIO()
|
| 1138 |
+
with pd.ExcelWriter(bytes_io, engine=engine_name) as writer:
|
| 1139 |
for sheet_name, df in sheets.items():
|
| 1140 |
df.to_excel(writer, sheet_name=sheet_name, index=False)
|
| 1141 |
|
tests/test_process_ciq_2g_final_schema.py
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import io
|
| 2 |
+
from numbers import Integral
|
| 3 |
+
from unittest.mock import patch
|
| 4 |
+
|
| 5 |
+
import pandas as pd
|
| 6 |
+
from openpyxl import load_workbook
|
| 7 |
+
|
| 8 |
+
from queries.ciq_2g_schema_loader import (
|
| 9 |
+
BTS_AMR_FINAL_COLUMNS,
|
| 10 |
+
BTS_AMR_FINAL_DEFAULTS,
|
| 11 |
+
BTS_FINAL_COLUMNS,
|
| 12 |
+
BTS_FINAL_DEFAULTS,
|
| 13 |
+
BTS_GPRS_FINAL_COLUMNS,
|
| 14 |
+
BTS_GPRS_FINAL_DEFAULTS,
|
| 15 |
+
HOC_FINAL_COLUMNS,
|
| 16 |
+
HOC_FINAL_DEFAULTS,
|
| 17 |
+
POC_FINAL_COLUMNS,
|
| 18 |
+
POC_FINAL_DEFAULTS,
|
| 19 |
+
)
|
| 20 |
+
from queries.process_ciq_2g import (
|
| 21 |
+
_PlannedSite,
|
| 22 |
+
_build_bts_amr_sheet_from_bts,
|
| 23 |
+
_build_bts_gprs_sheet_from_bts,
|
| 24 |
+
_build_bts_sheet_from_assigned_sites,
|
| 25 |
+
_build_hoc_sheet_from_bts,
|
| 26 |
+
_build_poc_sheet_from_bts,
|
| 27 |
+
_get_excel_writer_engine,
|
| 28 |
+
apply_final_schema,
|
| 29 |
+
generate_ciq_2g_excel,
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def _sample_ciq_df() -> pd.DataFrame:
|
| 34 |
+
return pd.DataFrame(
|
| 35 |
+
[
|
| 36 |
+
{
|
| 37 |
+
"Sites": "0273_TBC_DIRE-HAMDALLAYE_2G",
|
| 38 |
+
"NOM_CELLULE": "0273_TBC_DIRE-HAMDALLAYE_1_900",
|
| 39 |
+
"Nbre_TRE_DR": 4,
|
| 40 |
+
"LAC": 30802,
|
| 41 |
+
"RAC": 1,
|
| 42 |
+
"CI": 2731,
|
| 43 |
+
"Frequence": "GSM900",
|
| 44 |
+
"BCCH": 5,
|
| 45 |
+
"TRX": "47,51,58",
|
| 46 |
+
"NCC": 5,
|
| 47 |
+
"BCC": 5,
|
| 48 |
+
"HSN": 56,
|
| 49 |
+
"MAIO": 0,
|
| 50 |
+
"Nom BSC": "ASBSCMSC3",
|
| 51 |
+
"BSC ID": 403703,
|
| 52 |
+
"band": "G9",
|
| 53 |
+
"sector": 1,
|
| 54 |
+
"site_number": 273,
|
| 55 |
+
},
|
| 56 |
+
{
|
| 57 |
+
"Sites": "0273_TBC_DIRE-HAMDALLAYE_2G",
|
| 58 |
+
"NOM_CELLULE": "0273_TBC_DIRE-HAMDALLAYE_1_1800",
|
| 59 |
+
"Nbre_TRE_DR": 3,
|
| 60 |
+
"LAC": 30802,
|
| 61 |
+
"RAC": 1,
|
| 62 |
+
"CI": 2734,
|
| 63 |
+
"Frequence": "GSM1800",
|
| 64 |
+
"BCCH": 879,
|
| 65 |
+
"TRX": "859,864",
|
| 66 |
+
"NCC": 3,
|
| 67 |
+
"BCC": 6,
|
| 68 |
+
"HSN": 54,
|
| 69 |
+
"MAIO": 0,
|
| 70 |
+
"Nom BSC": "ASBSCMSC3",
|
| 71 |
+
"BSC ID": 403703,
|
| 72 |
+
"band": "G18",
|
| 73 |
+
"sector": 1,
|
| 74 |
+
"site_number": 273,
|
| 75 |
+
},
|
| 76 |
+
]
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def _sample_assigned_sites() -> list[_PlannedSite]:
|
| 81 |
+
return [
|
| 82 |
+
_PlannedSite(
|
| 83 |
+
site_name="0273_TBC_DIRE-HAMDALLAYE_2G",
|
| 84 |
+
site_number=273,
|
| 85 |
+
bsc=403703,
|
| 86 |
+
bsc_name="ASBSCMSC3",
|
| 87 |
+
name="0273_TBC_DIRE-HAMDALLAYE_2G_NA",
|
| 88 |
+
configuration="G9-4, G18-3",
|
| 89 |
+
assigned_bcf=200,
|
| 90 |
+
needed_bts_ids=(201, 204),
|
| 91 |
+
)
|
| 92 |
+
]
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def _sample_bts_base_df() -> pd.DataFrame:
|
| 96 |
+
return _build_bts_sheet_from_assigned_sites(
|
| 97 |
+
_sample_ciq_df(), _sample_assigned_sites(), mcc=610, mnc=2
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def test_apply_final_schema_bts_keeps_core_values_and_adds_formula_and_derived_fields():
|
| 102 |
+
df_bts = _sample_bts_base_df()
|
| 103 |
+
|
| 104 |
+
final_df = apply_final_schema(df_bts, "BTS")
|
| 105 |
+
|
| 106 |
+
assert list(final_df.columns) == BTS_FINAL_COLUMNS
|
| 107 |
+
assert len(final_df.columns) == 109
|
| 108 |
+
assert list(final_df["site"]) == [273, 273]
|
| 109 |
+
assert list(final_df["btsId"]) == [201, 204]
|
| 110 |
+
assert list(final_df["template_name"]) == ["GSM900", "GSM1800"]
|
| 111 |
+
assert list(final_df["frequencyBandInUse"]) == [0, 1]
|
| 112 |
+
assert list(final_df["hoppingSequenceNumber1"]) == [56, 54]
|
| 113 |
+
assert list(final_df["segmentId"]) == ["=E2", "=E3"]
|
| 114 |
+
assert final_df.loc[0, "masterBCF"] == BTS_FINAL_DEFAULTS["masterBCF"]
|
| 115 |
+
assert (
|
| 116 |
+
final_df.loc[0, "gprsCapacityThroughputFactor"]
|
| 117 |
+
== BTS_FINAL_DEFAULTS["gprsCapacityThroughputFactor"]
|
| 118 |
+
)
|
| 119 |
+
assert isinstance(final_df.loc[0, "fddRscpMin"], Integral)
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def test_apply_final_schema_bts_gprs_adds_defaults_without_overriding_base_columns():
|
| 123 |
+
final_df = apply_final_schema(
|
| 124 |
+
_build_bts_gprs_sheet_from_bts(_sample_bts_base_df()), "BTS_GPRS"
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
assert list(final_df.columns) == BTS_GPRS_FINAL_COLUMNS
|
| 128 |
+
assert len(final_df.columns) == 56
|
| 129 |
+
assert list(final_df["Site"]) == [273, 273]
|
| 130 |
+
assert list(final_df["btsId"]) == [201, 204]
|
| 131 |
+
assert list(final_df["template_name"]) == ["All", "All"]
|
| 132 |
+
assert (
|
| 133 |
+
final_df.loc[0, "dedicatedGPRScapacity"]
|
| 134 |
+
== BTS_GPRS_FINAL_DEFAULTS["dedicatedGPRScapacity"]
|
| 135 |
+
)
|
| 136 |
+
assert final_df.loc[0, "nsei"] == ""
|
| 137 |
+
assert final_df.loc[0, "rac"] == BTS_GPRS_FINAL_DEFAULTS["rac"]
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def test_apply_final_schema_bts_amr_keeps_bscid_renamed_as_bscid_final_name():
|
| 141 |
+
final_df = apply_final_schema(
|
| 142 |
+
_build_bts_amr_sheet_from_bts(_sample_bts_base_df()), "BTS_AMR"
|
| 143 |
+
)
|
| 144 |
+
|
| 145 |
+
assert list(final_df.columns) == BTS_AMR_FINAL_COLUMNS
|
| 146 |
+
assert len(final_df.columns) == 53
|
| 147 |
+
assert list(final_df["bscId"]) == [403703, 403703]
|
| 148 |
+
assert list(final_df["template_name"]) == ["All", "All"]
|
| 149 |
+
assert (
|
| 150 |
+
final_df.loc[0, "amrConfFrCodecModeSet"]
|
| 151 |
+
== BTS_AMR_FINAL_DEFAULTS["amrConfFrCodecModeSet"]
|
| 152 |
+
)
|
| 153 |
+
assert (
|
| 154 |
+
final_df.loc[0, "radioLinkTimeoutAmr"]
|
| 155 |
+
== BTS_AMR_FINAL_DEFAULTS["radioLinkTimeoutAmr"]
|
| 156 |
+
)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def test_apply_final_schema_hoc_and_poc_keep_identifiers_and_defaults():
|
| 160 |
+
df_bts = _sample_bts_base_df()
|
| 161 |
+
hoc_df = apply_final_schema(_build_hoc_sheet_from_bts(df_bts), "HOC")
|
| 162 |
+
poc_df = apply_final_schema(_build_poc_sheet_from_bts(df_bts), "POC")
|
| 163 |
+
|
| 164 |
+
assert list(hoc_df.columns) == HOC_FINAL_COLUMNS
|
| 165 |
+
assert len(hoc_df.columns) == 87
|
| 166 |
+
assert list(hoc_df["hocId"]) == [1, 1]
|
| 167 |
+
assert hoc_df.loc[0, "enableSddchHandover"] == ""
|
| 168 |
+
assert hoc_df.loc[0, "enableUmbrellaHo"] == HOC_FINAL_DEFAULTS["enableUmbrellaHo"]
|
| 169 |
+
|
| 170 |
+
assert list(poc_df.columns) == POC_FINAL_COLUMNS
|
| 171 |
+
assert len(poc_df.columns) == 65
|
| 172 |
+
assert "pocId" not in poc_df.columns
|
| 173 |
+
assert list(poc_df["hocId"]) == [1, 1]
|
| 174 |
+
assert poc_df.loc[0, "alpha"] == POC_FINAL_DEFAULTS["alpha"]
|
| 175 |
+
assert (
|
| 176 |
+
poc_df.loc[0, "transmitPowerReduction"]
|
| 177 |
+
== POC_FINAL_DEFAULTS["transmitPowerReduction"]
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
def test_get_excel_writer_engine_prefers_xlsxwriter_then_openpyxl():
|
| 182 |
+
with patch("queries.process_ciq_2g.importlib.util.find_spec") as mock_find_spec:
|
| 183 |
+
mock_find_spec.side_effect = lambda name: object() if name == "xlsxwriter" else None
|
| 184 |
+
assert _get_excel_writer_engine() == "xlsxwriter"
|
| 185 |
+
|
| 186 |
+
with patch("queries.process_ciq_2g.importlib.util.find_spec") as mock_find_spec:
|
| 187 |
+
mock_find_spec.side_effect = lambda name: object() if name == "openpyxl" else None
|
| 188 |
+
assert _get_excel_writer_engine() == "openpyxl"
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def test_get_excel_writer_engine_raises_clear_error_when_missing():
|
| 192 |
+
with patch("queries.process_ciq_2g.importlib.util.find_spec", return_value=None):
|
| 193 |
+
try:
|
| 194 |
+
_get_excel_writer_engine()
|
| 195 |
+
except RuntimeError as exc:
|
| 196 |
+
assert "xlsxwriter" in str(exc)
|
| 197 |
+
assert "openpyxl" in str(exc)
|
| 198 |
+
else:
|
| 199 |
+
raise AssertionError("Expected RuntimeError when no Excel writer engine is installed")
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def test_generate_ciq_2g_excel_raises_clear_error_when_hsn_is_missing():
|
| 203 |
+
ciq_df = _sample_ciq_df().drop(columns=["HSN"])
|
| 204 |
+
|
| 205 |
+
with (
|
| 206 |
+
patch(
|
| 207 |
+
"queries.process_ciq_2g._read_dump_bts_required_columns",
|
| 208 |
+
return_value=pd.DataFrame(columns=["BSC", "BCF", "BTS", "usedMobileAllocation"]),
|
| 209 |
+
),
|
| 210 |
+
patch("queries.process_ciq_2g._read_ciq_df", return_value=ciq_df),
|
| 211 |
+
):
|
| 212 |
+
try:
|
| 213 |
+
generate_ciq_2g_excel(io.BytesIO(b"dump"), io.BytesIO(b"ciq"))
|
| 214 |
+
except ValueError as exc:
|
| 215 |
+
assert "missing required column: HSN" in str(exc)
|
| 216 |
+
assert "BTS.hoppingSequenceNumber1" in str(exc)
|
| 217 |
+
else:
|
| 218 |
+
raise AssertionError("Expected ValueError when HSN is missing")
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def test_generate_ciq_2g_excel_returns_finalized_target_sheets_only():
|
| 222 |
+
captured_sheet_names = []
|
| 223 |
+
captured_engine = None
|
| 224 |
+
|
| 225 |
+
class DummyWriter:
|
| 226 |
+
def __enter__(self):
|
| 227 |
+
return self
|
| 228 |
+
|
| 229 |
+
def __exit__(self, exc_type, exc, tb):
|
| 230 |
+
return False
|
| 231 |
+
|
| 232 |
+
def _capture_excel_writer(*args, **kwargs):
|
| 233 |
+
nonlocal captured_engine
|
| 234 |
+
captured_engine = kwargs.get("engine")
|
| 235 |
+
return DummyWriter()
|
| 236 |
+
|
| 237 |
+
def _capture_to_excel(self, writer, sheet_name=None, index=True, **kwargs):
|
| 238 |
+
captured_sheet_names.append(sheet_name)
|
| 239 |
+
|
| 240 |
+
with (
|
| 241 |
+
patch(
|
| 242 |
+
"queries.process_ciq_2g._read_dump_bts_required_columns",
|
| 243 |
+
return_value=pd.DataFrame(columns=["BSC", "BCF", "BTS", "usedMobileAllocation"]),
|
| 244 |
+
),
|
| 245 |
+
patch("queries.process_ciq_2g._read_ciq_df", return_value=_sample_ciq_df()),
|
| 246 |
+
patch("queries.process_ciq_2g._read_forbidden_bcfs", return_value=({}, pd.DataFrame())),
|
| 247 |
+
patch("queries.process_ciq_2g._assign_bcfs", return_value=_sample_assigned_sites()),
|
| 248 |
+
patch("queries.process_ciq_2g.importlib.util.find_spec") as mock_find_spec,
|
| 249 |
+
patch("queries.process_ciq_2g.pd.ExcelWriter", side_effect=_capture_excel_writer),
|
| 250 |
+
patch.object(pd.DataFrame, "to_excel", autospec=True, side_effect=_capture_to_excel),
|
| 251 |
+
):
|
| 252 |
+
mock_find_spec.side_effect = lambda name: object() if name == "xlsxwriter" else None
|
| 253 |
+
sheets, excel_bytes = generate_ciq_2g_excel(io.BytesIO(b"dump"), io.BytesIO(b"ciq"))
|
| 254 |
+
|
| 255 |
+
assert list(sheets["BTS"].columns) == BTS_FINAL_COLUMNS
|
| 256 |
+
assert list(sheets["BTS_GPRS"].columns) == BTS_GPRS_FINAL_COLUMNS
|
| 257 |
+
assert list(sheets["BTS_AMR"].columns) == BTS_AMR_FINAL_COLUMNS
|
| 258 |
+
assert list(sheets["HOC"].columns) == HOC_FINAL_COLUMNS
|
| 259 |
+
assert list(sheets["POC"].columns) == POC_FINAL_COLUMNS
|
| 260 |
+
assert len(sheets["MAL"].columns) == 16
|
| 261 |
+
assert len(sheets["TRX"].columns) == 78
|
| 262 |
+
assert captured_sheet_names == [
|
| 263 |
+
"BCF",
|
| 264 |
+
"BCF_LIBRE",
|
| 265 |
+
"BTS",
|
| 266 |
+
"BTS_GPRS",
|
| 267 |
+
"BTS_AMR",
|
| 268 |
+
"HOC",
|
| 269 |
+
"POC",
|
| 270 |
+
"MAL",
|
| 271 |
+
"BTS_PLMNPERMITTED",
|
| 272 |
+
"TRX",
|
| 273 |
+
]
|
| 274 |
+
assert captured_engine == "xlsxwriter"
|
| 275 |
+
assert isinstance(excel_bytes, bytes)
|
| 276 |
+
assert list(sheets["BTS"]["segmentId"]) == ["=E2", "=E3"]
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
def test_generate_ciq_2g_excel_writes_real_workbook_with_segmentid_formula():
|
| 280 |
+
with (
|
| 281 |
+
patch(
|
| 282 |
+
"queries.process_ciq_2g._read_dump_bts_required_columns",
|
| 283 |
+
return_value=pd.DataFrame(columns=["BSC", "BCF", "BTS", "usedMobileAllocation"]),
|
| 284 |
+
),
|
| 285 |
+
patch("queries.process_ciq_2g._read_ciq_df", return_value=_sample_ciq_df()),
|
| 286 |
+
patch("queries.process_ciq_2g._read_forbidden_bcfs", return_value=({}, pd.DataFrame())),
|
| 287 |
+
patch("queries.process_ciq_2g._assign_bcfs", return_value=_sample_assigned_sites()),
|
| 288 |
+
):
|
| 289 |
+
sheets, excel_bytes = generate_ciq_2g_excel(io.BytesIO(b"dump"), io.BytesIO(b"ciq"))
|
| 290 |
+
|
| 291 |
+
assert isinstance(excel_bytes, bytes)
|
| 292 |
+
assert len(excel_bytes) > 0
|
| 293 |
+
assert list(sheets["BTS"]["segmentId"]) == ["=E2", "=E3"]
|
| 294 |
+
|
| 295 |
+
workbook = load_workbook(io.BytesIO(excel_bytes), data_only=False)
|
| 296 |
+
ws_bts = workbook["BTS"]
|
| 297 |
+
headers = [cell.value for cell in ws_bts[1]]
|
| 298 |
+
segment_col_idx = headers.index("segmentId") + 1
|
| 299 |
+
btsid_col_idx = headers.index("btsId") + 1
|
| 300 |
+
btsid_col_letter = ws_bts.cell(1, btsid_col_idx).column_letter
|
| 301 |
+
|
| 302 |
+
assert ws_bts.cell(2, segment_col_idx).value == f"={btsid_col_letter}2"
|
| 303 |
+
assert ws_bts.cell(3, segment_col_idx).value == f"={btsid_col_letter}3"
|