Compare commits
8
Commits
beeb83cda5
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96a283dd08 | ||
|
|
26451cbd1d | ||
|
|
3db978003f | ||
|
|
a527dd66e7 | ||
|
|
1875c3a3d8 | ||
|
|
95fcd10c41 | ||
|
|
ac113a8cf7 | ||
|
|
98af1aa4b9 |
+5
-4
@@ -13,9 +13,10 @@
|
||||
<cfset this.setclientcookies="No"/>
|
||||
<cfset this.mappings = structNew() />
|
||||
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
|
||||
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath())&'mod')/>
|
||||
<cfset this.datasource = "dwh"/>
|
||||
|
||||
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath())&'mod')/>
|
||||
<cfset this.timeZone = "Europe/Moscow"/><!--- для биллинга очень важен часовой пояс, поэтому ставим вручную в коде --->
|
||||
<cfset this.datasource = "dwh"/>
|
||||
|
||||
<cfset this.defaultdatasource = this.datasource/>
|
||||
<cfset request.DS = "#this.datasource#">
|
||||
<!--- кажется, нужно инициализировать датасорцы в псевдоконструкторе - onRequest не получается --->
|
||||
@@ -86,7 +87,7 @@
|
||||
|
||||
<!--- global settings --->
|
||||
<!--- *************************************************************************************************** --->
|
||||
<cfset request.APP_VERSION="0.00.077"/> <!--- *********************************************************** --->
|
||||
<cfset request.APP_VERSION="0.00.084"/> <!--- *********************************************************** --->
|
||||
<!--- *************************************************************************************************** --->
|
||||
<cfset request.STAND=getStand()/>
|
||||
<cfset request.RECORDS_PER_PAGE=500/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<cfdump var=#{
|
||||
"Template Charset (File compilation)": getPageContext().getConfig().getTemplateCharset(),
|
||||
"Web Charset (Forms, URLs, Responses)": getPageContext().getConfig().getWebCharset(),
|
||||
"Resource Charset (File system reads/writes)": getPageContext().getConfig().getResourceCharset()
|
||||
"Resource Charset (File system reads/writes)": getPageContext().getConfig().getResourceCharset(),
|
||||
"Time Zone": getTimeZone()
|
||||
}#/>
|
||||
+13
-5
@@ -21,10 +21,10 @@
|
||||
<cfquery name="qRead" datasource="#request.DS#">
|
||||
select
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="ID" cfSqlType="CF_SQL_OTHER">d.__id</d:field>
|
||||
<d:field title="ID" cfSqlType="CF_SQL_OTHER">d.__id::text as __id</d:field>
|
||||
<d:field title="Внут.номер">d.agreement_id</d:field>
|
||||
<d:field title="Договор">d.__name</d:field>
|
||||
<d:field title="company_uid">d.company_uid</d:field>
|
||||
<d:field title="company_uid">d.company_uid::text as company_uid</d:field>
|
||||
<d:field title="Контрагент">k.__name as contragent</d:field>
|
||||
<d:field title="WZ">k.id_klienta as wz</d:field>
|
||||
<d:field title="Дата договора">d.date_of_aggrement</d:field>
|
||||
@@ -33,15 +33,23 @@
|
||||
<d:field title="Ответственный за к/а">c.__name as responsible</d:field>
|
||||
<d:field title="Email отв-го">c.email as responsible_email</d:field>
|
||||
<d:field title="Статус">c.__status_status as responsible_status</d:field>
|
||||
<d:field title="Доп. соглашений">(select count(*) from elma.additional_agreements a where a.contract_uid=d.__id AND a."__deletedAt" IS NULL) as aa_cnt</d:field>
|
||||
<!--- <d:field title="Доп. соглашений">COALESCE(a.aa_cnt, 0) AS aa_cnt</d:field> --->
|
||||
<d:field title="Доп. соглашений">a.aa_cnt</d:field>нас null вместо 0 совершенно устраивает
|
||||
</d:field_set>
|
||||
from elma.aggrements d
|
||||
LEFT OUTER JOIN elma.companies k ON (d.company_uid=k.__id)
|
||||
LEFT OUTER JOIN elma.comp_users_ext c ON (k.responsible=c.__id)
|
||||
LEFT OUTER JOIN (
|
||||
SELECT contract_uid, count(*) AS aa_cnt
|
||||
FROM elma.additional_agreements
|
||||
WHERE "__deletedAt" IS NULL
|
||||
GROUP BY contract_uid
|
||||
) a ON (a.contract_uid = d.__id)
|
||||
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
|
||||
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
|
||||
</cfquery>
|
||||
|
||||
<!--- <cfdump var=#qRead#/> --->
|
||||
|
||||
<cfcatch type="database">
|
||||
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
|
||||
@@ -116,10 +124,10 @@ select count(*) as cnt from elma.aggrements d where 1=1
|
||||
<c:column width="1%" sortable="false"><!---*** class="c" не пробрасывается --->
|
||||
<c:td field="f_link_view_edit" class="c"/>
|
||||
</c:column>
|
||||
<c:column width="10%" field="__id"><c:td class="l"/></c:column>
|
||||
<c:column width="10%" field="__id" sortable=false><c:td class="l"/></c:column>
|
||||
<c:column width="10%" field="f_contract"/>
|
||||
<c:column width="10%" field="agreement_id"/>
|
||||
<c:column width="10%" field="company_uid"/>
|
||||
<c:column width="10%" field="company_uid" sortable=false/>
|
||||
<c:column width="10%" field="f_contragent"/>
|
||||
<c:column width="10%" field="wz"/>
|
||||
<c:column width="10%" field="responsible"/>
|
||||
|
||||
+22
-4
@@ -31,12 +31,30 @@
|
||||
<d:field title="Создано">k."__createdAt" as __createdAt</d:field>
|
||||
<d:field title="Обновлено">k."__updatedAt" as __updatedAt</d:field>
|
||||
<d:field title="Удалено">k."__deletedAt" as __deletedAt</d:field>
|
||||
<d:field title="Сделок">(select count(*) from elma.deals d where d._companies=k.__id) as deal_cnt</d:field>
|
||||
<d:field title="Договоров">(select count(*) from elma.aggrements d where d.company_uid=k.__id) as contract_cnt</d:field>
|
||||
<d:field title="Допников">(select count(*) from elma.additional_agreements g join elma.aggrements d on (g.contract_uid=d.__id) where d.company_uid=k.__id) as aa_cnt</d:field>
|
||||
<d:field title="Сделок">COALESCE(dc.deal_cnt, 0) AS deal_cnt</d:field>
|
||||
<d:field title="Договоров">COALESCE(cc.contract_cnt, 0) AS contract_cnt</d:field>
|
||||
<d:field title="Допников">COALESCE(aac.aa_cnt, 0) AS aa_cnt</d:field>
|
||||
</d:field_set>
|
||||
from elma.companies k
|
||||
LEFT OUTER JOIN elma.comp_users_ext c on (k.responsible=c.__id)
|
||||
LEFT JOIN (
|
||||
SELECT _companies AS company_id, count(*) AS deal_cnt
|
||||
FROM elma.deals
|
||||
GROUP BY _companies
|
||||
) dc ON dc.company_id = k.__id
|
||||
-- Считаем договоры
|
||||
LEFT JOIN (
|
||||
SELECT company_uid, count(*) AS contract_cnt
|
||||
FROM elma.aggrements
|
||||
GROUP BY company_uid
|
||||
) cc ON cc.company_uid = k.__id
|
||||
-- Считаем доп. соглашения
|
||||
LEFT JOIN (
|
||||
SELECT d.company_uid, count(*) AS aa_cnt
|
||||
FROM elma.additional_agreements g
|
||||
JOIN elma.aggrements d ON g.contract_uid = d.__id
|
||||
GROUP BY d.company_uid
|
||||
) aac ON aac.company_uid = k.__id
|
||||
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
|
||||
--AND exists (select * from elma.deals d where d._companies=k.__id)
|
||||
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
|
||||
@@ -109,7 +127,7 @@ select count(*) as cnt from elma.companies where 1=1
|
||||
<c:column width="1%" sortable="false">
|
||||
<c:td field="f_link_view_edit" class="c"/>
|
||||
</c:column>
|
||||
<c:column width="10%" field="__id"/>
|
||||
<c:column width="10%" field="__id" sortable="false"/>
|
||||
<c:column width="3%" field="__index"><c:td class="c"/></c:column>
|
||||
<c:column width="20%" field="f_contragent"/>
|
||||
<c:column width="5%" field="wz"/>
|
||||
|
||||
+2
-80
@@ -44,91 +44,13 @@
|
||||
|
||||
|
||||
select
|
||||
count(distinct obj_id) as unique_vm_cnt,
|
||||
sum(p.value)/12. as vm_h, -- 5 minute sampling
|
||||
sum(p.value)/12.*32.18 as cost,
|
||||
sum(p.value)/12./744 as avg_month_vm -- в августе 744 часа
|
||||
count(distinct obj)
|
||||
sum(p.value)/12. as vm_h -- 5 minute sampling
|
||||
from gpu.vm
|
||||
JOIN gpu.vm_power_state p on (vm.obj_uuid=p.obj_uuid)
|
||||
where 1=1
|
||||
AND p.ts >= '2026-08-01'
|
||||
AND p.ts < '2026-08-31'
|
||||
AND vm.client_id='WZ01516'
|
||||
-- упражнение: посчитать, сколько средних ВМ, включенных круглые сутки, создаст такой же движ за время оказания сервиса
|
||||
|
||||
select
|
||||
p.ts::date,
|
||||
count(distinct obj_id) as unique_vm_cnt,
|
||||
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./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 >= '2026-08-01'
|
||||
AND p.ts < '2026-08-31'
|
||||
AND vm.client_id='WZ01516'
|
||||
GROUP BY p.ts::date
|
||||
ORDER BY 1
|
||||
|
||||
select
|
||||
p.ts::date,
|
||||
count(distinct obj_id) as unique_vm_cnt,
|
||||
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_simplified, -- считаем все ВМ, включавшиеся за данные сутки
|
||||
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 >= '2026-08-01'
|
||||
AND p.ts < '2026-08-31'
|
||||
AND vm.client_id='WZ01516'
|
||||
GROUP BY p.ts::date
|
||||
ORDER BY 1
|
||||
|
||||
select
|
||||
p.ts::date,
|
||||
count(distinct obj_id) as unique_vm_cnt,
|
||||
(select count(distinct obj_id) from gpu.vm vm1
|
||||
JOIN gpu.vm_power_state p1 on (vm1.obj_uuid=p1.obj_uuid)
|
||||
WHERE vm1.client_id='WZ01516' AND p1.ts <= p.ts::date) as unique_vm_acc,
|
||||
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_simplified, -- считаем все ВМ, включавшиеся за данные сутки
|
||||
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 >= '2026-08-01'
|
||||
AND p.ts < '2026-08-31'
|
||||
AND vm.client_id='WZ01516'
|
||||
GROUP BY p.ts::date
|
||||
ORDER BY 1
|
||||
|
||||
|
||||
with daily as (
|
||||
select
|
||||
p.ts::date as dt,
|
||||
count(distinct obj_id) as unique_vm_cnt,
|
||||
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_simplified, -- считаем все ВМ, включавшиеся за данные сутки
|
||||
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 >= '2026-08-01'
|
||||
AND p.ts < '2026-08-31'
|
||||
AND vm.client_id='WZ01516'
|
||||
GROUP BY p.ts::date
|
||||
ORDER BY 1
|
||||
),
|
||||
acc as (select p.ts::date as dt, count(distinct obj_id) as unique_vm_accum from gpu.vm
|
||||
JOIN gpu.vm_power_state p on (vm.obj_uuid=p.obj_uuid)
|
||||
WHERE vm.client_id='WZ01516'
|
||||
group by p.ts::date)
|
||||
select * from daily join acc on daily.dt<=acc.dt
|
||||
|
||||
+33
-112
@@ -10,25 +10,13 @@
|
||||
|
||||
|
||||
|
||||
<cfquery name="qVM" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
|
||||
select "Name", "Object_UUID", "UUID_VM",
|
||||
"VDC", "Organization_UUID", "Organization", "WZ", "Cluster", "Host",
|
||||
"Host_Model", "CPU_Model", "Host_CPU_Cores", "Host_CPU_Sockets", "Host_CPU_Speed", "Host_RAM",
|
||||
"Host_CPU_Used", "Host_CPU_Used_Avg",
|
||||
"VDC_CPU_Reserv", "VDC_CPU_Speed",
|
||||
"VM_vCPU_count", "VM_CPU_Used", "VM_CPU_Used_AVG", "VM_CPU_Reserv_GHz", "VM_CPU_Reserv_perc",
|
||||
"VM_RAM_Allocated", "VM_RAM_Used",
|
||||
"VM_is_ON",
|
||||
k.__id as company_uid
|
||||
from vmreports.compute c
|
||||
left outer join elma.companies k ON (lower(k.id_klienta)=lower(c."WZ"))
|
||||
where c.ts=(select max(ts) from vmreports.compute)
|
||||
--order by "WZ"
|
||||
<cfquery name="qGPU" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
|
||||
select obj_uuid, obj_id, client_id as WZ, vcd, org, org_vdc, vcenter, gpu, dt_load, dt_load_ts, org_status, cluster as clus, is_template
|
||||
from gpu.vm
|
||||
order by client_id
|
||||
</cfquery>
|
||||
|
||||
<!--- <cfdump var=#qVM# abort=true/> --->
|
||||
|
||||
|
||||
|
||||
<!--- <cfdump var=#qGPU# abort=true/> --->
|
||||
|
||||
<cfif isDefined("output_xls")>
|
||||
<layout:xml qRead=#qCharge# titleMap=#titleMap# filename="#pageInfo.entity#.xml"/>
|
||||
@@ -40,7 +28,7 @@ where c.ts=(select max(ts) from vmreports.compute)
|
||||
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||
|
||||
<layout:attribute name="title">
|
||||
<cfoutput><b>Сверка CRM - Cloud</b></cfoutput>
|
||||
<cfoutput><b>VM с GPU</b></cfoutput>
|
||||
</layout:attribute>
|
||||
<layout:attribute name="controls">
|
||||
<!---skip filter link, filter is not implemented--->
|
||||
@@ -51,111 +39,44 @@ where c.ts=(select max(ts) from vmreports.compute)
|
||||
<!--- <cfdump var=#qReconciliation# abort=true/> --->
|
||||
|
||||
<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')#"/>
|
||||
<input type="submit" style="cursor:pointer;"/>
|
||||
<input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/>
|
||||
</form> --->
|
||||
<!--- Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#qCharge.recordCount#</b><br/>
|
||||
Актуальность данных:
|
||||
VCD Computing: <b>#dateFormat(qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(qComputingAge.dt_load,'HH:MM:SS')#</b>
|
||||
VCD Storage: <b>#dateFormat(qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(qStorageAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 хранение: <b>#dateFormat(qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3VolAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3OpsTrfAge.dt_load,'HH:MM:SS')#</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>
|
||||
<cfoutput><b>#qVM.recordCount#</b></cfoutput>
|
||||
<cfoutput><b>#qGPU.recordCount#</b></cfoutput>
|
||||
<table class="worktable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%">WZ</th>
|
||||
<th width="5%">Имя</th>
|
||||
<th width="5%">Уникальное имя</th>
|
||||
|
||||
<th width="3%">Organization</th>
|
||||
|
||||
<th width="3%">VDC</th>
|
||||
<th width="3%">VDC CPU Reserv</th>
|
||||
<th width="3%">VDC CPU Speed GHz</th>
|
||||
|
||||
<th width="3%">Cluster</th>
|
||||
|
||||
<th width="3%">Host</th>
|
||||
<th width="7%">Host Model</th>
|
||||
<th width="7%">CPU Model</th>
|
||||
<th width="3%">Host CPU Cores</th>
|
||||
<th width="3%">Host CPU Sockets</th>
|
||||
<th width="3%">Host CPU Speed GHz</th>
|
||||
<th width="3%">Host RAM GB</th>
|
||||
<th width="3%">Host CPU Used</th>
|
||||
<th width="3%">Host CPU Used_Avg</th>
|
||||
|
||||
<th width="3%">VM vCPU count</th>
|
||||
<th width="3%">VM CPU Used</th>
|
||||
<th width="3%">VM CPU Used AVG</th>
|
||||
<th width="3%">VM CPU Reserv GHz</th>
|
||||
<th width="3%">VM CPU Reserv perc</th>
|
||||
|
||||
<th width="3%">VM RAM Allocated GB</th>
|
||||
<th width="3%">VM RAM Used GB</th>
|
||||
|
||||
<th width="3%">VM is ON</th>
|
||||
|
||||
<th width="5%">WZ</th>
|
||||
<th width="5%">obj_uuid</th>
|
||||
<th width="5%">obj_id</th>
|
||||
<th width="3%">org</th>
|
||||
<th width="3%">org_vdc</th>
|
||||
<th width="3%">gpu</th>
|
||||
<th width="3%">dt_load</th>
|
||||
<th width="3%">dt_load_ts</th>
|
||||
<th width="7%">cluster</th>
|
||||
<th width="3%">is_template</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<cfoutput query="qVM">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td><a href="contragent.cfm?__id=#company_uid#&#tr.fwx#">#WZ#</a><a href="contragent_rpt.cfm?__id=#company_uid#&#tr.fwx#" style="float:right"><img src="img/view.gif" title="сводка по контрагенту"/></a></td>
|
||||
<td>#Name#</td>
|
||||
<td>#UUID_VM#</td>
|
||||
<td>#Organization#</td>
|
||||
|
||||
<td>#VDC#</td>
|
||||
<td><cftry>#round(VDC_CPU_Reserv,3)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#round(VDC_CPU_Speed,3)#<cfcatch></cfcatch></cftry></td>
|
||||
|
||||
<td>#qVM.Cluster#</td>
|
||||
|
||||
<td>#Host#</td>
|
||||
<td>#Host_Model#</td>
|
||||
<td>#CPU_Model#</td>
|
||||
<td>#Host_CPU_Cores#</td>
|
||||
<td>#Host_CPU_Sockets#</td>
|
||||
<td>#round(Host_CPU_Speed,3)#</td>
|
||||
<td>#round(Host_RAM)#</td>
|
||||
<td><cftry>#round(Host_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#round(Host_CPU_Used_Avg,1)#<cfcatch></cfcatch></cftry></td>
|
||||
|
||||
<td>#VM_vCPU_count#</td>
|
||||
<td><cftry>#round(VM_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#round(VM_CPU_Used_AVG,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#round(VM_CPU_Reserv_GHz,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td>#VM_CPU_Reserv_perc#</td>
|
||||
|
||||
<td>#VM_RAM_Allocated#</td>
|
||||
<td><cftry>#round(VM_RAM_Used)#<cfcatch></cfcatch></cftry></td>
|
||||
|
||||
<td>#VM_is_ON#</td>
|
||||
|
||||
|
||||
<!--- <td><a href="contragent.cfm?__id=#company_uid#&#tr.fwx#">#client_sold#</a></td> --->
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<cfoutput query="qGPU">
|
||||
<tr>
|
||||
<td><a href="contragent.cfm?wz=#WZ#&#tr.fwx#">#WZ#</a></td>
|
||||
<td>#obj_uuid#</td>
|
||||
<td>#obj_id#</td>
|
||||
<td>#org#</td>
|
||||
<td>#org_vdc#</td>
|
||||
<td>#gpu#</td>
|
||||
<td>#dateFormat(dt_load, "YYYY-MM-DD")# #timeFormat(dt_load, "HH:MM")#</td>
|
||||
<td>#dateFormat(dt_load_ts, "YYYY-MM-DD")# #timeFormat(dt_load_ts, "HH:MM")#</td>
|
||||
<td>#clus#</td>
|
||||
<td>#is_template#</td>
|
||||
</tr>
|
||||
</cfoutput>
|
||||
|
||||
|
||||
</table>
|
||||
<!--- <cfdump var=#qCharge#/> --->
|
||||
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ function skuCode(area_code="", abstract_service_code="") {
|
||||
}
|
||||
request.skuCode = skuCode;
|
||||
*/
|
||||
function roundSafe(a, precision) {
|
||||
function roundSafe(a, precision=0) {
|
||||
return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a;
|
||||
}
|
||||
request.roundSafe = roundSafe;
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
<c:menu_item acl="" page="deal_ls.cfm" label="Сделки"/>
|
||||
|
||||
<c:menu_item acl="" page="vm_ls.cfm" label="VM"/>
|
||||
<c:menu_item acl="" page="gpu_ls.cfm" label="GPU"/>
|
||||
|
||||
<li class="menu-title">Отчеты</li>
|
||||
<c:menu_item acl="" page="crm2cloud.cfm" label="CRM - Cloud"/>
|
||||
<c:menu_item acl="" page="cloud_capacity.cfm" label="Cloud Capacity"/>
|
||||
<c:menu_item acl="" page="payg.cfm" label="PAYG"/>
|
||||
<c:menu_item acl="" page="test_storage_rpt.cfm" label="Тесты и хранение"/>
|
||||
<c:menu_item acl="" page="vm_gpu_rpt.cfm" label="Аэроплан"/>
|
||||
|
||||
<li class="menu-title">Справочники</li>
|
||||
|
||||
|
||||
@@ -13,9 +13,14 @@
|
||||
<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=""/>
|
||||
|
||||
<cfparam name="local.only_articles_in_spec" type="boolean" default=#structIsEmpty(form)? true : (form?.only_articles_in_spec GT 0)# /> <!--- не вполне корректный способ определить наличие формы, если там все чекбоксы и ни один не выбран... --->
|
||||
<cfparam name="local.inner_join" type="boolean" default=#structIsEmpty(form)? true : (form?.inner_join GT 0)# />
|
||||
|
||||
|
||||
<cfparam name="code" default=""/>
|
||||
|
||||
<!--- *** коды лучше взять из каталога --->
|
||||
<cfquery name="qCode" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 20, 0)#>
|
||||
select distinct p.code
|
||||
@@ -64,7 +69,7 @@
|
||||
,siv.end_customer as end_customer_uid
|
||||
,z.id_klienta as end_customer_wz
|
||||
,z.__name as end_customer_name
|
||||
,ft.free_tier
|
||||
--,ft.free_tier
|
||||
,s.probability_pc
|
||||
,siv.__id::text as siv_uid
|
||||
from elma.deals d
|
||||
@@ -77,7 +82,7 @@
|
||||
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)/*****/
|
||||
@@ -89,6 +94,9 @@
|
||||
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'
|
||||
@@ -329,33 +337,109 @@ select
|
||||
<cfoutput>qS3OpsTrfAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||
|
||||
|
||||
|
||||
<!--- выданы права на схему и таблицы, чтобы без толку не плодить источники данных --->
|
||||
<!--- считаются часы работы ВМ с GPU --->
|
||||
<cfquery name="qGpu" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 31, 0)#>
|
||||
WITH card (model, cluster, code) as (VALUES
|
||||
('A100', 'msk1-pub02-i31', 'iaas.ngc.i31.gpu80'),
|
||||
('H100', 'msk1-pub07-a40', 'iaas.ngc.a40.gpuh100'), -- h200 нет в отчете
|
||||
('RTX 4090', 'msk1-pcs05-a45', 'iaas.ngc.a45.gpu4090'), -- нет такого в каталоге
|
||||
('RTX 5090', 'msk1-pcs05-a45', 'iaas.ngc.a45.gpu5090'),
|
||||
('RTX 6000', 'msk1-pub07-a40', 'iaas.ngc.a40.gpu6k'),
|
||||
('nvidia_a16-16q', 'msk1-pub07-a40', 'iaas.ngc.a40.gpu16'),
|
||||
('nvidia_a16-16q', 'msk1-pub01-i29', 'iaas.ngc.i29.gpu16'),
|
||||
('nvidia_a16-1b', 'msk1-pub07-a40', 'iaas.ngc.a40.gpu1'),
|
||||
('nvidia_a16-2q', 'msk1-pub07-a40', 'iaas.ngc.a40.gpu2'),
|
||||
('nvidia_a16-4q', 'msk1-pub07-a40', 'iaas.ngc.a40.gpu4'),
|
||||
('nvidia_rtx_pro_6000_blackwell_dc-4q', 'msk1-pub07-a40', 'iaas.ngc.a40.gpu6k4')
|
||||
)
|
||||
SELECT item.key AS gpu_model, c.code
|
||||
,SUM(item.value::int*p.value)/12. AS gpu_h -- 5 minute sampling
|
||||
,vm.obj_id, upper(trim(vm.client_id)) as WZ
|
||||
FROM gpu.vm
|
||||
CROSS JOIN LATERAL jsonb_each(vm.gpu) AS item(key, value)
|
||||
LEFT OUTER JOIN card c ON (item.key=c.model)
|
||||
JOIN gpu.vm_power_state p ON (vm.obj_uuid=p.obj_uuid)
|
||||
WHERE NOT vm.is_template
|
||||
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)#/>
|
||||
GROUP BY vm.client_id, item.key, c.code, vm.obj_id
|
||||
ORDER BY vm.client_id, item.key, c.code, vm.obj_id;
|
||||
</cfquery>
|
||||
|
||||
<cfoutput>qGpu:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||
|
||||
<cfif isDefined("DEBUG")>
|
||||
<cfdump var=#qGpu#/>
|
||||
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qGpuAge" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 31, 0)#>
|
||||
select max(dt_load) as dt_load from gpu.vm
|
||||
</cfquery>
|
||||
|
||||
<cfoutput>qGpuAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<cfquery name="qUnifiedMetric" dbType="query">
|
||||
select wz, code || '.vcpu' as code, core_h as raw_metric, core_h as metric, 'core-h' as unit, vdc as dimension1
|
||||
from qComputing
|
||||
<cfif len(code)>
|
||||
where code || '.vcpu' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code || '.ram', gb_h as raw_metric, gb_h as metric, 'GByte-h' as unit, vdc as dimension1
|
||||
from qComputing
|
||||
<cfif len(code)>
|
||||
where code || '.ram' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code, gb_m_used as raw_metric, gb_m_used as metric, 'GByte-m' as unit, vdc ||':'|| profile as dimension1
|
||||
from qStorage
|
||||
<cfif len(code)>
|
||||
where code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code || '.vol', vol_b as raw_metric, vol_gb as metric, 'GByte-m' as unit, bucket as dimension1
|
||||
from qS3Vol
|
||||
<cfif len(code)>
|
||||
where code || '.vol' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code || '.get', get as raw_metric, get_10k as metric, '10k' as unit, bucket as dimension1
|
||||
from qS3OpsTrf
|
||||
<cfif len(code)>
|
||||
where code || '.get' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code || '.put', put as raw_metric, put_10k as metric, '10k' as unit, bucket as dimension1
|
||||
from qS3OpsTrf
|
||||
<cfif len(code)>
|
||||
where code || '.put' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code || '.trf', bytes_sent as raw_metric, bytes_sent_gb as metric, 'GByte' as unit, bucket as dimension1
|
||||
from qS3OpsTrf
|
||||
<cfif len(code)>
|
||||
where code || '.trf' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
union all
|
||||
select wz, code, gpu_h as raw_metric, gpu_h as metric, 'h' as unit, obj_id as dimension1
|
||||
from qGpu
|
||||
<cfif len(code)>
|
||||
where code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
|
||||
</cfif>
|
||||
|
||||
order by wz, code
|
||||
</cfquery>
|
||||
@@ -404,10 +488,10 @@ SELECT
|
||||
<d:field title="Артикул по специф.">s.code as s_code</d:field><!--- содержит суффикс типа тарификации --->
|
||||
<d:field title="SKU code по специф.">s.sku_code as sku_code</d:field><!--- без суффикса --->
|
||||
<d:field title="Артикул по метрикам">m.code as m_code</d:field><!--- без суффикса --->
|
||||
<d:field title="Кол-во компонента по спец.">s.component_quantity</d:field>
|
||||
<d:field title="Кол-во сервиса по спец.">s.service_quantity</d:field>
|
||||
<d:field title="Скидка на сервис">s.service_discount</d:field>
|
||||
<d:field title="Free Tier">coalesce(s.free_tier,0) as free_tier</d:field>
|
||||
<d:field title="Кол-во компонента по спец." cfSqlType="CF_SQL_NUMERIC">s.component_quantity</d:field>
|
||||
<d:field title="Кол-во сервиса по спец." cfSqlType="CF_SQL_NUMERIC">s.service_quantity</d:field>
|
||||
<d:field title="Скидка на сервис" cfSqlType="CF_SQL_NUMERIC">s.service_discount</d:field>
|
||||
<d:field title="Free Tier" cfSqlType="CF_SQL_NUMERIC">coalesce(ft.free_tier,0) as free_tier</d:field>
|
||||
<d:field>m.dimension1</d:field>
|
||||
<d:field title="Тип по спец.">s.type</d:field>
|
||||
<d:field title="Ед.изм.">m.unit</d:field>
|
||||
@@ -436,9 +520,16 @@ SELECT
|
||||
<d:field title="Модификатор">s.modifier</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Клиентс. назв.">s.user_description</d:field>
|
||||
<d:field title="Pricing Model">CASE s.type WHEN 1 THEN 'install' WHEN 2 THEN 'fix' WHEN 3 THEN 'payg' ELSE NULL END as pricing_model</d:field>
|
||||
</d:field_set>
|
||||
FROM qUnifiedMetric m
|
||||
FULL JOIN qSpec s ON (m.wz=s.wz AND m.code=s.sku_code) -- сервис или компонент, но не цена с типом тарификации, суффикс типа тарификации отрезан
|
||||
<cfif local.inner_join>
|
||||
<cfelse>
|
||||
FULL
|
||||
</cfif>
|
||||
JOIN qSpec s ON (m.wz=s.wz AND m.code=s.sku_code) -- сервис или компонент, но не цена с типом тарификации, суффикс типа тарификации отрезан
|
||||
--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 (m.code=ft.code)
|
||||
left outer join (values ('paas.s3.ceph.vol',1),('paas.s3.ceph.get',10),('paas.s3.ceph.put',1),('paas.s3.ceph.trf',100)) as ft(code,free_tier) ON (m.code=ft.code)
|
||||
LEFT JOIN qContragent c ON ((coalesce(s.wz,m.wz))=(c.wz)) -- пробелы в составе WZ стоили нескольких часов работы
|
||||
--(поскольку trim слева в джойне катастрофически замедляет работу, делаем чистку выше при формировании исходных резалтсетов)
|
||||
WHERE 1=1
|
||||
@@ -498,17 +589,22 @@ ORDER BY coalesce(coalesce(c.wz, m.wz), s.wz), coalesce(s.code, m.code)
|
||||
<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="checkbox" name="only_articles_in_spec" id="only_articles_in_spec" value="1"<cfif local.only_articles_in_spec> checked</cfif>/><label for="only_articles_in_spec">Только PAYG </label>
|
||||
<input type="checkbox" name="inner_join" id="inner_join" value="1"<cfif local.inner_join> checked</cfif>/><label for="inner_join">Только найденные в договоре</label>
|
||||
|
||||
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;"/>
|
||||
<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')#</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')#</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')#</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')#</b>
|
||||
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>
|
||||
@@ -519,6 +615,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
<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>
|
||||
@@ -532,9 +629,8 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
|
||||
<td width="3%"> </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%">Скидка%</td>
|
||||
@@ -583,18 +679,19 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
|
||||
<cfset accum_metric_svc += isNumeric(metric) ? metric : 0/>
|
||||
<cfset accum_metric_dimension_1 = 0/>
|
||||
<cfset accum_metric_dimension_1_all = 0/><!--- не различая PAYG/FIX --->
|
||||
<cfset current_price=0/>
|
||||
|
||||
<cfoutput><!--- dimensions --->
|
||||
|
||||
<cfoutput><!--- dimensions --->
|
||||
<cfif type EQ 3>
|
||||
<cfset accum_metric_dimension_1 += isNumeric(metric) ? metric : 0/>
|
||||
<cfset current_price=gaussianRound(discounted_price, 2)/>
|
||||
</cfif>
|
||||
<cfset accum_metric_dimension_1_all += isNumeric(metric) ? metric : 0/>
|
||||
<!--- детализация --->
|
||||
<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>
|
||||
@@ -608,7 +705,6 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
|
||||
<td></td>
|
||||
|
||||
<td>#abstract_service# #modifier#</td>
|
||||
<td>#component#</td>
|
||||
<td>#user_description#</td>
|
||||
|
||||
@@ -624,7 +720,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
|
||||
<!--- сырые исходные данные без округлений --->
|
||||
<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_discount#</td>
|
||||
<td class="r">#component_quantity#</td>
|
||||
@@ -637,18 +733,21 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
</tr>
|
||||
</cfoutput>
|
||||
<cfset final_metric_dimension_1 = ceiling(accum_metric_dimension_1)/>
|
||||
<cfset final_metric_dimension_1_all = ceiling(accum_metric_dimension_1_all)/>
|
||||
<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="3"></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 colspan="4"></td>
|
||||
<td colspan="2" class="b r">Итого #code#:</td>
|
||||
<td class="b r" style="font-size:110%; padding:0 1em;">#accum_metric_dimension_1#<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="8"></td>
|
||||
<td class="b r" title="сумма корректна, если нет замножения строк из-за наличия PAYG и FIX по одному артикулу">#request.roundSafe(accum_metric_dimension_1_all,3)#<!--- #final_metric_dimension_1_all# ---></td>
|
||||
<td colspan="100"></td>
|
||||
</tr>
|
||||
</cfoutput><!--- serviceStart --->
|
||||
@@ -656,7 +755,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
|
||||
|
||||
<tr>
|
||||
<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" style="border-bottom:2px solid gray;"></td>
|
||||
<td bgcolor="##eee" colspan="99" style="border-bottom:2px solid gray;"></td>
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
<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_rpt" 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="qRead" datasource="billing-s3">
|
||||
select
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Час" cfSqlType="CF_SQL_TIMESTAMP">DATE_TRUNC('hour',p.ts) as ts_hour</d:field>
|
||||
<d:field title="Уникальных ВМ" cfSqlType="CF_SQL_INTEGER">count(distinct p.obj_uuid) as unique_vm_cnt</d:field> <!--- -- все ВМ, существовавшие в данный час --->
|
||||
<d:field title="ВМ вкл." cfSqlType="CF_SQL_INTEGER">count(distinct p.obj_uuid) FILTER (WHERE p.value=1) as unique_vm_cnt_on</d:field> <!--- -- все ВМ, включавшиеся за данный час --->
|
||||
<d:field title="ВМ-часов" cfSqlType="CF_SQL_NUMERIC">round((sum(p.value)/12.)::numeric,1) as vm_h</d:field> <!--- -- 5 minute sampling, so /12 --->
|
||||
<d:field title="Стоимость без диска" cfSqlType="CF_SQL_NUMERIC">round((sum(p.value)/12.*24.19)::numeric,2) as cost_wo_disk</d:field>
|
||||
<d:field title="Стоимость диска" cfSqlType="CF_SQL_NUMERIC">round((count(distinct obj_id)*8.00)::numeric,2) as disk_cost</d:field> <!--- -- считаем все ВМ, существовавшие в данный час --->
|
||||
<d:field title="Круглосуточных ВМ" cfSqlType="CF_SQL_NUMERIC">round((sum(p.value)/12.)::numeric, 1) as avg_roundclock_vm</d:field>
|
||||
</d:field_set>
|
||||
from gpu.vm
|
||||
JOIN gpu.vm_power_state p on (vm.obj_uuid=p.obj_uuid)
|
||||
where 1=1
|
||||
/*watch time zone, accounting by MSK*/
|
||||
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)#/>
|
||||
AND vm.client_id='WZ01516'
|
||||
GROUP BY DATE_TRUNC('hour',p.ts)
|
||||
ORDER BY 1;
|
||||
</cfquery>
|
||||
|
||||
|
||||
<cfif isDefined("DEBUG")>
|
||||
<cfdump var=#qRead#/>
|
||||
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qGpuAge" datasource="billing-s3"><!--- cachedWithin=#createTimeSpan(0, 0, 25, 0)# --->
|
||||
select max(ts) as dt_load from gpu.vm_power_state
|
||||
</cfquery>
|
||||
|
||||
<cfoutput>qGpuAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
|
||||
|
||||
|
||||
<cfif isDefined("output_xls")>
|
||||
<layout:xml qRead=#qRead# titleMap=#titleMap# filename="#pageInfo.entity#.xml"/>
|
||||
<cfabort/>
|
||||
</cfif><cfif isDefined("output_json")>
|
||||
<layout:json qRead=#qRead# titleMap=#titleMap# filename="#pageInfo.entity#.json"/>
|
||||
<cfabort/>
|
||||
</cfif><!---
|
||||
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||
|
||||
<layout:attribute name="title">
|
||||
<cfoutput><b>Отчет по включенным ВМ с GPU</b></cfoutput>
|
||||
</layout:attribute>
|
||||
<layout:attribute name="controls">
|
||||
<!---skip filter link, filter is not implemented--->
|
||||
<!---<layout:language_switch/>--->
|
||||
</layout:attribute>
|
||||
</layout:page>
|
||||
|
||||
|
||||
<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')#"/>
|
||||
|
||||
<!--- 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>#qRead.recordCount#</b><br/>
|
||||
Актуальность данных:
|
||||
GPU-VM Power State: <b<cfif datediff("h",qGpuAge.dt_load, Now()) GT 24> class="err"</cfif>>#dateFormat(qGpuAge.dt_load,'YYYY-MM-DD')# #timeFormat(qGpuAge.dt_load,'HH:mm:ss.lXX')#</b>
|
||||
</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>
|
||||
<th width="10%">Час</th>
|
||||
<th width="10%">Уникальных ВМ</th>
|
||||
<th width="10%">ВМ вкл</th>
|
||||
<th width="10%">ВМ-часов</th>
|
||||
<th width="10%">Стоимость без диска</th>
|
||||
<th width="10%">Стоимость диска</th>
|
||||
<th width="10%">Круглосуточных ВМ</th>
|
||||
</thead>
|
||||
|
||||
<cfoutput query="qRead">
|
||||
<tr>
|
||||
<td class="c">#dateFormat(ts_hour,"YYYY-MM-DD")# #timeFormat(ts_hour,"HH:MM")#</td>
|
||||
<td class="r">#unique_vm_cnt#</td>
|
||||
<td class="r">#unique_vm_cnt_on#</td>
|
||||
<td class="r">#vm_h#</td>
|
||||
<td class="r">#cost_wo_disk#</td>
|
||||
<td class="r">#disk_cost#</td>
|
||||
<td class="r">#avg_roundclock_vm#</td>
|
||||
</tr>
|
||||
</cfoutput>
|
||||
</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>#VDC#</td>
|
||||
<td><cftry>#round(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_Reserv,3)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#request.roundSafe(VDC_CPU_Speed,3)#<cfcatch></cfcatch></cftry></td>
|
||||
|
||||
<td>#qVM.Cluster#</td>
|
||||
|
||||
@@ -129,19 +129,19 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
|
||||
<td>#CPU_Model#</td>
|
||||
<td>#Host_CPU_Cores#</td>
|
||||
<td>#Host_CPU_Sockets#</td>
|
||||
<td>#round(Host_CPU_Speed,3)#</td>
|
||||
<td>#round(Host_RAM)#</td>
|
||||
<td><cftry>#round(Host_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#round(Host_CPU_Used_Avg,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td>#request.roundSafe(Host_CPU_Speed,3)#</td>
|
||||
<td>#request.roundSafe(Host_RAM)#</td>
|
||||
<td><cftry>#request.roundSafe(Host_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#request.roundSafe(Host_CPU_Used_Avg,1)#<cfcatch></cfcatch></cftry></td>
|
||||
|
||||
<td>#VM_vCPU_count#</td>
|
||||
<td><cftry>#round(VM_CPU_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#round(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_Used,1)#<cfcatch></cfcatch></cftry></td>
|
||||
<td><cftry>#request.roundSafe(VM_CPU_Used_AVG,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_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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user