spec/price_rpt.cfm
2025-06-02 16:16:51 +03:00

365 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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="priceWithVAT">
<cfargument name="price"/>
<cfargument name="vatRate"/>
<cftry>
<cfif isNumeric(arguments.price)>
<cfreturn price*(1+arguments.vatRate)/>
<cfelse>
<cfreturn ""/>
<!--- если вернуть "по запросу", Excel падает с ошибкой Ошибка XML в "Таблица"
Причина: Ошибочное значение
Файл: C:\Users\root\Downloads\price (5).xml
Группа: Cell
Тег: Data
Значение: по запросу --->
</cfif>
<cfcatch type="ANY"><cfreturn ""/></cfcatch>
</cftry>
</cffunction>
<m:prepare_ls entity="price" accessObject="price_rpt" pageInfoOut="pageInfo" trackOut="tr"/><!---synthetic entity, not a table--->
<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.param_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="qReadTitleMap" lengthOut="qReadFieldCount">
<d:field title="service_price_id" cfSqlType="CF_SQL_VARCHAR">prc.service_price_id</d:field>
<d:field title="service_param_price_id" cfSqlType="CF_SQL_VARCHAR">prc.service_param_price_id</d:field>
<d:field title="Модель цены">prm.pricing_model_id</d:field>
<d:field title="Модель цены">prm.pricing_model</d:field>
<d:field title="Модель цены">prm.pricing_model_short</d:field>
<d:field title="Модель цены">prm.pricing_model_code</d:field>
<d:field title="Период цены">prc.pricing_period</d:field>
<d:field title="Период опроса">prc.rating_period</d:field>
<d:field title="GPL, ₽" cfSqlType="CF_SQL_DECIMAL">prc.price</d:field>
<d:field title="Цена со ск., ₽" cfSqlType="CF_SQL_DECIMAL">case when price*.95 > coalesce(min_price,0) then price*.95 else min_price end as discount_price</d:field>/***/
<d:field title="Дно" cfSqlType="CF_SQL_DECIMAL">min_price</d:field>
<d:field title="Статус цены" cfSqlType="CF_SQL_DECIMAL">prc.status as price_status</d:field>
<d:field title="Начальная дата действия цены" cfSqlType="CF_SQL_TIMESTAMP">prc.dt_from</d:field>
<d:field title="Конечная дата действия цены" cfSqlType="CF_SQL_TIMESTAMP">prc.dt_to</d:field>
<d:field title="abstract_service_id" cfSqlType="CF_SQL_INTEGER">a.abstract_service_id</d:field>
<d:field title="service_id" cfSqlType="CF_SQL_INTEGER">s.service_id</d:field>
<d:field title=#i18("Код группы","Group Code")#>g.area_code</d:field>
<d:field title="Группа">g.area</d:field>
<d:field title="Группа">g.analytic_code</d:field>
<d:field title="Catalog Group">g.area_en</d:field>
<d:field title="ID статуса абстрактной услуги">a.status_id</d:field>
<d:field title="Статус абстрактной услуги">u.status</d:field>
<d:field title="Abstract Service Status">u.status_en</d:field>
<d:field>a.code</d:field>
<d:field>m.code as modifier_code</d:field>
<d:field>p.code as param_code</d:field>
<d:field title="Абстрактная услуга">a.abstract_service</d:field>
<d:field title="Abstract Service">a.abstract_service_en</d:field>
<d:field title="Описание услуги">case when (prc.service_price_id > 0) then s.descr else '' end as service_descr</d:field>
<d:field title="Коммерческие примечания">s.commercial_note</d:field>
<d:field title="modifier_id" cfSqlType="CF_SQL_INTEGER">m.modifier_id</d:field>
<d:field title="Класс модификатора">mc.modifier_class</d:field>
<d:field title="Модификатор">m.modifier</d:field>
<d:field title="Modifier class">mc.modifier_class_en</d:field>
<d:field title="Modifier">m.modifier_en</d:field>
<d:field title="service_param_id" cfSqlType="CF_SQL_INTEGER">sp.service_param_id</d:field>
<d:field title="param_class_id" cfSqlType="CF_SQL_INTEGER">pc.param_class_id</d:field>
<d:field title="param_class">pc.param_class</d:field>
<d:field title="Сортировка компонента">ac.sort as param_class_sort</d:field><!--- порядок сортировки в списке компонентов, например CPU-RAM-HDD-GPU --->
<d:field title="Сортировка варианта компонента">p.sort as param_sort</d:field><!--- порядок сортировки в списке вариантов компонентов, например SATA-SAS-SSD --->
<d:field title="Компонент">p.param</d:field>
<d:field title="param_id" cfSqlType="CF_SQL_INTEGER">p.param_id</d:field>
<d:field title="Ед.изм.">case when p.param_id IS NULL then se.measure_short else e.measure_short end as measure_short</d:field>
<d:field title="Measure">case when p.param_id IS NULL then se.measure_short_en else e.measure_short_en end as measure_short_en</d:field>
<d:field title="НДС%">s.vat_perc</d:field>
<d:field title="НДС не обл.">s.vat_free</d:field>
<d:field>case when s.vat_free then 0. else vat_perc/100. end as vat_rate</d:field>
<!--- <d:field title="service_param_price_cnt" cfSqlType="CF_SQL_INTEGER">(select count(*) from service_param_price spp join service_param sp on spp.service_param_id=sp.service_param_id )</d:field> --->
</d:field_set>
from (
select
t.service_param_price_id, t.price, t.min_price, t.service_param_id, t.pricing_model_id
, null as service_price_id, sp.service_id, t.pricing_period, t.rating_period
,t.status, t.dt_from, t.dt_to
from service_param_price t join service_param sp on (t.service_param_id=sp.service_param_id)
union all
select
null, st.price, st.min_price, null, st.pricing_model_id, st.service_price_id, st.service_id, st.pricing_period, st.rating_period
,st.status, st.dt_from, st.dt_to
from service_price st
) prc
left outer join service s on (prc.service_id=s.service_id)
left outer join service_param sp on (prc.service_param_id=sp.service_param_id)
left outer join abstract_service a on (s.abstract_service_id=a.abstract_service_id)
left outer join modifier m on (s.modifier_id=m.modifier_id)
left outer join modifier_class mc on (m.modifier_class_id=mc.modifier_class_id)
left outer join abstract_service_param_class ac on (sp.abstract_service_param_class_id=ac.abstract_service_param_class_id)
left outer join param_class pc on (ac.param_class_id=pc.param_class_id)
left outer join param p on (sp.param_id=p.param_id)
left outer join measure e on (p.measure_id=e.measure_id)
left outer join measure se on (s.measure_id=se.measure_id)
left outer join area g on (a.area_id=g.area_id)
left outer join status u on (a.status_id=u.status_id)
left outer join pricing_model prm on (prc.pricing_model_id=prm.pricing_model_id)
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
order by g.analytic_code
, a.abstract_service, s.service_id, m.sort, m.modifier_id
, prc.pricing_model_id
, coalesce(ac.sort,0) -- service_price should be before service_param_price, but null can be after 0
, p.sort, p.param_id
</cfquery>
<!---
<cfcatch type="database">
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
</cfcatch>
</cftry>--->
<cfquery name="qCountTotal" datasource="#request.DS#">
select (select count(*) from service_param_price) + (select count(*) from service_price) as cnt;
</cfquery>
<!--- Тут проблема, serializeJSON неправильно форматирует дату-время --->
<cfset qFmt=queryNew("area,code,service,param,measure_short,pricing_model_short,pricing_period,rating_period,price,discount_price,service_descr,commercial_note,param_class_sort,param_sort, sku, status_id, status, price_status, dt_from, dt_to, vat_free, vat_perc",
"varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,numeric,numeric,varchar,varchar,numeric,numeric,varchar,numeric,varchar,varchar,varchar,varchar,varchar,varchar")/>
<!--- Столь неудобная конструкция привела сразу к нескольким ошибкам, когда я добавил 2 поля vat_free, vat_perc - добавлять их надо в нескольких местах --->
<cfset qFmtTitleMap={
area={ordinal=1,title="Группа услуг",cfSqlType="CF_SQL_VARCHAR"}
,code={ordinal=2,title="Код",cfSqlType="CF_SQL_VARCHAR"}
,service={ordinal=3,title="Услуга",cfSqlType="CF_SQL_VARCHAR"}
,param={ordinal=4,title="Компонент",cfSqlType="CF_SQL_VARCHAR"}
,measure_short={ordinal=5,title="Ед.изм.",cfSqlType="CF_SQL_VARCHAR"}
,pricing_model_short={ordinal=6,title="Модель ц-обр.",cfSqlType="CF_SQL_VARCHAR"}
,pricing_period={ordinal=7,title="Период цены",cfSqlType="CF_SQL_VARCHAR"}
,rating_period={ordinal=8,title="Период замера",cfSqlType="CF_SQL_VARCHAR"}
,price={ordinal=9,title="Цена GPL, ₽ с НДС",cfSqlType="CF_SQL_DECIMAL"}
,discount_price={ordinal=10,title="GPL-5%, ₽ с НДС",cfSqlType="CF_SQL_DECIMAL"}
,service_descr={ordinal=11,title="Описание услуги",cfSqlType="CF_SQL_VARCHAR"}
,commercial_note={ordinal=12,title="Коммерческие примечания",cfSqlType="CF_SQL_VARCHAR"}
,param_class_sort={ordinal=13,title="Сортировка компонента",cfSqlType="CF_SQL_NUMERIC"}
,param_sort={ordinal=14,title="Сортировка варианта компонента",cfSqlType="CF_SQL_NUMERIC"}
,sku={ordinal=15,title="Полное название",cfSqlType="CF_SQL_VARCHAR"}
,status_id={ordinal=16,title="ID статуса абстрактной услуги",cfSqlType="CF_SQL_NUMERIC"}
,status={ordinal=17,title="Статус абстрактной услуги",cfSqlType="CF_SQL_VARCHAR"}
,price_status={ordinal=18,title="Статус цены",cfSqlType="CF_SQL_VARCHAR"}
,dt_from={ordinal=19,title="Начальная дата действия цены",cfSqlType="CF_SQL_TIMESTAMP"}
,dt_to={ordinal=20,title="Конечная дата действия цены",cfSqlType="CF_SQL_TIMESTAMP"}
,vat_free={ordinal=21,title="НДС не облагается",cfSqlType="CF_SQL_BIT"}
,vat_perc={ordinal=22,title="НДС%",cfSqlType="CF_SQL_INTEGER"}
}/><!--- когда я здесь забыл переименовать поле, в дальнейшем адресация шла по номеру, а количество полей в структуре было меньше, чем ordinal, xml.cfm падал с ошибкой --->
<!--- DIRTY HACK: in the query we have string formatted as ISO 8601 (json serializer takes it as is), but for excel declare CF_SQL_TIMESTAMP in titleMap metadata, and obtain decent formatting--->
<!--- <cfdump var=#qReadTitleMap#/>
<cfdump var=#qFmtTitleMap#/> --->
<cfloop query="qRead">
<cfset queryAddRow(qFmt ,[
"#analytic_code# #area#"
,#request.skuCode(area_code,code,modifier_code,param_code,pricing_model_code)#
,"#abstract_service# #modifier#"
,"#param_class##(len(param))?': ':''##param#"
,measure_short
,pricing_model_short
,pricing_period
,rating_period
,priceWithVAT(price,vat_rate)
,priceWithVAT(discount_price,vat_rate)
,service_descr
,commercial_note
,param_class_sort
,param_sort
,"#abstract_service# #modifier##(len(param_class))? ( ' (' & ((len(param))? param : param_class) & ')' ) : ''#"
/*,"#abstract_service# #modifier##(len(param_class))? ( ' [' & ((len(param))? param : param_class) & ']' ) : ''#"*/
/*,"#abstract_service# #modifier##(len(param_class))? (' (' & param_class & ((len(param)) ? (': ' & param) : '' ) & ')') : ''#"*/
/*,"#abstract_service# #modifier# (#param_class#: #param#)"*/
,status_id
,status
,price_status
,LSDateTimeFormat(dt_from,"yyyy-MM-dd'T'HH:nn:ssZ")
,LSDateTimeFormat(dt_to,"yyyy-MM-dd'T'HH:nn:ssZ")
,vat_free
,vat_perc
])/>
</cfloop>
<!--- <cfdump var=#qFmt#/> --->
</m:silent><!---
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
---><cfif isDefined("output_xls")><!---<cfdump var=#qFmt#/><cfdump var=#qFmtTitleMap#/><cfdump var=#pageInfo.entity#/><cfabort/>--->
<layout:xml qRead=#qFmt# titleMap=#qFmtTitleMap# filename="#pageInfo.entity#.xml"/>
<cfabort/>
</cfif><cfif isDefined("output_json")>
<layout:json qRead=#qFmt# filename="#pageInfo.entity#.json"/>
<cfabort/>
</cfif><!---
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput><b>#i18("Прайс-лист на компоненты","Resource Price List")#</b></cfoutput>
</layout:attribute>
</layout:page>
<!---<cfdump var=#qRead#/>--->
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
<layout:grid_summary
recordCount=#qRead.recordCount#
totalCount=#qCountTotal.cnt#
footerOut="gridFooter"
excelLink=#pageInfo.writePermitted()#
jsonLink=#pageInfo.writePermitted()#
/>
<cffunction name="formatPrice" output="true">
<cfargument name="price"/>
<cfif isNumeric(price)><cfreturn numberFormat(price,'.00')/><cfelse><cfreturn "(по запросу)"></cfif>
</cffunction>
<cfset request.formatPrice=formatPrice/>
<table class="worktable wide">
<thead>
<layout:grid_head titleMap=#qReadTitleMap# sortArray=#pageInfo.settings.sort.sortArray#>
<th width="5%">Группа услуг</th>
<th width="5%">Код</th>
<th width="10%">Услуга</th>
<th width="15%">Компонент</th>
<th width="3%">Единица измерения</th>
<th width="3%">Модель ц-обр.</th>
<th width="3%">Период цены</th>
<th width="3%">Период замера</th>
<th width="7%">Цена GPL, ₽ с НДС</th>
<th width="7%">GPL-5%, ₽ с НДС</th>
<th width="2%">НДС не обл.</th>
<th width="2%">НДС%</th>
</layout:grid_head>
</thead>
<cfoutput query="qRead" group="service_id">
<cfset groupCnt=0/>
<cfoutput>
<cfset groupCnt++/>
</cfoutput>
<cfif groupCnt GT 1>
<tr style="background-color:rgb(240,240,240);">
<td>#analytic_code# #area#</td>
<td>
<a href="service.cfm?service_id=#service_id#&#tr.fwx#">#request.skuCode(area_code,code,modifier_code)#</a>
</td>
<td class="c" colspan="100">
<a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">#abstract_service#</a> #modifier#
</td>
</tr>
</cfif>
<cfoutput group="pricing_model_id">
<cfoutput>
<tr>
<td>#analytic_code# #area#</td>
<td>
<cfif service_param_price_id GT 0>
<a href="service_param.cfm?service_param_id=#service_param_id#&#tr.fwx#">#request.skuCode(area_code,code,modifier_code,param_code,pricing_model_code)#</a>
<cfelse>
<a href="service.cfm?service_id=#service_id#&#tr.fwx#">#request.skuCode(area_code,code,modifier_code,param_code,pricing_model_code)#</a>
</cfif>
</td>
<cfif service_param_price_id GT 0>
<td><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">#abstract_service#</a> #modifier#</td>
<td>#param_class#<cfif len(param)>: #param#</cfif></td>
<cfelse>
<td colspan="2">
<a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">#abstract_service#</a> #modifier#
</td>
<!--- <td></td> --->
</cfif>
<td>#measure_short#</td>
<td class="c">#pricing_model_short#</td>
<td class="c">#pricing_period#</td>
<td class="c">#rating_period#</td>
<td class="r">
<cftry>
<cfif service_price_id GT 0>
<a href="service_price.cfm?service_price_id=#service_price_id#&#tr.fwx#">
<cfif isNumeric(price)>
#request.numFmt(priceWithVAT(price,vat_rate),2)#
<cfelse>
<i>по запросу</i>
</cfif>
</a>
<cfelse>
<a href="service_param_price.cfm?service_param_price_id=#service_param_price_id#&#tr.fwx#">
<cfif isNumeric(price)>
#request.numFmt(priceWithVAT(price,vat_rate),2)#
<cfelse>
<i>по запросу</i>
</cfif>
</a>
</cfif>
<cfcatch type="ANY">?<!--- #cfcatch.message# ---></cfcatch>
</cftry>
</td>
<td class="r">
<cftry>
<cfif service_price_id GT 0>
<cfif isNumeric(discount_price)>
#request.numFmt(priceWithVAT(discount_price,vat_rate),2)#
<cfelse>
<i>по запросу</i>
</cfif>
<cfelse>
<cfif isNumeric(discount_price)>
#request.numFmt(priceWithVAT(discount_price,vat_rate),2)#
<cfelse>
<i>по запросу</i>
</cfif>
</cfif>
<cfcatch type="ANY">?</cfcatch>
</cftry>
</td>
<td class="c"><cfif vat_free GT 0>Не облагается</cfif></td>
<td class="c">#vat_perc#</td>
</tr>
</cfoutput>
</cfoutput>
<cfif groupCnt GT 1>
<tr style="height:1em;"><td colspan="100" style="height:0;"></td></tr>
</cfif>
</cfoutput>
</table>
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>