21 with asymmetric time and local version

This commit is contained in:
msyu
2025-07-11 10:21:05 +03:00
parent e96eedece5
commit 2d270ef24f
9 changed files with 240 additions and 83 deletions
+141 -30
View File
@@ -10,6 +10,11 @@
<cfreturn (a GT 0)? a : ""/>
</cffunction>
<cffunction name="myNumFmt">
<cfargument name="a"/>
<cfreturn (isNumeric(a))? numberFormat(a,",.00") : ""/>
</cffunction>
<m:prepare_ls entity="specification_item" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<!--- <m:filter_settings target="#pageInfo.entity#_ls">
@@ -87,10 +92,40 @@ from (
,0
,0
,0
,COALESCE(sum(siv.price*siv.quantity*COALESCE(a.probability_perc,0)/100/dayscale.days),0)
+ COALESCE(sum(siv0.price*siv0.quantity*(100-COALESCE(a.probability_perc,0))/100/dayscale.days),0)
,sum(siv.price*siv.quantity*COALESCE(a.probability_perc,0)/100/dayscale.days)
,sum(siv0.price*siv0.quantity*(100-COALESCE(a.probability_perc,0))/100/dayscale.days)
,COALESCE(sum(
case when (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL) then
siv.price*siv.quantity*COALESCE(
case when a.is_actual then 100 else a.probability_perc end
,0)/100/dayscale.days
/*до окончания свежей сделки она суммируется с прошлой актуальной по правилу вероятностей, считая вероятность актуальной за сделки за 1*/
else 0 /*по окончании свежей сделки она дает нулевой вклад*/
end
),0)
+ COALESCE(sum(
case when (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL) then 0 else
siv0.price*siv0.quantity*(100-COALESCE(
case when a.is_actual then 100 else a.probability_perc end
,0))/100/dayscale.days
/*по окончании свежей сделки*/
end
),0)
,sum(
case when (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL) then
siv.price*siv.quantity*COALESCE(
case when a.is_actual then 100 else a.probability_perc end
,0)/100/dayscale.days
else 0
end
)
,sum(
case when (siv0.dt_to > dayscale.dt OR siv0
.dt_to IS NULL) then 0 else
siv0.price*siv0.quantity*(100-COALESCE(
case when a.is_actual then 100 else a.probability_perc end
,0))/100/dayscale.days
--else 0
end
)
,count(*)
from (SELECT dd::date as dt
@@ -100,32 +135,37 @@ from (
,'2029-12-31'::timestamp
,'1 day'::interval) dd
) dayscale
left outer join specification_item_version siv on (dayscale.dt >= siv.dt_from AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL))
left outer join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3))
left outer join specification s on (si.specification_id=s.specification_id )
left outer 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
left outer join specification_item_version siv on (dayscale.dt >= siv.dt_from /*AND (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL)*/
AND siv.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 (dayscale.dt >= iiv.dt_from AND (iiv.dt_to >= dayscale.dt OR iiv.dt_to IS NULL))
/*AND ia.is_actual*/
))
where iiv.specification_item_uid=siv.specification_item_uid
AND (dayscale.dt >= iiv.dt_from /*AND (iiv.dt_to > dayscale.dt OR iiv.dt_to IS NULL)*/)))
/*AND ia.is_actual*/ /*свежее соглашение не обязано быть действующим*/
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 a.agreement_version=siv.agreement_version)
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)
left outer join agreement a0 on (s.contract_id=a0.contract_id AND a0.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv
-- находим предыдущее действующее соглашение
-- если свежее соглашение действует, то впр
-- нам нужно, чтобы в прошлом (до dt_from свежего соглашения) свежак был прозрачен,
-- а в будущем (после dt_to) факт перетирался свежим соглашением
left outer join agreement a0 on (s.contract_id=a0.contract_id AND a0.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.agreement_version < a.agreement_version
AND ia.is_actual
))
AND ia.agreement_version < siv.agreement_version
AND ia.is_actual /*именно действующее соглашение, принимаемое за факт*/
)
)
left outer join specification_item_version siv0 on (siv0.specification_item_uid=si.specification_item_uid
AND siv0.agreement_version=a0.agreement_version AND (dayscale.dt >= siv0.dt_from AND (siv0.dt_to >= dayscale.dt OR siv0.dt_to IS NULL)))
AND siv0.agreement_version=a0.agreement_version AND (dayscale.dt >= siv0.dt_from /*AND (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL)*/)
)
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
group by dayscale.dt
) install_fix_payg
@@ -172,7 +212,9 @@ select count(*) as cnt from specification_item where 1=1
<a href="?output_xls" title="экспорт в Excel" style="margin:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
<a href="?output_json" title="экспорт в json" style="margin:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
<br/>
Дни и месяцы с нулевой суммой не показаны. Инсталл и ежемес могут генерировать отдельные строки на один день
Дни и месяцы без данных не показаны.
Инсталл и ежемес могут генерировать отдельные строки на один день.
Вариант с локальной рабочей версией строки (инстанса)
<table class="worktable">
<thead>
@@ -192,13 +234,13 @@ select count(*) as cnt from specification_item where 1=1
<cfoutput query="qRead">
<tr>
<td class="c">#dateFormat(dt,"DD.MM.YYYY")#</td>
<td class="r">#income_install#</td>
<td class="r">#inst1#</td>
<td class="r">#inst0#</td>
<td class="r">#income_recurring#</td>
<td class="r">#rec1#</td>
<td class="r">#rec0#</td>
<td class="r">#income#</td>
<td class="r">#myNumFmt(income_install)#</td>
<td class="r">#myNumFmt(inst1)#</td>
<td class="r">#myNumFmt(inst0)#</td>
<td class="r">#myNumFmt(income_recurring)#</td>
<td class="r">#myNumFmt(rec1)#</td>
<td class="r">#myNumFmt(rec0)#</td>
<td class="r">#myNumFmt(income)#</td>
<td class="r">#cnt#</td>
</tr>
</cfoutput>
@@ -233,9 +275,9 @@ select count(*) as cnt from specification_item where 1=1
<cfoutput query="qMonthly">
<tr>
<td class="c">#dateFormat(m,"MM.YYYY")#</td>
<td class="r">#nFmt(income_install)#</td>
<td class="r">#nFmt(income_recurring)#</td>
<td class="r">#nFmt(income)#</td>
<td class="r">#myNumFmt(income_install)#</td>
<td class="r">#myNumFmt(income_recurring)#</td>
<td class="r">#myNumFmt(income)#</td>
</tr>
</cfoutput>
</table>
@@ -243,3 +285,72 @@ select count(*) as cnt from specification_item where 1=1
</cfif>
<layout:page section="footer"/>
<!---
-- select *
select
--DATE_TRUNC('month', dayscale.dt)::date as m,
dayscale.dt::date
--,a.agreement_version as v
,siv.agreement_version
,siv.dt_from::date
,siv.dt_to::date
,siv.quantity
,case when siv.dt_to >=dayscale.dt OR siv.dt_to IS NULL then siv.quantity else -100500 end as q
,a0.agreement_version as v0
,siv0.dt_from::date
,siv0.dt_to::date
,siv0.quantity
--,0 ,0 ,0
/*
,COALESCE(sum(siv.price*siv.quantity*COALESCE(a.probability_perc,0)/100/dayscale.days),0)
+ COALESCE(sum(siv0.price*siv0.quantity*(100-COALESCE(a.probability_perc,0))/100/dayscale.days),0)
,sum(siv.price*siv.quantity*COALESCE(a.probability_perc,0)/100/dayscale.days)
,sum(siv0.price*siv0.quantity*(100-COALESCE(a.probability_perc,0))/100/dayscale.days)
,count(*)
*/
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
left outer join specification_item_version siv on (dayscale.dt >= siv.dt_from /*AND (siv.dt_to >= dayscale.dt OR siv.dt_to IS NULL)*/
AND siv.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=siv.specification_item_uid
AND (dayscale.dt >= iiv.dt_from /*AND (iiv.dt_to >= dayscale.dt OR iiv.dt_to IS NULL)*/)))
/*AND ia.is_actual*/ /*свежее соглашение не обязано быть действующим*/
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 a.agreement_version=siv.agreement_version)
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)
-- находим предыдущее действующее соглашение
-- если свежее соглашение действует, то впр
-- нам нужно, чтобы в прошлом (до dt_from свежего соглашения) свежак был прозрачен,
-- а в будущем (после dt_to) факт перетирался свежим соглашением
left outer join agreement a0 on (s.contract_id=a0.contract_id AND a0.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.agreement_version < siv.agreement_version
AND ia.is_actual /*именно действующее соглашение, принимаемое за факт*/
)
)
left outer join specification_item_version siv0 on (siv0.specification_item_uid=si.specification_item_uid
AND siv0.agreement_version=a0.agreement_version AND (dayscale.dt >= siv0.dt_from /*AND (siv0.dt_to >= dayscale.dt OR siv0.dt_to IS NULL)*/)
)
where d.contragent_id=4
--group by dayscale.dt
--->