026 ceiling
This commit is contained in:
+2
-2
@@ -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()/>
|
||||||
|
|
||||||
|
|||||||
@@ -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',''),
|
||||||
|
('','')
|
||||||
|
)
|
||||||
@@ -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
@@ -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/>
|
||||||
|
|
||||||
|
|||||||
@@ -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 раз или ни разу --->
|
||||||
|
|||||||
Reference in New Issue
Block a user