019 day loop
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<cfimport prefix="m" taglib="../lib"/>
|
||||
<cfimport prefix="d" taglib="../lib/data"/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.wz"/>
|
||||
<cfparam name="ATTRIBUTES.crm_cache_base" default="https://elma-cache.adl.nubes.ru/contract_ls.cfm"/>
|
||||
<cfparam name="ATTRIBUTES.out" default="qComponent"/>
|
||||
|
||||
<cfhttp method="get"
|
||||
url="#ATTRIBUTES.crm_cache_base#?wz=#ATTRIBUTES.wz#"
|
||||
timeout=10
|
||||
charset="utf-8"
|
||||
result="res"
|
||||
>
|
||||
</cfhttp>
|
||||
|
||||
<cfset local={}/>
|
||||
|
||||
<cfset company=deserializeJson(res.fileContent)/>
|
||||
<!--- <cfdump var=#company#/> --->
|
||||
<!--- *** это не слишком надежно, некорректно представленный NULL (обыкновенно представляемый пустой строкой) может все сломать. Да и корректный --->
|
||||
<!--- мартышкин труд собирать этот запрос из JSON , может, лучше было динамически --->
|
||||
<cfset qComponent = queryNew("
|
||||
contractId
|
||||
,contractOutsideId
|
||||
|
||||
,additionalAgreementId
|
||||
,additionalAgreementName
|
||||
|
||||
,dealIndex
|
||||
,serviceId
|
||||
,serviceType
|
||||
,catalogName
|
||||
,serviceCode
|
||||
,serviceCustomName
|
||||
,serviceStart
|
||||
,serviceEnd
|
||||
,serviceDiscount
|
||||
,serviceQuantity
|
||||
,serviceHash
|
||||
|
||||
,paramId
|
||||
,componentCode
|
||||
,component
|
||||
,measureShort
|
||||
,quantity
|
||||
,priceWVat
|
||||
,discount
|
||||
,atomicCode
|
||||
,fullCode
|
||||
")/>
|
||||
|
||||
<!--- this.nullSupport = true in Application.cfc ... no way --->
|
||||
<cfloop array=#company.contracts# item="local.contract"><!--- имя массива писать в ##, иначе думает, что это строковый литерал --->
|
||||
<cfloop array=#local.contract.additionalAgreements# item="local.additionalAgreement">
|
||||
<cfif NOT local.additionalAgreement.isActual><cfcontinue/></cfif>
|
||||
<cfloop array=#local.additionalAgreement.services# item="local.service">
|
||||
<cfloop array=#local.service.components# item="local.component">
|
||||
<cfset queryAddRow(qComponent, [{
|
||||
contractId=local.contract.contractId,
|
||||
contractOutsideId=local.contract.contractOutsideId,
|
||||
|
||||
additionalAgreementId=local.additionalAgreement.additionalAgreementId,
|
||||
additionalAgreementName=local.additionalAgreement.additionalAgreementName,
|
||||
|
||||
dealIndex=local.service.dealIndex ,
|
||||
serviceId=local.service.serviceId ,
|
||||
serviceType=local.service.serviceType,
|
||||
catalogName=local.service.catalogName,
|
||||
serviceCode=local.service.serviceCode,
|
||||
serviceCustomName=local.service.serviceCustomName,
|
||||
serviceStart=parseDateTime(local.service.serviceStart.ts),
|
||||
serviceEnd=isDate(structGet("local.service.serviceEnd.ts"))? parseDateTime(local.service.serviceEnd.ts):javacast('null',''),
|
||||
serviceDiscount=local.service.discount,
|
||||
serviceQuantity=local.service.quantity,
|
||||
serviceHash=local.service.serviceHash,
|
||||
|
||||
paramId=local.component.paramId,
|
||||
componentCode=local.component.componentCode,
|
||||
component=local.component.component,
|
||||
measureShort=local.component.measureShort,
|
||||
quantity=local.component.quantity,
|
||||
priceWVat=local.component.priceWVat,
|
||||
discount=local.component.discount,
|
||||
atomicCode=local.component.atomicCode,
|
||||
fullCode="#local.component.componentCode#-#listGetAt('i,f,m',local.service.serviceType)#"
|
||||
}])/>
|
||||
</cfloop>
|
||||
</cfloop>
|
||||
</cfloop>
|
||||
</cfloop>
|
||||
|
||||
<!--- <cfdump var=#qComponent#/> --->
|
||||
<cfset "CALLER.#ATTRIBUTES.out#" = qComponent/>
|
||||
<cfexit method="exittag"/>
|
||||
+309
-234
@@ -7,277 +7,352 @@
|
||||
<cfparam name="ATTRIBUTES.debug" type="boolean" default=false/>
|
||||
<cfparam name="ATTRIBUTES.tenant_wz_index" type="string"/>
|
||||
|
||||
<cfset hours=dateDiff('h', ATTRIBUTES.dt_start, ATTRIBUTES.dt_finish)/>
|
||||
|
||||
<cfset hours=dateDiff('h', ATTRIBUTES.dt_start, ATTRIBUTES.dt_finish)/> <!--- *** нужно для каждого фрагмента --->
|
||||
<!---
|
||||
*** ВНИМАНИЕ! Вычитать минимальный лимит нужно после агрегации!
|
||||
Исходная последовательность расчетов сначала делает агрегацию по месяцу, при расчете по дням нужно менять порядок
|
||||
--->
|
||||
<!---
|
||||
Скрытое противоречие, которое требует разрешения: если у нас несколько периодов тарификации в одном месяце (по разной цене), ИЗ КАКОГО вычитать минимальный лимит?
|
||||
Еще сложность, если лимита хватает на несколько периодов тарификации, как его распределять по периодам. Если тарификация строго по месяцам, этой проблемы нет.
|
||||
Это можно сделать процедурно, но сложность расчета все возрастает
|
||||
--->
|
||||
<!--- *** Проверить, что у нас не биллится закрытый период (закрытый следующим) - возможно, с учетом line_key
|
||||
- насколько вижу, прошлый период закрывается, причем концы отрезки закрытые (конец включается). Считаем, что этой проблемы нет
|
||||
--->
|
||||
|
||||
|
||||
<!--- QoQ does not support join syntax, and of course outer joins, at least of Lucee 5.4--->
|
||||
<!--- а внешние джойны хорошо подсвечивают ошибки, особенно помогает full --->
|
||||
|
||||
<!--- QoQ does not support join syntax, at least of Lucee 5.4--->
|
||||
|
||||
|
||||
<!--- Для начала выкатываем просто кусок каталога, не фильтруя по спеке (которой иногда нет) --->
|
||||
<cfquery name="qSpec">
|
||||
select * from (
|
||||
values
|
||||
('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения (HOT)','paas.s3.ceph.vol-m','ГБайт',1.80,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик (HOT)','paas.s3.ceph.trf-m','ГБайт',1.50,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS (HOT)','paas.s3.ceph.get-m','10тыс.шт.',0.35,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH (HOT)','paas.s3.ceph.put-m','10тыс.шт.',4.50,0)
|
||||
|
||||
,('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения (COLD)','paas.s3.cphc.vol-m','ГБайт',0.84*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик (COLD)','paas.s3.cphc.trf-m','ГБайт',1.25*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS (COLD)','paas.s3.cphc.get-m','10тыс.шт.',0.8*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH (COLD)','paas.s3.cphc.put-m','10тыс.шт.',9.7*1.2,0)
|
||||
) as
|
||||
s (svc, component, code, unit, price, discount)
|
||||
order by code
|
||||
</cfquery>
|
||||
|
||||
|
||||
<!--- Нужно еще реализовать в модели данных политики бесплатного минимума --->
|
||||
<cfquery name="qComputing">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
case
|
||||
when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29'
|
||||
when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31'
|
||||
when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28'
|
||||
when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28'
|
||||
else '['||vdc.name||']' end as code,
|
||||
sum(cpu_used/cpu_speed)/4. as core_h,
|
||||
sum(mem_used)/1024/4. as gb_h
|
||||
from ngcloud_ru.capacity_resource
|
||||
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by tenant.wzcode, vdc.name
|
||||
order by tenant.wzcode, vdc.name;
|
||||
</cfquery>
|
||||
|
||||
<cfmodule template="crm_contract.cfm" wz="WZ01348" out="qSpecification"/>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfdump var=#qComputing#/>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qSpecification#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qComputingAge">
|
||||
select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
|
||||
</cfquery>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputingAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
|
||||
<cfquery name="qStorage">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
case
|
||||
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
|
||||
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
|
||||
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
|
||||
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
|
||||
ELSE '['||vdc.name||']' END
|
||||
|| CASE
|
||||
WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-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
|
||||
as code,
|
||||
storage_profile_types.name, -- *** это не тип, а профайл
|
||||
sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут
|
||||
sum(used)/1024./4 as gb_h_used
|
||||
from ngcloud_ru.capacity_storage
|
||||
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.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
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by tenant.wzcode, vdc.name, storage_profile_types.name
|
||||
order by tenant.wzcode, vdc.name, storage_profile_types.name;
|
||||
</cfquery>
|
||||
<cfquery name="qStorageAge" datasource="rpt">
|
||||
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qStorage#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!---
|
||||
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
|
||||
HOT_FREE_LIMIT 1 10 1 100
|
||||
--->
|
||||
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
|
||||
<cfquery name="qS3Vol">
|
||||
select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
|
||||
(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
|
||||
,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>
|
||||
/1024/1024/1024)-
|
||||
case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/
|
||||
,case
|
||||
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
|
||||
--,bucket_stat.placement_id
|
||||
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
|
||||
|
||||
from s3billing.bucket_stat
|
||||
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
|
||||
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
|
||||
where bucket_stat.placement_id in (1,2)
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by bucket_stat.owner, bucket_stat.placement_id
|
||||
order by bucket_stat.owner, bucket_stat.placement_id;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfdump var=#qS3Vol#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qS3VolAge">
|
||||
select max(timestamp_addition) as dt_load from s3billing.bucket_stat
|
||||
</cfquery>
|
||||
|
||||
<cfquery name="qS3OpsTrf">
|
||||
select
|
||||
sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
) as get
|
||||
,ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) as get_10k
|
||||
,greatest(ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0
|
||||
) as get_10k_free_tier_subtracted
|
||||
|
||||
,sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
) as put
|
||||
,ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) as put_10k
|
||||
,greatest(ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0
|
||||
) as put_10k_free_tier_subtracted
|
||||
|
||||
,(sum(bytes_sent)) as bytes_sent
|
||||
,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB
|
||||
,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0
|
||||
) as bytes_sent_GB_free_tier_subtracted
|
||||
|
||||
,case
|
||||
when bucket_info.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_info.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint
|
||||
,bucket_info.placement_id
|
||||
--category.name, bucket_info.name
|
||||
,'WZ'||lpad(user_info.name, 5, '0') as wz
|
||||
from s3billing.usage_bucket_by_user
|
||||
join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id
|
||||
join s3billing.category on usage_bucket_by_user.category_id=category.id
|
||||
join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id
|
||||
join s3billing.placement on bucket_info.placement_id=placement.id
|
||||
where 1=1
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by user_info.name, bucket_info.placement_id
|
||||
order by user_info.name, bucket_info.placement_id;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfdump var=#qS3OpsTrf#/>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3VolAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qS3OpsTrfAge">
|
||||
select max(time) as dt_load from s3billing.usage_bucket_by_user
|
||||
</cfquery>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrfAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<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
|
||||
select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing
|
||||
union all
|
||||
select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
|
||||
<!--- здесь нужно организовать пересечение версионной спецификации с анализируемым диапазоном дат --->
|
||||
<cfquery name="qSpec" dbtype="query">
|
||||
select catalogName as svc, component, fullCode as code, measureShort as unit
|
||||
, priceWVat as price, (discount + serviceDiscount - discount*serviceDiscount/100) as discount
|
||||
,serviceStart, serviceEnd, serviceHash
|
||||
from qSpecification
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
|
||||
<cfset qTotal=""/>
|
||||
|
||||
<cfloop from=#attributes.dt_start# to=#attributes.dt_finish# step="#CreateTimeSpan( 1, 0, 0, 0 )#" index="local.dt">
|
||||
<cfdump var=#dateFormat(local.dt,"YYYY-MM-DD")#/>
|
||||
|
||||
<!--- *** Нужно еще реализовать в модели данных политики бесплатного минимума, сейчас пробито гвоздями --->
|
||||
<cfquery name="qComputing">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
case
|
||||
when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29'
|
||||
when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31'
|
||||
when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28'
|
||||
when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28'
|
||||
else '['||vdc.name||']' end as code,
|
||||
sum(cpu_used/cpu_speed)/4. as core_h,
|
||||
sum(mem_used)/1024/4. as gb_h
|
||||
from ngcloud_ru.capacity_resource
|
||||
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_resource.timestamp::date = <cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/>
|
||||
|
||||
group by tenant.wzcode, vdc.name
|
||||
order by tenant.wzcode, vdc.name;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputing#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
|
||||
<cfquery name="qStorage">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
case
|
||||
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
|
||||
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
|
||||
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
|
||||
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
|
||||
ELSE '['||vdc.name||']' END
|
||||
|| CASE
|
||||
WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-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
|
||||
as code,
|
||||
storage_profile_types.name, -- *** это не тип, а профайл
|
||||
sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут
|
||||
sum(used)/1024./4 as gb_h_used
|
||||
from ngcloud_ru.capacity_storage
|
||||
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.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
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_storage.timestamp ::date = <cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/>
|
||||
group by tenant.wzcode, vdc.name, storage_profile_types.name
|
||||
order by tenant.wzcode, vdc.name, storage_profile_types.name;
|
||||
</cfquery>
|
||||
|
||||
|
||||
<!---
|
||||
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
|
||||
HOT_FREE_LIMIT 1 10 1 100
|
||||
--->
|
||||
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
|
||||
<cfquery name="qS3Vol">
|
||||
select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
|
||||
(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
|
||||
,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>
|
||||
/1024/1024/1024)-
|
||||
case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/
|
||||
,case
|
||||
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
|
||||
--,bucket_stat.placement_id
|
||||
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
|
||||
|
||||
from s3billing.bucket_stat
|
||||
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
|
||||
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
|
||||
where bucket_stat.placement_id in (1,2)
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND bucket_stat.timestamp_addition::date = <cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/>
|
||||
|
||||
group by bucket_stat.owner, bucket_stat.placement_id
|
||||
order by bucket_stat.owner, bucket_stat.placement_id;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3Vol#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<cfquery name="qS3OpsTrf">
|
||||
select
|
||||
sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
) as get
|
||||
,ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) as get_10k
|
||||
,greatest(ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0
|
||||
) as get_10k_free_tier_subtracted
|
||||
|
||||
,sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
) as put
|
||||
,ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) as put_10k
|
||||
,greatest(ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0
|
||||
) as put_10k_free_tier_subtracted
|
||||
|
||||
,(sum(bytes_sent)) as bytes_sent
|
||||
,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB
|
||||
,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0
|
||||
) as bytes_sent_GB_free_tier_subtracted
|
||||
,case
|
||||
when bucket_info.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_info.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint
|
||||
,bucket_info.placement_id
|
||||
--category.name, bucket_info.name
|
||||
,'WZ'||lpad(user_info.name, 5, '0') as wz
|
||||
from s3billing.usage_bucket_by_user
|
||||
join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id
|
||||
join s3billing.category on usage_bucket_by_user.category_id=category.id
|
||||
join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id
|
||||
join s3billing.placement on bucket_info.placement_id=placement.id
|
||||
where 1=1
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND usage_bucket_by_user.time::date = <cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/>
|
||||
group by user_info.name, bucket_info.placement_id
|
||||
order by user_info.name, bucket_info.placement_id;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrf#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- собрали все метрики в один резалтсет --->
|
||||
<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
|
||||
select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing
|
||||
union all
|
||||
select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
</cfquery>
|
||||
|
||||
<cfdump var=#qUnifiedMetric#/>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qUnifiedMetric#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- умножаем на цену, вычисляем дисконт (довольно поздно) и форматируем
|
||||
*** здесь нужно учесть версионность. Самым простым кажется декомпозировать по дням и снова собрать
|
||||
*** только как нам это сделать без нормального SQL движка
|
||||
Может быть, процедурная обработка не будет выглядеть ужасно, и не хуже SQL
|
||||
В конце концов, можно просто В ЦИКЛЕ обсчитать диапазон по дням, выполнив запрос 30 раз, или сколько надо
|
||||
Если будет тупить - оптимизируем
|
||||
--->
|
||||
|
||||
<!--- Для декомпозиции на более мелкие объекты мы можем как полумеру - профильтровать по конкретному бакету или ВМ-ВДЦ
|
||||
Что не нравится - для ВМ у нас может быть целое дерево нижележащих объектов вместо линейного списка бакетов --->
|
||||
<cfquery name="qCharge" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Артикул">s.code</d:field>
|
||||
<d:field title="Артикул">m.code as m_code</d:field>
|
||||
<d:field title="Услуга">s.svc</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
|
||||
<d:field title="Ед.изм.">s.unit</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.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_to</d:field>
|
||||
<d:field title="Ключ строки">s.line_key</d:field> --->
|
||||
<d:field title="Цена с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</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.metric</d:field>
|
||||
<d:field title="serviceStart" cfSqlType="CF_SQL_TIMESTAMP">s.serviceStart</d:field>
|
||||
<d:field title="serviceEnd" cfSqlType="CF_SQL_TIMESTAMP">s.serviceEnd</d:field>
|
||||
<d:field title="serviceHash">s.serviceHash</d:field>
|
||||
<d:field title="dt" cfSqlType="CF_SQL_TIMESTAMP"><cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/>as dt</d:field>
|
||||
<!--- <d:field title="Клиентс. назв.">s.user_description</d:field> --->
|
||||
</d:field_set>
|
||||
FROM qSpec as s, qUnifiedMetric as m
|
||||
WHERE m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/> AND s.code=m.code
|
||||
AND s.serviceStart <= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/>
|
||||
AND (<cfqueryparam cfsqltype="cf_sql_timestamp" value=#local.dt#/> <= s.serviceEnd OR s.serviceEnd IS NULL)
|
||||
order by s.code
|
||||
</cfquery>
|
||||
|
||||
<!--- тут могут быть подводные камни с копированием и переиспользованием объектов --->
|
||||
<cfif isQuery(qTotal)>
|
||||
<cfquery name="qTotalNew" dbType="query">
|
||||
select * from qTotal
|
||||
union all
|
||||
select * from qCharge
|
||||
</cfquery>
|
||||
<cfset qTotal = qTotalNew/>
|
||||
<cfelse>
|
||||
<cfset qTotal = qCharge/>
|
||||
</cfif>
|
||||
<cfdump var=#qTotal#/>
|
||||
<!--- *** проверить краевые даты --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qCharge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qCharge" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Артикул">s.code</d:field>
|
||||
<d:field title="Артикул">m.code as m_code</d:field>
|
||||
<d:field title="Услуга">s.svc</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
|
||||
<d:field title="Ед.изм.">s.unit</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.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_to</d:field>
|
||||
<d:field title="Ключ строки">s.line_key</d:field> --->
|
||||
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</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.metric</d:field>
|
||||
|
||||
<!--- <d:field title="Клиентс. назв.">s.user_description</d:field> --->
|
||||
</d:field_set>
|
||||
FROM qSpec as s, qUnifiedMetric as m
|
||||
WHERE m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/> AND s.code=m.code
|
||||
order by s.code
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfdump var=#qCharge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<cfdump var=#qTotal#/>
|
||||
|
||||
|
||||
<cfset var report={}/>
|
||||
|
||||
<cfset report.qComputingAge = qComputingAge/>
|
||||
|
||||
@@ -5,25 +5,46 @@
|
||||
<cfparam name="ATTRIBUTES.dt_start" type="date" default=#dateAdd('m',-1,ATTRIBUTES.dt_finish)#/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string" default="report"/>
|
||||
<cfparam name="ATTRIBUTES.debug" type="boolean" default=false/>
|
||||
|
||||
<cfset hours=dateDiff('h',dt_start,dt_finish)/>
|
||||
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->
|
||||
<cfparam name="ATTRIBUTES.tenant_wz_index" type="string"/>
|
||||
|
||||
|
||||
<!--- QoQ does not support join syntax, at least of Lucee 5.4--->
|
||||
<cfset hours=dateDiff('h', ATTRIBUTES.dt_start, ATTRIBUTES.dt_finish)/>
|
||||
|
||||
|
||||
|
||||
<!--- QoQ does not support join syntax, and of course outer joins, at least of Lucee 5.4--->
|
||||
<!--- а внешние джойны хорошо подсвечивают ошибки, особенно помогает full --->
|
||||
|
||||
<cfmodule template="crm_contract.cfm" wz="WZ01348" out="qSpecification"/>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qSpecification#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- Для начала выкатываем просто кусок каталога, не фильтруя по спеке (которой иногда нет) --->
|
||||
<cfquery name="qSpec">
|
||||
<!--- <cfquery name="qSpec">
|
||||
select * from (
|
||||
values
|
||||
('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения','paas.s3.ceph.vol-m','ГБайт',1.80,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик','paas.s3.ceph.trf-m','ГБайт',1.50,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS','paas.s3.ceph.get-m','10тыс.шт.',0.35,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH','paas.s3.ceph.put-m','10тыс.шт.',4.50,0)
|
||||
('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения (HOT)','paas.s3.ceph.vol-m','ГБайт',1.80,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик (HOT)','paas.s3.ceph.trf-m','ГБайт',1.50,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS (HOT)','paas.s3.ceph.get-m','10тыс.шт.',0.35,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH (HOT)','paas.s3.ceph.put-m','10тыс.шт.',4.50,0)
|
||||
|
||||
,('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения (COLD)','paas.s3.cphc.vol-m','ГБайт',0.84*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик (COLD)','paas.s3.cphc.trf-m','ГБайт',1.25*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS (COLD)','paas.s3.cphc.get-m','10тыс.шт.',0.8*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH (COLD)','paas.s3.cphc.put-m','10тыс.шт.',9.7*1.2,0)
|
||||
) as
|
||||
s (svc, component, code, unit, price, discount)
|
||||
order by code
|
||||
</cfquery> --->
|
||||
<!--- здесь нужно организовать пересечение версионной спецификации с анализируемым диапазоном дат --->
|
||||
<cfquery name="qSpec" dbtype="query">
|
||||
select catalogName as svc, component, fullCode as code, measureShort as unit
|
||||
, priceWVat as price, (discount + serviceDiscount - discount*serviceDiscount/100) as discount
|
||||
,serviceStart, serviceEnd
|
||||
from qSpecification
|
||||
</cfquery>
|
||||
|
||||
|
||||
@@ -41,7 +62,7 @@
|
||||
from ngcloud_ru.capacity_resource
|
||||
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#tenant_wz_index#/>
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by tenant.wzcode, vdc.name
|
||||
@@ -49,6 +70,7 @@
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputing#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -57,6 +79,12 @@
|
||||
select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputingAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
|
||||
<cfquery name="qStorage">
|
||||
@@ -80,7 +108,7 @@
|
||||
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.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
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#tenant_wz_index#/>
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by tenant.wzcode, vdc.name, storage_profile_types.name
|
||||
@@ -91,6 +119,7 @@
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qStorage#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -118,7 +147,7 @@ HOT_FREE_LIMIT 1 10 1 100
|
||||
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
|
||||
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
|
||||
where bucket_stat.placement_id in (1,2)
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#tenant_wz_index#/>
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by bucket_stat.owner, bucket_stat.placement_id
|
||||
@@ -126,6 +155,7 @@ HOT_FREE_LIMIT 1 10 1 100
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3Vol#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -134,6 +164,12 @@ HOT_FREE_LIMIT 1 10 1 100
|
||||
select max(timestamp_addition) as dt_load from s3billing.bucket_stat
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3VolAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qS3OpsTrf">
|
||||
select
|
||||
sum(
|
||||
@@ -203,7 +239,7 @@ select
|
||||
join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id
|
||||
join s3billing.placement on bucket_info.placement_id=placement.id
|
||||
where 1=1
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#tenant_wz_index#/>
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by user_info.name, bucket_info.placement_id
|
||||
@@ -211,6 +247,7 @@ select
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrf#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -219,7 +256,13 @@ select
|
||||
select max(time) as dt_load from s3billing.usage_bucket_by_user
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrfAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- собрали все метрики в один резалтсет --->
|
||||
<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
|
||||
@@ -237,14 +280,30 @@ select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric,
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qUnifiedMetric#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- умножаем на цену, вычисляем дисконт (довольно поздно) и форматируем
|
||||
*** здесь нужно учесть версионность. Самым простым кажется декомпозировать по дням и снова собрать
|
||||
*** только как нам это сделать без нормального SQL движка
|
||||
Может быть, процедурная обработка не будет выглядеть ужасно, и не хуже SQL
|
||||
В конце концов, можно просто В ЦИКЛЕ обсчитать диапазон по дням, выполнив запрос 30 раз, или сколько надо
|
||||
Если будет тупить - оптимизируем
|
||||
--->
|
||||
|
||||
<!--- Для декомпозиции на более мелкие объекты мы можем как полумеру - профильтровать по конкретному бакету или ВМ-ВДЦ
|
||||
Что не нравится - для ВМ у нас может быть целое дерево нижележащих объектов --->
|
||||
|
||||
<cfloop from=#attribute.dt_start# to=#attribute.dt_finish# index="dt">
|
||||
</cfloop>
|
||||
|
||||
<cfquery name="qCharge" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Артикул">s.code</d:field>
|
||||
<d:field title="Артикул">m.code as m_code</d:field>
|
||||
<d:field title="Услуга">s.svc</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
|
||||
@@ -254,7 +313,7 @@ SELECT
|
||||
<!--- <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="Ключ строки">s.line_key</d:field> --->
|
||||
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field>
|
||||
<d:field title="Цена с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</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.metric</d:field>
|
||||
@@ -266,6 +325,12 @@ WHERE m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/> AN
|
||||
order by s.code
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qCharge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfset var report={}/>
|
||||
|
||||
<cfset report.qComputingAge = qComputingAge/>
|
||||
Reference in New Issue
Block a user