Compare commits

...
10 Commits
7 changed files with 539 additions and 161 deletions
+1 -1
View File
@@ -89,7 +89,7 @@
<!--- global settings ---> <!--- global settings --->
<!--- *************************************************************************************************** ---> <!--- *************************************************************************************************** --->
<cfset request.APP_VERSION="0.00.092"/> <!--- *********************************************************** ---> <cfset request.APP_VERSION="0.00.100"/> <!--- *********************************************************** --->
<!--- *************************************************************************************************** ---> <!--- *************************************************************************************************** --->
<cfset request.STAND=getStand()/> <cfset request.STAND=getStand()/>
<cfset request.RECORDS_PER_PAGE=500/> <cfset request.RECORDS_PER_PAGE=500/>
+1
View File
@@ -150,6 +150,7 @@ ORDER BY h."Cluster"
cluster_naming (cluster,commercial_name) AS (VALUES cluster_naming (cluster,commercial_name) AS (VALUES
('cl01-vsan','msk1, Intel Cascade Lake 2,9 ГГц') ('cl01-vsan','msk1, Intel Cascade Lake 2,9 ГГц')
,('msk1-pub01-i29','msk1, Intel Cascade Lake 2,9 ГГц')
,('cl02','msk1, Intel Cascade Lake 3,1 ГГц') ,('cl02','msk1, Intel Cascade Lake 3,1 ГГц')
,('cl04-vsan','msk1, AMD Milan 2,8 ГГц') ,('cl04-vsan','msk1, AMD Milan 2,8 ГГц')
,('cl05-1c','msk1, AMD Raphael 4,5 ГГц') ,('cl05-1c','msk1, AMD Raphael 4,5 ГГц')
+47 -17
View File
@@ -185,6 +185,7 @@
,p.cnt as p_cnt ,p.cnt as p_cnt
,p.ed_izm ,p.ed_izm
,p.code ,p.code
,p.type as p_type
,p.discount as p_discount ,p.discount as p_discount
,p.__id as p_uid ,p.__id as p_uid
,p.name ,p.name
@@ -245,22 +246,23 @@
<!--- <td class="c">#__name#</td> ---> <!--- <td class="c">#__name#</td> --->
<td class="l">#user_description#</td> <td class="l">#user_description#</td>
<td> <td>
<table class="wide"> <table class="wide">
<cfset cost=0/> <cfset cost=0/>
<cfoutput group="p_uid"> <cfoutput group="p_uid">
<cfif p_cnt NEQ 0> <cfif p_cnt NEQ 0>
<tr> <tr>
<td class="nw">#code#</td> <td class="nw">#code#</td>
<td>#name#</td> <td>#name#</td>
<td>#p_cnt#</td> <td>#p_cnt#</td>
<td>#ed_izm#</td> <td>#ed_izm#</td>
<td class="r nw">#nFmt(price,3)#</td> <td class="r nw">#nFmt(price,3)#</td>
<td class="r">#p_discount#%</td> <td class="r">#p_discount#%</td>
</tr> <td class="r"><cftry>#gaussianRound((100.-discount)/100.*price*(100.-p_discount)/100.,2)#<cfcatch type="any"></cfcatch></cftry></td>
<cfset cost+=price*p_cnt*(100-(isNumeric(p_discount)?p_discount:0))/100 /> </tr>
</cfif> <cfset cost+=price*p_cnt*(100-(isNumeric(p_discount)?p_discount:0))/100 />
</cfoutput> </cfif>
</table> </cfoutput>
</table>
</td> </td>
<td class="c">#cnt#</td> <td class="c">#cnt#</td>
<td class="c">#discount#%</td> <td class="c">#discount#%</td>
@@ -536,4 +538,32 @@
</table> </table>
</cfif><!--- len(d.__id) ---> </cfif><!--- len(d.__id) --->
<layout:page section="footer"/> <layout:page section="footer"/>
<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>
+5 -1
View File
@@ -1,9 +1,13 @@
<!--- version 2.01---><!---15:25 31.01.2019---> <!--- version 2.01---><!---15:25 31.01.2019--->
<!--- version 2.02---><!---2025-08-04 15:19:34 postgre specific ilike instead of like---> <!--- version 2.02---><!---2025-08-04 15:19:34 postgre specific ilike instead of like--->
<!--- version 2.03---><!---2026-04-27 ftype=integer support---> <!--- version 2.03---><!---2026-04-27 ftype=integer support--->
<!--- version 2.04---><!---2026-10-28 ATTRIBUTES.target--->
<!--- build query filter string ---> <!--- build query filter string --->
<!--- пустые и некорректные значения параметров вызвыают пропуск параметра ---> <!--- пустые и некорректные значения параметров вызвыают пропуск параметра --->
<cfparam name="ATTRIBUTES.filter" type="struct"/> <cfparam name="ATTRIBUTES.filter" type="struct"/>
<cfparam name="ATTRIBUTES.target" type="string" default="postgresql"/> <!--- патч на случай, если целевая база не поддерживает оператор ILIKE --->
<cfset likeOp = (ATTRIBUTES.target EQ "postgresql") ? "ILIKE" : "LIKE"/>
<cfloop collection=#ATTRIBUTES.filter# item="item"> <cfloop collection=#ATTRIBUTES.filter# item="item">
<cfsilent> <cfsilent>
@@ -22,7 +26,7 @@
---><cfif i LT #len#><cfqueryparam cfsqltype="#getCfSqLType(fltr.ftype)#" list="#fltr.list#" value="#fltr.prefix##fltr.val##fltr.suffix#"/></cfif><!--- ---><cfif i LT #len#><cfqueryparam cfsqltype="#getCfSqLType(fltr.ftype)#" list="#fltr.list#" value="#fltr.prefix##fltr.val##fltr.suffix#"/></cfif><!---
---></cfloop><!--- ---></cfloop><!---
---><cfelse><!--- ---><cfelse><!---
---><cfoutput>#fltr.field#</cfoutput><cfswitch expression=#fltr.compare#><cfcase value="EQ"> = </cfcase><cfcase value="NE,NEQ"> <> </cfcase><cfcase value="LE"> <= </cfcase><cfcase value="LT"> < </cfcase><cfcase value="GE"> >= </cfcase><cfcase value="GT"> > </cfcase><cfcase value="LIKE"> ILIKE </cfcase><cfcase value="NOTLIKE"> NOT ILIKE </cfcase><cfcase value="LIKE%"> ILIKE <cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# value="%#fltr.val#%"/><cfcontinue/></cfcase><cfcase value="NOTLIKE%"> NOT ILIKE <cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# value="%#fltr.val#%"/><cfcontinue/></cfcase><cfcase value="IN"> IN (<cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# list="#fltr.list#" value="#fltr.val#"/>)<cfcontinue/></cfcase><cfdefaultcase> = <cfoutput> #fltr.field#</cfoutput><cfcontinue/><!---***криво---></cfdefaultcase></cfswitch><cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# value="#fltr.val#"/><cfcontinue/> ---><cfoutput>#fltr.field#</cfoutput><cfswitch expression=#fltr.compare#><cfcase value="EQ"> = </cfcase><cfcase value="NE,NEQ"> <> </cfcase><cfcase value="LE"> <= </cfcase><cfcase value="LT"> < </cfcase><cfcase value="GE"> >= </cfcase><cfcase value="GT"> > </cfcase><cfcase value="LIKE"> <cfoutput>#likeOp#</cfoutput> </cfcase><cfcase value="NOTLIKE"> <cfoutput>NOT #likeOp#</cfoutput> </cfcase><cfcase value="LIKE%"> <cfoutput>#likeOp#</cfoutput> <cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# value="%#fltr.val#%"/><cfcontinue/></cfcase><cfcase value="NOTLIKE%"> <cfoutput>NOT #likeOp#</cfoutput> <cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# value="%#fltr.val#%"/><cfcontinue/></cfcase><cfcase value="IN"> IN (<cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# list="#fltr.list#" value="#fltr.val#"/>)<cfcontinue/></cfcase><cfdefaultcase> = <cfoutput> #fltr.field#</cfoutput><cfcontinue/><!---***криво---></cfdefaultcase></cfswitch><cfqueryparam cfsqltype=#getCfSqLType(fltr.ftype)# value="#fltr.val#"/><cfcontinue/>
</cfif> </cfif>
</cfloop> </cfloop>
+331 -133
View File
@@ -7,26 +7,34 @@
<m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/> <m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<!--- проблема: пустой чек-бокс не передается, невозможно отличить "чек-бокс очищен" от "параметров нет, использовать дефолт" (например, при обращении к странице по GET)
решение: если передается форма, то отсутствие чек-бокса однозначно означает, что он очищен.
Передачу формы можно надежно обозначить скрытым полем. Можно для экономии использовать имя кнопки, но кнопок у меня 2, сабмит и дебаг
NB при передаче формы GET структура FORM пустая
мне подсказывают, что удобно передавать qwery or filter гетом, тогда можно урлу сохранить --->
<cfparam name="submit" default=""/>
<cfparam name="debug" default=""/>
<cfif len(submit) or len(debug)>
<!--- считаем, что отправлена форма и отсутствие чекбокса нужно трактовать как FALSE --->
<cfparam name="only_articles_in_spec" default=0/>
<cfparam name="inner_join" default=0/>
<cfelse>
<!--- это обращение по неквалифицированному URL и отсутствие чекбокса означает USE DEFAULT --->
<cfparam name="only_articles_in_spec" default=1/>
<cfparam name="inner_join" default=1/>
</cfif>
<cfparam name="code" default=""/>
<!--- <!---
<cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/> <cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/> ---> <cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/> --->и
<cfparam name="dt_finish" type="date" default=#dateAdd('d',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/> <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))#/> <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))/> <cfset hours=dateDiff('h', dt_start, dateAdd('d', 1, dt_finish))/>
<cfparam name="wz" default=""/> <cfparam name="wz" default=""/>
<!--- *** костыль --->
<cfparam name="only_articles_in_spec" default=0/>
<cfset local.only_articles_in_spec=only_articles_in_spec/>
<cfparam name="inner_join" default=0/>
<cfset local.inner_join=inner_join/>
<!--- <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)#> <cfquery name="qCode" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 20, 0)#>
select distinct p.code select distinct p.code
@@ -63,35 +71,46 @@
AS (VALUES AS (VALUES
('Закрыта неуспешно',7,0),('Закрыта успешно',6,100),('Договор подписан',5,100),('Договор на подписании',15,90),('Договор на согласовании',12,70), ('Закрыта неуспешно',7,0),('Закрыта успешно',6,100),('Договор подписан',5,100),('Договор на подписании',15,90),('Договор на согласовании',12,70),
('Тестирование',8,50),('Отправлено ТКП',10,20),('Внутреннее согласование',37,10),('Проработка решения',4,10),('Сбор потребностей',1,0) ('Тестирование',8,50),('Отправлено ТКП',10,20),('Внутреннее согласование',37,10),('Проработка решения',4,10),('Сбор потребностей',1,0)
) ),
select upper(trim(k.id_klienta)) as wz, k.__id::text as contragent_uid, line as (
select
upper(trim(k.id_klienta)) as wz,
k.__id::text as contragent_uid,
p.code, p.code,
SUBSTRING(p.code FROM 1 FOR LENGTH(p.code) - 2) as sku_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 p.price,
,siv.date_nop as serviceStart, siv.date_end as serviceEnd, siv.discount as service_discount, siv.cnt as service_quantity p.discount as component_discount,
/*,p.__name as line_key*/, p.ed_izm, p.name as component, p.type, p.cnt*coalesce(siv.cnt,1) as component_quantity, k.__name as contragent,
a.__name as contract,
a.__id::text as contract_uid,
d.__name as deal,
d.__id::text as deal_uid,
d.__index AS deal_index,
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.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.__name as additional_agreement, aa.__id::text as additional_agreement_uid
--, aa.is_actual ,siv.end_customer::text as end_customer_uid
,siv.end_customer as end_customer_uid
,z.id_klienta as end_customer_wz ,z.id_klienta as end_customer_wz
,z.__name as end_customer_name ,z.__name as end_customer_name
--,ft.free_tier
,s.probability_pc ,s.probability_pc
,siv.__id::text as siv_uid ,siv.__id::text as siv_uid
,CASE WHEN p.type=3 THEN coalesce(siv.cnt*(100.-siv.discount)/100.*p.price*(100.-p.discount)/100., 0.) ELSE NULL END as discounted_price
from elma.deals d from elma.deals d
JOIN STATUS s ON (d.__status_status = s.status_id) JOIN STATUS s ON (d.__status_status = s.status_id)
join elma.deals_services siv on (d.__id=ANY(siv.deal)) 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 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.service_parametrs p ON (p.__id = arr.param_id)
join elma.companies k on (d._companies=k.__id) join elma.companies k on (d._companies=k.__id)
join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement)) join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement))
join elma.aggrements a on (aa.contract_uid = a.__id) join elma.aggrements a on (aa.contract_uid = a.__id)
left outer join elma.companies z on (siv.end_customer=z.__id) LEFT OUTER JOIN elma.companies z on (siv.end_customer=z.__id)
WHERE p.type IN (2,3) AND aa.is_actual
where p.type IN (2,3) AND aa.is_actual
AND siv.date_nop < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND (siv.date_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL)/*****/
AND aa."__deletedAt" IS NULL AND aa."__deletedAt" IS NULL
AND a."__deletedAt" IS NULL AND a."__deletedAt" IS NULL
AND d."__deletedAt" IS NULL AND d."__deletedAt" IS NULL
@@ -103,17 +122,43 @@
</cfif> </cfif>
<cfif len(code)> <cfif len(code)>
AND p.code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/> AND p.code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
<cfif only_articles_in_spec>
AND p.type=3
</cfif> </cfif>
--AND k.id_klienta='WZ01031' ),
--AND k.id_klienta='WZ01112' stair
order by k.id_klienta, p.code AS (
SELECT *
FROM (
SELECT *
,MIN(serviceStart) OVER (
PARTITION BY line_key ORDER BY deal_index DESC
) running_min_dt
,COALESCE((
LEAD(serviceStart) OVER (
PARTITION BY line_key ORDER BY serviceStart
,deal_index
)
), (
SELECT CURRENT_TIMESTAMP + INTERVAL '1 day' --*** not sure
)) dt_next
FROM line
WHERE probability_pc = 100
) t
WHERE t.serviceStart = t.running_min_dt
)
select d.* from stair d
WHERE d.serviceStart < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND (d.serviceEnd > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR d.serviceEnd IS NULL)
order by wz, type DESC, code
</cfquery> </cfquery>
<!--- select * from elma.deals_services where __id='019edf9c-c1e8-7acd-8b63-5369e5be5bf5' <!--- select * from elma.deals_services where __id='019edf9c-c1e8-7acd-8b63-5369e5be5bf5'
union all union all
select * from elma.deals_services where __id='019edf9c-c23d-7ad6-a990-643dd09579b8' ---> select * from elma.deals_services where __id='019edf9c-c23d-7ad6-a990-643dd09579b8' --->
<!--- здесь имеем список кодов с ценами и WZ. Каждому коду можно поставить в соответствие запрос, который даст по нему выборку. Изредка один запрос может вывести 2 кода, но разбить на 2 запроса легко. Кроме того, запросы можно объединить через union в один - может быть, так будет лучше читаться (быстрее выполняться не будет) ---> <!--- здесь имеем список кодов с ценами и WZ. Каждому коду можно поставить в соответствие запрос, который даст по нему выборку. Изредка один запрос может вывести 2 кода, но разбить на 2 запроса легко. Кроме того, запросы можно объединить через union в один - может быть, так будет лучше читаться (быстрее выполняться не будет) --->
<cfoutput>qSpec:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qSpec:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qSpec#/> <cfdump var=#qSpec#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -162,7 +207,7 @@ select * from elma.deals_services where __id='019edf9c-c23d-7ad6-a990-643dd09579
<cfoutput>qComputing:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qComputing:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qComputing#/> <cfdump var=#qComputing#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -219,7 +264,7 @@ select * from elma.deals_services where __id='019edf9c-c23d-7ad6-a990-643dd09579
<cfoutput>qStorage:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qStorage:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qStorage#/> <cfdump var=#qStorage#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -262,7 +307,7 @@ HOT_FREE_LIMIT 1 10 1 100
<cfoutput>qS3Vol:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qS3Vol:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qS3Vol#/> <cfdump var=#qS3Vol#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -333,7 +378,7 @@ select
<cfoutput>qS3OpsTrf:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qS3OpsTrf:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qS3OpsTrf#/> <cfdump var=#qS3OpsTrf#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -344,7 +389,8 @@ select
<cfoutput>qS3OpsTrfAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qS3OpsTrfAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfquery name="qS3User" datasource="cmdb" cachedWithin=#createTimeSpan(0, 0, 31, 0)#> <!--- /*прибегаем к cmdb для разрешения инстанса, нейминг некорректен и ненадежен*/ --->
<cfquery name="qS3User" datasource="cmdb" cachedWithin=#createTimeSpan(0, 0, 32, 0)#>
WITH current_state AS ( WITH current_state AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY instance_uid ORDER BY version DESC) as rn SELECT *, ROW_NUMBER() OVER (PARTITION BY instance_uid ORDER BY version DESC) as rn
FROM instance_state FROM instance_state
@@ -353,17 +399,18 @@ select
FROM current_state s FROM current_state s
JOIN instance e on (s.instance_uid=e.instance_uid) JOIN instance e on (s.instance_uid=e.instance_uid)
WHERE rn = 1 AND e.service_id=12 WHERE rn = 1 AND e.service_id=12
AND NOT cast(s.instance_data->>'isDeleted' as boolean)
</cfquery> </cfquery>
<cfoutput>qS3User:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qS3User:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qS3User#/> <cfdump var=#qS3User#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
<!--- выданы права на схему и таблицы, чтобы без толку не плодить источники данных ---> <!--- выданы права на схему и таблицы, чтобы без толку не плодить источники данных --->
<!--- считаются часы работы ВМ с GPU ---> <!--- считаются часы работы ВМ с GPU --->
<cfquery name="qGpu" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 31, 0)#> <cfquery name="qGpu" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 33, 0)#>
WITH card (model, cluster, code) as (VALUES WITH card (model, cluster, code) as (VALUES
('A100', 'msk1-pub02-i31', 'iaas.ngc.i31.gpu80'), ('A100', 'msk1-pub02-i31', 'iaas.ngc.i31.gpu80'),
('H100', 'msk1-pub07-a40', 'iaas.ngc.a40.gpuh100'), -- h200 нет в отчете ('H100', 'msk1-pub07-a40', 'iaas.ngc.a40.gpuh100'), -- h200 нет в отчете
@@ -396,7 +443,8 @@ select
<cfoutput>qGpu:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qGpu:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfif len(debug)>
<cfdump var=#qGpu#/> <cfdump var=#qGpu#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -407,13 +455,66 @@ select
<cfoutput>qGpuAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qGpuAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfquery name="qLlm" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 33, 0)#>
WITH cred as (
SELECT
column1::varchar(255) as model_name,
column2::decimal(10,6) as weight_in,
column3::decimal(10,6) as weight_out,
column4::decimal(10,6) as weight_cached,
column5::decimal(10,6) as weight_audio_sec
FROM
(VALUES
('qwen3.8-27b-fp8', 0.329400, 2.196000, null, null),
('gpt-oss-120b', 0.242000, 0.980000, null, null),
('user-bge-m3', 0.006000, null, null, null),
('bge-reranker-v2-m3', 0.002400, null, null, null),
('whisper-large-v3-turbo', null, null, null, 0.006500)
)
)
SELECT m.organization_name, m.model_name
,SUM(m.prompt_tokens) as tokens_in
,SUM(m.completion_tokens) as tokens_out
,SUM(m.cached_tokens) as tokens_cached
,SUM(m.audio_seconds) as audio_seconds
,SUM(m.prompt_tokens)*c.weight_in/1e6 as cred_in
,SUM(m.completion_tokens)*c.weight_out/1e6 as cred_out
,SUM(m.cached_tokens)*c.weight_cached/1e6 as cred_cached
,SUM(m.audio_seconds)*c.weight_audio_sec/60e6 as cred_audio_minutes
FROM aillm.usage_metric m join cred c on (m.model_name=c.model_name)
WHERE 1=1
AND m.interval_start >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND m.interval_start < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/> <!--- *** может быть, краевое уточнение для 15 мин --->
<cfif len(wz)>
AND m.organization_name ilike <cfqueryparam cfsqltype="cf_sql_varchar" value="%#wz#%"/>
</cfif>
GROUP BY m.organization_id, m.organization_name, m.model_name, c.weight_in, c.weight_out, c.weight_cached, c.weight_audio_sec
ORDER BY m.organization_id, m.organization_name, m.model_name;
</cfquery>
<cfoutput>qLlm:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif len(debug)>
<cfdump var=#qLlm#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfquery name="qLlmAge" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 31, 0)#>
select max(ts) as dt_load from aillm.usage_metric
</cfquery>
<cfoutput>qLlmAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfset db = new MemoryDbHelper()/> <cfset db = new MemoryDbHelper()/>
<cfset db.register("qComputing", qComputing, "inmem")/> <cfset db.register("qComputing", qComputing, "inmem")/>
<cfset db.register("qStorage", qStorage, "inmem")/> <cfset db.register("qStorage", qStorage, "inmem")/>
<cfset db.register("qS3Vol", qS3Vol, "inmem")/> <cfset db.register("qS3Vol", qS3Vol, "inmem")/>
<cfset db.register("qS3OpsTrf", qS3OpsTrf, "inmem")/> <cfset db.register("qS3OpsTrf", qS3OpsTrf, "inmem")/>
<cfset db.register("qGpu", qGpu, "inmem")/>
<cfset db.register("qS3User", qS3User, "inmem")/> <cfset db.register("qS3User", qS3User, "inmem")/>
<cfset db.register("qGpu", qGpu, "inmem")/>
<cfset db.register("qLlm", qLlm, "inmem")/>
<cfquery name="qUnifiedMetric" datasource="inmem"> <cfquery name="qUnifiedMetric" datasource="inmem">
select wz, code || '.vcpu' as code, core_h as raw_metric, core_h as metric, 'core-h' as unit, vdc as dimension1 select wz, code || '.vcpu' as code, core_h as raw_metric, core_h as metric, 'core-h' as unit, vdc as dimension1
@@ -474,6 +575,34 @@ select
<cfif len(code)> <cfif len(code)>
where code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/> where code like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif> </cfif>
union all
select organization_name as wz, 'tokens_in', tokens_in as raw_metric, cred_in as metric, 'cred' as unit, model_name as dimension1
from qLlm
<cfif len(code)>
where 'tokens_in' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
union all
select organization_name as wz, 'tokens_out', tokens_out as raw_metric, cred_out as metric, 'cred' as unit, model_name as dimension1
from qLlm
<cfif len(code)>
where 'tokens_out' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
union all
select organization_name as wz, 'tokens_cached', tokens_cached as raw_metric, cred_cached as metric, 'cred' as unit, model_name as dimension1
from qLlm
<cfif len(code)>
where 'tokens_cached' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
union all
select organization_name as wz, 'audio_minutes', audio_seconds as raw_metric, cred_audio_minutes as metric, 'cred' as unit, model_name as dimension1
from qLlm
<cfif len(code)>
where 'audio_minutes' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
order by wz, code order by wz, code
</cfquery> </cfquery>
@@ -482,7 +611,7 @@ select
<cfoutput>qUnifiedMetric:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qUnifiedMetric:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qUnifiedMetric#/> <cfdump var=#qUnifiedMetric#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -515,39 +644,87 @@ FULL JOIN, потому что нам нужны бесхозные записи
<cfquery name="qCharge" datasource="inmem"> <cfquery name="qCharge" datasource="inmem">
/*EXPLAIN PLAN FOR*/ /*EXPLAIN PLAN FOR*/
WITH
metric as (select count(*) as cnt, wz, code, dimension1, max(unit) as unit, max(raw_metric) as raw_metric, max(metric) as metric
from qUnifiedMetric
group by wz,code, dimension1
),
spec as (select count(*) as cnt, wz, sku_code,
max(end_customer_wz) as wze,
max(code) as code,
max(component_quantity) as component_quantity,
max(service_quantity) as service_quantity,
max(service_discount) as service_discount,
max(discounted_price) as discounted_price,
max(type) as type,
max(ed_izm) as ed_izm,
--max(coalesce(service_quantity*(100.-service_discount)/100.*price*(100.-component_discount)/100., 0.)) as discounted_price,
max(serviceStart) as serviceStart,
max(serviceEnd) as serviceEnd,
max(line_key) as line_key,
max(price) as price,
max(component_discount) as component_discount,
max(contract) as contract,
max(contract_uid) as contract_uid,
max(additional_agreement) as additional_agreement,
max(additional_agreement_uid) as additional_agreement_uid,
max(deal) as deal,
max(deal_uid) as deal_uid,
max(abstract_service) as abstract_service,
max(modifier) as modifier,
max(component) as component,
max(user_description) as user_description,
max(CASE type WHEN 1 THEN 'install' WHEN 2 THEN 'fix' WHEN 3 THEN 'payg' ELSE NULL END) as pricing_model
from qSpec
group by wz, sku_code
)
SELECT SELECT
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount"> <d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
<d:field>s.cnt as occurrences_spec</d:field>
<d:field>m.cnt as occurrences_metric</d:field>
<d:field title="Точное соотв. специф. - метр.">CASE WHEN (m.cnt=1 AND s.cnt=1) THEN 1 ELSE 0 END as exact_match</d:field>
<d:field title="Диагностика">
CASE
WHEN (m.cnt=1 AND s.cnt=1) THEN 'EXACT MATCH'
WHEN (m.cnt>1 AND s.cnt>1) THEN 'CRITICAL: Many-to-Many Explosion (Duplicates on BOTH sides)'
WHEN (s.cnt>1) THEN 'DUP: Multiple entries in Spec'
WHEN (m.cnt>1) THEN 'DUP: Multiple entries in Metrics'
WHEN (coalesce(m.cnt,0)=0 AND s.cnt>0) THEN 'ORPHAN: Only in Spec'
WHEN (m.cnt>0 AND coalesce(s.cnt,0)=0) THEN 'ORPHAN: Only in Metrics'
ELSE 'Other Discrepancy'
END as diag
</d:field>
<d:field title="WZ">coalesce(coalesce(c.wz, m.wz), s.wz) as wz</d:field> <d:field title="WZ">coalesce(coalesce(c.wz, m.wz), s.wz) as wz</d:field>
<d:field title="WZ spec">s.wz as wzs</d:field> <d:field title="WZ spec">s.wz as wzs</d:field>
<d:field title="WZ contragent">c.wz as wzc</d:field> <d:field title="WZ contragent">c.wz as wzc</d:field>
<d:field title="WZ metric">m.wz as wzm</d:field> <d:field title="WZ metric">m.wz as wzm</d:field>
<d:field title="WZ конечника">s.end_customer_wz as wze</d:field> <d:field title="WZ конечника">s.wze</d:field>
<d:field title="Артикул">coalesce(s.sku_code, m.code) as code</d:field> <d:field title="Артикул">coalesce(s.sku_code, m.code) as code</d:field>
<d:field title="Артикул по специф.">s.code as s_code</d:field><!--- содержит суффикс типа тарификации ---> <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="SKU code по специф.">s.sku_code as sku_code</d:field><!--- без суффикса --->
<d:field title="Артикул по метрикам">m.code as m_code</d:field><!--- без суффикса --->
<d:field title="Кол-во компонента по спец." cfSqlType="CF_SQL_NUMERIC">s.component_quantity</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_quantity</d:field>
<d:field title="Скидка на сервис" cfSqlType="CF_SQL_NUMERIC">s.service_discount</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 title="Тип по спец.">s.type</d:field>
<d:field>m.dimension1</d:field>
<d:field title="Тип по спец.">s.type</d:field>
<d:field title="Ед.изм.">m.unit</d:field>
<d:field title="Ед.изм.">s.ed_izm</d:field> <d:field title="Ед.изм.">s.ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">coalesce(s.service_quantity*(100.-s.service_discount)/100.*s.price*(100.-s.component_discount)/100., 0.) as discounted_price</d:field> <d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">
CASE --inline implementation of gaussian round to 2 decimal places
-- Isolate the 3rd decimal place using MOD instead of %, hsql syntax
WHEN ABS(MOD(TRUNCATE(s.discounted_price * 1000, 0), 10)) = 5
AND ABS(MOD(TRUNCATE(s.discounted_price * 100, 0), 2)) = 0
-- If it's a perfect .xx5 tie and the 2nd digit is EVEN, shave off the 5
THEN TRUNCATE(s.discounted_price, 2)
-- In all other cases, standard mathematical rounding applies safely
ELSE ROUND(s.discounted_price, 2)
END as discounted_price
</d:field>
<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.serviceStart</d:field> <d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.serviceStart</d:field>
<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.serviceEnd</d:field> <d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.serviceEnd</d:field>
<d:field title="Ключ строки">s.line_key</d:field> <d:field title="Ключ строки">s.line_key</d:field>
<d:field title="Цена с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field> <!--- <d:field title="Цена с НДС до скидки" cfSqlType="CF_SQL_NUMERIC">s.price</d:field> --->
<d:field title="Скидка % на компонент" cfSqlType="CF_SQL_NUMERIC">s.component_discount</d:field> <!--- <d:field title="Скидка % на компонент" cfSqlType="CF_SQL_NUMERIC">s.component_discount</d:field> --->
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведенная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field>
<d:field title="Ответственный">c.responsible</d:field>
<d:field title="Email отв-го">c.responsible_email</d:field>
<d:field title="Статус отв-го">c.responsible_status</d:field>
<d:field title="Договор">s.contract</d:field> <d:field title="Договор">s.contract</d:field>
<d:field title="contract_uid">s.contract_uid</d:field> <d:field title="contract_uid">s.contract_uid</d:field>
<d:field title="Допник">s.additional_agreement</d:field> <d:field title="Допник">s.additional_agreement</d:field>
@@ -559,22 +736,39 @@ SELECT
<d:field title="Компонент">s.component</d:field> <d:field title="Компонент">s.component</d:field>
<d:field title="Клиентс. назв.">s.user_description</d:field> <d:field title="Клиентс. назв.">s.user_description</d:field>
<d:field 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 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 title="Артикул по метрикам">m.code as m_code</d:field><!--- без суффикса --->
<d:field>m.dimension1</d:field>
<d:field title="Ед.изм.">m.unit</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведенная метрика" cfSqlType="CF_SQL_NUMERIC">round(m.metric,3) as metric</d:field>
<d:field title="Free Tier" cfSqlType="CF_SQL_NUMERIC">coalesce(ft.free_tier,0) as free_tier</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field>
<d:field title="Ответственный">c.responsible</d:field>
<d:field title="Email отв-го">c.responsible_email</d:field>
<d:field title="Статус отв-го">c.responsible_status</d:field>
</d:field_set> </d:field_set>
,'***' as delim,s.* <!--- --,'***' as delim,s.* --->
FROM qUnifiedMetric m FROM metric m
<cfif local.inner_join> <cfif inner_join>
INNER INNER
<cfelse> <cfelse>
FULL FULL
</cfif> </cfif>
JOIN qSpec s ON (m.wz=s.wz AND m.code=s.sku_code) -- сервис или компонент, но не цена с типом тарификации, суффикс типа тарификации отрезан JOIN spec 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-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 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 стоили нескольких часов работы LEFT JOIN qContragent c ON ((coalesce(s.wz,m.wz))=(c.wz)) -- пробелы в составе WZ стоили нескольких часов работы
--(поскольку trim слева в джойне катастрофически замедляет работу, делаем чистку выше при формировании исходных резалтсетов) <!--- --(поскольку trim слева в джойне катастрофически замедляет работу, делаем чистку выше при формировании исходных резалтсетов) --->
WHERE 1=1 WHERE 1=1
<cfif only_articles_in_spec> <cfif only_articles_in_spec>
AND EXISTS(select * from qSpec qs where qs.wz=m.wz AND qs.type=3) AND EXISTS(select * from spec qs where qs.wz=m.wz AND qs.type=3)
<!--- вообще-то есть смысл добавить и все строки, где что-то намеряли ---> <!--- вообще-то есть смысл добавить и все строки, где что-то намеряли --->
</cfif> </cfif>
<cfif len(wz)> <cfif len(wz)>
@@ -595,7 +789,7 @@ ORDER BY coalesce(coalesce(c.wz, m.wz), s.wz), coalesce(s.code, m.code)
<!--- <cfdump var=#qCharge#/> ---> <!--- <cfdump var=#qCharge#/> --->
<cfoutput>qCharge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfoutput>qCharge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")> <cfif len(debug)>
<cfdump var=#qCharge#/> <cfdump var=#qCharge#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif> <cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> </cfif>
@@ -626,40 +820,42 @@ ORDER BY coalesce(coalesce(c.wz, m.wz), s.wz), coalesce(s.code, m.code)
<br/> <br/>
Даты актуальности пока проверять вручную. Обращать внимание на замножение строк. Даты актуальности пока проверять вручную. Обращать внимание на замножение строк.
<cfoutput> <cfoutput>
<form method="post" action=""> <form method="get" action="">
Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/> Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/>
по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/> по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/>
<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="only_articles_in_spec" id="only_articles_in_spec" value="1"<cfif 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> <input type="checkbox" name="inner_join" id="inner_join" value="1"<cfif inner_join> checked</cfif>/><label for="inner_join">Только найденные в договоре</label>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
WZ <input type="text" name="wz" value="#wz#"/>по вхождению, с регистром WZ <input type="text" name="wz" value="#wz#"/>по вхождению, с регистром
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
Код <input type="text" name="code" value="#code#"/>по вхождению Код <input type="text" name="code" value="#code#"/>по вхождению
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
<input type="submit" style="cursor:pointer;"/> <input type="submit" name="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" )# ---> <input type="submit" name="debug" value="DEBUG" style="cursor:pointer;"/><!--- #dateFormat( input, "yyyy-mm-dd" )#T#timeFormat( input, "HH:mm:ss.lXX" )# --->
</form> </form>
Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#qCharge.recordCount#</b><br/> Часов в периоде: <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 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:ssX')#</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> 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:ssX')#</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",qS3VolAge.dt_load, Now()) GT 24> class="err"</cfif>>#dateFormat(qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(qS3VolAge.dt_load,'HH:mm:ssX')#</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> 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:ssX')#</b>
GPU: <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:ssX')#</b>
LLM: <b<cfif datediff("h",qLlmAge.dt_load, Now()) GT 24> class="err"</cfif>>#dateFormat(qLlmAge.dt_load,'YYYY-MM-DD')# #timeFormat(qLlmAge.dt_load,'HH:mm:ssX')#</b>
<br/> <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> --->
<a href="#request.thisPage#?output_xls&dt_start=#dateFormat(dt_start,'YYYY-MM-DD')#&dt_finish=#dateFormat(dt_finish,'YYYY-MM-DD')#&inner_join=#local.inner_join#&only_articles_in_spec=#local.only_articles_in_spec#&code=#code#&wz=#wz#" 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_xls&submit=1&dt_start=#dateFormat(dt_start,'YYYY-MM-DD')#&dt_finish=#dateFormat(dt_finish,'YYYY-MM-DD')#&inner_join=#inner_join#&only_articles_in_spec=#only_articles_in_spec#&code=#code#&wz=#wz#" 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&dt_start=#dateFormat(dt_start,'YYYY-MM-DD')#&dt_finish=#dateFormat(dt_finish,'YYYY-MM-DD')#&inner_join=#local.inner_join#&only_articles_in_spec=#local.only_articles_in_spec#&code=#code#&wz=#wz#" 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> <a href="#request.thisPage#?output_json&submit=1&dt_start=#dateFormat(dt_start,'YYYY-MM-DD')#&dt_finish=#dateFormat(dt_finish,'YYYY-MM-DD')#&inner_join=#inner_join#&only_articles_in_spec=#only_articles_in_spec#&code=#code#&wz=#wz#" 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>
<i><b>(перед выгрузкой отчета на произвольную дату или с параметрами сначала просмотрите его в браузере)</b></i> <i><b>(перед выгрузкой отчета на произвольную дату или с параметрами сначала просмотрите его в браузере)</b></i>
<br/>
<span class="gray">серая строка</span> - нет метрик; <span class="err">красное</span> число в поле "Кол-во специф." - для PAYG в спецификации кол-во не 1
</cfoutput> </cfoutput>
<table class="worktable"> <table class="worktable">
<thead> <thead>
<td width="1%"></td> <td width="1%"></td>
<!--- <th width="3%">WZ</th> ---> <th width="3%">Match</th>
<th width="7%">Услуга</th> <th width="7%">Услуга</th>
<th width="7%">Артикул специф.</th> <th width="7%">Артикул специф.</th>
<th width="5%">Кол-во специф.</th> <th width="5%">Кол-во специф.</th>
@@ -668,36 +864,35 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
<th width="5%">Кол-во метр.</th> <th width="5%">Кол-во метр.</th>
<th width="5%">Free Tier.</th> <th width="5%">Free Tier.</th>
<th width="5%">Опл. объем</th> <th width="5%">Опл. объем</th>
<th width="3%">Ед.изм.</th> <th width="2%">Ед.изм.</th>
<th width="3%">Цена &#8381; со скид., с НДС</th> <th width="3%">Цена &#8381; со скид., с НДС</th>
<th width="3%">Стоимость &#8381; с НДС</th> <th width="3%">Стоимость &#8381; с НДС</th>
<td width="3%">&nbsp;&nbsp;&nbsp;</td> <td width="10%">Сделка</td>
<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%">GPL с НДС</td>
<td width="3%">Скидка%</td> <td width="3%">Скидка%</td> --->
<td width="3%">Дата НОУ</td> <td width="3%">Дата НОУ</td>
<td width="3%">Дата КОУ</td> <td width="3%">Дата КОУ</td>
<td width="5%">Ключ строки</td> <!--- <td width="5%">Ключ строки</td> --->
<td width="3%">Сырая метрика</td> <td width="3%">Сырая метрика</td>
<td width="3%">Приведен&shy;ная метрика</td> <td width="3%">Приведен&shy;ная метрика</td>
<td width="3%">Цена &#8381; до ск. с НДС</td> <!--- <td width="3%">Цена &#8381; до ск. с НДС</td>
<td width="3%">Цена &#8381; co ск. с НДС без окр.</td> <td width="3%">Цена &#8381; co ск. с НДС без окр.</td> --->
<td width="3%">Service Quantity</td> <!--- <td width="3%">Кол-во сервиса</td> --->
<td width="3%">Service Discount</td> <!--- <td width="3%">Скидка на сервис</td> --->
<td width="3%">Component Quantity</td> <!--- <td width="3%">Кол-во комп-та</td> --->
<td width="3%">Component Discount</td> <!--- <td width="3%">Скидка на комп-т %</td> --->
<td width="5%">Договор</td> <!--- <td width="5%">Договор</td>
<td width="10%">Допник</td> <td width="10%">Допник</td> --->
<td width="10%">Сделка</td>
<td width="3%">Конечник</td>
</thead> </thead>
@@ -722,11 +917,11 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
<cfoutput group="code"> <cfoutput group="code">
<cfoutput group="serviceStart"> <cfoutput group="serviceStart">
<cfset accum_metric_svc += isNumeric(metric) ? metric : 0/> <cfset accum_metric_svc += isNumeric(metric) ? metric : 0/>
<cfset accum_metric_dimension_1 = 0/> <cfset accum_metric_dimension_1 = 0/>
<cfset accum_metric_dimension_1_all = 0/><!--- не различая PAYG/FIX ---> <cfset accum_metric_dimension_1_all = 0/><!--- не различая PAYG/FIX --->
<cfset current_price=0/> <cfset current_price=0/>
<cfoutput><!--- dimensions ---> <cfoutput><!--- dimensions --->
<cfif type EQ 3> <cfif type EQ 3>
<cfset accum_metric_dimension_1 += isNumeric(metric) ? metric : 0/> <cfset accum_metric_dimension_1 += isNumeric(metric) ? metric : 0/>
@@ -736,73 +931,76 @@ 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<cfif exact_match GT 0> style="color:green"<cfelse> style="color:red"</cfif>>
#occurrences_spec#|#occurrences_metric#
#diag#
</td>
<td>#abstract_service#<cfif len(modifier)>: #modifier#</cfif></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>
<td>#dimension1#</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 class="r" style="padding:0 1em;">#metric#</td>
<td></td> <td class="r"><!--- #free_tier# ---></td>
<td style="font-size:90%;">#unit# <cfif len(ed_izm)>[#ed_izm#]</cfif></td><!--- #len(unit)?unit:'['& ed_izm &']'# ---> <td></td>
<td class="r">#gaussianRound(discounted_price,2)#</td> <td class="c" style="font-size:80%;">#unit# <cfif len(ed_izm)>[#ed_izm#]</cfif></td><!--- #len(unit)?unit:'['& ed_izm &']'# --->
<td class="r">#discounted_price#</td>
<td class="r"></td> <td class="r"></td>
<td></td> <td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
<td><a href="contragent.cfm?id_klienta=#WZE#&#tr.fwx#">#WZE#</a></td>
<td>#component#</td> <td>#component#</td>
<td>#user_description#</td> <td>#user_description#</td>
<td class="r">#gaussianRoundSafe(price,2)#</td> <!--- <td class="r">#gaussianRoundSafe(price,2)#</td>
<td class="r">#component_discount#</td> <td class="r">#component_discount#</td> --->
<td class="r">#dateFormat(serviceStart,'YYYY-MM-DD')#</td> <td class="r">#dateFormat(serviceStart,'YYYY-MM-DD')#</td>
<td class="r">#dateFormat(serviceEnd,'YYYY-MM-DD')#</td> <td class="r">#dateFormat(serviceEnd,'YYYY-MM-DD')#</td>
<td class="r">#line_key#</td> <!--- <td class="r">#line_key#</td> --->
<td class="r" style="color:##bbb">#request.roundSafe(raw_metric,3)#</td> <td class="r" style="color:##bbb">#raw_metric#</td>
<td class="r">#request.roundSafe(metric,3)#</td> <td class="r">#metric#</td>
<!--- сырые исходные данные без округлений ---> <!--- сырые исходные данные без округлений --->
<td class="r">#price#</td> <!--- <td class="r">#price#</td> --->
<td class="r">#discounted_price#</td><!--- style="word-wrap:break-word" ---> <!--- <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> --->
<td class="r">#component_discount#</td> <!--- <td class="r">#component_discount#</td> --->
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a></td> <!--- <td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a></td>
<td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td> <td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td> --->
<td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
<td>#WZE#</td>
</tr> </tr>
</cfoutput> </cfoutput><!--- /dimensions --->
<cfset final_metric_dimension_1 = ceiling(accum_metric_dimension_1)/> <cfset final_metric_dimension_1 = ceiling(accum_metric_dimension_1)/>
<cfset final_metric_dimension_1_all = ceiling(accum_metric_dimension_1_all)/> <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 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="4"></td> <td colspan="5"></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;"><!--- #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" style="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">#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="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 c">#unit# <cfif len(ed_izm)>[#ed_izm#]</cfif></td>
<td class="b r">#current_price#</td> <td class="b r">#current_price#</td>
<td class="b r">#gaussianRoundSafe(cost_dimension_1,2)#</td> <td class="b r">#gaussianRoundSafe(cost_dimension_1,2)#</td>
<td></td> <td colspan="7"></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 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> </tr>
</cfoutput><!--- serviceStart ---> </cfoutput><!--- serviceStart --->
</cfoutput><!--- code ---> </cfoutput><!--- code --->
<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="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" colspan="11" 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;">#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> <td bgcolor="##eee" colspan="99" style="border-bottom:2px solid gray;"></td>
</tr > </tr >
</cfoutput><!--- wz ---> </cfoutput><!--- wz --->
+9 -9
View File
@@ -10,12 +10,8 @@
<cfreturn (a GT 0)? a : ""/> <cfreturn (a GT 0)? a : ""/>
</cffunction> </cffunction>
<m:prepare_ls entity="s3_user" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/> <m:prepare_ls entity="s3_user" settingsKey="s3_user" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/><!--- NB settingsKey --->
<!--- <m:filter_settings target="#pageInfo.entity#_ls">
<m:filterparam filter=#filter# param="quickfilter" ftype="string" prefix="%" suffix="%" expression="((p.project like ?) OR (p.customer like ?) OR (p.customer_alias like ?) OR (p.contragent_class_type like ?) OR (p.division like ?) OR (p.performer_short like ?))" default=""/>
</m:filter_settings> --->
<!--- <cfset pageInfo.settings.filter=#filter#/> --->
<!--- <cftry> ---> <!--- <cftry> --->
<cfquery name="qS3" datasource="billing-s3"> <cfquery name="qS3" datasource="billing-s3">
@@ -40,7 +36,7 @@
cross join (select max(timestamp_addition) as timestamp_addition from s3billing.bucket_stat) t cross join (select max(timestamp_addition) as timestamp_addition from s3billing.bucket_stat) t
</cfquery> </cfquery>
<cfquery name="qS3User" datasource="cmdb" cachedWithin=#createTimeSpan(0, 0, 31, 0)#> <cfquery name="qS3User" datasource="cmdb" cachedWithin=#createTimeSpan(0, 0, 1, 0)#>
WITH current_state AS ( WITH current_state AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY instance_uid ORDER BY version DESC) as rn SELECT *, ROW_NUMBER() OVER (PARTITION BY instance_uid ORDER BY version DESC) as rn
FROM instance_state FROM instance_state
@@ -54,8 +50,9 @@
left join contract d on (p.contract_id=d.contract_id) left join contract d on (p.contract_id=d.contract_id)
left join contragent k on (d.contragent_id=k.contragent_id) left join contragent k on (d.contragent_id=k.contragent_id)
WHERE rn = 1 AND e.service_id=12 WHERE rn = 1 AND e.service_id=12
AND NOT cast(s.instance_data->>'isDeleted' as boolean) /*не вдаваясь в другие статусы*/
</cfquery> </cfquery>
<!--- <cfdump var=#qRead#/> --->
<!--- <cfcatch type="database"> <!--- <cfcatch type="database">
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/> <m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
@@ -100,10 +97,12 @@ select
from qS3 s from qS3 s
left outer join qContragent c on (s.wz=c.wz) left outer join qContragent c on (s.wz=c.wz)
full outer join qS3User u on (s.owner=u.user_id) full outer join qS3User u on (s.owner=u.user_id)
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/> where 1=1 <m:filter_build filter=#pageInfo.settings.filter# target="hsql"/>
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/> order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
</cfquery> </cfquery>
<!--- <cfdump var=#qRead#/> --->
<cfquery name="qCountTotal" datasource="inmem"> <cfquery name="qCountTotal" datasource="inmem">
select count(*) as cnt select count(*) as cnt
from qS3 s from qS3 s
@@ -179,7 +178,8 @@ full outer join qS3User u on (s.owner=u.user_id)
<td><a href="mailto:#responsible_email#">#responsible_email#</a></td> <td><a href="mailto:#responsible_email#">#responsible_email#</a></td>
<td class="r">#id#</td> <td class="r">#id#</td>
<td<cfif !(isNumeric(owner) AND owner LT 10000)> class="err"</cfif>>#owner#</td> <!--- <td<cfif !(isNumeric(owner) AND owner LT 10000)> class="err"</cfif>>#owner#</td> --->
<td>#owner#</td>
<td class="r">#bucket_cnt#</td> <td class="r">#bucket_cnt#</td>
<td class="r">#size_byte#</td> <td class="r">#size_byte#</td>
+145
View File
@@ -0,0 +1,145 @@
<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:silent silent="No">
<m:prepare_filter entity="s3_user" accessObject="" lsPage="s3_ls" pageInfoOut="pageInfo" trackOut="tr"/>
<m:filter_settings target="s3_user">
<m:filterparam filter=#filter# param="owner" ftype="string" compare="LIKE%" field="s.owner" default=""/>
<m:filterparam filter=#filter# param="display_name" ftype="string" compare="LIKE%" field="u.display_name" default=""/>
<m:filterparam filter=#filter# param="contragent" ftype="string" compare="LIKE%" field="c.contragent" default=""/>
<!--- <m:filterparam filter=#filter# param="contragent_id" ftype="guid" compare="EQ" field="k.__id" default=""/> --->
<m:filterparam filter=#filter# param="wz" ftype="string" compare="LIKE%" field="c.wz" default=""/>
<m:filterparam filter=#filter# param="wzs" ftype="string" compare="LIKE%" field="u.wz" default=""/>
<m:filterparam filter=#filter# param="external_code" ftype="string" compare="LIKE%" field="u.external_code" default=""/>
</m:filter_settings>
<cfif isDefined("resetAndClose") or isDefined("saveAndClose")>
<cflocation url="#tr.backUrl#" addtoken="No"/>
</cfif>
<!--- ЗАСАДА для inmem HSQLDB: не поддерживает ilike --->
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title"><cfoutput>Учетные записи S3 - фильтр</cfoutput></layout:attribute>
</layout:page>
<!--- <script type="text/javascript"/>
$(document).ready(function() {
try {
$("#contragent_id").searchable({maxMultiMatch: 50});
} catch (e) {alert(e)}
});
</script> --->
<cfoutput>
<input type="hidden" name="track" value="#tr.self#"/>
<div class="detail">
<div class="tr">
<div class="th"></div>
<div class="td">
<button type="button" name="reset" onClick="document.location.href='#request.thisPage#?reset=yes&track=#tr.self#'">#i18("Очистить","Clear")#</button>
</div>
</div>
<!--- <div class="tr">
<div class="th">Номер сделки</div>
<div class="td">
<input type="text" name="__index" value="#__index#" size="5"/>
<i></i>
</div>
</div>
<div class="tr">
<div class="th">Название сделки</div>
<div class="td">
<input type="text" name="__name" value="#__name#" size="50"/>
<i>#i18("по вхождению подстроки","by substring")#</i>
</div>
</div> --->
<!--- <div class="tr">
<div class="th">Контрагент (CMDB)</div>
<div class="td" style="vertical-align:top;">
<cfquery name="qList">
select __id::text as __id, __name, id_klienta
from elma.companies
order by __name
</cfquery>
<!--- <cfdump var=#qList#/> --->
<c:combo
query=#qList#
combo="contragent_id"
id="contragent_id"
key="__id"
displayf="##__name## ##id_klienta##"
selected=#contragent_id#
empty=""
/>
</div>
--->
<div class="tr">
<div class="th">Контрагент (CMDB)</div>
<div class="td">
<input type="text" name="contragent" value="#contragent#" size="50"/>
<i>по вхождению подстроки</i>
</div>
</div>
<div class="tr">
<div class="th">WZ (по точному совпадению с именем учетки)</div>
<div class="td">
<input type="text" name="wz" value="#wz#" size="50"/>
<i>по вхождению подстроки</i>
</div>
</div>
<div class="tr">
<div class="th">WZ (state)</div>
<div class="td">
<input type="text" name="wzs" value="#wzs#" size="50"/>
<i>по вхождению подстроки</i>
</div>
</div>
<div class="tr">
<div class="th">WZ (instance)</div>
<div class="td">
<input type="text" name="external_code" value="#external_code#" size="50"/>
<i>по вхождению подстроки</i>
</div>
</div>
<div class="tr">
<div class="th">Owner (имя учетки S3)</div>
<div class="td">
<input type="text" name="owner" value="#owner#" size="50"/>
<i>по вхождению подстроки</i>
</div>
</div>
<div class="tr">
<div class="th">Display Name экземпляра в CMDB</div>
<div class="td">
<input type="text" name="display_name" value="#display_name#" size="50"/>
<i>по вхождению подстроки</i>
</div>
</div>
</div>
</cfoutput>
<layout:page section="footer" closeForm="Yes"/>
<!--- <cfdump var=#filter#> --->