059 inmem full join with spec

This commit is contained in:
2026-07-26 23:01:27 +03:00
parent 59bf109ba5
commit 274643ed28
6 changed files with 342 additions and 154 deletions
+16 -3
View File
@@ -6,7 +6,7 @@
<!--- Set up the application. ---> <!--- Set up the application. --->
<cfset this.Name = "PAYG" /> <cfset this.Name = "PAYG" />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 3, 0 ) /> <cfset this.applicationTimeout = createTimeSpan( 0, 1, 0, 0 ) />
<cfset this.sessionmanagement="Yes"/> <cfset this.sessionmanagement="Yes"/>
<cfset this.clientmanagement="No"/> <cfset this.clientmanagement="No"/>
<cfset this.sessiontimeout=CreateTimeSpan(0, 0, 120, 0)/> <cfset this.sessiontimeout=CreateTimeSpan(0, 0, 120, 0)/>
@@ -25,10 +25,23 @@
<!--- но датасорцы таинственно прочухались с прошлым пушем, без переноса инициализации в псевдоконструктор ---> <!--- но датасорцы таинственно прочухались с прошлым пушем, без переноса инициализации в псевдоконструктор --->
<!--- а потом опять... ---> <!--- а потом опять... --->
<cfset this.datasources["inmem"] = {
class: "org.hsqldb.jdbcDriver",
// Внимание наjdbc:hsqldb:mem:
connectionString: "jdbc:hsqldb:mem:lucee_mem;shutdown=false",
username: "sa",
password: "",
// Защита от "висяка" и исчезновения базы:
// заставляем Lucee держать минимум 1 коннект открытым всегда
connectionLimit: 5,
connectionMin: 1
}
/><!--- inmemory DB --->
<cfset COOKIEENCKEY = "PREVED!Y2"/> <cfset COOKIEENCKEY = "PREVED!Y2"/>
<!--- Define the page request properties. ---> <!--- Define the page request properties. --->
<cfsetting <cfsetting
requesttimeout="20" requesttimeout="45"
showdebugoutput="false" showdebugoutput="false"
enablecfoutputonly="false" enablecfoutputonly="false"
/> />
@@ -76,7 +89,7 @@
<!--- global settings ---> <!--- global settings --->
<cfset request.RECORDS_PER_PAGE=500/> <cfset request.RECORDS_PER_PAGE=500/>
<cfset request.APP_VERSION="0.00.058"/> <cfset request.APP_VERSION="0.00.059"/>
<cfset request.STAND=getStand()/> <cfset request.STAND=getStand()/>
<cflock scope="application" type="readonly" timeout=3> <cflock scope="application" type="readonly" timeout=3>
+98
View File
@@ -0,0 +1,98 @@
component {
/**
* HSQL 1.8
* Принимает Lucee Query, создает в HSQL временную таблицу и льет в нее данные
* @name Имя таблицы, которое ты хочешь использовать в SQL
* @data Сам запрос (результат queryExecute или cfhttp)
* @dsn Имя datasource для HSQL (по умолчанию "inmem")
*/
public string function register(required string name, required query data, string dsn = "inmem") {
var cols = arguments.data.columnList;
var meta = getMetaData(arguments.data);
//writedump(meta);
var colDefs = [];
var colTypes = {};
var params = [];
// 1. Генерируем "CREATE TEMP TABLE name (col1 TYPE, col2 TYPE...)"
for (var i = 1; i <= arrayLen(meta); i++) {
var colName = meta[i].name;
// Маппинг типов Lucee -> типы H2
var dbType = mapType(meta[i].typeName);
arrayAppend(colDefs, "#colName# #dbType#");
colTypes[colName] = meta[i].typeName;
}
//writedump(colDefs);
//var checkSql = "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_TABLES WHERE TABLE_NAME = '#ucase(arguments.name)#';"
//var res = queryExecute(checkSql, {}, { datasource: arguments.dsn });
//if (res.recordCount EQ 0) {
var createSql = "DROP TABLE IF EXISTS #arguments.name#;
CREATE TEMPORARY TABLE #arguments.name#(#arrayToList(colDefs, ', ')#) ON COMMIT PRESERVE ROWS";
queryExecute(createSql, {}, { datasource: arguments.dsn });
//}
// 2. Цикл вставки
var insertSql = "INSERT INTO #arguments.name# (#cols#) VALUES (#repeatString("?,", listLen(cols)-1)#?)";
for (var row in arguments.data) {
var rowData = [];
for (var col in cols) {
arrayAppend(rowData, formatValue(row[col], colTypes[col]));
}
queryExecute(insertSql, rowData, { datasource: arguments.dsn });
}
return arguments.name;
}
/**
* Удалить временные таблицы (опционально, база сама почистит при закрытии коннекта)
*/
public void function drop(required string names, string dsn = "inmem") {
var list = arguments.names;
if (!isArray(list)) list = [list];
for (var name in list) {
queryExecute("DROP TABLE IF EXISTS #name#", {}, { datasource: arguments.dsn });
}
}
// --- Вспомогательная функция маппинга типов ---
private string function mapType(required string luceeType) {
switch (arguments.luceeType) {
case "VARCHAR": case "CHAR": case "LONGVARCHAR": return "LONGVARCHAR";
case "INTEGER": case "BIGINT": case "SMALLINT": case "TINYINT": return "INT";
case "DOUBLE": case "FLOAT": case "REAL": return "DOUBLE";
case "BOOLEAN": case "BIT": return "BIT";
case "DECIMAL": case "NUMERIC": return "DECIMAL(20,6)";
default: return "LONGVARCHAR"; // И тут тоже
}
}
private function formatValue(required any val, required string targetType) {
var isTextType = listFindNoCase("VARCHAR,CHAR,LONGVARCHAR", arguments.targetType);
// 1. Обработка пустых значений
if (isNull(arguments.val) || (isSimpleValue(arguments.val) && len(trim(arguments.val)) == 0)) {
// Если это текстовое поле — сохраняем пустую строку как есть
if (isTextType) {
return "";
}
// Для чисел, дат и булев — отдаем настоящий SQL NULL
return javaCast("null", "");
}
// 2. Форматирование непустых дат
if (listFindNoCase("DATE,TIMESTAMP,TIME", arguments.targetType)) {
return dateFormat(arguments.val, "yyyy-mm-dd") & " " & timeFormat(arguments.val, "HH:mm:ss");
}
// 3. Числа и непустой текст отдаем как есть
return arguments.val;
}
}
+1 -1
View File
@@ -246,7 +246,7 @@
<cfcase value=3>-m</cfcase> <cfcase value=3>-m</cfcase>
</cfswitch> ---> </cfswitch> --->
</td> </td>
<td class="c">#type#</td> <td class="c"<cfif type EQ 3> style="background:lightgreen"</cfif>>#type#</td>
<td class="c">#is_actual#</td> <td class="c">#is_actual#</td>
<td class="c">#hash#</td> <td class="c">#hash#</td>
<td class="c">#version#</td> <td class="c">#version#</td>
+23 -17
View File
@@ -62,6 +62,7 @@
<cfif len(d.__id)> <cfif len(d.__id)>
<b>#d.__name#</b> <b>#d.__name#</b>
[#d.__id#] [#d.__id#]
<b>#d.id_klienta#</b>
</cfif> </cfif>
</cfoutput> </cfoutput>
</layout:attribute> </layout:attribute>
@@ -235,7 +236,7 @@
<!--- <cfdump var=#qService#/> ---> <!--- <cfdump var=#qService#/> --->
<cfoutput> <cfoutput>
<h3>Услуги по данным CRM (версии строк спецификации, только актуальные на сегодня, сделки с вероятностью от 50% (начиная с тестирования) <!--- (#qService.recordCount#) ---></h3> <h3>Услуги по данным CRM (из DWH, версии строк спецификации, только актуальные на сегодня, сделки с вероятностью от 50% (начиная с тестирования) <!--- (#qService.recordCount#) ---></h3>
</cfoutput> </cfoutput>
@@ -265,7 +266,7 @@
<td class="l">#user_description#</td> <td class="l">#user_description#</td>
<td style="padding:0; vertical-align:bottom;"> <td style="padding:0; vertical-align:bottom;">
<table class="wide" style="height:100%"> <table class="wide" style="height:100%">
<cfset cost=0/> <cfset cost = 0/>
<cfoutput group="p_uid"> <cfoutput group="p_uid">
<cfif p_cnt NEQ 0> <cfif p_cnt NEQ 0>
<tr> <tr>
@@ -283,7 +284,7 @@
<td class="c">#cnt#</td> <td class="c">#cnt#</td>
<td class="r">#nFmt(cost*cnt*(100-(isNumeric(discount)?discount:0))/100)#</td> <td class="r">#nFmt(cost*cnt*(100-(isNumeric(discount)?discount:0))/100)#</td>
<td class="c"> <td class="c"<cfif line_pricing_model_id EQ 3> style="background:lightgreen;color:black;"</cfif>>
<cfswitch expression=#line_pricing_model_id#> <cfswitch expression=#line_pricing_model_id#>
<cfcase value=1>install</cfcase> <cfcase value=1>install</cfcase>
<cfcase value=2>fix</cfcase> <cfcase value=2>fix</cfcase>
@@ -301,6 +302,7 @@
</cfoutput> </cfoutput>
</table> </table>
<!--- <i>отображаются позиции сделок, начиная с тестирования</i> ---> <!--- <i>отображаются позиции сделок, начиная с тестирования</i> --->
<h2>Текущее потребление по данным VmReports (VROPS)</h1>
<cfquery name="qCompute"> <cfquery name="qCompute">
select select
@@ -309,13 +311,14 @@
,c."VDC" ,c."VDC"
,c."VDC_CPU_Reserv" ,c."VDC_CPU_Reserv"
,"Cluster" ,"Cluster"
, round(sum(c."VM_RAM_Allocated")) as ram ,round(sum(c."VM_RAM_Allocated")) as ram
, round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_RAM_Allocated" ELSE 0 END)) as ram_on ,round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_RAM_Allocated" ELSE 0 END)) as ram_on
, round(sum(c."VM_vCPU_count")) as cpu ,round(sum(c."VM_vCPU_count")) as cpu
, round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_vCPU_count" ELSE 0 END)) as cpu_on ,round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_vCPU_count" ELSE 0 END)) as cpu_on
, round(avg(c."VDC_CPU_Speed")::numeric,1) as ghz ,round(avg(c."VDC_CPU_Speed")::numeric,1) as ghz
,min(c.ts) as ts
FROM vmreports.compute c FROM vmreports.compute c
WHERE ts=(select max(ts) from vmreports.compute) WHERE c.ts=(select max(ts) from vmreports.compute)
AND lower(c."WZ")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>) AND lower(c."WZ")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>)
GROUP BY c."Organization_UUID", c."Organization", c."VDC", c."VDC_CPU_Reserv", c."Cluster" GROUP BY c."Organization_UUID", c."Organization", c."VDC", c."VDC_CPU_Reserv", c."Cluster"
</cfquery> </cfquery>
@@ -329,7 +332,7 @@
FROM qCompute FROM qCompute
</cfquery> </cfquery>
<h3>Compute факт</h3> <h3>Compute факт <cfif len(qCompute.ts)><cfoutput>#dateFormat(qCompute.ts,'YYYY-MM-DD')# #timeFormat(qCompute.ts,'HH:MM:SS')#</cfoutput></cfif></h3>
<table class="worktable"> <table class="worktable">
<thead> <thead>
<tr> <tr>
@@ -379,10 +382,11 @@
,"VDC" ,"VDC"
,"Cluster" ,"Cluster"
,"Storage_Policy" ,"Storage_Policy"
, round(sum(c."Disk_Allocated")) as disk_alloc ,round(sum(c."Disk_Allocated")) as disk_alloc
, round(sum(c."Disk_Used")) as disk_used ,round(sum(c."Disk_Used")) as disk_used
,min(c.ts) as ts
FROM vmreports.storage c FROM vmreports.storage c
WHERE ts=(select max(ts) from vmreports.storage) WHERE c.ts=(select max(ts) from vmreports.storage)
AND lower(c."WZ")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>) AND lower(c."WZ")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>)
GROUP BY c."Organization_UUID",c."Organization",c."VDC",c."Cluster",c."Storage_Policy" GROUP BY c."Organization_UUID",c."Organization",c."VDC",c."Cluster",c."Storage_Policy"
</cfquery> </cfquery>
@@ -394,7 +398,7 @@
FROM qStorage FROM qStorage
</cfquery> </cfquery>
<h3>Storage факт</h3> <h3>Storage факт <cfif len(qStorage.ts)><cfoutput>#dateFormat(qStorage.ts,'YYYY-MM-DD')# #timeFormat(qStorage.ts,'HH:MM:SS')#</cfoutput></cfif></h3>
<table class="worktable"> <table class="worktable">
<thead> <thead>
<tr> <tr>
@@ -436,17 +440,19 @@
,"OrgVDC" ,"OrgVDC"
,(select STRING_AGG(DISTINCT "Cluster",',') FROM vmreports.compute c ,(select STRING_AGG(DISTINCT "Cluster",',') FROM vmreports.compute c
WHERE ts=(select max(ts) from vmreports.compute) WHERE ts=(select max(ts) from vmreports.compute)
AND g."Org"=c."Organization") as org_cluster AND g."Org"=c."Organization"
) as org_cluster
,"Name" ,"Name"
,"GPU" ,"GPU"
,g.ts as ts
FROM vmreports.vm_gpu g FROM vmreports.vm_gpu g
WHERE ts=(select max(ts) from vmreports.vm_gpu) WHERE g.ts=(select max(ts) from vmreports.vm_gpu)
AND lower(g."ClientID")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>) AND lower(g."ClientID")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>)
</cfquery> </cfquery>
<h3>GPU факт</h3> <h3>GPU факт <cfif len(qGpu.ts)><cfoutput>#dateFormat(qGpu.ts,'YYYY-MM-DD')# #timeFormat(qGpu.ts,'HH:MM:SS')#</cfoutput></cfif></h3>
<table class="worktable"> <table class="worktable">
<thead> <thead>
<tr> <tr>
+179 -128
View File
@@ -7,18 +7,16 @@
<m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/> <m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<!---
<cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/> <cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/> <cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/> --->
<cfset hours=dateDiff('h',dt_start,dt_finish)/> <cfparam name="dt_finish" type="date" default=#dateAdd('d',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
<cfset hours=dateDiff('h', dt_start, dateAdd('d', 1, dt_finish))/>
<cfparam name="only_articles_in_spec" type="boolean" default=false/>
<!--- Нужно еще применить политики бесплатного минимума --->
<!--- *** коды лучше взять из каталога ---> <!--- *** коды лучше взять из каталога --->
<cfquery name="qCode" datasource="dwh"> <cfquery name="qCode" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select distinct p.code select distinct p.code
from elma.deals d from elma.deals d
join elma.deals_services siv on (d.__id=ANY(siv.deal)) join elma.deals_services siv on (d.__id=ANY(siv.deal))
@@ -29,22 +27,26 @@
where p.type=3 AND aa.is_actual where p.type=3 AND aa.is_actual
order by p.code order by p.code
</cfquery> </cfquery>
<cfoutput>qCode:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- <cfdump var=#qCode#/> ---> <!--- <cfdump var=#qCode#/> --->
<cfquery name="qContragent" datasource="dwh"> <cfquery name="qContragent" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select k.id_klienta as wz, k.__id::text as contragent_uid, k.__name as contragent select k.id_klienta as wz, k.__id::text as contragent_uid, k.__name as contragent
from elma.companies k from elma.companies k
where k."__deletedAt" IS NULL where k."__deletedAt" IS NULL
</cfquery> </cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/> <cfoutput>qContragent:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- <cfif isDefined("DEBUG")>
<cfdump var=#qContragent#/>
<cfflush/>
</cfif> --->
<!--- нужны компании, которые есть в пейге ---> <!--- нужны компании, которые есть в пейге --->
<cfquery name="qSpec" datasource="dwh">
<cfquery name="qSpec" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select k.id_klienta as wz, k.__id::text as contragent_uid, p.code, p.price, p.discount, k.__name as contragent, a.__name as contract, a.__id::text as contract_uid, d.__name as deal, d.__id::text as deal_uid, siv.abstractive_service as abstract_service, siv.modifier, siv.user_description, siv.hash as line_key select k.id_klienta as wz, k.__id::text as contragent_uid, p.code, p.price, p.discount, k.__name as contragent, a.__name as contract, a.__id::text as contract_uid, d.__name as deal, d.__id::text as deal_uid, siv.abstractive_service as abstract_service, siv.modifier, siv.user_description, siv.hash as line_key
,siv.date_nop as dt_from, siv.date_end as dt_to ,siv.date_nop as dt_from, siv.date_end as dt_to, siv.discount as service_discount, siv.cnt as service_quantity
/*,p.__name as line_key*/, p.ed_izm, p.name as component, aa.__name as additional_agreement, aa.__id::text as additional_agreement_uid /*,p.__name as line_key*/, p.ed_izm, p.name as component, p.type, aa.__name as additional_agreement, aa.__id::text as additional_agreement_uid
--, aa.is_actual --, aa.is_actual
from elma.deals d from elma.deals d
join elma.deals_services siv on (d.__id=ANY(siv.deal)) join elma.deals_services siv on (d.__id=ANY(siv.deal))
@@ -52,35 +54,34 @@
join elma.companies k on (d._companies=k.__id) join elma.companies k on (d._companies=k.__id)
join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement)) join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement))
join elma.aggrements a on (aa.contract_uid = a.__id) join elma.aggrements a on (aa.contract_uid = a.__id)
where p.type=3 AND aa.is_actual where p.type IN (2,3) AND aa.is_actual
AND siv.date_nop < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/> AND siv.date_nop < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND (siv.date_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL) AND (siv.date_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL)/*****/
order by k.id_klienta, p.code order by k.id_klienta, p.code
</cfquery> </cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- siv means specification item version --->
<cfquery name="qSivAge" datasource="dwh">
select max(dt_load) as dt_load from elma.deals_services
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- здесь имеем список кодов с ценами и WZ. Каждому коду можно поставить в соответствие запрос, который даст по нему выборку. Изредка один запрос может вывести 2 кода, но разбить на 2 запроса легко. Кроме того, запросы можно объединить через union в один - может быть, так будет лучше читаться (быстрее выполняться не будет) ---> <!--- здесь имеем список кодов с ценами и WZ. Каждому коду можно поставить в соответствие запрос, который даст по нему выборку. Изредка один запрос может вывести 2 кода, но разбить на 2 запроса легко. Кроме того, запросы можно объединить через union в один - может быть, так будет лучше читаться (быстрее выполняться не будет) --->
<cfoutput>qSpec:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfif isDefined("DEBUG")> <cfif isDefined("DEBUG")>
<cfdump var=#qSpec#/> <cfdump var=#qSpec#/>
<cfflush/> <cfflush/>
</cfif> </cfif>
<!--- siv means specification item version --->
<cfquery name="qSivAge" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(dt_load) as dt_load from elma.deals_services
</cfquery>
<cfoutput>qSivAge:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qComputing" datasource="billing-vc">
<cfquery name="qComputing" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select m.clientid as wz, vdc.name as vdc_name, select m.clientid as wz, vdc.name as vdc_name,
case case
when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29' WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31' WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28' WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28' WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера
else '['||vdc.name||']' end as code, else '['||vdc.name||']' end as code,
sum(cpu_used/cpu_speed)/4. as core_h, sum(cpu_used/cpu_speed)/4. as core_h,
sum(mem_used)/1024/4. as gb_h sum(mem_used)/1024/4. as gb_h
@@ -94,44 +95,47 @@
) tm on (t.id = tm.tenant_id AND tm.rn = 1) ) tm on (t.id = tm.tenant_id AND tm.rn = 1)
left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id) left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id)
where length(m.clientid) > 0 where length(m.clientid) > 0
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> AND capacity_resource.timestamp::date >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/> AND capacity_resource.timestamp::date <= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by m.clientid, vdc.name group by m.clientid, vdc.name
order by m.clientid, vdc.name; order by m.clientid, vdc.name;
</cfquery> </cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/> <cfoutput>qComputing:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfif isDefined("DEBUG")> <cfif isDefined("DEBUG")>
<cfdump var=#qComputing#/> <cfdump var=#qComputing#/>
<cfflush/> <cfflush/>
</cfif> </cfif>
<cfquery name="qComputingAge" datasource="billing-vc"> <cfquery name="qComputingAge" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
</cfquery> </cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/> <cfoutput>qComputingAge:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода ---> <!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
<cfquery name="qStorage" datasource="billing-vc"> <cfquery name="qStorage" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select m.clientid as wz, vdc.name as vdc_name, select m.clientid as wz, vdc.name as vdc_name,
case case
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29' WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31' WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28' WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера
ELSE '['||vdc.name||']' END ELSE '['||vdc.name||']' END
|| CASE || CASE
WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m' WHEN storage_profile_types.name ILIKE '%FASTSSD%' THEN '.fstssd-m'
WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m' WHEN storage_profile_types.name ILIKE '%SSD%' THEN '.ssd-m'
WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m' WHEN storage_profile_types.name ILIKE '%SAS%' THEN '.sas-m'
WHEN storage_profile_types.name ILIKE '%SATA%' THEN '.sata-m'
ELSE '.['|| storage_profile_types.name ||']' END ELSE '.['|| storage_profile_types.name ||']' END
as code, as code,
storage_profile_types.name, -- *** это не тип, а профайл storage_profile_types.name, -- *** это не тип, а профайл
sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут sum("limit")/1024./4./720. as gb_m_limit, -- 4 потому, что сбор раз в 15 минут
sum(used)/1024./4 as gb_h_used sum(used)/1024./4./720. as gb_m_used -- 720 это количество часов в условном месяце
from ngcloud_ru.capacity_storage from ngcloud_ru.capacity_storage
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 t on t.id=vdc.tenant_id join ngcloud_ru.tenant t on t.id=vdc.tenant_id
@@ -143,31 +147,31 @@
left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id) left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.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 length(m.clientid) > 0 where length(m.clientid) > 0
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> AND capacity_storage.timestamp::date >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/> AND capacity_storage.timestamp::date < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by m.clientid, vdc.name, storage_profile_types.name group by m.clientid, vdc.name, storage_profile_types.name
order by m.clientid, vdc.name, storage_profile_types.name; order by m.clientid, vdc.name, storage_profile_types.name;
</cfquery> </cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/> <cfoutput>qStorage:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qStorageAge" datasource="billing-vc">
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
</cfquery>
<cfif isDefined("DEBUG")> <cfif isDefined("DEBUG")>
<cfdump var=#qStorage#/> <cfdump var=#qStorage#/>
<cfflush/> <cfflush/>
</cfif> </cfif>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qStorageAge" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
</cfquery>
<cfoutput>qStorageAge:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- <!---
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb" "placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
HOT_FREE_LIMIT 1 10 1 100 HOT_FREE_LIMIT 1 10 1 100
---> --->
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы ---> <!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
<cfquery name="qS3Vol" datasource="billing-s3"> <cfquery name="qS3Vol" datasource="billing-s3" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */ select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>) as vol_B (sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>) as vol_B
,ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>/1024/1024/1024) as vol_GB ,ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>/1024/1024/1024) as vol_GB
@@ -178,31 +182,31 @@ HOT_FREE_LIMIT 1 10 1 100
when bucket_stat.placement_id = 1 then 'paas.s3.ceph' when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
when bucket_stat.placement_id = 2 then 'paas.s3.cphc' when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
--,bucket_stat.placement_id ,bucket_stat.placement_id
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ ,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
from s3billing.bucket_stat from s3billing.bucket_stat
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
where bucket_stat.placement_id in (1,2) where bucket_stat.placement_id in (1,2)
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> AND bucket_stat.timestamp_addition::date >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/> AND bucket_stat.timestamp_addition::date <= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by bucket_stat.owner, bucket_stat.placement_id group by bucket_stat.owner, bucket_stat.placement_id
order by bucket_stat.owner, bucket_stat.placement_id; order by bucket_stat.owner, bucket_stat.placement_id;
</cfquery> </cfquery>
<cfoutput>qS3Vol:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfif isDefined("DEBUG")> <cfif isDefined("DEBUG")>
<cfdump var=#qS3Vol#/> <cfdump var=#qS3Vol#/>
<cfflush/> <cfflush/>
</cfif> </cfif>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/> <cfquery name="qS3VolAge" datasource="billing-s3" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
<cfquery name="qS3VolAge" datasource="billing-s3">
select max(timestamp_addition) as dt_load from s3billing.bucket_stat select max(timestamp_addition) as dt_load from s3billing.bucket_stat
</cfquery> </cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/> <cfoutput>qS3VolAge:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qS3OpsTrf" datasource="billing-s3"> <cfquery name="qS3OpsTrf" datasource="billing-s3">
select select
@@ -273,51 +277,83 @@ select
join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id
join s3billing.placement on bucket_info.placement_id=placement.id join s3billing.placement on bucket_info.placement_id=placement.id
where 1=1 where 1=1
AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> AND usage_bucket_by_user.time::date >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/> AND usage_bucket_by_user.time::date <= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by user_info.name, bucket_info.placement_id group by user_info.name, bucket_info.placement_id
order by user_info.name, bucket_info.placement_id; order by user_info.name, bucket_info.placement_id;
</cfquery> </cfquery>
<cfoutput>qS3OpsTrf:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfif isDefined("DEBUG")> <cfif isDefined("DEBUG")>
<cfdump var=#qS3OpsTrf#/> <cfdump var=#qS3OpsTrf#/>
<cfflush/> <cfflush/>
</cfif> </cfif>
<cfquery name="qS3OpsTrfAge" datasource="billing-s3"> <cfquery name="qS3OpsTrfAge" datasource="billing-s3" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(time) as dt_load from s3billing.usage_bucket_by_user select max(time) as dt_load from s3billing.usage_bucket_by_user
</cfquery> </cfquery>
<cfoutput>qS3OpsTrfAge:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qUnifiedMetric" dbType="query" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric, 'ядро-ч' as unit
from qComputing
<cfquery name="qUnifiedMetric" dbType="query">
select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing
union all union all
select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing select wz, code || '.ram-m', gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric, 'ГБайт-ч' as unit
from qComputing
union all union all
select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage select wz, code, gb_m_used as raw_metric, gb_m_used as metric, gb_m_used as chargeable_metric, 'ГБайт-м' as unit
from qStorage
union all union all
select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric from qS3Vol select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric, 'ГБайт-м' as unit
from qS3Vol
union all union all
select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric, '10тыс.шт.' as unit
from qS3OpsTrf
union all union all
select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric, '10тыс.шт.' as unit
from qS3OpsTrf
union all union all
select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric from qS3OpsTrf select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric, 'ГБайт' as unit
from qS3OpsTrf
order by wz, code
</cfquery> </cfquery>
<cfoutput>qUnifiedMetric:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfif isDefined("DEBUG")> <cfif isDefined("DEBUG")>
<cfdump var=#qUnifiedMetric#/> <cfdump var=#qUnifiedMetric#/>
<cfflush/> <cfflush/>
</cfif> </cfif>
<cfquery name="qChargeInner" dbType="query">
<cfset db = new MemoryDbHelper()/>
<cfset db.register("qUnifiedMetric", qUnifiedMetric, "inmem")/>
<cfset db.register("qContragent", qContragent, "inmem")/>
<cfset db.register("qSpec", qSpec, "inmem")/>
<cfquery name="qCharge" datasource="inmem">
SELECT SELECT
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount"> <d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
<d:field title="WZ">c.wz</d:field> <d:field title="WZ">coalesce(coalesce(c.wz, m.wz), s.wz) as wz</d:field>
<d:field title="Артикул">m.code</d:field> <d:field title="Артикул">coalesce(m.code, s.code) as code</d:field>
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field> <d:field title="Артикул фикс">f.code as f_code</d:field>
<d:field title="Кол-во к оплате" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
<d:field title="Ед.изм.">m.unit</d:field>
<d:field title="Ед.изм.">s.ed_izm</d:field> <d:field title="Ед.изм.">s.ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100 as discounted_price</d:field> <d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.service_quantity*(100-s.service_discount)/100*s.price*(100-s.discount)/100 as discounted_price</d:field>
<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100*m.chargeable_metric as charge</d:field> <d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.service_quantity*(100-s.service_discount)/100*s.price*(100-s.discount)/100*m.chargeable_metric as charge</d:field>
<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.dt_from</d:field> <d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.dt_from</d:field>
<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.dt_to</d:field> <d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.dt_to</d:field>
<d:field title="Ключ строки">s.line_key</d:field> <d:field title="Ключ строки">s.line_key</d:field>
@@ -325,8 +361,8 @@ SELECT
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field> <d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field> <d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведен&shy;ная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field> <d:field title="Приведен&shy;ная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">c.contragent</d:field> <d:field title="Контрагент">coalesce(c.contragent,cs.contragent) as contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field> <d:field title="contragent_uid">coalesce(c.contragent_uid,cs.contragent_uid) as contragent_uid</d:field>
<d:field title="Договор">s.contract</d:field> <d:field title="Договор">s.contract</d:field>
<d:field title="contract_uid">s.contract_uid</d:field> <d:field title="contract_uid">s.contract_uid</d:field>
<d:field title="Допник">s.additional_agreement</d:field> <d:field title="Допник">s.additional_agreement</d:field>
@@ -338,49 +374,30 @@ SELECT
<d:field title="Компонент">s.component</d:field> <d:field title="Компонент">s.component</d:field>
<d:field title="Клиентс. назв.">s.user_description</d:field> <d:field title="Клиентс. назв.">s.user_description</d:field>
</d:field_set> </d:field_set>
FROM qUnifiedMetric m, qContragent c, qSpec s WHERE m.wz=c.wz AND m.wz=s.wz AND m.code=s.code FROM qUnifiedMetric m
FULL JOIN qSpec s ON (m.wz=s.wz AND m.code=s.code)
LEFT JOIN qSpec f ON (m.wz=f.wz AND m.code=f.code AND f.type=2)
LEFT JOIN qContragent c ON (m.wz=c.wz)
LEFT JOIN qContragent cs ON (s.wz=cs.wz) -- неуклюже, но иначе контрагент теряется
WHERE 1=1 AND s.type=3
<cfif only_articles_in_spec>
AND EXISTS(select * from qSpec qs where qs.wz=m.wz AND qs.type=3)
</cfif>
--AND s.wz='WZ01762'
<!---
AND 1=0
--->
ORDER BY wz,code
</cfquery> </cfquery>
<cfquery name="qChargeOuter" dbType="query"> <!--- <cfdump var=#qCharge#/> --->
SELECT
<d:field_set titleMapOut="titleMap_" lengthOut="fieldCount_">
<d:field title="WZ">c.wz</d:field>
<d:field title="Артикул">m.code</d:field>
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
<d:field title="Ед.изм.">null as ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">null discounted_price</d:field>
<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">0 as charge</d:field>
<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">null as dt_from</d:field>
<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">null as dt_to</d:field>
<d:field title="Ключ строки">null as line_key</d:field>
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">null as price</d:field>
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">null as discount</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведен&shy;ная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field>
<d:field title="Договор">null as contract</d:field>
<d:field title="contract_uid">null as contract_uid</d:field>
<d:field title="Допник">null as additional_agreement</d:field>
<d:field title="additional_agreement_uid">null as additional_agreement_uid</d:field>
<d:field title="Сделка">null as deal</d:field>
<d:field title="deal_uid">null as deal_uid</d:field>
<d:field title="Абстрактная услуга">null as abstract_service</d:field>
<d:field title="Модификатор">null as modifier</d:field>
<d:field title="Компонент">null as component</d:field>
<d:field title="Клиентс. назв.">null as user_description</d:field>
</d:field_set>
FROM qUnifiedMetric m, qContragent c WHERE m.wz=c.wz AND m.wz NOT IN (#listQualify(listRemoveDuplicates(ValueList(qChargeInner.wz)),"'")#)
</cfquery>
<cfquery name="qCharge" dbType="query">
select * from qChargeInner
union
select * from qChargeOuter
order by wz,code
</cfquery>
<!--- QoQ does not support join syntax, at least of Lucee 5.4--->
<cfoutput>qCharge:#getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfif isDefined("DEBUG")>
<cfdump var=#qCharge#/>
<cfflush/>
</cfif>
<cfif isDefined("output_xls")> <cfif isDefined("output_xls")>
@@ -401,6 +418,8 @@ order by wz,code
</layout:attribute> </layout:attribute>
</layout:page> </layout:page>
Факт потребления по основной базе биллинга, спецификации из DWH. Без детализации по бакетам, VDC и т.д.
Все запросы кэшированы на 25 минут.<br/>
Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе. Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе.
<b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b> <b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b>
<br/> <br/>
@@ -409,8 +428,10 @@ order by wz,code
<form method="post" action=""> <form method="post" action="">
Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/> Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/>
по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/> по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/>
Только контрагенты с PAYG* <input type="checkbox" name="only_articles_in_spec" value="1"<cfif only_articles_in_spec> checked</cfif>/>
<input type="submit" style="cursor:pointer;"/> <input type="submit" style="cursor:pointer;"/>
<input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/> <input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/>
* любым PAYG, не только по облаку
</form> </form>
Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#qCharge.recordCount#</b><br/> Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#qCharge.recordCount#</b><br/>
Актуальность данных: Актуальность данных:
@@ -465,15 +486,15 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<td bgcolor="##ccc" colspan="99"></td> <td bgcolor="##ccc" colspan="99"></td>
</tr> </tr>
<cfoutput> <cfoutput>
<cfset acc=acc+charge/> <cfset acc += (isNumeric(charge)) ? charge : 0/>
<tr> <tr>
<td>#currentRow#</a></td> <td>#currentRow#</a></td>
<td>#code#</td> <td>#code# <cfif !len(metric) and len(f_code)>(#f_code#)</cfif></td>
<td class="r" style="font-size:120%; padding:0 1em;">#chargeable_metric#</td> <td class="r" style="font-size:120%; padding:0 1em;">#request.roundSafe(chargeable_metric,3)#</td>
<td class="c" style="font-size:90%;">#ed_izm#</td> <td class="c" style="font-size:90%;">#len(unit)?unit:'['& ed_izm &']'#</td>
<td class="r">#discounted_price#</td> <td class="r">#gaussianRoundSafe(discounted_price,2)#</td>
<td class="r">#charge#</td> <td class="r">#gaussianRoundSafe(charge,2)#</td>
<td></td> <td></td>
@@ -481,15 +502,15 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<td>#component#</td> <td>#component#</td>
<td>#user_description#</td> <td>#user_description#</td>
<td class="r">#price#</td> <td class="r">#gaussianRoundSafe(price,2)#</td>
<td class="r">#discount#</td> <td class="r">#discount#</td>
<td class="r">#dateFormat(dt_from,'YYYY-MM-DD')#</td> <td class="r">#dateFormat(dt_from,'YYYY-MM-DD')#</td>
<td class="r">#dateFormat(dt_to,'YYYY-MM-DD')#</td> <td class="r">#dateFormat(dt_to,'YYYY-MM-DD')#</td>
<td class="r">#line_key#</td> <td class="r">#line_key#</td>
<td class="r" style="color:##bbb">#raw_metric#</td> <td class="r" style="color:##bbb">#request.roundSafe(raw_metric,3)#</td>
<td class="r">#metric#</td> <td class="r">#request.roundSafe(metric,3)#</td>
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a></td> <td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a></td>
<td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td> <td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td>
<td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td> <td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
@@ -498,7 +519,7 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<tr> <tr>
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td> <td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
<td bgcolor="##eee" colspan="4" class="r" style="border-bottom:2px solid gray;"><b>Итого</b> <a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#:</td> <td bgcolor="##eee" colspan="4" class="r" style="border-bottom:2px solid gray;"><b>Итого</b> <a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#:</td>
<td bgcolor="##eee" colspan="1" class="r b" style="border-bottom:2px solid gray;">#NumFmt(acc,2)#</td> <td bgcolor="##eee" colspan="1" class="r b nw" style="border-bottom:2px solid gray;">#NumFmt(acc,2)#</td>
<td colspan="14" style="border-bottom:2px solid gray;"></td> <td colspan="14" style="border-bottom:2px solid gray;"></td>
</tr > </tr >
</cfoutput> </cfoutput>
@@ -506,6 +527,9 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
</table> </table>
<!--- <cfdump var=#qCharge#/> ---> <!--- <cfdump var=#qCharge#/> --->
<cfdump var=#this.datasources[request.ds].connectionString#/>
<cfdump var=#this.datasources["billing-vc"].connectionString#/>
<cfdump var=#this.datasources["billing-s3"].connectionString#/>
<layout:page section="footer"/> <layout:page section="footer"/>
@@ -520,3 +544,30 @@ left outer join
from ngcloud_ru.tenant_metadata) tm from ngcloud_ru.tenant_metadata) tm
on (t.id = tm.tenant_id AND tm.rn = 1) on (t.id = tm.tenant_id AND tm.rn = 1)
left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id) ---> left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id) --->
<cfscript>
string function gaussianRoundSafe(any num, numeric precision = 0, string default="") {
return (isNumeric(arguments.num)) ? gaussianRound(arguments.num, arguments.precision) : arguments.default;
}
function gaussianRound(numeric number, numeric precision = 0) {
var factor = 10 ^ precision;
var scaledNumber = number * factor;
var absScaled = abs(scaledNumber);
var sign = sgn(scaledNumber);
var floored = int(absScaled);
// If it's not ending in exactly .5, use standard rounding or precision scaling
if (absScaled - floored != 0.5) {
return round(number * factor) / factor;
}
// If it is exactly .5, round towards the nearest even number
if (floored % 2 != 0) {
// Nearest even is UP
return (floored + 1) * sign / factor;
} else {
// Nearest even is DOWN
return floored * sign / factor;
}
}
</cfscript>
+20
View File
@@ -0,0 +1,20 @@
<cfquery name="qEq" datasource="cmdb">
select svc_id,svc,descr,dt_created,creator_id,DT_UPDATED, UPDATER_ID, IS_PRODUCTION_READY, CODE, MAN SVC_SHORT, RESOURCE_REALM_TYPE_ID, VERSION ,ORCHESTRATOR_NAME, SORT, SVC_GROUP_ID, ICON_SRC, SYNONYMS from svc limit 100;
</cfquery>
<!--- <cfdump var=#qEq#/> --->
<!--- <cfquery name="qt" datasource="inmem">
SELECT CURRENT_DATE FROM (VALUES(0));
</cfquery>
<cfdump var=#qt#/>--->
<cfset db = new MemoryDbHelper()/>
<!--- <cfset db.drop("eq")/> --->
<cfset db.register("eq", qEq, "inmem")/>
<cfquery name="qTest" datasource="inmem">
select * from eq
</cfquery>
<!---
<cfset db.drop("eq")/> --->
<cfdump var=#qTest#/>