Compare commits

...
2 Commits
Author SHA1 Message Date
smishchuk c7986e3385 126 tenant metadata 2025-12-11 15:39:53 +03:00
smishchuk ce44051801 025 interface imptovements 2025-10-14 15:14:14 +03:00
15 changed files with 405 additions and 576 deletions
+3 -5
View File
@@ -19,14 +19,12 @@
<cfset this.defaultdatasource = this.datasource/>
<cfset request.DS = "#this.datasource#">
<!--- кажется, нужно инициализировать датасорцы в псевдоконструкторе - onRequest не получается --->
<cfset this.datasources["#this.datasource#"]=getDS("#this.datasource#","ds_#this.datasource#")/>
<!--- <cfset this.datasources["#this.datasource#"]=getDS("#this.datasource#","ds_#this.datasource#")/>
<cfset this.datasources["billing-vc"]=getDS("billing-vc","ds_billing_vc")/>
<cfset this.datasources["billing-s3"]=getDS("billing-s3","ds_billing_s3")/>
<cfset this.datasources["billing-s3"]=getDS("billing-s3","ds_billing_s3")/> --->
<!--- но датасорцы таинственно прочухались с прошлым пушем, без переноса инициализации в псевдоконструктор --->
<cfset COOKIEENCKEY = "PREVED!Y2"/>
<!--- Define the page request properties. --->
<cfsetting
@@ -99,7 +97,7 @@
<cfset request.RECORDS_PER_PAGE=500/>
<cfset request.APP_VERSION="0.00.025"/>
<cfset request.APP_VERSION="0.00.026"/>
<cfset request.STAND=getStand()/>
<cflock scope="application" type="readonly" timeout=3>
+3 -2
View File
@@ -27,6 +27,7 @@
<d:param field="__deletedAt" type="timestamp" forNull=""/> --->
<d:param field="documents" type="ARRAY" forNull=""/>
<d:param field="contract_uid" type="uuid" forNull=""/>
<d:param field="__index" type="integer" forNull="" default="0" init="0"/>
<d:param field="index" type="integer" forNull="" default="0" init="0"/>
<!--- <d:param field="services" type="ARRAY" forNull=""/> --->
<d:param field="is_actual" type="bit" forNull=""/>
@@ -93,7 +94,7 @@
<div class="tr">
<div class="th">__id</div>
<div class="td">#d.__id#</div>
<div class="td">#d.__id# &nbsp;&nbsp;&nbsp;__index #d.__index#</div>
</div>
<div class="tr">
@@ -296,7 +297,7 @@
<td class="c">#dateFormat(date_nop,'YYYY-MM-DD')#</td>
<td class="c">#dateFormat(date_end,'YYYY-MM-DD')#</td>
<td class="c"><cfif is_easy GT 0>Простая<cfelse>Композитная</cfif></td>
<td class="c">#params#</td>
<td>#params#</td>
</tr>
</cfoutput>
</table>
+1 -1
View File
@@ -52,7 +52,7 @@
</cftry>
<cfquery name="qCountTotal" datasource="#request.DS#">
select count(*) as cnt from elma.aggrements d where 1=1
select count(*) as cnt from elma.additional_agreements d where 1=1
</cfquery>
</m:silent><!---
+148
View File
@@ -0,0 +1,148 @@
<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">
<cffunction name="hideNonPositive">
<cfargument name="a"/>
<cfreturn (a GT 0)? a : ""/>
</cffunction>
<m:prepare_ls entity="additional_agreement" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<!--- <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.contract_class_type like ?) OR (p.division like ?) OR (p.performer_short like ?))" default=""/>
</m:filter_settings> --->
<!--- <cfset pageInfo.settings.filter=#filter#/> --->
<cftry>
<cfquery name="qRead" datasource="#request.DS#">
select
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
<d:field title="ID" cfSqlType="CF_SQL_OTHER">a.__id</d:field>
<d:field title="Внут.номер">g.agreement_id</d:field>
<d:field title="Доп.соглашение">a.__name</d:field>
<d:field title="Версия">a.index</d:field>
<d:field title="Сделка">d.__name as deal</d:field>
<d:field title="Сделка">d.__id as deal_uid</d:field>
<d:field title="Договор">g.__name as contract</d:field>
<d:field title="Договор">g.__id as contract_uid</d:field>
<d:field title="company_uid">g.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="Дата договора">g.date_of_aggrement</d:field>
<d:field title="Дата окончания">g.date_end_aggrement</d:field>
<d:field title="Тип договора">g.type_of_agreement</d:field>
</d:field_set>
from elma.additional_agreements a
left outer join elma.additional_agreements b on (b.__id=ANY(a.base_by))
left outer join elma.aggrements g on (a.contract_uid=g.__id)
left outer join elma.deals d on (a.deal_uid=d.__id)
left outer join elma.companies k on (g.company_uid=k.__id)
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
</cfquery>
<cfcatch type="database">
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
</cfcatch>
</cftry>
<cfquery name="qCountTotal" datasource="#request.DS#">
select count(*) as cnt from elma.aggrements d where 1=1
</cfquery>
</m:silent><!---
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
---><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>Дополнительные соглашения</b></cfoutput>
</layout:attribute>
<!--- <layout:attribute name="controls"></layout:attribute> --->
</layout:page>
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
<layout:grid_summary
recordCount=#qRead.recordCount#
totalCount=#qCountTotal.cnt#
footerOut="gridFooter"
excelLink="Yes"
jsonLink="Yes"
/>
<!--- так довольно громоздко, но можно обойтись без Dynamic Evaluation --->
<cfset queryAddColumn(qRead,'f_link_view_edit')/>
<cfset titleMap.f_link_view_edit={ordinal=#StructCount(titleMap)+1#}/><!--- *** Это легко забыть, потому что TitleMap никак не сцеплен с qRead. Напрашивается: упаковать их в одну обертку (но тогда обращение станет длиннее). Еще идея - назвать qRead и TitleMap так, чтобы была видна их связь. --->
<!--- <cfdump var=#titleMap#/> --->
<cfset queryAddColumn(qRead,'f_contract')/>
<cfset titleMap.f_contract=titleMap.contract/>
<cfset queryAddColumn(qRead,'f_contragent')/>
<cfset titleMap.f_contragent=titleMap.contragent/>
<cfset queryAddColumn(qRead,'f_deal')/>
<cfset titleMap.f_deal=titleMap.deal/>
<cfset queryAddColumn(qRead,'f_link_del')/>
<cfset titleMap.f_link_del={ordinal=0}/>
<!--- <cfdump var=#titleMap#/> --->
<cfoutput query=#qRead# startRow=#pageInfo.nStart# maxRows=#pageInfo.recordsPerPage#>
<cfsavecontent variable="qRead.f_link_view_edit">
<a href="additional_agreement.cfm?__id=#__id#&#tr.fwx#" name="#__id#" title="просмотр" class="view"></a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_contract">
<a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_contragent">
<a href="contragent.cfm?__id=#company_uid#&#tr.fwx#">#contragent#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_deal">
<a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a>
</cfsavecontent>
</cfoutput>
<c:table query=#qRead# recordsPerPage=#pageInfo.recordsPerPage# nStart=#pageInfo.nStart# titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray# class="worktable wide">
<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="3%" field="index"/>
<c:column width="15%" field="__name"/>
<c:column width="15%" field="f_contract"/>
<c:column width="6%" field="agreement_id"/>
<c:column width="10%" field="f_deal"/>
<c:column width="15%" field="f_contragent"/>
<c:column width="5%" field="wz"/>
<c:column width="10%" field="date_of_aggrement" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="10%" field="date_end_aggrement" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="10%" field="type_of_agreement"><c:td class="l"/></c:column>
</c:table>
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>
+21 -10
View File
@@ -118,12 +118,15 @@
select
a.__id::text
,a.__name
,contract_uid::text
,is_actual
,last_aa
,index
,deal_uid::text
,base_by::text
,a.__index
,a.contract_uid::text
,a.is_actual
,a.last_aa
,a.index
,a.deal_uid::text
,a.base_by[1]::text as base_by_uid
,b.__name as base_by_name
,b.__index as base_by_index
,d.__name as deal
,d.__status_status as status_id
,s.status
@@ -131,6 +134,7 @@
from elma.additional_agreements a
left outer join elma.deals d on (a.deal_uid=d.__id)
left outer join s on (d.__status_status=s.status_id)
left outer join elma.additional_agreements b on (a.base_by[1]=b.__id)
where a.contract_uid=<cfqueryparam cfsqltype="cf_sql_other" value="#d.__id#" null=#!isValid('guid',d.__id)#/>
order by 1
</cfquery>
@@ -143,10 +147,11 @@
<table class="worktable">
<thead>
<tr>
<th>__index</th>
<th>__id</th>
<th>__name</th>
<th>версия</th>
<th>contract_uid</th>
<!--- <th>contract_uid</th> --->
<th>is_actual</th>
<th>last_aa</th>
<th>deal_uid</th>
@@ -154,16 +159,19 @@
<th>status_id</th>
<th>status</th>
<th>вер-ть</th>
<th>base_by</th>
<th>base_by_index</th>
<th>base_by_uid</th>
<th>base_by_name</th>
</tr>
</thead>
<cfoutput query="qAdditionalAgreement">
<tr>
<td><a href="additional_agreement.cfm?__id=#__id#&#tr.fwx#">#__index#</a></td>
<td><a href="additional_agreement.cfm?__id=#__id#&#tr.fwx#">#__id#</a></td>
<td>#__name#</td>
<td class="c">#index#</td>
<td>#contract_uid#</td>
<!--- <td>#contract_uid#</td> --->
<td class="c">#is_actual#</td>
<td class="c">#last_aa#</td>
<td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal_uid#</a></td>
@@ -171,7 +179,10 @@
<td class="c">#status_id#</td>
<td>#status#</td>
<td class="r">#probability_pc#</td>
<td>#base_by#</td>
<td class="r"><a href="additional_agreement.cfm?__id=#base_by_uid#&#tr.fwx#">#base_by_index#</a></td>
<td><a href="additional_agreement.cfm?__id=#base_by_uid#&#tr.fwx#">#base_by_uid#</a></td>
<td><a href="additional_agreement.cfm?__id=#base_by_uid#&#tr.fwx#">#base_by_name#</a></td>
<!--- <td class="c">
#dateFormat(dt_contract,'YYYY-MM-DD')#
</td> --->
+2
View File
@@ -30,6 +30,7 @@
<d:field title="Дата договора">d.date_of_aggrement</d:field>
<d:field title="Дата окончания">d.date_end_aggrement</d:field>
<d:field title="Тип договора">d.type_of_agreement</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_set>
from elma.aggrements d
left outer join elma.companies k on (d.company_uid=k.__id)
@@ -120,6 +121,7 @@ select count(*) as cnt from elma.aggrements d where 1=1
<c:column width="10%" field="date_of_aggrement" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#/>
<c:column width="10%" field="date_end_aggrement" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#/>
<c:column width="10%" field="type_of_agreement"><c:td class="l"/></c:column>
<c:column width="10%" field="aa_cnt"><c:td class="c"/></c:column>
</c:table>
+22 -14
View File
@@ -15,7 +15,7 @@
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="contragent" accessObject="" key="contragent_id" pageInfoOut="pageInfo"/>
<m:prepare_detail entity="contragent" accessObject="" key="__id" pageInfoOut="pageInfo"/>
<d:bean readonly=true table="elma.companies" datasource="#request.DS#" output="d" status="status">
<d:param field="__id" type="uuid" key/>
@@ -179,10 +179,12 @@
component as (select siv.deal as deal_uids, siv.type, (siv.cnt*(100-COALESCE(siv.discount,0))/100*p.price*p.cnt*(100-COALESCE(p.discount,0))) as param_cost
from elma.deals_services siv
join elma.service_parametrs p on (p.__id = ANY(siv.params))
where p."__deletedAt" IS NULL AND siv."__deletedAt" IS NULL AND siv.is_actual
)
select
a.__id::text
,a.__name as additional_agreement
,a.__index
,a.contract_uid::text
,a.is_actual
,a.last_aa
@@ -197,16 +199,16 @@
,s.probability_pc
,u.__name as owner
,(select sum(param_cost)
from component
where d.__id = ANY(component.deal_uids) AND component.type IN (1)
from component p
where d.__id = p.deal_uids[1] AND p.type IN (1)
) as install
,(select sum(param_cost)
from component
where d.__id = ANY(component.deal_uids) AND component.type IN (2)
from component p
where d.__id = p.deal_uids[1] AND p.type IN (2)
) as periodical
,(select sum(param_cost)
from component
where d.__id = ANY(component.deal_uids) AND component.type IN (3)
from component p
where d.__id = p.deal_uids[1] AND p.type IN (3)
) as metered
from elma.additional_agreements a
join elma.aggrements c on (a.contract_uid=c.__id)
@@ -215,6 +217,7 @@
left outer join elma.comp_users_ext u on (d._owner=c.__id)
where c.company_uid=<cfqueryparam cfsqltype="cf_sql_other" value=#d.__id# null=#!isValid("guid",d.__id)#/>
AND s.probability_pc > 0
order by a.__index
</cfquery>
@@ -228,6 +231,7 @@
<thead>
<tr>
<th>__id</th>
<th>__index</th>
<th>Доп. соглашение</th>
<th>Внут. н-р дог.</th>
<th>Дата договора</th>
@@ -243,6 +247,7 @@
<cfoutput query="qAdditionalAgreement">
<tr>
<td><a href="additional_agreement.cfm?__id=#__id#&#tr.fwx#">#__id#</a></td>
<td><a href="additional_agreement.cfm?__id=#__id#&#tr.fwx#">#__index#</a></td>
<td>#additional_agreement#</td>
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#agreement_id#</a></td>
<td>#dateFormat(date_of_aggrement,"YYYY-MM-DD")#</td>
@@ -250,9 +255,9 @@
<td>#status#</td>
<td>#probability_pc#</td>
<td>#owner#</td>
<td class="r">#nFmt(install)#</td>
<td class="r">#nFmt(periodical)#</td>
<td class="r">#nFmt(metered)#</td>
<td class="r nw">#nFmt(install)#</td>
<td class="r nw">#nFmt(periodical)#</td>
<td class="r nw">#nFmt(metered)#</td>
</tr>
</cfoutput>
</table>
@@ -270,6 +275,7 @@
component as (select siv.deal as deal_uids, siv.type, (siv.cnt*(100-COALESCE(siv.discount,0))/100*p.price*p.cnt*(100-COALESCE(p.discount,0))) as param_cost
from elma.deals_services siv
join elma.service_parametrs p on (p.__id = ANY(siv.params))
where p."__deletedAt" IS NULL AND siv."__deletedAt" IS NULL AND siv.is_actual
)
select
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
@@ -353,9 +359,9 @@
<td>#contract#</td>
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#agreement_id#</a></td>
<td>#dateFormat(date_of_aggrement,"YYYY-MM-DD")#</td>
<td class="r">#nFmt(install)#</td>
<td class="r">#nFmt(periodical)#</td>
<td class="r">#nFmt(metered)#</td>
<td class="r nw">#nFmt(install)#</td>
<td class="r nw">#nFmt(periodical)#</td>
<td class="r nw">#nFmt(metered)#</td>
</tr>
</cfoutput>
</table>
@@ -396,10 +402,12 @@
sum(siv.cnt*(100-COALESCE(siv.discount,0))/100*p.price*p.cnt*(100-COALESCE(p.discount,0))/100)
from elma.service_parametrs p
where p.__id = ANY (siv.params)
AND p."__deletedAt" IS NULL
) as line_cost
,(select count(*)
from elma.service_parametrs p
where p.__id = ANY (siv.params)
AND p."__deletedAt" IS NULL
) as param_cnt
,s.probability_pc
,d.__index
@@ -414,7 +422,7 @@
</cfquery>
<cfoutput>
<h4>Услуги (версии строк спецификации, только актуальные) (#qService.recordCount#)</h4>
<h4>Услуги (версии строк спецификации, только актуальные) (#qService.recordCount#) *** здесь не учтено дублирование строк в новых версиях</h4>
</cfoutput>
<!--- <layout:render_query query=#qService#/> --->
+14 -10
View File
@@ -257,18 +257,17 @@
<tr>
<th>__index</th>
<!--- <th>__name</th> --->
<th width="12%">user_description</th>
<th>Код</th><th>type</th><th width="12%">user_description</th>
<th>Кол-во</th>
<th>Скидка%</th>
<th width="5%">Сумма</th>
<th>Код</th>
<th>type</th>
<th>is_actual</th>
<th>hash</th>
<th>version</th>
<th>name_version</th>
<th>date_accept</th>
<th>__index</th>
<th width="5%">date_nop</th>
<th width="5%">date_end</th>
<th>is_easy</th>
@@ -281,10 +280,6 @@
<tr>
<td class="c"><a href="deal_service.cfm?__id=#__id#&#tr.fwx#" title="__id">#__index#</a></td>
<!--- <td class="c">#__name#</td> --->
<td class="l">#user_description#</td>
<td class="c">#cnt#</td>
<td class="c">#discount#</td>
<td class="r">#nFmt(line_cost)#</td>
<td class="l">
#abstractive_service_code#.#modifier_code#<!--- <cfswitch expression=#type#>
<cfcase value=1>-i</cfcase>
@@ -292,13 +287,22 @@
<cfcase value=3>-m</cfcase>
</cfswitch> --->
</td>
<td class="c">#type#</td>
<td class="c">#type# (<cfswitch expression=#type#>
<cfcase value=1>i</cfcase>
<cfcase value=2>f</cfcase>
<cfcase value=3>m</cfcase>
</cfswitch>)</td>
<td class="l">#user_description#</td>
<td class="c">#cnt#</td>
<td class="c">#discount#</td>
<td class="r">#nFmt(line_cost)#</td>
<td class="c">#is_actual#</td>
<td class="c">#hash#</td>
<td class="c">#version#</td>
<td class="c">#name_version#</td>
<td class="c">#date_accept#</td>
<td class="c">#__index#</td>
<td class="c">#dateFormat(date_nop,'YYYY-MM-DD')#</td>
<td class="c">#dateFormat(date_end,'YYYY-MM-DD')#</td>
<td class="c"><cfif is_easy GT 0>Простая<cfelseif is_easy EQ 0>Композитная<cfelse>is_easy=#is_easy#</cfif></td>
+9
View File
@@ -13,6 +13,7 @@
<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="k.id_klienta" default=""/>
<m:filterparam filter=#filter# param="status_id" ftype="numeric" compare="EQ" field="d.__status_status" default=""/>
<m:filterparam filter=#filter# param="__index" ftype="numeric" compare="EQ" field="d.__index" default=""/>
</m:filter_settings>
<cfif isDefined("resetAndClose") or isDefined("saveAndClose")>
@@ -46,6 +47,14 @@ $(document).ready(function() {
</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">
+3 -2
View File
@@ -52,9 +52,9 @@
where d.__id = ANY(siv.deal)
) as line_cnt
</d:field> --->
<!--- <d:field>(select count(*)
<!--- <d:field title="Строк">(select count(*)
from elma.deals_services siv
where d.__id = ANY(siv.deal) AND siv.is_actual
where d.__id = ANY(siv.deal) AND siv.is_actual AND siv."__deletedAt" IS NULL
) as line_cnt_actual
</d:field> --->
<!---<d:field>(select sum(param_cost)
@@ -176,6 +176,7 @@ select count(*) as cnt from elma.deals d where 1=1
<c:column width="3%" field="__status_status"><c:td class="c"/></c:column>
<c:column width="5%" field="status"><c:td class="c"/></c:column>
<c:column width="3%" field="probability_pc"><c:td class="c"/></c:column>
<!--- <c:column width="3%" field="line_cnt_actual"><c:td class="c"/></c:column> --->
<c:column width="5%" field="__createdAt" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="8%" field="owner"><c:td class="l"/></c:column>
<c:column width="5%" field="f_additional_agreement"><c:td class="l"/></c:column>
+80 -44
View File
@@ -145,6 +145,7 @@
from elma.service_parametrs p
join elma.deals_services siv on (p.__id = ANY (siv.params))
where siv.__id=<cfqueryparam cfsqltype="cf_sql_other" value=#d.__id# null=#!isValid("guid",d.__id)#/>
AND p."__deletedAt" IS NULL
</cfquery>
<b>#nFmt(qParamCost.line_cost)#</b> по строке, с количеством и скидкой (<b>#nFmt(qParamCost.param_cost)#</b> по компонентам)
</div>
@@ -177,24 +178,24 @@
,(select
sum(siv.cnt*(100-COALESCE(siv.discount,0))/100*p.price*p.cnt*(100-COALESCE(p.discount,0))/100)
from elma.service_parametrs p
where p.__id = ANY (siv.params)
where p.__id = ANY (siv.params) AND p."__deletedAt" IS NULL
) as line_cost
from elma.deals_services siv
left outer join elma.additional_agreements a on (a.__id = ANY(siv.additional_agreement))
join elma.deals d on (d.__id = ANY(siv.deal))
left outer join status on (d.__status_status = status.status_id)
where hash=<cfqueryparam cfsqltype="cf_sql_varchar" value=#d.hash#/>
AND siv.is_actual
order by siv.__index, siv.version
AND siv."__deletedAt" IS NULL AND siv.is_actual
order by d.__index --siv.__index, siv.version
</cfquery>
<cfloop query=#qV#>
<cfif __id EQ toString(d.__id)>
<b>#aa_version#:#version#[#__index#]</b>
<cfelse>
<a href="deal_service.cfm?__id=#__id#&#tr.fwx#">#aa_version#:#version#[#__index#]</a>
<a href="deal_service.cfm?__id=#__id#&#tr.fwx#" title="версия_дс : версия_строки [индекс_сделки]">#aa_version#:#version#[#__index#]</a>
</cfif>
</cfloop>
(только актуальные и со сделкой)
(версия_дс : версия_строки [индекс_сделки], только актуальные и со сделкой)
</div>
</div>
@@ -241,10 +242,10 @@
</cfquery>
<!--- <cfdump var=#qDeal#/> --->
<cfif qDeal.recordCount>
<a href="deal.cfm?__id=#qDeal.__id#&#tr.fwx#">#qDeal.__id#</a> |
<a href="deal.cfm?__id=#qDeal.__id#&#tr.fwx#">#qDeal.__index# #qDeal.__id#</a> |
<a href="contragent.cfm?__id=#qDeal.contragent_uid#&#tr.fwx#">#qDeal.contragent# #qDeal.wz#</a> |
#qDeal.__name# |
_plannedDueDate: <cfif len(qDeal._plannedDueDate)><b>#dateFormat(qDeal._plannedDueDate,'DD.MM.YYYY')#</b><cfelse>--</cfif>
<!--- _plannedDueDate: <cfif len(qDeal._plannedDueDate)><b>#dateFormat(qDeal._plannedDueDate,'DD.MM.YYYY')#</b><cfelse>--</cfif> --->
<b>#qDeal.__status_status#: #qDeal.status# (#qDeal.probability_pc#%)</b>
</cfif>
</div>
@@ -256,12 +257,17 @@
<cfquery name="qAdditionalAgreement">
select
a.__id::text
,b.__id::text as base_by_uid
,a.__index
,a.__name as additional_agreement
,a2.__id::text as base_by_uid
,a2.__index
,a2.__name as base_by
,a.contract_uid::text
,a.is_actual
,a.last_aa
,a.deal_uid::text
,a2.deal_uid::text as deal2_uid
,d2.__name as deal2
,c.__name as contract
,c.agreement_id
,c.date_of_aggrement
@@ -270,23 +276,37 @@
,z.id_klienta as wz
from elma.deals_services siv
join elma.additional_agreements a on (a.__id = ANY(siv.additional_agreement))
join elma.additional_agreements b on (b.__id = ANY(a.base_by))
left outer join elma.additional_agreements a2 on (a2.__id = ANY(a.base_by))
left outer join elma.deals d2 on (a2.deal_uid = d2.__id)
left outer join elma.aggrements c on (a.contract_uid=c.__id)
left outer join elma.companies z on (c.company_uid=z.__id)
where siv.__id=<cfqueryparam cfsqltype="cf_sql_other" value=#d.__id# null=#!isValid("guid",d.__id)#/>
</cfquery>
<!--- <cfdump var=#qAdditionalAgreement#/> --->
<cfif len(qAdditionalAgreement.__id)>
<a href="additional_agreement.cfm?__id=#qAdditionalAgreement.__id#&#tr.fwx#">#qAdditionalAgreement.__id#</a> |
<a href="contragent.cfm?__id=#qAdditionalAgreement.contragent_uid#&#tr.fwx#">#qAdditionalAgreement.contragent# #qAdditionalAgreement.wz#</a> |
<a href="contract.cfm?__id=#qAdditionalAgreement.contract_uid#&#tr.fwx#">#qAdditionalAgreement.contract# (#qAdditionalAgreement.agreement_id#)
#dateFormat(qAdditionalAgreement.date_of_aggrement,"YYYY-MM-DD")#
<a href="additional_agreement.cfm?__id=#qAdditionalAgreement.__id#&#tr.fwx#">
#qAdditionalAgreement.__index# #qAdditionalAgreement.__id# #qAdditionalAgreement.additional_agreement#
</a> |
#qAdditionalAgreement.additional_agreement# |
<a href="contragent.cfm?__id=#qAdditionalAgreement.contragent_uid#&#tr.fwx#">
#qAdditionalAgreement.contragent# #qAdditionalAgreement.wz#
</a> |
Договор
<a href="contract.cfm?__id=#qAdditionalAgreement.contract_uid#&#tr.fwx#">
#qAdditionalAgreement.contract# (#qAdditionalAgreement.agreement_id#)
#dateFormat(qAdditionalAgreement.date_of_aggrement,"YYYY-MM-DD")#
</a>
<br/>
is_actual: <b>#qAdditionalAgreement.is_actual#</b>
last_aa: <b>#qAdditionalAgreement.last_aa#</b>
base_by: <a href="additional_agreement.cfm?__id=#qAdditionalAgreement.base_by_uid#&#tr.fwx#">#qAdditionalAgreement.base_by_uid#</a>
base_by: <a href="additional_agreement.cfm?__id=#qAdditionalAgreement.base_by_uid#&#tr.fwx#">
#qAdditionalAgreement.base_by_uid#
#qAdditionalAgreement.base_by#
</a>
(<a href="deal.cfm?__id=#qAdditionalAgreement.deal2_uid#&#tr.fwx#" title="сделка base_by">
#qAdditionalAgreement.deal2_uid#
#qAdditionalAgreement.deal2#
</a>)
</cfif>
</div>
</div>
@@ -414,16 +434,20 @@
left outer join elma.deals d on (d.__id = ANY(siv.deal))
left outer join status on (d.__status_status = status.status_id)
where hash=<cfqueryparam cfsqltype="cf_sql_varchar" value=#d.hash#/>
order by siv.__index, siv.version
order by d.__index
</cfquery>
<cfquery name="qVerActual" dbtype="query">
select * from qVer where is_actual > 0
</cfquery>
</cfquery> <!--- не повторяем сортировку, хотя это некорректно --->
<cfquery name="qVerDraft" dbtype="query">
select * from qVer where is_actual = 0 OR is_actual IS NULL
</cfquery><!--- не повторяем сортировку, хотя это некорректно --->
<cfoutput>
<h4>Версии строки (без черновиков) (#qVerActual.recordCount#)</h4>
<h4>Версии строки без черновиков (#qVerActual.recordCount#)</h4>
</cfoutput>
<table class="worktable">
@@ -431,47 +455,53 @@
<tr>
<th>Индекс версии</th>
<th>Создана</th>
<th>Версия доп.с.</th>
<th>Верс. доп.с.</th>
<th>Версия строки</th>
<th>is_actual</th>
<th>is actual</th>
<th>НОУ</th>
<th>КОУ</th>
<th>User Description</th>
<th>type</th>
<th>Кол-во</th>
<th>Скидка%</th>
<th>Скид&shy;ка%</th>
<th>Ст-ть</th>
<th>Сделка</th>
<th>Статус</th>
<th>Вер-ть</th>
<th>Вер.</th>
<th>Доп.с.</th>
</tr>
</thead>
<cfoutput query="qVerActual">
<tr>
<td class="c"><a href="deal_service.cfm?__id=#__id#&#tr.fwx#" title="#__id#">#__index#</a></td>
<td class="c">#dateFormat(__createdAt,"YYYY-MM-DD")#</td>
<td class="c">
<cfif __id EQ toString(d.__id)>
<b>#__index#</b>
<cfelse>
<a href="deal_service.cfm?__id=#__id#&#tr.fwx#" title="#__id#">#__index#</a>
</cfif>
</td>
<td class="c nw">#dateFormat(__createdAt,"YYYY-MM-DD")#</td>
<td class="c">#aa_version#</td>
<td class="c">#version#</td>
<td class="c">#is_actual#</td>
<td class="c">#dateFormat(date_nop,"YYYY-MM-DD")#</td>
<td class="r">#dateFormat(date_end,"YYYY-MM-DD")#</td>
<td class="c">#user_description#</td>
<td class="c nw">#dateFormat(date_nop,"YYYY-MM-DD")#</td>
<td class="c nw">#dateFormat(date_end,"YYYY-MM-DD")#</td>
<td>#user_description#</td>
<td class="r">#type#</td>
<td class="c">#cnt#</td>
<td class="c">#discount#</td>
<td class="r">#nFmt(line_cost)#</td>
<td class="c"><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#" title="#deal_uid#">#deal#</a></td>
<td class="r nw">#nFmt(line_cost)#</td>
<td class="l"><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#" title="#deal_uid#">#deal#</a></td>
<td class="c">#__status_status#</td>
<td class="c">#probability_pc#</td>
<td class="c"><a href="additional_agreement.cfm?__id=#aa_uid#&#tr.fwx#" title="#aa_uid#">#additional_agreement#</a></td>
<td class="l"><a href="additional_agreement.cfm?__id=#aa_uid#&#tr.fwx#" title="#aa_uid#">#additional_agreement#</a></td>
</tr>
</cfoutput>
</table>
<cfoutput>
<h4>Версии строки (включая черновики) (#qVer.recordCount#)</h4>
<h4>Версии строки - черновики (#qVerDraft.recordCount#)</h4>
</cfoutput>
<table class="worktable">
@@ -479,40 +509,46 @@
<tr>
<th>Индекс версии</th>
<th>Создана</th>
<th>Версия доп.с.</th>
<th>Верс. доп.с.</th>
<th>Версия строки</th>
<th>is_actual</th>
<th>is actual</th>
<th>НОУ</th>
<th>КОУ</th>
<th>User Description</th>
<th>type</th>
<th>Кол-во</th>
<th>Скидка%</th>
<th>Скид&shy;ка%</th>
<th>Ст-ть</th>
<th>Сделка</th>
<th>Статус</th>
<th>Вер-ть</th>
<th>Вер.</th>
<th>Доп.с.</th>
</tr>
</thead>
<cfoutput query="qVer">
<cfoutput query="qVerDraft">
<tr>
<td class="c"><a href="deal_service.cfm?__id=#__id#&#tr.fwx#" title="#__id#">#__index#</a></td>
<td class="c">#dateFormat(__createdAt,"YYYY-MM-DD")#</td>
<td class="c">
<cfif __id EQ toString(d.__id)>
<b>#__index#</b>
<cfelse>
<a href="deal_service.cfm?__id=#__id#&#tr.fwx#" title="#__id#">#__index#</a>
</cfif>
</td>
<td class="c nw">#dateFormat(__createdAt,"YYYY-MM-DD")#</td>
<td class="c">#aa_version#</td>
<td class="c">#version#</td>
<td class="c">#is_actual#</td>
<td class="c">#dateFormat(date_nop,"YYYY-MM-DD")#</td>
<td class="r">#dateFormat(date_end,"YYYY-MM-DD")#</td>
<td class="c">#user_description#</td>
<td class="c nw">#dateFormat(date_nop,"YYYY-MM-DD")#</td>
<td class="c nw">#dateFormat(date_end,"YYYY-MM-DD")#</td>
<td class="l">#user_description#</td>
<td class="r">#type#</td>
<td class="c">#cnt#</td>
<td class="c">#discount#</td>
<td class="r">#nFmt(line_cost)#</td>
<td class="c"><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#" title="#deal_uid#">#deal#</a></td>
<td class="r nw">#nFmt(line_cost)#</td>
<td class="l"><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#" title="#deal_uid#">#deal#</a></td>
<td class="c">#__status_status#</td>
<td class="c">#probability_pc#</td>
<td class="c"><a href="additional_agreement.cfm?__id=#aa_uid#&#tr.fwx#" title="#aa_uid#">#additional_agreement#</a></td>
<td class="l"><a href="additional_agreement.cfm?__id=#aa_uid#&#tr.fwx#" title="#aa_uid#">#additional_agreement#</a></td>
</tr>
</cfoutput>
</table>
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
12:58 09.10.2025 дополнительное соглашение к сделке. Шедевр
-456
View File
@@ -1,456 +0,0 @@
<cfset dt_finish=createDateTime(year(Now()),month(Now()),1,0,0,0)/>
<cfset dt_start=dateAdd('m',-1,dt_finish)/>
<cfset hours=dateDiff('h',dt_start,dt_finish)/>
Внимание! округление вверх при расчете метрик
<cfdump var=#dt_start#/>
<cfdump var=#dt_finish#/>
<cfdump var=#hours#/>
<!--- Нужно еще применить политики бесплатного минимума --->
<cfquery name="qCode" datasource="dwh">
select distinct p.code
from elma.deals d
join elma.deals_services siv on (d.__id=ANY(siv.deal))
join elma.service_parametrs p on (p.__id = ANY(siv.params))
join elma.companies k on (d._companies=k.__id)
join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement))
join elma.aggrements a on (aa.contract_uid = a.__id)
where p.type=3 AND aa.is_actual
order by p.code
</cfquery>
<!--- <cfdump var=#qCode#/> --->
<cfquery name="qSpec" datasource="dwh">
select k.id_klienta as wz, p.code, p.price, p.discount, k.__name as contragent, a.__name as contract, d.__name as deal, siv.abstractive_service as abstract_service, siv.modifier, siv.user_description
,p.__name as metric, p.ed_izm
--, 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=3 AND aa.is_actual
order by k.id_klienta, p.code
</cfquery>
<!--- здесь имеем список кодов с ценами и WZ. Каждому коду можно поставить в соответствие запрос, который даст по нему выборку. Изредка один запрос может вывести 2 кода, но разбить на 2 запроса легко. Кроме того, запросы можно объединить через union в один - может быть, так будет лучше читаться (быстрее выполняться не будет) --->
<cfdump var=#qSpec#/>
<cfquery name="qComputing" datasource="billing-vc">
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
case
when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29'
when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31'
when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28'
when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28'
else '['||vdc.name||']' end as code,
sum(cpu_used/cpu_speed)/4. as core_h,
sum(mem_used)/1024/4. as gb_h
from ngcloud_ru.capacity_resource
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
where tenant.wzcode > 0
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by tenant.wzcode, vdc.name
order by tenant.wzcode, vdc.name;
</cfquery>
<!--- <cfdump var=#qComputing#/> --->
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
<cfquery name="qStorage" datasource="billing-vc">
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
case
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
ELSE '['||vdc.name||']' END
|| CASE
WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m'
WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m'
WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m'
ELSE '.['|| storage_profile_types.name ||']' END
as code,
storage_profile_types.name, -- *** это не тип, а профайл
sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут
sum(used)/1024./4 as gb_h_used
from ngcloud_ru.capacity_storage
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id
where tenant.wzcode > 0
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by tenant.wzcode, vdc.name, storage_profile_types.name
order by tenant.wzcode, vdc.name, storage_profile_types.name;
</cfquery>
<!--- <cfdump var=#qStorage#/> --->
<!---
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
HOT_FREE_LIMIT 1 10 1 100
--->
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
<cfquery name="qS3Vol" datasource="billing-s3">
select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>) as vol_B
,round(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>/1024/1024/1024) as vol_GB
,greatest(round(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>
/1024/1024/1024)-
case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/
,case
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
--,bucket_stat.placement_id
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
from s3billing.bucket_stat
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
where bucket_stat.placement_id in (1,2)
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by bucket_stat.owner, bucket_stat.placement_id
order by bucket_stat.owner, bucket_stat.placement_id;
</cfquery>
<!--- <cfdump var=#qS3Vol#/> --->
<cfquery name="qS3OpsTrf" datasource="billing-s3">
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 >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by user_info.name, bucket_info.placement_id
order by user_info.name, bucket_info.placement_id;
</cfquery>
<!--- <cfdump var=#qS3OpsTrf#/> --->
<cfquery name="qUnifiedMetric" dbType="query">
select wz, code || '.cpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing
union all
select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing
union all
select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage
union all
select wz, code || '.vol', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric from qS3Vol
union all
select wz, code || '.get', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf
union all
select wz, code || '.put', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf
union all
select wz, code || '.trf', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric from qS3OpsTrf
</cfquery>
<cfdump var=#qUnifiedMetric#/>
<cfquery name="qCharge" dbType="query">
SELECT
wz
,code
,price
,discount
,contragent
,contract
,deal
,abstract_service
,modifier
,user_description
,ed_izm
FROM qSpec as s, qUnifiedMetric as m WHERE s.wz=m.wz AND s.code=m.code
</cfquery>
<!--- looks like QoQ does not support join syntax, at least of Lucee 5.4--->
<cfdump var=#qCharge#/>
<!---
--->
<!--- --,m.*
--,s.price*(100-s.discount)/100 as discounted_price
--,s.price*(100-s.discount)/100*m.chargeable_metric as charge --->
<!--- В одном месте user_id int в другом owner varchar --->
<!---
задача (вызванная сыростью базы биллинга)
смапить код параметра с VDC (1:n)
iaas.ngc.i31.ram-m
iaas.ngc.a28.ram-m
cl01:
7 хостов Lenovo ThinkSystem SR650 -[7X06CTO1WW]-
2 процессора Xeon(R) Gold 6226R 16 ядер 32 потока каждый 2.9 ГГц
1.25тб озу в каждом.
В 4 из 7 есть по 4 GPU NVIDIA A16 16GB в каждом.
cl01-vsan:
16 хостов Lenovo ThinkSystem SR650 -[7X06CTO1WW]-
2 процессора Xeon(R) Gold 6226R 16 ядер 32 потока каждый 2.9 ГГц
1.25тб озу в каждом.
В 9 из 16 есть по 4 GPU NVIDIA A16 16GB в каждом.
cl02:
10 Huawei 2488H V5
4 процессора Xeon(R) Gold 6254 18 ядер 36 потоков каждый. 3.1 ГГц
2тб озу в каждом.
5 Huawei Atlas 800 (Model 3010)
2 процессора Xeon(R) Gold 6254 18 ядер 36 потоков каждый. 3.1 ГГц
1.5тб озу в каждом.
cl04-vsan:
10 Apex AR320-12
2 процессора AMD EPYC 7543 32 ядра 64 потока каждый. 2.8 ГГц
2тб озу в каждом.
18 Apex AR320-12-E7543
2 процессора AMD EPYC 7543 32 ядра 64 потока каждый. 2.8 ГГц
2тб озу в каждом.
cl05-1c:
1 Asus RS720A-E12-RS24U
2 процессора AMD EPYC 9274F 24 ядра 48 потоков каждый. 4.05 ГГц
1тб озу.
7 ручная сборка
MB Asus ProArt B650-Creator
Процессор AMD Ryzen 9 7950X 16 ядер 32 потока каждый. 4.5 ГГц
192гб озу каждый.
1 ручная сборка
процессор AMD Ryzen Threadripper PRO 5995WX 64 ядра 128 потоков каждый. 2.7 ГГц
512гб озу.
cl06-vsan:
15 R320
2 процессора Xeon(R) Gold 6342 24 ядра 48 потоков каждый. 2.8 ГГц
1тб озу каждый.
Xeon(R) Gold 6226R 2.9 ГГц
Xeon(R) Gold 6254 3.1 ГГц
AMD EPYC 7543 2.8 ГГц
AMD EPYC 9274F 4.05 ГГц
AMD Ryzen 9 7950X 4.5 ГГц
AMD Ryzen Threadripper PRO 5995WX 2.7 ГГц
Xeon(R) Gold 6342 2.8 ГГц --->
<!--- 2025-08-15 20:47:44 *** Операции S3 считаются не так, как написано в тарифе. Например, считается list. В тарифе вообще не описан минимальный лимит --->
<!--- BEGIN
RETURN QUERY
(
select
billing_per_user_fix_pl.placement as placement,
(CASE
WHEN ( billing_per_user_fix_pl.placement = 'HOT'
) THEN greatest(ceil(sum(size)/1024/1024/1024)-1,0)
WHEN ( not billing_per_user_fix_pl.placement = 'HOT'
) THEN ceil(sum(size)/1024/1024/1024)
END) AS size_GB,
(CASE
WHEN ( billing_per_user_fix_pl.placement = 'HOT'
) THEN greatest(ceil(sum(get)/10000)-10,0)
WHEN ( not billing_per_user_fix_pl.placement = 'HOT'
) THEN ceil(sum(get)/10000)
END) AS get_10k,
(CASE
WHEN ( billing_per_user_fix_pl.placement = 'HOT'
) THEN greatest(ceil(sum(put)/10000)-1,0)
WHEN ( not billing_per_user_fix_pl.placement = 'HOT'
) THEN ceil(sum(put)/10000)
END) AS put_10k,
(CASE
WHEN ( billing_per_user_fix_pl.placement = 'HOT'
) then greatest(ceil(sum(bytes_sent)/1024/1024/1024)-100,0)
WHEN ( not billing_per_user_fix_pl.placement = 'HOT'
) THEN ceil(sum(bytes_sent)/1024/1024/1024)
END) AS bytes_sent_GB
from s3billing.billing_per_user_fix_pl(_ds,_df,_user)
group by billing_per_user_fix_pl.placement
UNION all
select
'HOT_FREE_LIMIT' as placement,
'1' AS size_GB,
'10' AS get_10k,
'1' AS put_10k,
'100' AS bytes_sent_GB
);
END; --->
<!---
BEGIN
RETURN QUERY
SELECT
s3billing.bucket_info.name AS bucket_name,
(case
when ( s3billing.placement.name = 'default-placement') then 'HOT'
WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name
end
) as placement,
coalesce(round(sum(usage_rgw_main_size_actual)/
(SELECT (DATE_PART('day',
((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS'))
-TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS'))
)*24+
DATE_PART('hour',
((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS'))
-TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS'))
)))
)::numeric,0) AS size
,coalesce(s2.get, 0) AS get
,coalesce(s2.put, 0) AS put
,coalesce(s2.bytes_sent, 0) as bytes_sent
FROM s3billing.bucket_stat
INNER JOIN s3billing.placement ON s3billing.bucket_stat.placement_id=s3billing.placement.id
INNER JOIN s3billing.bucket_info ON s3billing.bucket_stat.bucket_id=s3billing.bucket_info.id
LEFT JOIN (
SELECT
s1.bucket_id AS bucket_id
,s1.bucket_name AS bucket_name,
(case
when ( s1.placement = 'default-placement') then 'HOT'
WHEN ( not s1.placement = 'default-placement' ) THEN s1.placement
end
) as placement
,coalesce(sum(s1.get) ,0) AS get
,coalesce(sum(s1.put) ,0) AS put
,coalesce(sum(s1.bytes_sent), 0) AS bytes_sent
FROM (
SELECT
s3billing.bucket_info.id AS bucket_id
,s3billing.bucket_info.name AS bucket_name
,(case
when ( s3billing.placement.name = 'default-placement') then 'HOT'
WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name
end
) as placement
,(CASE
WHEN ( s3billing.category.name LIKE 'get%'
OR s3billing.category.name LIKE 'head%'
OR s3billing.category.name LIKE 'options%'
) THEN coalesce(sum(ops), 0)
END) AS get
,(CASE
WHEN ( s3billing.category.name LIKE 'put%'
OR s3billing.category.name LIKE 'post%'
OR s3billing.category.name LIKE 'patch%'
OR s3billing.category.name LIKE 'list%'
) THEN coalesce(sum(ops), 0)
END) AS put
,coalesce(sum(usage_bucket_by_user.bytes_sent), 0) AS bytes_sent
FROM
s3billing.usage_bucket_by_user
INNER JOIN s3billing.bucket_info ON s3billing.usage_bucket_by_user.bucketid = s3billing.bucket_info.id
INNER JOIN s3billing.placement ON s3billing.bucket_info.placement_id = s3billing.placement.id
INNER JOIN s3billing.user_info ON s3billing.usage_bucket_by_user.user_id = s3billing.user_info.id
INNER JOIN s3billing.category ON s3billing.usage_bucket_by_user.category_id = s3billing.category.id
WHERE
s3billing.user_info.name=_user
AND s3billing.usage_bucket_by_user.time >=TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')
AND s3billing.usage_bucket_by_user.time < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')
GROUP BY
s3billing.bucket_info.name
,s3billing.placement.name
,s3billing.category.name
,s3billing.bucket_info.id
) AS s1
GROUP BY
s1.bucket_name
,s1.bucket_id
,s1.placement
ORDER BY
s1.placement
,s1.bucket_name
) AS s2 ON s2.bucket_id = s3billing.bucket_stat.bucket_id
WHERE owner=_user
AND timestamp_addition >= TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')
AND timestamp_addition < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')
GROUP BY
s3billing.bucket_info.name
,s3billing.placement.name
,s3billing.bucket_stat.bucket_id
,s2.get
,s2.put
,s2.bytes_sent
ORDER BY
s3billing.placement.name
,s3billing.bucket_info.name
;
END; --->
<!--- select * from s3billing.billing_per_user_fix_pl('2025-05-01 00:00:00','2025-06-01 00:00:00','1395'); --->
+86 -20
View File
@@ -17,7 +17,7 @@
<!--- Нужно еще применить политики бесплатного минимума --->
<!--- *** коды лучше взять из каталога --->
<cfquery name="qCode" datasource="dwh">
select distinct p.code
from elma.deals d
@@ -30,7 +30,13 @@
order by p.code
</cfquery>
<!--- <cfdump var=#qCode#/> --->
<cfquery name="qContragent" datasource="dwh">
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
</cfquery>
<!--- нужны компании, которые есть в пейге --->
<cfquery name="qSpec" datasource="dwh">
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
@@ -47,6 +53,7 @@
AND (siv.date_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL)
order by k.id_klienta, p.code
</cfquery>
<!--- siv means specification item version --->
<cfquery name="qSivAge" datasource="dwh">
select max(dt_load) as dt_load from elma.deals_services
</cfquery>
@@ -58,7 +65,7 @@
<cfquery name="qComputing" datasource="billing-vc">
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
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'
@@ -69,12 +76,18 @@
sum(mem_used)/1024/4. as gb_h
from ngcloud_ru.capacity_resource
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
where tenant.wzcode > 0
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 >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by tenant.wzcode, vdc.name
order by tenant.wzcode, vdc.name;
group by m.clientid, vdc.name
order by m.clientid, vdc.name;
</cfquery>
<cfif isDefined("DEBUG")>
@@ -89,7 +102,7 @@
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
<cfquery name="qStorage" datasource="billing-vc">
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
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'
@@ -107,13 +120,19 @@
sum(used)/1024./4 as gb_h_used
from ngcloud_ru.capacity_storage
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
join ngcloud_ru.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 tenant.wzcode > 0
where length(m.clientid) > 0
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
group by tenant.wzcode, vdc.name, storage_profile_types.name
order by tenant.wzcode, vdc.name, storage_profile_types.name;
group by m.clientid, vdc.name, storage_profile_types.name
order by m.clientid, vdc.name, storage_profile_types.name;
</cfquery>
<cfquery name="qStorageAge" datasource="billing-vc">
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
@@ -267,11 +286,11 @@ select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric,
<cfflush/>
</cfif>
<cfquery name="qCharge" dbType="query">
<cfquery name="qChargeInner" dbType="query">
SELECT
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
<d:field title="WZ">s.wz</d:field>
<d:field title="Артикул">s.code</d:field>
<d:field title="WZ">c.wz</d:field>
<d:field title="Артикул">m.code</d:field>
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
<d:field title="Ед.изм.">s.ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100 as discounted_price</d:field>
@@ -283,8 +302,8 @@ SELECT
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведен&shy;ная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">s.contragent</d:field>
<d:field title="contragent_uid">s.contragent_uid</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field>
<d:field title="Договор">s.contract</d:field>
<d:field title="contract_uid">s.contract_uid</d:field>
<d:field title="Допник">s.additional_agreement</d:field>
@@ -296,10 +315,48 @@ SELECT
<d:field title="Компонент">s.component</d:field>
<d:field title="Клиентс. назв.">s.user_description</d:field>
</d:field_set>
FROM qSpec as s, qUnifiedMetric as m WHERE s.wz=m.wz AND s.code=m.code
order by s.wz, s.code
FROM qUnifiedMetric m, qContragent c, qSpec s WHERE m.wz=c.wz AND m.wz=s.wz AND m.code=s.code
</cfquery>
<!--- looks like QoQ does not support join syntax, at least of Lucee 5.4--->
<cfquery name="qChargeOuter" dbType="query">
SELECT
<d:field_set titleMapOut="titleMap_" lengthOut="fieldCount_">
<d:field title="WZ">c.wz</d:field>
<d:field title="Артикул">m.code</d:field>
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
<d:field title="Ед.изм.">null as ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">null discounted_price</d:field>
<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">0 as charge</d:field>
<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">null as dt_from</d:field>
<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">null as dt_to</d:field>
<d:field title="Ключ строки">null as line_key</d:field>
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">null as price</d:field>
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">null as discount</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведен&shy;ная метрика" 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="Договор">null as contract</d:field>
<d:field title="contract_uid">null as contract_uid</d:field>
<d:field title="Допник">null as additional_agreement</d:field>
<d:field title="additional_agreement_uid">null as additional_agreement_uid</d:field>
<d:field title="Сделка">null as deal</d:field>
<d:field title="deal_uid">null as deal_uid</d:field>
<d:field title="Абстрактная услуга">null as abstract_service</d:field>
<d:field title="Модификатор">null as modifier</d:field>
<d:field title="Компонент">null as component</d:field>
<d:field title="Клиентс. назв.">null as user_description</d:field>
</d:field_set>
FROM qUnifiedMetric m, qContragent c WHERE m.wz=c.wz AND m.wz NOT IN (#listQualify(listRemoveDuplicates(ValueList(qChargeInner.wz)),"'")#)
</cfquery>
<cfquery name="qCharge" dbType="query">
select * from qChargeInner
union
select * from qChargeOuter
order by wz,code
</cfquery>
<!--- QoQ does not support join syntax, at least of Lucee 5.4--->
@@ -408,7 +465,7 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<td class="r">#dateFormat(dt_to,'YYYY-MM-DD')#</td>
<td class="r">#line_key#</td>
<td class="r" style="color:lightgray">#raw_metric#</td>
<td class="r" style="color:##bbb">#raw_metric#</td>
<td class="r">#metric#</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>
@@ -431,3 +488,12 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<!--- 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) --->