81 vm_ls fix
This commit is contained in:
+1
-1
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
<!--- global settings --->
|
<!--- global settings --->
|
||||||
<!--- *************************************************************************************************** --->
|
<!--- *************************************************************************************************** --->
|
||||||
<cfset request.APP_VERSION="0.00.080"/> <!--- *********************************************************** --->
|
<cfset request.APP_VERSION="0.00.081"/> <!--- *********************************************************** --->
|
||||||
<!--- *************************************************************************************************** --->
|
<!--- *************************************************************************************************** --->
|
||||||
<cfset request.STAND=getStand()/>
|
<cfset request.STAND=getStand()/>
|
||||||
<cfset request.RECORDS_PER_PAGE=500/>
|
<cfset request.RECORDS_PER_PAGE=500/>
|
||||||
|
|||||||
+1
-1
@@ -159,7 +159,7 @@ function skuCode(area_code="", abstract_service_code="") {
|
|||||||
}
|
}
|
||||||
request.skuCode = skuCode;
|
request.skuCode = skuCode;
|
||||||
*/
|
*/
|
||||||
function roundSafe(a, precision) {
|
function roundSafe(a, precision=0) {
|
||||||
return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a;
|
return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a;
|
||||||
}
|
}
|
||||||
request.roundSafe = roundSafe;
|
request.roundSafe = roundSafe;
|
||||||
|
|||||||
@@ -601,6 +601,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
<thead>
|
<thead>
|
||||||
<td width="1%"></td>
|
<td width="1%"></td>
|
||||||
<!--- <th width="3%">WZ</th> --->
|
<!--- <th width="3%">WZ</th> --->
|
||||||
|
<th width="7%">Услуга</th>
|
||||||
<th width="7%">Артикул специф.</th>
|
<th width="7%">Артикул специф.</th>
|
||||||
<th width="5%">Кол-во специф.</th>
|
<th width="5%">Кол-во специф.</th>
|
||||||
<th width="5%">Артикул метр.</th>
|
<th width="5%">Артикул метр.</th>
|
||||||
@@ -614,9 +615,8 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
|
|
||||||
<td width="3%"> </td>
|
<td width="3%"> </td>
|
||||||
|
|
||||||
<td width="10%">Услуга</td>
|
|
||||||
<td width="10%">Компонент</td>
|
<td width="10%">Компонент</td>
|
||||||
<td width="15%">Клиентс. назв.</td>
|
<td width="15%">Польз. наим.</td>
|
||||||
|
|
||||||
<td width="3%">GPL с НДС</td>
|
<td width="3%">GPL с НДС</td>
|
||||||
<td width="3%">Скидка%</td>
|
<td width="3%">Скидка%</td>
|
||||||
@@ -676,7 +676,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
<!--- детализация --->
|
<!--- детализация --->
|
||||||
<tr<cfif !len(unit)> class="gray"</cfif>>
|
<tr<cfif !len(unit)> class="gray"</cfif>>
|
||||||
<td>#currentRow#</a></td>
|
<td>#currentRow#</a></td>
|
||||||
|
<td>#abstract_service#<cfif len(modifier)>: #modifier#</cfif></a></td>
|
||||||
<td><div<cfif type EQ 3> style="background:lightgreen;color:black;"</cfif>>#s_code#</div></td>
|
<td><div<cfif type EQ 3> style="background:lightgreen;color:black;"</cfif>>#s_code#</div></td>
|
||||||
<td class=<cfif type EQ 3 AND component_quantity NEQ 1>"err r"<cfelse>"r"</cfif>>#component_quantity#</td>
|
<td class=<cfif type EQ 3 AND component_quantity NEQ 1>"err r"<cfelse>"r"</cfif>>#component_quantity#</td>
|
||||||
<td>#m_code#</td>
|
<td>#m_code#</td>
|
||||||
@@ -690,7 +690,6 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
|
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
||||||
<td>#abstract_service# #modifier#</td>
|
|
||||||
<td>#component#</td>
|
<td>#component#</td>
|
||||||
<td>#user_description#</td>
|
<td>#user_description#</td>
|
||||||
|
|
||||||
@@ -706,7 +705,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
|
|
||||||
<!--- сырые исходные данные без округлений --->
|
<!--- сырые исходные данные без округлений --->
|
||||||
<td class="r">#price#</td>
|
<td class="r">#price#</td>
|
||||||
<td class="r">#discounted_price#</td>
|
<td class="r">#discounted_price#</td><!--- style="word-wrap:break-word" --->
|
||||||
<td class="r">#service_quantity#</td>
|
<td class="r">#service_quantity#</td>
|
||||||
<td class="r">#service_discount#</td>
|
<td class="r">#service_discount#</td>
|
||||||
<td class="r">#component_quantity#</td>
|
<td class="r">#component_quantity#</td>
|
||||||
@@ -722,8 +721,8 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
<cfset cost_dimension_1 = precisionEvaluate("gaussianRound(max(final_metric_dimension_1 - free_tier, 0)*current_price, 2)")/>
|
<cfset cost_dimension_1 = precisionEvaluate("gaussianRound(max(final_metric_dimension_1 - free_tier, 0)*current_price, 2)")/>
|
||||||
<cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/><!--- простое сложение дает ошибку округления и лишние знаки, но и precisionEvaluate не выглядит слишком надежным --->
|
<cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/><!--- простое сложение дает ошибку округления и лишние знаки, но и precisionEvaluate не выглядит слишком надежным --->
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3"></td>
|
<td colspan="4"></td>
|
||||||
<td colspan="2" class="b r">Итого #code#:</td>
|
<td colspan="2" class="b r">Итого #code#:</td>
|
||||||
<td class="b r" style="font-size:110%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#round(final_metric_dimension_1,3)#</cfif></td>
|
<td class="b r" style="font-size:110%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#round(final_metric_dimension_1,3)#</cfif></td>
|
||||||
<td class="b r">#free_tier#</td>
|
<td class="b r">#free_tier#</td>
|
||||||
<td class="b r" style="font-size:120%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#max(ceiling(final_metric_dimension_1) - free_tier, 0)#</cfif></td>
|
<td class="b r" style="font-size:120%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#max(ceiling(final_metric_dimension_1) - free_tier, 0)#</cfif></td>
|
||||||
@@ -738,7 +737,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
|||||||
|
|
||||||
<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="9" class="r b" style="border-bottom:2px solid gray;">Итого <a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#:</td>
|
<td bgcolor="##eee" colspan="10" class="r b" style="border-bottom:2px solid gray;">Итого <a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#:</td>
|
||||||
<td bgcolor="##eee" class="r b nw" style="border-bottom:2px solid gray; font-size:130%;">#accum_cost_svc#</td>
|
<td bgcolor="##eee" class="r b nw" style="border-bottom:2px solid gray; font-size:130%;">#accum_cost_svc#</td>
|
||||||
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
||||||
<td bgcolor="##eee" colspan="99" style="border-bottom:2px solid gray;"></td>
|
<td bgcolor="##eee" colspan="99" style="border-bottom:2px solid gray;"></td>
|
||||||
|
|||||||
+406
@@ -0,0 +1,406 @@
|
|||||||
|
<cfsilent>
|
||||||
|
<cfimport prefix="m" taglib="lib"/>
|
||||||
|
<cfimport prefix="c" taglib="lib/controls"/>
|
||||||
|
<cfimport prefix="d" taglib="lib/data"/>
|
||||||
|
<cfimport prefix="layout" taglib="layout"/>
|
||||||
|
</cfsilent>
|
||||||
|
|
||||||
|
<m:prepare_ls entity="vm_gpu" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
|
||||||
|
|
||||||
|
|
||||||
|
<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/> --->
|
||||||
|
<cfparam name="wz" default="WZ01516"/>
|
||||||
|
<cfparam name="code" default=""/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--- <cfquery name="qCode" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 20, 0)#>
|
||||||
|
select distinct p.code
|
||||||
|
from elma.deals d
|
||||||
|
join elma.deals_services siv on (d.__id=ANY(siv.deal))
|
||||||
|
join elma.service_parametrs p on (p.__id = ANY(siv.params))
|
||||||
|
join elma.companies k on (d._companies=k.__id)
|
||||||
|
join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement))
|
||||||
|
join elma.aggrements a on (aa.contract_uid = a.__id)
|
||||||
|
where p.type=3 AND aa.is_actual
|
||||||
|
order by p.code
|
||||||
|
</cfquery>
|
||||||
|
<cfoutput>qCode:#getTickCount()-request.startTickCount#</cfoutput>
|
||||||
|
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
|
||||||
|
|
||||||
|
<cfquery name="qContragent" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 22, 0)#>
|
||||||
|
select upper(trim(k.id_klienta)) as wz, k.__id::text as contragent_uid, k.__name as contragent,
|
||||||
|
c.__name as responsible, c.email as responsible_email, c.__status_status as responsible_status
|
||||||
|
from elma.companies k
|
||||||
|
LEFT OUTER JOIN elma.comp_users_ext c on (k.responsible=c.__id)
|
||||||
|
where k."__deletedAt" IS NULL
|
||||||
|
<cfif len(wz)>
|
||||||
|
AND k.id_klienta like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#wz#%"/>
|
||||||
|
</cfif>
|
||||||
|
</cfquery> --->
|
||||||
|
|
||||||
|
<!--- <cfoutput>qContragent:#getTickCount()-request.startTickCount#</cfoutput>
|
||||||
|
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> --->
|
||||||
|
|
||||||
|
<!--- <cfquery name="qSpec" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 23, 0)#>
|
||||||
|
WITH
|
||||||
|
status(status, status_id, probability_pc)
|
||||||
|
AS (VALUES
|
||||||
|
('Закрыта неуспешно',7,0),('Закрыта успешно',6,100),('Договор подписан',5,100),('Договор на подписании',15,90),('Договор на согласовании',12,70),
|
||||||
|
('Тестирование',8,50),('Отправлено ТКП',10,20),('Внутреннее согласование',37,10),('Проработка решения',4,10),('Сбор потребностей',1,0)
|
||||||
|
)
|
||||||
|
select upper(trim(k.id_klienta)) as wz, k.__id::text as contragent_uid,
|
||||||
|
p.code,
|
||||||
|
SUBSTRING(p.code FROM 1 FOR LENGTH(p.code) - 2) as sku_code,
|
||||||
|
p.price, p.discount as component_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 serviceStart, siv.date_end as serviceEnd, siv.discount as service_discount, siv.cnt as service_quantity
|
||||||
|
/*,p.__name as line_key*/, p.ed_izm, p.name as component, p.type, p.cnt*coalesce(siv.cnt,1) as component_quantity,
|
||||||
|
aa.__name as additional_agreement, aa.__id::text as additional_agreement_uid
|
||||||
|
--, aa.is_actual
|
||||||
|
,siv.end_customer as end_customer_uid
|
||||||
|
,z.id_klienta as end_customer_wz
|
||||||
|
,z.__name as end_customer_name
|
||||||
|
,ft.free_tier
|
||||||
|
,s.probability_pc
|
||||||
|
,siv.__id::text as siv_uid
|
||||||
|
from elma.deals d
|
||||||
|
JOIN STATUS s ON (d.__status_status = s.status_id)
|
||||||
|
join elma.deals_services siv on (d.__id=ANY(siv.deal))
|
||||||
|
--join elma.service_parametrs p on (p.__id = ANY(siv.params))
|
||||||
|
LEFT JOIN LATERAL unnest(siv.params) AS arr(param_id) ON TRUE
|
||||||
|
JOIN elma.service_parametrs p ON (p.__id = arr.param_id)
|
||||||
|
join elma.companies k on (d._companies=k.__id)
|
||||||
|
join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement))
|
||||||
|
join elma.aggrements a on (aa.contract_uid = a.__id)
|
||||||
|
left outer join elma.companies z on (siv.end_customer=z.__id)
|
||||||
|
left outer join (values ('paas.s3.ceph.vol-m',1),('paas.s3.ceph.get-m',10),('paas.s3.ceph.put-m',1),('paas.s3.ceph.trf-m',100)) as ft(code,free_tier) ON (p.code=ft.code)
|
||||||
|
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_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL)/*****/
|
||||||
|
AND aa."__deletedAt" IS NULL
|
||||||
|
AND a."__deletedAt" IS NULL
|
||||||
|
AND d."__deletedAt" IS NULL
|
||||||
|
AND siv."__deletedAt" IS NULL
|
||||||
|
AND p."__deletedAt" IS NULL
|
||||||
|
AND p.cnt <> 0 --похоже, только так можно отфильтровать паразитные строки с нулем
|
||||||
|
<cfif len(wz)>
|
||||||
|
AND k.id_klienta like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#wz#%"/>
|
||||||
|
</cfif>
|
||||||
|
<cfif len(code)>
|
||||||
|
AND p.code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||||
|
</cfif>
|
||||||
|
--AND k.id_klienta='WZ01031'
|
||||||
|
--AND k.id_klienta='WZ01112'
|
||||||
|
order by k.id_klienta, p.code
|
||||||
|
</cfquery> --->
|
||||||
|
<!--- select * from elma.deals_services where __id='019edf9c-c1e8-7acd-8b63-5369e5be5bf5'
|
||||||
|
union all
|
||||||
|
select * from elma.deals_services where __id='019edf9c-c23d-7ad6-a990-643dd09579b8' --->
|
||||||
|
|
||||||
|
<!--- <cfoutput>qSpec:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
<cfif isDefined("DEBUG")>
|
||||||
|
<cfdump var=#qSpec#/>
|
||||||
|
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
</cfif> --->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<cfquery name="qGpu" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
|
||||||
|
select
|
||||||
|
p.ts::date,
|
||||||
|
count(distinct p.obj_uuid) as unique_vm_cnt,
|
||||||
|
count(distinct p.obj_uuid) FILTER (WHERE p.value=1) as unique_vm_cnt_on,
|
||||||
|
round((sum(p.value)/12.)::numeric,1) as vm_h, -- 5 minute sampling
|
||||||
|
round((sum(p.value)/12.*32.18)::numeric,2) as cost,
|
||||||
|
<!--- round((sum(p.value)/12.*32.18*(1-0.02*400/32.18))::numeric,2) as cost_wo_disk,
|
||||||
|
round((count(distinct obj_id)*0.02*400*24)::numeric,2) as disk_cost, -- считаем все ВМ, включавшиеся за данные сутки --->
|
||||||
|
round((sum(p.value)/12./24)::numeric, 1) as avg_roundclock_vm
|
||||||
|
from gpu.vm
|
||||||
|
JOIN gpu.vm_power_state p on (vm.obj_uuid=p.obj_uuid)
|
||||||
|
where 1=1
|
||||||
|
AND p.ts >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
|
||||||
|
AND p.ts < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
|
||||||
|
<cfif len(wz)>
|
||||||
|
AND vm.client_id like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#wz#%"/>
|
||||||
|
</cfif>
|
||||||
|
GROUP BY p.ts::date
|
||||||
|
ORDER BY 1
|
||||||
|
</cfquery>
|
||||||
|
|
||||||
|
<!--- recommended CREATE INDEX idx_tenant_metadata_tenant_ts_desc ON ngcloud_ru.tenant_metadata (tenant_id, ts DESC, metadata_id DESC); --->
|
||||||
|
|
||||||
|
<cfoutput>qComputing:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
|
||||||
|
<cfif isDefined("DEBUG")>
|
||||||
|
<cfdump var=#qComputing#/>
|
||||||
|
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
</cfif>
|
||||||
|
|
||||||
|
<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
|
||||||
|
</cfquery>
|
||||||
|
|
||||||
|
<cfoutput>qComputingAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
<cfset db = new MemoryDbHelper()/>
|
||||||
|
<cfset db.register("qUnifiedMetric", qUnifiedMetric, "inmem")/>
|
||||||
|
<cfset db.register("qContragent", qContragent, "inmem")/>
|
||||||
|
<cfset db.register("qSpec", qSpec, "inmem")/> --->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--- <cfdump var=#qCharge#/> --->
|
||||||
|
|
||||||
|
<cfoutput>qCharge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
<cfif isDefined("DEBUG")>
|
||||||
|
<cfdump var=#qCharge#/>
|
||||||
|
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||||
|
</cfif>
|
||||||
|
|
||||||
|
|
||||||
|
<cfif isDefined("output_xls")>
|
||||||
|
<layout:xml qRead=#qCharge# titleMap=#titleMap# filename="#pageInfo.entity#.xml"/>
|
||||||
|
<cfabort/>
|
||||||
|
</cfif><cfif isDefined("output_json")>
|
||||||
|
<layout:json qRead=#qCharge# titleMap=#titleMap# filename="#pageInfo.entity#.json"/>
|
||||||
|
<cfabort/>
|
||||||
|
</cfif><!---
|
||||||
|
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||||
|
|
||||||
|
<layout:attribute name="title">
|
||||||
|
<cfoutput><b>Отчет по PAYG</b></cfoutput>
|
||||||
|
</layout:attribute>
|
||||||
|
<layout:attribute name="controls">
|
||||||
|
<!---skip filter link, filter is not implemented--->
|
||||||
|
<!---<layout:language_switch/>--->
|
||||||
|
</layout:attribute>
|
||||||
|
</layout:page>
|
||||||
|
|
||||||
|
Факт потребления по основной базе биллинга, спецификации из DWH. Без детализации по бакетам, VDC и т.д.
|
||||||
|
Все запросы кэшированы на 25 минут.<br/>
|
||||||
|
Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе.
|
||||||
|
<b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b>
|
||||||
|
<br/>
|
||||||
|
Даты актуальности пока проверять вручную. Обращать внимание на замножение строк.
|
||||||
|
<cfoutput>
|
||||||
|
<form method="post" action="">
|
||||||
|
Период с <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')#"/>
|
||||||
|
Только PAYG <input type="checkbox" name="only_articles_in_spec" value="1"<cfif only_articles_in_spec> checked</cfif>/>
|
||||||
|
WZ <input type="text" name="wz" value="#wz#"/>по вхождению, с регистром
|
||||||
|
Код <input type="text" name="code" value="#code#"/>по вхождению
|
||||||
|
<input type="submit" style="cursor:pointer;"/>
|
||||||
|
<input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/><!--- #dateFormat( input, "yyyy-mm-dd" )#T#timeFormat( input, "HH:mm:ss.lXX" )# --->
|
||||||
|
</form>
|
||||||
|
Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#qCharge.recordCount#</b><br/>
|
||||||
|
Актуальность данных:
|
||||||
|
VCD Computing: <b<cfif datediff("h",qComputingAge.dt_load, Now()) GT 24> class="err"</cfif>>>#dateFormat(qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(qComputingAge.dt_load,'HH:mm:ss.lXX')#</b>
|
||||||
|
VCD Storage: <b<cfif datediff("h",qStorageAge.dt_load, Now()) GT 24> class="err"</cfif>>>#dateFormat(qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(qStorageAge.dt_load,'HH:mm:ss.lXX')#</b>
|
||||||
|
S3 хранение: <b<cfif datediff("h",qS3VolAge.dt_load, Now()) GT 24> class="err"</cfif>>>#dateFormat(qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3VolAge.dt_load,'HH:mm:ss.lXX')#</b>
|
||||||
|
S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load, Now()) GT 24> class="err"</cfif>>>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3OpsTrfAge.dt_load,'HH:mm:ss.lXX')#</b>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<a href="#request.thisPage#?output_xls" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
|
||||||
|
|
||||||
|
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
||||||
|
</cfoutput>
|
||||||
|
<table class="worktable">
|
||||||
|
<thead>
|
||||||
|
<td width="1%"></td>
|
||||||
|
<!--- <th width="3%">WZ</th> --->
|
||||||
|
<th width="7%">Услуга</th>
|
||||||
|
<th width="7%">Артикул специф.</th>
|
||||||
|
<th width="5%">Кол-во специф.</th>
|
||||||
|
<th width="5%">Артикул метр.</th>
|
||||||
|
<th width="10%">Детализация</th>
|
||||||
|
<th width="5%">Кол-во метр.</th>
|
||||||
|
<th width="5%">Free Tier.</th>
|
||||||
|
<th width="5%">Опл. объем</th>
|
||||||
|
<th width="3%">Ед.изм.</th>
|
||||||
|
<th width="3%">Цена ₽ со скид., с НДС</th>
|
||||||
|
<th width="3%">Стоимость ₽ с НДС</th>
|
||||||
|
|
||||||
|
<td width="3%"> </td>
|
||||||
|
|
||||||
|
<td width="10%">Компонент</td>
|
||||||
|
<td width="15%">Польз. наим.</td>
|
||||||
|
|
||||||
|
<td width="3%">GPL с НДС</td>
|
||||||
|
<td width="3%">Скидка%</td>
|
||||||
|
|
||||||
|
<td width="3%">Дата НОУ</td>
|
||||||
|
<td width="3%">Дата КОУ</td>
|
||||||
|
|
||||||
|
<td width="5%">Ключ строки</td>
|
||||||
|
<td width="3%">Сырая метрика</td>
|
||||||
|
<td width="3%">Приведен­ная метрика</td>
|
||||||
|
|
||||||
|
<td width="3%">Цена ₽ до ск. с НДС</td>
|
||||||
|
<td width="3%">Цена ₽ co ск. с НДС без окр.</td>
|
||||||
|
<td width="3%">Service Quantity</td>
|
||||||
|
<td width="3%">Service Discount</td>
|
||||||
|
<td width="3%">Component Quantity</td>
|
||||||
|
<td width="3%">Component Discount</td>
|
||||||
|
|
||||||
|
<td width="5%">Договор</td>
|
||||||
|
<td width="10%">Допник</td>
|
||||||
|
<td width="10%">Сделка</td>
|
||||||
|
<td width="3%">Конечник</td>
|
||||||
|
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<cfoutput query="qCharge" group="wz">
|
||||||
|
|
||||||
|
<cfset var accum_cost_svc = 0/>
|
||||||
|
<cfset var accum_metric_svc = 0/>
|
||||||
|
<cfset var acc=0/>
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="##ccc"></td>
|
||||||
|
<td bgcolor="##ccc" colspan="99">
|
||||||
|
<b>
|
||||||
|
<a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a>
|
||||||
|
#contragent#
|
||||||
|
<a href="contragent_rpt.cfm?__id=#contragent_uid#&#tr.fwx#">(сводка)</a>
|
||||||
|
</b>
|
||||||
|
ответственный:
|
||||||
|
<span <cfif responsible_status NEQ 2> class="err"</cfif>>#responsible# <a href="mailto:#responsible_email#">#responsible_email#</a></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<cfoutput group="code">
|
||||||
|
<cfoutput group="serviceStart">
|
||||||
|
|
||||||
|
<cfset accum_metric_svc += isNumeric(metric) ? metric : 0/>
|
||||||
|
<cfset accum_metric_dimension_1 = 0/>
|
||||||
|
<cfset current_price=0/>
|
||||||
|
|
||||||
|
<cfoutput><!--- dimensions --->
|
||||||
|
|
||||||
|
<cfif type EQ 3>
|
||||||
|
<cfset accum_metric_dimension_1 += isNumeric(metric) ? metric : 0/>
|
||||||
|
<cfset current_price=gaussianRound(discounted_price, 2)/>
|
||||||
|
</cfif>
|
||||||
|
<!--- детализация --->
|
||||||
|
<tr<cfif !len(unit)> class="gray"</cfif>>
|
||||||
|
<td>#currentRow#</a></td>
|
||||||
|
<td>#abstract_service#<cfif len(modifier)>: #modifier#</cfif></a></td>
|
||||||
|
<td><div<cfif type EQ 3> style="background:lightgreen;color:black;"</cfif>>#s_code#</div></td>
|
||||||
|
<td class=<cfif type EQ 3 AND component_quantity NEQ 1>"err r"<cfelse>"r"</cfif>>#component_quantity#</td>
|
||||||
|
<td>#m_code#</td>
|
||||||
|
<td>#dimension1#</td>
|
||||||
|
<td class="r" style="font-size:110%; padding:0 1em;">#request.roundSafe(metric,3)#</td>
|
||||||
|
<td class="r">#free_tier#</td>
|
||||||
|
<td></td>
|
||||||
|
<td style="font-size:90%;">#unit# <cfif len(ed_izm)>[#ed_izm#]</cfif></td><!--- #len(unit)?unit:'['& ed_izm &']'# --->
|
||||||
|
<td class="r">#gaussianRound(discounted_price,2)#</td>
|
||||||
|
<td class="r"></td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>#component#</td>
|
||||||
|
<td>#user_description#</td>
|
||||||
|
|
||||||
|
<td class="r">#gaussianRoundSafe(price,2)#</td>
|
||||||
|
<td class="r">#component_discount#</td>
|
||||||
|
|
||||||
|
<td class="r">#dateFormat(serviceStart,'YYYY-MM-DD')#</td>
|
||||||
|
<td class="r">#dateFormat(serviceEnd,'YYYY-MM-DD')#</td>
|
||||||
|
|
||||||
|
<td class="r">#line_key#</td>
|
||||||
|
<td class="r" style="color:##bbb">#request.roundSafe(raw_metric,3)#</td>
|
||||||
|
<td class="r">#request.roundSafe(metric,3)#</td>
|
||||||
|
|
||||||
|
<!--- сырые исходные данные без округлений --->
|
||||||
|
<td class="r">#price#</td>
|
||||||
|
<td class="r">#discounted_price#</td><!--- style="word-wrap:break-word" --->
|
||||||
|
<td class="r">#service_quantity#</td>
|
||||||
|
<td class="r">#service_discount#</td>
|
||||||
|
<td class="r">#component_quantity#</td>
|
||||||
|
<td class="r">#component_discount#</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="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
|
||||||
|
<td>#WZE#</td>
|
||||||
|
</tr>
|
||||||
|
</cfoutput>
|
||||||
|
<cfset final_metric_dimension_1 = ceiling(accum_metric_dimension_1)/>
|
||||||
|
<cfset cost_dimension_1 = precisionEvaluate("gaussianRound(max(final_metric_dimension_1 - free_tier, 0)*current_price, 2)")/>
|
||||||
|
<cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/><!--- простое сложение дает ошибку округления и лишние знаки, но и precisionEvaluate не выглядит слишком надежным --->
|
||||||
|
<tr>
|
||||||
|
<td colspan="4"></td>
|
||||||
|
<td colspan="2" class="b r">Итого #code#:</td>
|
||||||
|
<td class="b r" style="font-size:110%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#round(final_metric_dimension_1,3)#</cfif></td>
|
||||||
|
<td class="b r">#free_tier#</td>
|
||||||
|
<td class="b r" style="font-size:120%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#max(ceiling(final_metric_dimension_1) - free_tier, 0)#</cfif></td>
|
||||||
|
<td class="b c">#unit# <cfif len(ed_izm)>[#ed_izm#]</cfif></td>
|
||||||
|
<td class="b r">#current_price#</td>
|
||||||
|
<td class="b r">#gaussianRoundSafe(cost_dimension_1,2)#</td>
|
||||||
|
<td></td>
|
||||||
|
<td colspan="100"></td>
|
||||||
|
</tr>
|
||||||
|
</cfoutput><!--- serviceStart --->
|
||||||
|
</cfoutput><!--- code --->
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
||||||
|
<td bgcolor="##eee" colspan="10" class="r b" style="border-bottom:2px solid gray;">Итого <a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#:</td>
|
||||||
|
<td bgcolor="##eee" class="r b nw" style="border-bottom:2px solid gray; font-size:130%;">#accum_cost_svc#</td>
|
||||||
|
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
||||||
|
<td bgcolor="##eee" colspan="99" style="border-bottom:2px solid gray;"></td>
|
||||||
|
</tr >
|
||||||
|
</cfoutput><!--- wz --->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!--- <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"/>
|
||||||
|
|
||||||
|
<!--- select * from s3billing.billing_per_user_fix_pl('2025-05-01 00:00:00','2025-06-01 00:00:00','1395'); --->
|
||||||
|
|
||||||
|
<!--- select t.id as tenant_id,
|
||||||
|
from ngcloud_ru.tenant t
|
||||||
|
left outer join
|
||||||
|
(select tenant_id, ts, metadata_id,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY tenant_id ORDER BY ts desc, metadata_id desc)
|
||||||
|
as rn
|
||||||
|
from ngcloud_ru.tenant_metadata) tm
|
||||||
|
on (t.id = tm.tenant_id AND tm.rn = 1)
|
||||||
|
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>
|
||||||
@@ -119,8 +119,8 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
|
|||||||
<td>#Organization#</td>
|
<td>#Organization#</td>
|
||||||
|
|
||||||
<td>#VDC#</td>
|
<td>#VDC#</td>
|
||||||
<td><cftry>#round(VDC_CPU_Reserv,3)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(VDC_CPU_Reserv,3)#<cfcatch></cfcatch></cftry></td>
|
||||||
<td><cftry>#round(VDC_CPU_Speed,3)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(VDC_CPU_Speed,3)#<cfcatch></cfcatch></cftry></td>
|
||||||
|
|
||||||
<td>#qVM.Cluster#</td>
|
<td>#qVM.Cluster#</td>
|
||||||
|
|
||||||
@@ -129,19 +129,19 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
|
|||||||
<td>#CPU_Model#</td>
|
<td>#CPU_Model#</td>
|
||||||
<td>#Host_CPU_Cores#</td>
|
<td>#Host_CPU_Cores#</td>
|
||||||
<td>#Host_CPU_Sockets#</td>
|
<td>#Host_CPU_Sockets#</td>
|
||||||
<td>#round(Host_CPU_Speed,3)#</td>
|
<td>#request.roundSafe(Host_CPU_Speed,3)#</td>
|
||||||
<td>#round(Host_RAM)#</td>
|
<td>#request.roundSafe(Host_RAM)#</td>
|
||||||
<td><cftry>#round(Host_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(Host_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||||
<td><cftry>#round(Host_CPU_Used_Avg,1)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(Host_CPU_Used_Avg,1)#<cfcatch></cfcatch></cftry></td>
|
||||||
|
|
||||||
<td>#VM_vCPU_count#</td>
|
<td>#VM_vCPU_count#</td>
|
||||||
<td><cftry>#round(VM_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(VM_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||||
<td><cftry>#round(VM_CPU_Used_AVG,1)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(VM_CPU_Used_AVG,1)#<cfcatch></cfcatch></cftry></td>
|
||||||
<td><cftry>#round(VM_CPU_Reserv_GHz,1)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(VM_CPU_Reserv_GHz,1)#<cfcatch></cfcatch></cftry></td>
|
||||||
<td>#VM_CPU_Reserv_perc#</td>
|
<td>#VM_CPU_Reserv_perc#</td>
|
||||||
|
|
||||||
<td>#VM_RAM_Allocated#</td>
|
<td>#VM_RAM_Allocated#</td>
|
||||||
<td><cftry>#round(VM_RAM_Used)#<cfcatch></cfcatch></cftry></td>
|
<td><cftry>#request.roundSafe(VM_RAM_Used)#<cfcatch></cfcatch></cftry></td>
|
||||||
|
|
||||||
<td>#VM_is_ON#</td>
|
<td>#VM_is_ON#</td>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user