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 qCode:#getTickCount()-request.startTickCount# select k.id_klienta as wz, k.__id::text as contragent_uid, k.__name as contragent from elma.companies k where k."__deletedAt" IS NULL qContragent:#getTickCount()-request.startTickCount# select k.id_klienta as wz, k.__id::text as contragent_uid, p.code, p.price, p.discount, k.__name as contragent, a.__name as contract, a.__id::text as contract_uid, d.__name as deal, d.__id::text as deal_uid, siv.abstractive_service as abstract_service, siv.modifier, siv.user_description, siv.hash as line_key ,siv.date_nop as dt_from, siv.date_end as dt_to, siv.discount as service_discount, siv.cnt as service_quantity /*,p.__name as line_key*/, p.ed_izm, p.name as component, p.type, aa.__name as additional_agreement, aa.__id::text as additional_agreement_uid --, aa.is_actual 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 IN (2,3) AND aa.is_actual AND siv.date_nop < AND (siv.date_end > OR siv.date_end IS NULL)/*****/ order by k.id_klienta, p.code qSpec:#getTickCount()-request.startTickCount# select max(dt_load) as dt_load from elma.deals_services qSivAge:#getTickCount()-request.startTickCount# select m.clientid 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 '%-v1cl5%' THEN 'iaas.ngc.a45' WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера else '['||vdc.name||']' end as code, 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 t on (t.id=vdc.tenant_id) 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) where length(m.clientid) > 0 AND capacity_resource.timestamp::date >= AND capacity_resource.timestamp::date <= group by m.clientid, vdc.name order by m.clientid, vdc.name; qComputing:#getTickCount()-request.startTickCount# select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource qComputingAge:#getTickCount()-request.startTickCount# select m.clientid 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 '%-v1cl5%' THEN 'iaas.ngc.a45' WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера ELSE '['||vdc.name||']' END || CASE WHEN storage_profile_types.name ILIKE '%FASTSSD%' THEN '.fstssd-m' 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./720. as gb_m_limit, -- 4 потому, что сбор раз в 15 минут sum(used)/1024./4./720. as gb_m_used -- 720 это количество часов в условном месяце from ngcloud_ru.capacity_storage join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id join ngcloud_ru.tenant t on t.id=vdc.tenant_id 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) join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id where length(m.clientid) > 0 AND capacity_storage.timestamp::date >= AND capacity_storage.timestamp::date < group by m.clientid, vdc.name, storage_profile_types.name order by m.clientid, vdc.name, storage_profile_types.name; qStorage:#getTickCount()-request.startTickCount# select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage qStorageAge:#getTickCount()-request.startTickCount# select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */ (sum(bucket_stat.usage_rgw_main_size_actual)/) as vol_B ,ceil(sum(bucket_stat.usage_rgw_main_size_actual)//1024/1024/1024) as vol_GB ,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/ /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.timestamp_addition::date >= AND bucket_stat.timestamp_addition::date <= group by bucket_stat.owner, bucket_stat.placement_id order by bucket_stat.owner, bucket_stat.placement_id; qS3Vol:#getTickCount()-request.startTickCount# select max(timestamp_addition) as dt_load from s3billing.bucket_stat qS3VolAge:#getTickCount()-request.startTickCount# 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 usage_bucket_by_user.time::date >= AND usage_bucket_by_user.time::date <= group by user_info.name, bucket_info.placement_id order by user_info.name, bucket_info.placement_id; qS3OpsTrf:#getTickCount()-request.startTickCount# select max(time) as dt_load from s3billing.usage_bucket_by_user qS3OpsTrfAge:#getTickCount()-request.startTickCount# select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric, 'ядро-ч' as unit from qComputing union all select wz, code || '.ram-m', gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric, 'ГБайт-ч' as unit from qComputing union all select wz, code, gb_m_used as raw_metric, gb_m_used as metric, gb_m_used as chargeable_metric, 'ГБайт-м' as unit from qStorage union all select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric, 'ГБайт-м' as unit from qS3Vol union all select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric, '10тыс.шт.' as unit from qS3OpsTrf union all select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric, '10тыс.шт.' as unit from qS3OpsTrf union all select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric, 'ГБайт' as unit from qS3OpsTrf order by wz, code qUnifiedMetric:#getTickCount()-request.startTickCount# SELECT coalesce(coalesce(c.wz, m.wz), s.wz) as wz coalesce(m.code, s.code) as code f.code as f_code m.chargeable_metric m.unit s.ed_izm s.service_quantity*(100-s.service_discount)/100*s.price*(100-s.discount)/100 as discounted_price s.service_quantity*(100-s.service_discount)/100*s.price*(100-s.discount)/100*m.chargeable_metric as charge s.dt_from s.dt_to s.line_key s.price s.discount m.raw_metric m.metric coalesce(c.contragent,cs.contragent) as contragent coalesce(c.contragent_uid,cs.contragent_uid) as contragent_uid s.contract s.contract_uid s.additional_agreement s.additional_agreement_uid s.deal s.deal_uid s.abstract_service s.modifier s.component s.user_description FROM qUnifiedMetric m FULL JOIN qSpec s ON (m.wz=s.wz AND m.code=s.code) LEFT JOIN qSpec f ON (m.wz=f.wz AND m.code=f.code AND f.type=2) LEFT JOIN qContragent c ON (m.wz=c.wz) LEFT JOIN qContragent cs ON (s.wz=cs.wz) -- неуклюже, но иначе контрагент теряется WHERE 1=1 AND s.type=3 AND EXISTS(select * from qSpec qs where qs.wz=m.wz AND qs.type=3) --AND s.wz='WZ01762' ORDER BY wz,code qCharge:#getTickCount()-request.startTickCount# Отчет по PAYG Факт потребления по основной базе биллинга, спецификации из DWH. Без детализации по бакетам, VDC и т.д. Все запросы кэшированы на 25 минут.
Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе. Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную
Даты актуальности пока проверять вручную. Обращать внимание на замножение строк.
Период с по Только контрагенты с PAYG* checked/> * любым PAYG, не только по облаку
Часов в периоде: #hours# Строк в отчете: #qCharge.recordCount#
Актуальность данных: VCD Computing: #dateFormat(qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(qComputingAge.dt_load,'HH:MM:SS')# VCD Storage: #dateFormat(qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(qStorageAge.dt_load,'HH:MM:SS')# S3 хранение: #dateFormat(qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3VolAge.dt_load,'HH:MM:SS')# S3 операции и трафик: #dateFormat(qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3OpsTrfAge.dt_load,'HH:MM:SS')#
Артикул Кол-во (метрика) Ед.изм. Цена ₽ со скид., с НДС Стоимость ₽ с НДС     Услуга Компонент Клиентс. назв. GPL с НДС Скидка% Дата НОУ Дата оконч. Ключ строки Сырая метрика Приведен­ная метрика Договор Допник Сделка
#wz# #contragent#
#currentRow# #code# (#f_code#) #request.roundSafe(chargeable_metric,3)# #len(unit)?unit:'['& ed_izm &']'# #gaussianRoundSafe(discounted_price,2)# #gaussianRoundSafe(charge,2)# #abstract_service# #modifier# #component# #user_description# #gaussianRoundSafe(price,2)# #discount# #dateFormat(dt_from,'YYYY-MM-DD')# #dateFormat(dt_to,'YYYY-MM-DD')# #line_key# #request.roundSafe(raw_metric,3)# #request.roundSafe(metric,3)# #contract# #additional_agreement# #deal#
Итого #wz# #contragent#: #NumFmt(acc,2)#
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; } }