026 ceiling

This commit is contained in:
2026-07-28 12:38:02 +03:00
parent 849a4c2796
commit e8df23c2e2
5 changed files with 31 additions and 70 deletions
+2 -2
View File
@@ -8,7 +8,7 @@
<!--- Set up the application. ---> <!--- Set up the application. --->
<cfset this.Name = "PAYG-REPORT" /> <cfset this.Name = "PAYG-REPORT" />
<cfset this.applicationTimeout = createTimeSpan( 0, 3, 0, 0 ) /> <cfset this.applicationTimeout = createTimeSpan( 0, 3, 0, 0 ) />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 0, 10 ) /> <cfset this.requestTimeout = createTimeSpan( 0, 0, 2, 0 )/>
<cfset this.sessionmanagement="Yes"/> <cfset this.sessionmanagement="Yes"/>
<cfset this.clientmanagement="No"/> <cfset this.clientmanagement="No"/>
<cfset this.sessiontimeout=CreateTimeSpan(0, 1, 0, 0)/> <cfset this.sessiontimeout=CreateTimeSpan(0, 1, 0, 0)/>
@@ -94,7 +94,7 @@
<!--- global settings ---> <!--- global settings --->
<cfset request.RECORDS_PER_PAGE=500/> <cfset request.RECORDS_PER_PAGE=500/>
<cfset request.APP_VERSION="0.00.024"/> <cfset request.APP_VERSION="0.00.026"/>
<cfheader name="X-Application-Version" value=#request.APP_VERSION#/> <cfheader name="X-Application-Version" value=#request.APP_VERSION#/>
<cfset request.STAND=getStand()/> <cfset request.STAND=getStand()/>
+10
View File
@@ -0,0 +1,10 @@
pvdc_map(pvdc,code) as (VALUES
('v1cl1-vsan-pvdc',''),
('v1cl2-pvdc',''),
('v2cl2-1c-pvdc',''),
('v1cl4-vsan-pvdc',''),
('v1cl6-vsan-pvdc',''),
('v1cl7-vsan-pvdc',''),
('hystax-pvdc',''),
('','')
)
+2 -59
View File
@@ -4,64 +4,7 @@
<cfset hours=dateDiff('h',dt_start,dt_finish)/> <cfset hours=dateDiff('h',dt_start,dt_finish)/>
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ ---> <cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->
<!--- <cffunction name="snake2camel"
returntype="string"
output="false"
hint="convert snake style name to camel style name">
<cfargument name="snake" type="string" required="true" />
<cfreturn #reReplace(ARGUMENTS.snake,"_([a-z])","\u\1","ALL")#/>
</cffunction>
<cffunction name="camel2snake"
returntype="string"
output="false"
hint="convert camel style name to snake style name">
<cfargument name="camel" type="string" required="true" />
<cfreturn #reReplace(ARGUMENTS.camel,"([A-Z])","_\l\1","ALL")#/>
</cffunction>
<cffunction name="iso8601dtFormat"
returntype="string"
output="false"
hint="formates date and time like this: 2023-12-18T15:41:42.516+0300">
<cfargument name="input" required="true" />
<cfreturn "#dateFormat( input, "yyyy-mm-dd" )#T#timeFormat( input, "HH:mm:ss.lXX" )#"/>
</cffunction>
<cffunction name="query2array"
output="false"
hint="print query in json format as array of structures">
<cfargument name="qry" type="query" required="true"/><!--- column names should not contain commas --->
<cfargument name="convertSnakeToCamel" type="boolean" default=true/>
<cfset var columnsIn=#arguments.qry.columnList()#/>
<cfset var columnsOut=""/>
<cfif arguments.convertSnakeToCamel>
<cfloop list=#columnsIn# item="col">
<cfset columnsOut=listAppend(columnsOut,snake2camel(lcase(col)))/>
</cfloop>
<cfset var outArray=arrayNew(1)/>
<!--- //copy fields to structure, renaming fields, this preserves data type --->
<cfloop query=#arguments.qry#>
<cfset var structRow=structNew()/>
<cfloop index="i" from="1" to=#listLen(columnsOut)#>
<cfset structInsert(structRow,"#listGetAt(#columnsOut#,i)#",arguments.qry["#listGetAt(#columnsIn#,i)#"])/>
</cfloop>
<cfset arrayAppend(outArray,structRow)/>
</cfloop>
<!--- <cfdump var=#outArray#/> --->
<cfreturn outArray/>
<cfelse>
<cfreturn #arguments.qry.reduce((result, row) => {
result.append(row);
return result;
}, [])#/>
</cfif>
</cffunction> --->
<cfscript> <cfscript>
function gaussianRound(numeric number, numeric precision = 0) { function gaussianRound(numeric number, numeric precision = 0) {
@@ -117,7 +60,7 @@ function gaussianRound(numeric number, numeric precision = 0) {
<!--- <cfset var accum_metric_component = 0/> ---> <!--- <cfset var accum_metric_component = 0/> --->
<cfset "temp.service"=["svc"="#svc#" <cfset "temp.service"=["svc"="#svc#"
,"serviceСode"="#service_code#" ,"serviceCode"="#service_code#"
,"serviceCustomName"="#serviceCustomName#" ,"serviceCustomName"="#serviceCustomName#"
<!--- ,"note"="#(serviceHash EQ '')?'не найдено в договоре':''#" ---> <!--- ,"note"="#(serviceHash EQ '')?'не найдено в договоре':''#" --->
,"hash"="#serviceHash#" ,"hash"="#serviceHash#"
@@ -155,7 +98,7 @@ function gaussianRound(numeric number, numeric precision = 0) {
</cfoutput><!--- dimension_1 ---> </cfoutput><!--- dimension_1 --->
<!--- считаем, что free_tier NOT NULL (вместо NULL 0) ---> <!--- считаем, что free_tier NOT NULL (вместо NULL 0) --->
<cfset var payable_metric_dimension_1 = (isNumeric(accum_metric_dimension_1))? round(max(accum_metric_dimension_1 - free_tier, 0),3):javaCast("null",0)/> <cfset var payable_metric_dimension_1 = (isNumeric(accum_metric_dimension_1))? max(ceiling(accum_metric_dimension_1) - free_tier, 0):javaCast("null",0)/>
<cfset var cost_dimension_1 = precisionEvaluate("gaussianRound(payable_metric_dimension_1*gaussianRound(discounted_price, 2), 2)")/> <cfset var cost_dimension_1 = precisionEvaluate("gaussianRound(payable_metric_dimension_1*gaussianRound(discounted_price, 2), 2)")/>
<cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/> <cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/>
+13 -6
View File
@@ -186,13 +186,20 @@ from a
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/> where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/> --AND 1=0
AND capacity_storage.timestamp::date >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_start#/> AND capacity_storage.timestamp::date >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_start#/>
AND capacity_storage.timestamp::date <= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_finish#/> AND capacity_storage.timestamp::date <= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_finish#/>
group by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date group by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date
order by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date; order by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date
;
</cfquery> </cfquery>
<!--- create index IX_capacity_storage_sort on ngcloud_ru.capacity_storage(vdc_id,storage_profile_types_id,timestamp); --->
<cfif (ATTRIBUTES.debug)>
qStorage
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
<cfdump var=#qStorage#/>
<cfflush/>
</cfif>
<!--- <!---
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb" "placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
@@ -466,7 +473,7 @@ from a
<!--- Здесь агрегировано за месяц, но детализировано по измерениям ---> <!--- Здесь агрегировано за месяц, но детализировано по измерениям --->
<cfquery name="qChargeMonthly" dbType="query"> <cfquery name="qChargeMonthly" dbType="query">
SELECT SELECT
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount"> <d:field_set titleMapOut="chargeTitleMap" lengthOut="chargeFieldCount">
<d:field title="Артикул по договору">s_code</d:field> <d:field title="Артикул по договору">s_code</d:field>
<d:field title="Артикул по системам">m_code</d:field> <d:field title="Артикул по системам">m_code</d:field>
<d:field title="Артикул">s_code as code</d:field> <d:field title="Артикул">s_code as code</d:field>
@@ -538,8 +545,8 @@ from a
<cfset report.qSpecification = qSpecification/> <cfset report.qSpecification = qSpecification/>
<cfset report.qCharge = qChargeMonthly/> <cfset report.qCharge = qChargeMonthly/>
<cfset report.qFreeTier = qFreeTier/><!--- мы не применяем скидку на уровне детализации, а только после агрегации. На самом деле правильно было бы агрегировать натуральные метрики, а умножать на цену уже агрегаты ---> <cfset report.qFreeTier = qFreeTier/><!--- мы не применяем скидку на уровне детализации, а только после агрегации. На самом деле правильно было бы агрегировать натуральные метрики, а умножать на цену уже агрегаты --->
<!--- <cfset report.chargeTitleMap = titleMap/> <cfset report.chargeTitleMap = chargeTitleMap/><!--- нужен для экспорта в XL --->
<cfset report.chargeFieldCount = fieldCount/> ---> <!--- <cfset report.chargeFieldCount = chargeFieldCount/> --->
<cfset "CALLER.#ATTRIBUTES.output#" = report/> <cfset "CALLER.#ATTRIBUTES.output#" = report/>
+4 -3
View File
@@ -29,7 +29,8 @@
output="report" output="report"
debug=#isDefined("DEBUG")# debug=#isDefined("DEBUG")#
restrict_to_own_instances=#restrict_to_own_instances# restrict_to_own_instances=#restrict_to_own_instances#
/><layout:xml qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.xml"/> />
<layout:xml qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.xml"/>
<cfabort/> <cfabort/>
</cfif><cfif isDefined("output_json")><cfmodule template="mod/compute_payg.cfm" </cfif><cfif isDefined("output_json")><cfmodule template="mod/compute_payg.cfm"
dt_finish=#dt_finish# dt_finish=#dt_finish#
@@ -103,7 +104,7 @@ S3 операции и трафик: <b<cfif datediff("h",report.qS3OpsTrfAge.dt
#dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')# #dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')#
</b> </b>
<br/> <br/>
Цены по данным договора из CRM (через elma-cache). Учитываются метрики по S3, vCloud (кроме GPU) Цены по данным договора из CRM (через elma-cache). Учитываются метрики по S3, vCloud (кроме GPU). Внимание! количество за период *** округляется вверх, но делается это после всех агрегаций.
<br/> <br/>
@@ -209,7 +210,7 @@ S3 операции и трафик: <b<cfif datediff("h",report.qS3OpsTrfAge.dt
<td colspan="4">Итого #code# <cfif code EQ "">(#m_code#)</cfif>:</td> <td colspan="4">Итого #code# <cfif code EQ "">(#m_code#)</cfif>:</td>
<td class="r"><cfif accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1)>#round(accum_metric_dimension_1,3)#</cfif></td> <td class="r"><cfif accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1)>#round(accum_metric_dimension_1,3)#</cfif></td>
<td class="r">#free_tier#</td> <td class="r">#free_tier#</td>
<td class="r" style="font-size:120%; padding:0 1em;"><cfif accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1)>#round(max(accum_metric_dimension_1 - free_tier, 0),3)#</cfif></td> <td class="r" style="font-size:120%; padding:0 1em;"><cfif accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1)>#max(ceiling(accum_metric_dimension_1) - free_tier, 0)#</cfif></td>
<td class="c">#unit#</td> <td class="c">#unit#</td>
<td class="r">#gaussianRound(discounted_price,2)#</td><!--- если цена менялась в периоде, неправильно показыввать последнюю - но мы не тестировали с изменением в периоде ---> <td class="r">#gaussianRound(discounted_price,2)#</td><!--- если цена менялась в периоде, неправильно показыввать последнюю - но мы не тестировали с изменением в периоде --->
<!--- непонятно, как вычитать Free Tier для неполных месяцев. Если с 15 по 15 - вычитать 2 раза, вычитать (каким-то сложным образом) 1 раз или ни разу ---> <!--- непонятно, как вычитать Free Tier для неполных месяцев. Если с 15 по 15 - вычитать 2 раза, вычитать (каким-то сложным образом) 1 раз или ни разу --->