009 reports

This commit is contained in:
msyu 2025-06-21 17:06:29 +03:00
parent 89a3407fc3
commit 672123968b
12 changed files with 729 additions and 14 deletions

View File

@ -69,7 +69,7 @@
<!--- <cfset this.datasources["#this.datasource#"]=getDS("#this.datasource#","datasource_#this.datasource#")/> --->
<cfset request.RECORDS_PER_PAGE=500/>
<cfset request.APP_VERSION="0.00.008"/>
<cfset request.APP_VERSION="0.00.009"/>
<cflock scope="application" type="readonly" timeout=3>
<cfset request.APP_NAME=this.Name/>

View File

@ -300,7 +300,7 @@
<cfoutput>
<p>
Строки спецификаций (#qItem.recordCount#)
Строки спецификаций (#qItem.recordCount#) (все суммы без вероятности)
</p>
</cfoutput>
<table class="worktable">

183
etc/db/analytics.sql Normal file
View File

@ -0,0 +1,183 @@
select /*переделать выборку версий через group by*/
/* dayscale.dt
,a.contract_id
,a.agreement_version
,a.deal_uid
,a.probability_perc
,siv.dt_from
,siv.dt_to
,siv.quantity
,siv.price*/
DATE_TRUNC('month', siv.dt_from)::date AS month_install
,sum(siv.price*siv.quantity*a.probability_perc/100) as cost_install
--,si.pricing_model_id
from
(SELECT dd::date as dt FROM generate_series
( '2024-01-01'::timestamp
, '2029-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt=siv.dt_from)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid)
join specification s on (si.specification_id=s.specification_id)
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
where si.pricing_model_id=1
group by DATE_TRUNC('month', siv.dt_from)
--order by ds.dt
union all
select
/*dayscale.dt
,a.contract_id
,a.agreement_version
,a.deal_uid
,a.probability_perc
,siv.dt_from
,siv.quantity
,siv.price
,si.pricing_model_id*/
DATE_TRUNC('month', dayscale.dt)::date AS month_i
,sum(siv.price*siv.quantity*a.probability_perc/100/dayscale.days) as cost_install
from
(SELECT dd::date as dt, DATE_PART('days',
DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL
) days FROM generate_series
( '2025-01-01'::timestamp
, '2025-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt >= siv.dt_from /**/)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid)
join specification s on (si.specification_id=s.specification_id AND si.pricing_model_id in (2,3))
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by DATE_TRUNC('month', dayscale.dt)
order by DATE_TRUNC('month', dayscale.dt)
select
DATE_TRUNC('month', dayscale.dt)::date AS month_start
,sum(siv.price*siv.quantity*a.probability_perc/100) as income
from
(SELECT dd::date as dt FROM generate_series
( '2023-01-01'::timestamp
, '2027-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt=siv.dt_from)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (1))
join specification s on (si.specification_id=s.specification_id)
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
where si.pricing_model_id=1
group by DATE_TRUNC('month', dayscale.dt)
union all
select
DATE_TRUNC('month', dayscale.dt)::date
,sum(siv.price*siv.quantity*a.probability_perc/100/dayscale.days)
from
(SELECT dd::date as dt, DATE_PART('days',
DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL
) days FROM generate_series
( '2023-01-01'::timestamp
, '2027-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt >= siv.dt_from AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL))
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3))
join specification s on (si.specification_id=s.specification_id )
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by DATE_TRUNC('month', dayscale.dt)
order by 1
select
DATE_TRUNC('month', dayscale.dt)::date AS month_start
,sum(siv.price*siv.quantity*a.probability_perc/100) as income
from (SELECT dd::date as dt FROM generate_series(
'2023-01-01'::timestamp
, '2027-12-31'::timestamp
, '1 day'::interval) dd
) dayscale
join specification_item_version siv on (dayscale.dt=siv.dt_from)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (1))
join specification s on (si.specification_id=s.specification_id)
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
where si.pricing_model_id=1
group by DATE_TRUNC('month', dayscale.dt)
union all
select
DATE_TRUNC('month', dayscale.dt)::date
,sum(siv.price*siv.quantity*a.probability_perc/100/dayscale.days)
from (SELECT dd::date as dt
, DATE_PART('days', DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL) days
FROM generate_series(
'2023-01-01'::timestamp
, '2027-12-31'::timestamp
, '1 day'::interval) dd
) dayscale
join specification_item_version siv on (dayscale.dt >= siv.dt_from AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL))
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3))
join specification s on (si.specification_id=s.specification_id )
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by DATE_TRUNC('month', dayscale.dt)
order by 1

View File

@ -16,6 +16,9 @@
<c:menu_item acl="" page="specification_ls.cfm" label="Спецификации"/>
<c:menu_item acl="" page="agreement_ls.cfm" label="Сделки"/>
<c:menu_item acl="" page="specification_item_ls.cfm" label="Экземпляры услуг"/>
<li class="menu-title">Отчеты</li>
<c:menu_item acl="" page="income_daily_rpt.cfm" label="Выручка по дням"/>
<c:menu_item acl="" page="income_monthly_rpt.cfm" label="Выручка по месяцам"/>
<li class="menu-title">Справочники</li>
@ -43,11 +46,7 @@
<c:menu_item acl="" page="logout.cfm" queryString="target_page=#URLEncodedFormat(ATTRIBUTES.thisUrl)#" label="Выход"/>
</cfif>
<!--- <li class="menu-item-noaction nw">
#i18("Язык:", "Language:")#
<a href="?language=ru"<cfif request.language EQ 'ru'> style="font-weight:bold;"</cfif>>Ru</a>
<a href="?language=en"<cfif request.language EQ 'en'> style="font-weight:bold;"</cfif>>En</a>
</li> --->
</ul>
</cfoutput>
<cfexit method="exittag"/>

160
income_daily_rpt.cfm Normal file
View File

@ -0,0 +1,160 @@
<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="specification_item" 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.specification_item_class_type like ?) OR (p.division like ?) OR (p.performer_short like ?))" default=""/>
</m:filter_settings> --->
<!--- <cfset pageInfo.settings.filter=#filter#/> --->
<cfquery name="qRead" datasource="#request.DS#">
select
--install
DATE_TRUNC('month', dayscale.dt)::date as m,
dayscale.dt::date,
sum(siv.price*siv.quantity*a.probability_perc/100) as income
from (SELECT dd::date as dt FROM generate_series(
'2023-01-01'::timestamp
, '2029-12-31'::timestamp
, '1 day'::interval) dd
) dayscale
join specification_item_version siv on (dayscale.dt=siv.dt_from)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (1))
join specification s on (si.specification_id=s.specification_id)
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by dayscale.dt
union all
--fix and payg
select
DATE_TRUNC('month', dayscale.dt)::date as m,
dayscale.dt::date,
sum(siv.price*siv.quantity*a.probability_perc/100/dayscale.days)
from (SELECT dd::date as dt
, DATE_PART('days', DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL) days
FROM generate_series(
'2023-01-01'::timestamp
, '2029-12-31'::timestamp
, '1 day'::interval) dd
) dayscale
join specification_item_version siv on (dayscale.dt >= siv.dt_from AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL))
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3))
join specification s on (si.specification_id=s.specification_id )
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by dayscale.dt
order by 1
<!--- where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/> --->
</cfquery>
<!--- <cfquery name="qCountTotal" datasource="#request.DS#">
select count(*) as cnt from specification_item 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>Выручка по дням 2023-01-01 .. 2029-12-31</b></cfoutput>
</layout:attribute>
<layout:attribute name="controls">
<!---skip filter link, filter is not implemented--->
<!---<layout:language_switch/>--->
</layout:attribute>
</layout:page>
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
<div style="display:inline-block; width:30%; vertical-align:top;">
Дни и месяцы с нулевой суммой не показаны
<table class="worktable">
<thead>
<th>Дата</th>
<th>Выручка</th>
<th>Округл</th>
</thead>
<cfoutput query="qRead">
<tr>
<td class="c">#dateFormat(dt,"DD.MM.YYYY")#</td>
<td class="r">#income#</td>
<td class="r">#round(income)#</td>
</tr>
</cfoutput>
</table>
</div>
<div style="display:inline-block; width:30%; vertical-align:top;">
<cfquery dbtype="query" name="qMonthly">
select m, sum(income) as income from qRead group by m order by m
</cfquery>
Суммировано по месяцам:
<table class="worktable">
<thead>
<th>Месяц</th>
<th>Выручка</th>
<th>Округл</th>
</thead>
<cfoutput query="qMonthly">
<tr>
<td class="c">#dateFormat(m,"MM.YYYY")#</td>
<td class="r">#income#</td>
<td class="r">#round(income)#</td>
</tr>
</cfoutput>
</table>
</div>
</cfif>
<layout:page section="footer"/>

137
income_monthly_rpt.cfm Normal file
View File

@ -0,0 +1,137 @@
<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="specification_item" 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.specification_item_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
DATE_TRUNC('month', dayscale.dt)::date AS dt
,sum(siv.price*siv.quantity*a.probability_perc/100) as income
from
(SELECT dd::date as dt FROM generate_series
( '2023-01-01'::timestamp
, '2029-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt=siv.dt_from)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (1))
join specification s on (si.specification_id=s.specification_id)
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by DATE_TRUNC('month', dayscale.dt)
union all
select
DATE_TRUNC('month', dayscale.dt)::date
,sum(siv.price*siv.quantity*a.probability_perc/100/dayscale.days)
from
(SELECT dd::date as dt, DATE_PART('days',
DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL
) days FROM generate_series
( '2023-01-01'::timestamp
, '2029-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt >= siv.dt_from AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL))
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3))
join specification s on (si.specification_id=s.specification_id )
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by DATE_TRUNC('month', dayscale.dt)
order by 1
<!--- 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 specification_item 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>Выручка по месяцам 2023-01-01 .. 2029-12-31</b></cfoutput>
</layout:attribute>
<layout:attribute name="controls">
<!---skip filter link, filter is not implemented--->
<!---<layout:language_switch/>--->
</layout:attribute>
</layout:page>
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
Месяцы с нулевой суммой не показаны
<table class="worktable">
<thead>
<th>Дата</th>
<th>Выручка</th>
<th>Округл</th>
</thead>
<cfoutput query="qRead">
<tr>
<td class="c">#dateFormat(dt,"MM.YYYY")#</td>
<td class="r">#income#</td>
<td class="r">#round(income)#</td>
</tr>
</cfoutput>
</table>
</cfif>
<layout:page section="footer"/>

211
income_rpt.cfm Normal file
View File

@ -0,0 +1,211 @@
<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="specification_item" 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.specification_item_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
DATE_TRUNC('month', siv.dt_from)::date AS month_start
,sum(siv.price*siv.quantity*a.probability_perc/100) as income
from
(SELECT dd::date as dt FROM generate_series
( '2024-01-01'::timestamp
, '2029-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt=siv.dt_from)
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (1))
join specification s on (si.specification_id=s.specification_id)
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
where si.pricing_model_id=1
group by DATE_TRUNC('month', dayscale.dt)
union all
select
DATE_TRUNC('month', dayscale.dt)::date
,sum(siv.price*siv.quantity*a.probability_perc/100/dayscale.days)
from
(SELECT dd::date as dt, DATE_PART('days',
DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL
) days FROM generate_series
( '2025-01-01'::timestamp
, '2025-12-31'::timestamp
, '1 day'::interval) dd) dayscale
join specification_item_version siv on (dayscale.dt >= siv.dt_from AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL))
join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3))
join specification s on (si.specification_id=s.specification_id )
join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid)
join specification isp on (ii.specification_id=isp.specification_id)
join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version)
where iiv.specification_item_uid=si.specification_item_uid
AND ia.is_actual
))
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
group by DATE_TRUNC('month', dayscale.dt)
order by DATE_TRUNC('month', dayscale.dt)
<!--- 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 specification_item 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">
<!---skip filter link, filter is not implemented--->
<!---<layout:language_switch/>--->
</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_deal_uid')/>
<cfset titleMap.f_deal_uid=titleMap.deal_uid/>
<cfset queryAddColumn(qRead,'f_specification_item_uid')/>
<cfset titleMap.f_specification_item_uid=titleMap.specification_item_uid/>
<cfset queryAddColumn(qRead,'f_contract')/>
<cfset titleMap.f_contract=titleMap.contract/>
<cfset queryAddColumn(qRead,'f_specification')/>
<cfset titleMap.f_specification=titleMap.specification/>
<cfset queryAddColumn(qRead,'f_version_prev')/>
<cfset titleMap.f_version_prev=titleMap.version_prev/>
<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#><!--- *** Здесь некомфортное дублирование startRow, maxRows с вызовом c:table ниже, причем в c:table оно закопано в модуль, и аргументы называются по-разному... но мы хотим немного сэкономить и не обрабатывать весь резалтсет --->
<!--- *** тут можно было бы спокойно использовать суррогатный альтернативный ключ, но хочется проверить, как будет работать track на составном ключе. Кстати, я все равно его использую как ancor name --->
<cfsavecontent variable="qRead.f_link_view_edit">
<a href="specification_item_version.cfm?specification_item_uid=#specification_item_uid#&agreement_version=#agreement_version#&#tr.fwx#" name="#specification_item_uid#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_deal_uid">
<a href="agreement.cfm?contract_id=#contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#deal_uid#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_specification_item_uid">
<a href="specification_item.cfm?specification_item_uid=#specification_item_uid#&#tr.fwx#">#specification_item_uid#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_contract">
<a href="contract.cfm?contract_id=#contract_id#&#tr.fwx#">#contract# #dateformat(dt_contract,"YYYY-MM-DD")#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_specification">
<a href="specification.cfm?specification_id=#specification_id#&#tr.fwx#">#specification#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_version_prev">
<a href="specification_item_version.cfm?specification_item_uid=#specification_item_uid#&agreement_version=#agreement_version#&#tr.fwx#">#version_prev#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_link_del">
<cfif pageInfo.writePermitted()><a href="specification_item_version_del.cfm?specification_item_uid=#specification_item_uid#&agreement_version=#agreement_version#&#tr.fwx#" class="del" title="удалить"></a></cfif>
</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:th><!--- <a href="specification_item.cfm?contract_id=&specification_item_version="><img src="img/add.gif"/></a> ---></c:th>
<c:td field="f_link_view_edit" class="c"/>
</c:column>
<c:column width="12%" field="f_deal_uid"/>
<c:column width="12%" field="f_specification_item_uid"/>
<c:column width="3%" field="probability_perc"><c:td class="r"/></c:column>
<c:column width="2%" field="f_specification"/>
<c:column width="5%" field="f_contract"/>
<!--- <c:column width="5%" field="dt_contract" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column> --->
<c:column width="7%" field="contragent"/>
<c:column width="7%" field="svc"/>
<c:column width="1%" field="pricing_model_short"/>
<c:column width="5%" field="dt_from" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="5%" field="dt_to" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="3%" field="agreement_version"><c:td class="c"/></c:column>
<c:column width="3%" field="quantity"><c:td class="r"/></c:column>
<c:column width="3%" field="price"><c:td class="r"/></c:column>
<c:column width="3%" field="cost"><c:td class="r"/></c:column>
<c:column width="3%" field="f_version_prev"><c:td class="c"/></c:column>
<c:column width="3%" field="quantity_prev"><c:td class="r"/></c:column>
<c:column width="3%" field="price_prev"><c:td class="r"/></c:column>
<c:column width="3%" field="cost_prev"><c:td class="r"/></c:column>
<c:column width="3%" field="cost_diff"><c:td class="r"/></c:column>
<c:column width="3%" field="cost_diff_prob"><c:td class="r"/></c:column>
<c:column width="1%" sortable="false">
<c:td field="f_link_del" class="c"/>
</c:column>
</c:table>
<cfoutput>#gridFooter#</cfoutput>
Расчета по дням тут нет.
Дата по на самом деле нигде не используется.
Важное допущение: вероятность прошлой сделки принимается за 100% (то есть изменения имеют смысл только к действующему договору)
</cfif>
<layout:page section="footer"/>

View File

@ -165,6 +165,10 @@
join agreement a on (siv.agreement_version=a.agreement_version AND a.contract_id=s.contract_id)
where siv.specification_item_uid=i.specification_item_uid AND a.is_actual
order by siv.agreement_version desc limit 1) as agreement
,(select a.probability_perc from specification_item_version siv
join agreement a on (siv.agreement_version=a.agreement_version AND a.contract_id=s.contract_id)
where siv.specification_item_uid=i.specification_item_uid AND a.is_actual
order by siv.agreement_version desc limit 1) as probability_perc
,(select a.is_actual from specification_item_version siv
join agreement a on (siv.agreement_version=a.agreement_version AND a.contract_id=s.contract_id)
where siv.specification_item_uid=i.specification_item_uid AND a.is_actual
@ -264,7 +268,7 @@
<td class="c"></td>
<td class="c">#item_version_count#</td>
<td><a href="agreement.cfm?contract_id=#contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#agreement# /#dateFormat(dt_agreement,'DD.MM.YYYY')#</td>
<td><a href="agreement.cfm?contract_id=#contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#agreement# /#dateFormat(dt_agreement,'DD.MM.YYYY')# #probability_perc#%</td>
<td class="c">
<a href="specification_item_version.cfm?specification_item_uid=#specification_item_uid#&agreement_version=#agreement_version#&#tr.fwx#">#agreement_version#</a>
<cfif is_actual GT 0><img src="img/ok.png"/></cfif>
@ -291,6 +295,7 @@
a.agreement
,a.dt_agreement
,a.agreement_version
,a.probability_perc
,a.is_actual
,(select count(*) from specification_item si
join specification_item_version iv on (si.specification_item_uid=iv.specification_item_uid)
@ -328,6 +333,7 @@
<th>Соглашение (имя)</th>
<th>Дата согл.</th>
<th>Н-р согл.</th>
<th>Вероятность %</th>
<th>Действует</th>
<th>Строк изменено</th>
</tr>
@ -343,6 +349,7 @@
<td class="c">
<a href="agreement.cfm?contract_id=#d.contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#agreement_version#</a>
</td>
<td class="c">#probability_perc#</td>
<td class="c"><cfif is_actual GT 0><img src="img/ok.png"/></cfif></td>
<td class="c">#changed_item_cnt#</td>
</tr>

View File

@ -195,6 +195,7 @@
,a.agreement
,a.dt_agreement
,a.is_actual
,a.probability_perc
from specification_item_version siv
left join specification_item i on (siv.specification_item_uid=i.specification_item_uid)
left join specification s on (i.specification_id=s.specification_id)
@ -225,6 +226,7 @@
<th>Соглашение</th>
<th>Дата соглашения</th>
<th>Согл. действ.</th>
<th>Вер-ть%</th>
<th>Дата с</th>
<th>Дата по</th>
<th>Услуга (для печати)</th>
@ -245,6 +247,7 @@
<td>#agreement#</td>
<td class="c">#dateFormat(dt_agreement,'DD.MM.YYYY')#</td>
<td class="c"><cfif is_actual GT 0><img src="img/ok.png"/></cfif></td>
<td class="c">#probability_perc#</td>
<td class="c">#dateFormat(dt_from, 'DD.MM.YYYY')#</td>
<td class="c">#dateFormat(dt_to, 'DD.MM.YYYY')#</td>
<td>#specification_item_version#</td>

View File

@ -38,6 +38,7 @@
<d:field title="Сервис">svc.svc</d:field>
<d:field title="svc_id">si.svc_id</d:field>
<d:field title="Ц/обр">si.pricing_model_id</d:field>
<d:field title="Ц/обр">p.pricing_model_short</d:field>
<d:field title="Код">svc.code</d:field>
<d:field title="Дата с">siv.dt_from</d:field>
<d:field title="Дата по">siv.dt_to</d:field>
@ -58,6 +59,7 @@
join contract d on s.contract_id=d.contract_id
join contragent k on d.contragent_id=k.contragent_id
join svc on (si.svc_id=svc.svc_id)
join pricing_model p on (si.pricing_model_id=p.pricing_model_id)
left outer join (select
siv1.agreement_version
,siv1.specification_item_uid
@ -146,7 +148,10 @@ select count(*) as cnt from specification_item where 1=1
<cfset titleMap.f_link_view_edit={ordinal=#StructCount(titleMap)+1#}/><!--- *** Это легко забыть, потому что TitleMap никак не сцеплен с qRead. Напрашивается: упаковать их в одну обертку (но тогда обращение станет длиннее). Еще идея - назвать qRead и TitleMap так, чтобы была видна их связь. --->
<!--- <cfdump var=#titleMap#/> --->
<cfset queryAddColumn(qRead,'f_deal_uid')/>
<cfset titleMap.f_deal_uid=titleMap.deal_uid/>
<cfset titleMap.f_deal_uid=titleMap.deal_uid/>
<cfset queryAddColumn(qRead,'f_specification_item_uid')/>
<cfset titleMap.f_specification_item_uid=titleMap.specification_item_uid/>
<cfset queryAddColumn(qRead,'f_contract')/>
<cfset titleMap.f_contract=titleMap.contract/>
@ -168,6 +173,9 @@ select count(*) as cnt from specification_item where 1=1
</cfsavecontent>
<cfsavecontent variable="qRead.f_deal_uid">
<a href="agreement.cfm?contract_id=#contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#deal_uid#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_specification_item_uid">
<a href="specification_item.cfm?specification_item_uid=#specification_item_uid#&#tr.fwx#">#specification_item_uid#</a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_contract">
<a href="contract.cfm?contract_id=#contract_id#&#tr.fwx#">#contract# #dateformat(dt_contract,"YYYY-MM-DD")#</a>
@ -190,12 +198,14 @@ select count(*) as cnt from specification_item where 1=1
</c:column>
<c:column width="12%" field="f_deal_uid"/>
<c:column width="12%" field="f_specification_item_uid"/>
<c:column width="3%" field="probability_perc"><c:td class="r"/></c:column>
<c:column width="2%" field="f_specification"/>
<c:column width="5%" field="f_contract"/>
<!--- <c:column width="5%" field="dt_contract" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column> --->
<c:column width="7%" field="contragent"/>
<c:column width="7%" field="svc"/>
<c:column width="1%" field="pricing_model_short"/>
<c:column width="5%" field="dt_from" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="5%" field="dt_to" formatter=#function(dt){return dateformat(dt,"YYYY-MM-DD");}#><c:td class="c"/></c:column>
<c:column width="3%" field="agreement_version"><c:td class="c"/></c:column>

View File

@ -157,7 +157,7 @@
</layout:detail_line>
<layout:detail_line title="Строка">
#d.specification_item_uid#
<a href="specification_item.cfm?specification_item_uid=#d.specification_item_uid#&#tr.fwx#">#d.specification_item_uid#</a>
</layout:detail_line>
<layout:detail_line title="Услуга">

View File

@ -61,7 +61,7 @@
</cfquery>
<cfquery name="qAgreement" datasource="#request.DS#">
select a.agreement, a.agreement_version, a.dt_agreement, a.is_actual
select a.agreement, a.agreement_version, a.dt_agreement, a.is_actual, a.probability_perc
from agreement a
where a.contract_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.contract_id#"/>
AND a.agreement_version=<cfqueryparam cfsqltype="cf_sql_integer" value="#agreement_version#" null=#!isValid('integer', agreement_version)#>
@ -143,7 +143,7 @@
<div class="th">Соглашение</div>
<div class="td">
<a href="argeement.cfm?contract_id=#d.contract_id#&agreement_version=#agreement_version#&#tr.fwx#">
#qAgreement.agreement# [#qAgreement.agreement_version#] #dateFormat(qAgreement.dt_agreement,'DD.MM.YYYY')#
#qAgreement.agreement# [#qAgreement.agreement_version#] #dateFormat(qAgreement.dt_agreement,'DD.MM.YYYY')# <cfif len(qAgreement.probability_perc)>#qAgreement.probability_perc#%</cfif>
</a>
</div>
@ -203,16 +203,18 @@
,p.pricing_model_short
,s.specification_id
,s.contract_id
,(select count(*) from specification_item_version siv where siv.specification_item_uid=i.specification_item_uid) as item_version_count
,(select count(*) from specification_item_version siv where siv.specification_item_uid=i.specification_item_uid) as item_version_count
,ver.agreement_version
,ver.specification_item_uid
,ver.agreement
,ver.dt_agreement
,ver.is_actual
,ver.probability_perc
,ver.specification_item_version as specification_item
,ver.quantity
,ver.price
,ver.quantity*ver.price as cost
,ver.quantity*ver.price*probability_perc/100 as cost_p
,ver.dt_from
,ver.dt_to
from specification_item i
@ -225,6 +227,7 @@
,a.contract_id
,a.dt_agreement
,a.is_actual
,a.probability_perc
,siv.specification_item_version
,siv.quantity
,siv.price
@ -281,6 +284,7 @@
<th>Кол-во</th>
<th>Цена</th>
<th>Стоимость</th>
<th>Ст-ть с вер.</th>
<th>Дата с</th>
<th>Дата по</th>
@ -311,6 +315,7 @@
<td class="r">#quantity#</td>
<td class="r">#price#</td>
<td class="r">#cost#</td>
<td class="r">#cost_p#</td>
<td class="c">#dateFormat(dt_from,'DD.MM.YYYY')#</td>
<td class="c">#dateFormat(dt_to,'DD.MM.YYYY')#</td>
@ -318,7 +323,7 @@
<td class="c"></td>
<td class="c">#item_version_count#</td>
<td><a href="agreement.cfm?contract_id=#contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#agreement# #dateFormat(dt_agreement,'DD.MM.YYYY')#</td>
<td><a href="agreement.cfm?contract_id=#contract_id#&agreement_version=#agreement_version#&#tr.fwx#">#agreement# #dateFormat(dt_agreement,'DD.MM.YYYY')# <cfif len(probability_perc)>#probability_perc#%</cfif></td>
<td class="c"><a href="specification_item_version.cfm?specification_item_uid=#specification_item_uid#&agreement_version=#qItem.agreement_version#&#tr.fwx#">#qItem.agreement_version#</a> <cfif is_actual><img src="img/ok.png"/></cfif></td>