initial draft

This commit is contained in:
msyu 2025-06-02 16:16:51 +03:00
commit 529334d03b
272 changed files with 22684 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
etc/info/

285
Application.cfc Normal file
View File

@ -0,0 +1,285 @@
<cfcomponent
displayname="Application"
output="true"
hint="Handle the application.">
<!--- Set up the application. --->
<cfset this.Name = "Contracts and Specifications" />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 1, 0 ) />
<cfset this.sessionmanagement="Yes"/>
<cfset this.clientmanagement="No"/>
<cfset this.sessiontimeout=CreateTimeSpan(0, 0, 120, 0)/>
<cfset this.setclientcookies="No"/>
<cfset this.mappings = structNew() />
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath())&'mod')/>
<cfset this.datasource = "spec"/>
<cfset this.defaultdatasource = this.datasource/>
<cfset request.DS = "#this.datasource#">
<cfset COOKIEENCKEY = "PREVED!Y2"/>
<!--- Define the page request properties. --->
<cfsetting
requesttimeout="20"
showdebugoutput="false"
enablecfoutputonly="false"
/>
<cffunction
name="OnApplicationStart"
access="public"
returntype="boolean"
output="false"
hint="Fires when the application is first created.">
<cfreturn true />
</cffunction>
<cffunction
name="OnRequest"
access="public"
returntype="void"
output="true"
hint="Fires after pre page processing is complete.">
<cfargument name="template" type="string" required="true"/>
<cfset request.startTickCount=getTickCount()/>
<cfset setEncoding("FORM", "UTF-8")>
<cfset setEncoding("URL", "UTF-8")>
<cfset request.PERMISSION_NONE=0/>
<cfset request.PERMISSION_READ=1/>
<cfset request.PERMISSION_WRITE=2/>
<cfset request.UNDEFINED_USR_ID=-1/>
<!--- request.ROOT_USR_ID=1 not used --->
<cfset request.ANONYMOUS_USR_ID=2/>
<cfset request.GUEST_USR_ID=3/>
<!--- global settings --->
<!--- <cfset this.datasource = "spec"/>
*** здесь не работает!<cfset this.defaultdatasource = this.datasource/>
<cfset request.DS = "#this.datasource#"> --->
<!--- <cfset this.datasources["#this.datasource#"]=getDS("#this.datasource#","datasource_#this.datasource#")/> --->
<cfset request.RECORDS_PER_PAGE=500/>
<cfset request.APP_VERSION="0.00.000"/>
<cflock scope="application" type="readonly" timeout=3>
<cfset request.APP_NAME=this.Name/>
</cflock>
<cfset local = {} />
<cfset local.basePath = getDirectoryFromPath(
getCurrentTemplatePath()
) />
<cfset local.targetPath = getDirectoryFromPath(
expandPath( arguments.template )
) />
<cfset local.requestDepth = (
listLen( local.targetPath, "\/" ) -
listLen( local.basePath, "\/" )
) />
<cfset request.webRoot = repeatString(
"../",
local.requestDepth
) />
<!---
While we wouldn't normally do this for every page
request (it would normally be cached in the
application initialization), I'm going to calculate
the site URL based on the web root.
--->
<cfset request.siteUrl = (
IIF(
(CGI.server_port_secure <!--- CGI.https EQ "On" does not work with apache+tomcat and nginx+tomcat --->),
DE( "https://" ),
DE( "http://" )
) &
cgi.http_host &
reReplace(
getDirectoryFromPath( arguments.template ),
"([^\\/]+[\\/]){#local.requestDepth#}$",
"",
"one"
)
) />
<cfset request.thisPage=Replace(ReplaceNoCase(expandPath(ARGUMENTS.template), local.basePath, ""), "\", "/")/>
<cfinclude template="inc/functions.cfm"/>
<cfcookie name="CFID" value="#session.CFID#">
<cfcookie name="CFTOKEN" value="#session.CFTOKEN#">
<!--- check saved login --->
<!---
если в сессии есть usr_id, ничего делать не нужно
если его нет (то есть сессия новая или свежесброшенная),
- проверить куки.
Дополнительное условие: если происходит процесс установки-сброса кук,
(в процессе установки-сброса определена переменная session.save_login) - не вмешиваемся
--->
<cflock scope="session" type="exclusive" timeout="3">
<cfset session.usr_id = 10><!--- *** --->
<cfif NOT structKeyExists(session,"usr_id") OR (structKeyExists(session,"usr_id") AND NOT isNumeric(session.usr_id))>
<cfset session.usr_id=#request.UNDEFINED_USR_ID#>
</cfif>
<cfif session.usr_id EQ request.UNDEFINED_USR_ID>
<cfif NOT structKeyExists(session, "save_login")>
<cfif structKeyExists(cookie, "portalUser")>
<cftry>
<cfset login = Decrypt(cookie.portalUser,COOKIEENCKEY)>
<cfoutput>#login#</cfoutput>
<cfquery name="qGetCredentials" datasource="#request.DS#">
select usr_id from usr where login='#login#'
</cfquery>
<cfset session.usr_id = qGetCredentials.usr_id>
<m:settings action="create"/>
<cfcatch type="Any">
<cfoutput>#cfcatch.message#</cfoutput>
<cfset session.usr_id = request.UNDEFINED_USR_ID>
</cfcatch>
</cftry>
</cfif>
</cfif>
</cfif>
<cfif session.usr_id EQ request.UNDEFINED_USR_ID>
<cfset session.usr_id = request.ANONYMOUS_USR_ID>
</cfif>
<cfset request.usr_id=session.usr_id/>
<cfif structKeyExists(session, "username")>
<cfset request.username=#session.username#/>
<cfelse>
<cfset request.username=""/>
</cfif>
<cfparam name="language" default=""/>
<cfif language EQ "ru" OR language EQ "en">
<cfset session.language=language/>
<cfelse>
<cfparam name="session.language" default="ru"/>
</cfif>
<cfset request.language=session.language/>
</cflock><!--- session exclusive --->
<cfset request.usr_is_admin=0/>
<cfif request.usr_id GT 0><!--- AND request.usr_id NEQ request.ANONYMOUS_USR_ID в данном случае закрыли анонимный доступ --->
<cfinclude template="#ARGUMENTS.template#"/>
<cfelse>
<cfset currentDir = (
lCase(
replace(
getDirectoryFromPath(
replaceNoCase(
expandPath(
ARGUMENTS.template
),
getDirectoryFromPath(
getCurrentTemplatePath()
),
""
)
), "\", "/", "ALL"
)
)
)/>
<cfif currentDir EQ "saml/"><!--- note traling slash --->
<cfinclude template="#ARGUMENTS.template#"/>
<cfelse>
<cfinclude template="login.cfm" />
</cfif>
</cfif>
<cfreturn />
</cffunction>
<cffunction
name="OnRequestEnd"
access="public"
returntype="void"
output="true"
hint="Fires after the page processing is complete.">
<!--- Attention! Before CF9, OnrequestEnd is not executed in case of redirect. That is why we use session.save_login --->
<cfif structKeyExists(session, "save_login")>
<cfif session.save_login EQ "">
<!--- unset (expire) cookie --->
<cfcookie expires="-1" name="portalUser" value="">
<cfelse>
<!--- set persistent cookie with no expiration --->
<cfcookie expires="NEVER" name="portalUser" value="#encrypt(session.save_login,COOKIEENCKEY)#">
</cfif>
<cfset structDelete(session, "save_login")>
</cfif>
<cfreturn />
</cffunction>
<cffunction
name="getDS"
access="private"
returntype="struct"
output="true"
hint="Configure data source from environment variables. Convention: data source name is an environment varialble prefix">
<cfargument name="dsname" type="string" required="true"/>
<cfargument name="prefix" type="string" default=#dsname#/>
<cfset system = createObject("java", "java.lang.System")/>
<cfset var ds={}/>
<cfloop list="class,connectionString,database,driver,dbdriver,host,port,type,url,username,password,bundleName,bundleVersion,connectionLimit,liveTimeout,validate" item="field"><!--- driver vs dbdriver --->
<cfset var value=system.getEnv("#arguments.prefix#_#field#")/>
<cfif isDefined("value") AND len(value)>
<cfset structInsert(ds,field,value)/>
</cfif>
</cfloop>
<cfif structIsEmpty(ds)>
<cfthrow type="application" message="Datasource not configured" detail="Datasource not defined in the environment. Expected prefix is #arguments.prefix#"/>
</cfif>
<!--- test datasource (just to get exception if invalid) --->
<cftry>
<cfquery name="qTestDs" datasource=#ds#>
select 1;
</cfquery>
<cfcatch type="any">
<!--- <cfdump var=#ds#/><cfabort/> --->
<cfrethrow/>
</cfcatch>
</cftry>
<cfreturn ds/>
</cffunction>
</cfcomponent>

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Svc
Каталог услуг

21
_doc_ls.cfm Normal file
View File

@ -0,0 +1,21 @@
<cfquery name="qRead" datasource="#request.DS#">
select
d.abstract_service_id as entity_id, d.abstract_service_doc_id as doc_id, d.abstract_service_doc as title, datalength(d.doc) as doc_size, d.contenttype, d.fname,
a.login as creator, a.shortname as creator_name, u.login as modifier, u.shortname as modifier_name
from abstract_service_doc d
left outer join usr a on (d.creator_id=a.usr_id)
left outer join usr u on (d.modifier_id=u.usr_id)
</cfquery>
<!---<cfdump var=#qRead#/>--->
<cfoutput query="qRead">
<a href="doc_get.cfm?entity=abstract_service&doc_id=#doc_id#&action=download">#title#</a>
<br/>
</cfoutput>

575
abstract_service.cfm Normal file
View File

@ -0,0 +1,575 @@
<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="Yes">
<cffunction name="plain2HtmClean">
<cfargument name="s" type="string"/>
<cfreturn request.plain2htm(request.cleanHtm(s))/>
</cffunction>
<cffunction name="cleanInput">
<cfargument name="s" type="string"/>
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="abstract_service" key="abstract_service_id" pageInfoOut="pageInfo"/>
<d:bean readonly=#!pageInfo.writePermitted()# table="abstract_service" datasource="#request.DS#" output="d" status="status">
<d:param field="abstract_service_id" type="integer" key autoincrement/>
<d:param field="measure_id" type="integer" init="1" required/>
<d:param field="precision" type="integer" init="0" required/>
<d:param field="area_id" type="integer" required/>
<d:param field="modifier_class_id" type="integer" forNull=""/>
<d:param field="manager_id" type="integer" forNull=""/>
<d:param field="abstract_service" type="varchar" size="255" preprocessor=#cleanInput#/>
<d:param field="abstract_service_en" type="varchar" size="255" preprocessor=#cleanInput#/>
<d:param field="code" type="varchar" size="31" preprocessor=#cleanInput#/>
<d:param field="version" type="integer" default="1" init="1"/>
<d:param field="status_id" type="integer" default="1" init="1"/>
<d:param field="dt_status" type="timestamp" default="#Now()#" init="#Now()#"/>
<d:param field="descr" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="commercial_note" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<d:param field="updater_id" type="integer" value="#request.usr_id#" />
<d:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<d:param field="dt_updated" type="timestamp" value="#Now()#"/>
</d:bean>
<cfset pageInfo.status=#status#/>
<m:dispatch_detail
usePRG="No"<!---*** --->
pageInfo=#pageInfo#
id="#d.abstract_service_id#"
status=#pageInfo.status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- save doc --->
<cfmodule template="mod/documents.cfm" section="model" entity="#pageInfo.entity#" id="#id.value#" tr=#tr# writePermitted=#pageInfo.writePermitted()#/>
<!---/save doc --->
<cfquery name="qArea" datasource="#request.DS#">
select a.analytic_code, a.area_code, a.area
from area a
where area_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.area_id#" null=#!isNumeric(d.area_id)#/>
</cfquery>
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.login as creator, a.shortname as creator_shortname, m.login as updater, m.shortname as updater_shortname
from #pageInfo.entity# e
left outer join usr a on (e.creator_id=a.usr_id)
left outer join usr m on (e.updater_id=m.usr_id)
where e.#pageInfo.key#=<cfqueryparam attributeCollection=#id#/>
</cfquery>
</m:silent><!---
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Абстрактная услуга
<cfif d.abstract_service_id GT 0>
<b>#d.abstract_service#</b>
[#d.abstract_service_id#]
</cfif>
</cfoutput>
</layout:attribute>
</layout:page>
<!---<cfif status.errorState GT 0>
<cfoutput><div class="err">#status.errorMessage#</div></cfoutput>
</cfif>
--->
<cfoutput>
<input type="hidden" name="abstract_service_id" value="#d.abstract_service_id#"/>
<input type="hidden" name="track" value="#tr.self#" size="200"/>
<input type="hidden" name="pass" value=""/><!--- pass marker to prevent save on submit --->
<div class="detail">
<div class="tr">
<div class="th">Номенклатура (RUS)</div>
<div class="td">
<input type="text" name="abstract_service" value="#d.abstract_service#" size="70" style="width:97%"/>
</div>
</div>
<div class="tr">
<div class="th">Номенклатура (ENG)</div>
<div class="td">
<input type="text" name="abstract_service_en" value="#d.abstract_service_en#" size="70" style="width:97%"/>
</div>
</div>
<div class="tr">
<div class="th">Группа услуг</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select area_id, area_code, analytic_code, area
from area
order by 3
</cfquery>
<c:combo
query=#qList#
combo="area_id"
id="area_id"
key="area_id"
selected="#d.area_id#"
displayf="##analytic_code## ##area##"
class=""
<!---onchange="submit();"--->
/>
</div>
</div>
<div class="tr">
<div class="th">Код услуги</div>
<div class="td">
#qArea.area_code#.<input type="text" name="code" value="#d.code#" size="7"/>
</div>
</div>
<div class="tr">
<div class="th">Единица измерения</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select measure_id, measure
from measure
order by 2
</cfquery>
<c:combo
query=#qList#
combo="measure_id"
id="measure_id"
key="measure_id"
selected="#d.measure_id#"
displayf="##measure##"
empty=""
class=""
<!---onchange="submit();"--->
/>
<i>для композитных услуг (состоящих из компонентов) указывать штуки. Часто композитные услуги попадают в спецификацию в количестве 1 шт.</i>
</div>
</div>
<div class="tr">
<div class="th">Точность</div>
<div class="td">
<input type="text" name="precision" value="#d.precision#" size="1" class="r"/>
<i>Количество знаков после запятой, 0 - целое число</i>
</div>
</div>
<div class="tr">
<div class="th">Класс характеристики</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select modifier_class_id, modifier_class
from modifier_class
order by 2
</cfquery>
<c:combo
query=#qList#
combo="modifier_class_id"
id="modifier_class_id"
key="modifier_class_id"
selected="#d.modifier_class_id#"
displayf="##modifier_class##"
empty=""
class=""
<!---onchange="submit();"--->
/>
<cfif d.abstract_service_id GT 0>
<cfif d.modifier_class_id GT 0>
<a href="modifier_class.cfm?modifier_class_id=#d.modifier_class_id#&#tr.fwx#">
<img src="img/edit.gif"/>
</a>
</cfif>
<a href="modifier_class.cfm?modifier_class_id=-1&#tr.fwx#">
<img src="img/add.gif"/>
</a>
</cfif>
<i>
Список, из которого выбирается значение характеристики-модификатора, определяющее конкретную услугу (вариант). <br/>
Если варианты не предусмотрены, нужно оставить поле пустым.
</i>
</div>
</div>
<div class="tr">
<div class="th">Ответственный</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select usr_id, firstname, middlename, lastname
from usr
order by 4,2,3
</cfquery>
<c:combo
query=#qList#
combo="manager_id"
id="manager_id"
key="usr_id"
selected="#d.manager_id#"
displayf="##lastname## ##firstname## ##middlename## "
empty=""
class=""
/>
</div>
</div>
<div class="tr">
<div class="th">Версия</div>
<div class="td">
<input type="text" name="version" value="#d.version#" size="3"/>
</div>
</div>
<div class="tr">
<div class="th">Статус</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select status_id, status
from status
order by 1
</cfquery>
<c:combo
query=#qList#
combo="status_id"
id="status_id"
key="status_id"
selected="#d.status_id#"
displayf="##status##"
class=""
<!---onchange="submit();"--->
/>
с <input type="text" name="dt_status" id="dt_status" value="#dateFormat(d.dt_status,'DD.MM.YYYY')#" size="10"/>
<button type="button" onclick="document.getElementById('dt_status').value='#DateFormat(Now(), 'DD.MM.YYYY')#';">Сегодня</button>
</div>
</div>
<div class="tr">
<div class="th">Описание</div>
<div class="td">
<textarea name="descr" rows="5" cols="100" style="width:97%">#request.htm2plain(d.descr)#</textarea>
</div>
</div>
<div class="tr">
<div class="th">Коммерческие примечания</div>
<div class="td">
<textarea name="commercial_note" rows="5" cols="100" style="width:97%">#request.htm2plain(d.commercial_note)#</textarea>
</div>
</div>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'DD.MM.YYYY')# #timeFormat(d.dt_created,'HH:MM')#
#qDecoration.creator# <cfif len(qDecoration.creator_shortname)>(#qDecoration.creator_shortname#)</cfif>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Изменено
#dateFormat(d.dt_updated,'DD.MM.YYYY')# #timeFormat(d.dt_updated,'HH:MM')#
#qDecoration.updater# <cfif len(qDecoration.updater_shortname)>(#qDecoration.updater_shortname#)</cfif>
</div>
</div>
</div>
</cfoutput>
<layout:page section="extension" closeForm="Yes"/>
<!--- --------------------------------------------------- --->
<!--- --------------------------------------------------- --->
<!--- --------------------------------------------------- --->
<cfif d.abstract_service_id GT 0>
<!--- documents ---><!--- call MODEL section for save! --->
<cfmodule template="mod/documents.cfm" section="view" entity="#pageInfo.entity#" id="#id.value#" tr=#tr# writePermitted=#pageInfo.writePermitted()#/>
<!---/documents --->
<!--- <cfmodule template="mod/abstract_service_param_class.cfm"
abstract_service_id=#d.abstract_service_id#
fwx=#tr.fwx#
self=#tr.self#
editable=#pageInfo.writePermitted()#
/> --->
<!--- ------------------------------------------------------------------------------- --->
<!--- ------------------------------------------------------------------------------- --->
<!--- ------------------------------------------------------------------------------- --->
<cfquery name="qAbstractServiceParamClass" datasource="#request.DS#">
select
ac.abstract_service_param_class_id
,ac.param_class_id
,ac.is_multiple
,ac.sort
,c.param_class
,c.measure_id
,m.measure_id
,m.measure
,m.measure_short
<!--- ,(select count(*) from price p where p.service_param_id=sp.service_param_id) as prc_cnt --->
,(select count(*) from param p where p.param_class_id=ac.param_class_id) as param_cnt
from abstract_service_param_class ac
left outer join param_class c on (ac.param_class_id=c.param_class_id)
left outer join measure m on (c.measure_id=m.measure_id)
where ac.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#"/>
order by ac.sort
</cfquery>
<cfoutput>
<p>
<b>Компоненты (#qAbstractServiceParamClass.recordCount#)</b>
<cfif pageInfo.writePermitted()>
<cfoutput>
<cfset addUrl="abstract_service_param_class.cfm?abstract_service_param_class_id=-1&abstract_service_id=#d.abstract_service_id#&#tr.fwx#"/>
<button type="button" class="maincontrol" onclick="document.location.href='#addUrl#'">
<a href="#addUrl#">Добавить</a>
</button>
</cfoutput>
</cfif>
</p>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th></th>
<th>Компонент</th>
<th>Единица измерения</th>
<th>Вариантов</th>
<th>Множественный</th>
<th>Сортировка</th>
<th></th>
</tr>
</thead>
<cfoutput query="qAbstractServiceParamClass">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="abstract_service_param_class" id=#abstract_service_param_class_id# fwx=#tr.fwx#/>
</td>
<td>
<cfif param_class_id GT 0><a href="param_class.cfm?param_class_id=#param_class_id#&#tr.fwx#">#param_class#</a></cfif>
</td>
<td class="c">
#measure# <cfif len(#measure_short#)>(#measure_short#)</cfif>
</td>
<td class="c">
<cfif param_cnt GT 0>#param_cnt#</cfif>
</td>
<td class="c">
<cfif is_multiple GT 0>
Да
</cfif>
</td>
<td class="c">
#sort#
</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="abstract_service_param_class" id=#abstract_service_param_class_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
<!--- --------------------------------------------------- --->
<cfquery name="qService" datasource="#request.DS#">
select
s.service_id
,m.modifier_id
,m.modifier
<!--- ,s.base_price--->
,c.modifier_class_id
,c.modifier_class
,m.code as modifier_code
,(select count(*) from service_param sp where sp.service_id=s.service_id) as param_count
,(select count(*) from service_param sp join service_param_price spp on (sp.service_param_id=spp.service_param_id) where sp.service_id=s.service_id) as service_param_price_count
,(select sp.price from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=1 order by service_price_id desc limit 1) as prc_inst
,(select count(*) from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=1) as prc_inst_cnt
,(select sp.service_price_id from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=1 order by service_price_id desc limit 1) as prc_inst_id
,(select sp.price from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=2 order by service_price_id desc limit 1)as prc_fix
,(select count(*) from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=2) as prc_fix_cnt
,(select sp.service_price_id from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=2 order by service_price_id desc limit 1)as prc_fix_id
,(select sp.price from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=3 order by service_price_id desc limit 1) as prc_payg
,(select count(*) from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=3) as prc_payg_cnt
,(select sp.service_price_id from service_price sp where sp.service_id=s.service_id AND sp.pricing_model_id=3 order by service_price_id desc limit 1) as prc_payg_id
<!--- -- *** ну и уродливый селект --->
from service s
left outer join modifier m on (s.modifier_id=m.modifier_id)
left outer join modifier_class c on (m.modifier_class_id=c.modifier_class_id)
where s.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#"/>
order by m.sort, m.code, m.modifier
</cfquery>
<!--- <cfdump var=#qService#/> --->
<cffunction name="formatPrice" output="true">
<cfargument name="price"/>
<cfif isNumeric(price)><cfreturn numberFormat(price,'.00')/><cfelse><cfreturn "(по запросу)"></cfif>
</cffunction>
<cfoutput>
<p>
<b>Варианты услуги (#qService.recordCount#)</b><!---#d.code# #d.abstract_service#--->
<cfif pageInfo.writePermitted()>
<cfoutput>
<cfset addUrl="service.cfm?service_id=-1&abstract_service_id=#d.abstract_service_id#&#tr.fwx#"/>
<button type="button" class="maincontrol" onclick="document.location.href='#addUrl#'">
<a href="#addUrl#">Создать</a>
</button>
</cfoutput>
</cfif>
</p>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th></th>
<th></th>
<th>Код</th>
<th>Название</th>
<!--- <th>Кл. модиф.</th>--->
<!--- <th>Порядок</th> --->
<th>Цена усл. инст.</th>
<th>Цена усл. фикс.</th>
<th>Цена усл. payg</th>
<th>Компонентов</th>
<th>Цен комп-в</th>
<!--- <th>Цена без НДС, ₽</th>--->
<th></th>
</tr>
</thead>
<cfoutput query="qService">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="service" id=#service_id# fwx=#tr.fwx#/>
</td>
<td>
<form name="frmClone#service_id#" action="service_clone.cfm">
<input type="hidden" name="service_id" value="#service_id#"/>
<input type="hidden" name="track" value="#tr.fw#"/>
<button type="submit"<cfif !pageInfo.writePermitted()> disabled</cfif>>clone</button>
</form>
</td>
<td>#request.skuCode(qArea.area_code,d.code,modifier_code)#</td>
<td>#d.abstract_service#<cfif len(modifier) GT 0> - #modifier#</cfif></td>
<!--- <td class="r">#modifier_class#</td> --->
<!--- <td>#sort#</td> --->
<td class="r">
<cfif prc_inst_id GT 0>
<a href="service_price.cfm?service_price_id=#prc_inst_id#&#tr.fwx#">#formatPrice(prc_inst)#</a>
</cfif>
</td>
<td class="r">
<cfif prc_fix_id GT 0>
<a href="service_price.cfm?service_price_id=#prc_fix_id#&#tr.fwx#">#formatPrice(prc_fix)#</a>
</cfif>
</td>
<td class="r">
<cfif prc_payg_id GT 0>
<a href="service_price.cfm?service_price_id=#prc_payg_id#&#tr.fwx#">#formatPrice(prc_payg)#</a>
</cfif>
</td>
<td class="r"><cfif param_count GT 0>#param_count#</cfif></td>
<td class="r"><cfif service_param_price_count GT 0>#service_param_price_count#</cfif></td>
<!--- <td class="r">#base_price#</td> --->
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="service" id=#service_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
<!--- --------------------------------------------------- --->
<cfquery name="qAbstractServiceComplementary" datasource="#request.DS#">
select
ac.abstract_service_complementary_id
,ac.abstract_service_id
,ac.complementary_id
,ac.quantity
,ac.sort
,c.code
,c.abstract_service
,c.area_id
,g.area_code
from abstract_service_complementary ac
left outer join abstract_service c on (ac.complementary_id=c.abstract_service_id)
left outer join area g on (c.area_id=g.area_id)
where ac.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#"/>
order by ac.sort
</cfquery>
<cfoutput>
<p>
<b>Дополнительные услуги (#qAbstractServiceComplementary.recordCount#)</b>
<cfif pageInfo.writePermitted()>
<cfoutput>
<cfset addUrl="abstract_service_complementary.cfm?abstract_service_complementary_id=-1&abstract_service_id=#d.abstract_service_id#&#tr.fwx#"/>
<button type="button" class="maincontrol" onclick="document.location.href='#addUrl#'">
<a href="#addUrl#">Добавить</a>
</button>
</cfoutput>
</cfif>
</p>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th></th>
<th>Код</th>
<th>Абстрактная услуга</th>
<th>Кол-во</th>
<th>Сортировка</th>
<th></th>
</tr>
</thead>
<cfoutput query="qAbstractServiceComplementary">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="abstract_service_complementary" id=#abstract_service_complementary_id# fwx=#tr.fwx#/>
</td>
<td>
<a href="abstract_service.cfm?abstract_service_id=#complementary_id#&#tr.fwx#">#request.skuCode(area_code,code)#</a>
</td>
<td>
<a href="abstract_service.cfm?abstract_service_id=#complementary_id#&#tr.fwx#">#abstract_service#</a>
</td>
<td class="c">
#quantity#
</td>
<td class="c">
#sort#
</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="abstract_service_complementary" id=#abstract_service_complementary_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
</cfif>
<!--- Добавить "дополнительна для услуг"? --->
<layout:page section="footer"/>

View File

@ -0,0 +1,200 @@
<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="plain2HtmClean">
<cfargument name="s" type="string"/>
<cfreturn request.plain2htm(request.cleanHtm(s))/>
</cffunction>
<cffunction name="cleanInput">
<cfargument name="s" type="string"/>
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="abstract_service_complementary" key="abstract_service_complementary_id" pageInfoOut="pageInfo"/>
<d:bean readonly=#!pageInfo.writePermitted()# table="#pageInfo.entity#" datasource="#request.DS#" output="d" status="status">
<d:param field="abstract_service_complementary_id" type="integer" key autoincrement/>
<d:param field="abstract_service_id" type="integer" required/>
<d:param field="complementary_id" type="integer" required/>
<d:param field="quantity" type="integer" forNull=""/>
<d:param field="sort" type="integer" forNull=""/>
<d:param field="descr" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<d:param field="updater_id" type="integer" value="#request.usr_id#" />
<d:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<d:param field="dt_updated" type="timestamp" value="#Now()#"/>
</d:bean>
<!--- <cfdump var=#form#/>
<cfdump var=#d#/> --->
<m:dispatch_detail
usePRG="No"<!---*** --->
pageInfo=#pageInfo#
id="#d.abstract_service_complementary_id#"
status=#pageInfo.status#
trackOut="tr"
idAttributesOut="id"
/>
<cfquery name="qAbstractService" datasource="#request.DS#">
select
a.abstract_service
,a.abstract_service_id
,a.code
,g.area_code
from abstract_service a
left outer join area g on (a.area_id=g.area_id)
where a.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#" null=#!isNumeric(d.abstract_service_id)#/>
</cfquery>
<!---*** Имена запросов ниже по тексту переопределяются--->
<cfquery name="qComplementary" datasource="#request.DS#">
select
a.abstract_service
,a.abstract_service_id
,a.code
,g.area_code
from abstract_service a
left outer join area g on (a.area_id=g.area_id)
where a.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.complementary_id#" null=#!isNumeric(d.complementary_id)#/>
</cfquery>
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.login as creator, a.shortname as creator_shortname, m.login as updater, m.shortname as updater_shortname
from #pageInfo.entity# e
left outer join usr a on (e.creator_id=a.usr_id)
left outer join usr m on (e.updater_id=m.usr_id)
where e.#pageInfo.key#=<cfqueryparam attributeCollection=#id#/>
</cfquery>
<!--- *** при создании не проверяется Permission --->
</m:silent><!---
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Дополнительная абстрактная услуга
<cfif d.complementary_id GT 0>
<b>#qComplementary.abstract_service#</b>
#request.skuCode(qComplementary.area_code,qComplementary.code)#
[#d.complementary_id#]
</cfif>
для абстрактной услуги
<cfif d.abstract_service_id GT 0>
<b>#qAbstractService.abstract_service#</b>
#request.skuCode(qAbstractService.area_code,qAbstractService.code)#
[#d.abstract_service_id#]
</cfif>
</cfoutput>
</layout:attribute>
</layout:page>
<cfif status.errorState GT 0>
<cfoutput><div class="err">#status.errorMessage#</div></cfoutput>
</cfif>
<cfoutput>
<input type="hidden" name="abstract_service_complementary_id" value="#d.abstract_service_complementary_id#"/>
<input type="hidden" name="abstract_service_id" value="#d.abstract_service_id#"/>
<input type="hidden" name="track" value="#tr.self#"/>
<input type="hidden" name="pass" value=""/><!--- pass marker to prevent save on submit --->
<div class="detail">
<div class="tr">
<div class="th">Абстрактная услуга</div>
<div class="td">
<a href="abstract_service.cfm?abstract_service_id=#qAbstractService.abstract_service_id#&#tr.fwx#">#qAbstractService.code# <b>#qAbstractService.abstract_service#</b> </a>
</div>
</div>
<div class="tr">
<div class="th">Дополнительная услуга</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select
a.abstract_service
,a.abstract_service_id
,a.code
,g.area_code
from abstract_service a
left outer join area g on (a.area_id=g.area_id)
where a.abstract_service_id <> <cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#"/>
<!--- AND NOT exists (select * from abstract_service_complementary sc where sc.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#"/> AND sc.complementary_id=a.complementary_id) --->
order by g.analytic_code, a.code
</cfquery>
<c:combo
query=#qList#
combo="complementary_id"
id="complementary_id"
key="abstract_service_id"
selected="#d.complementary_id#"
displayf="##request.skuCode(area_code,code)## ##abstract_service##"
empty=""
class=""
<!--- onchange="document.getElementById('param_id').selectedIndex=0; /*document.getElementById('base_price').value='';*/ --->
onchange="submit();"
/>
<cfif d.abstract_service_id GT 0>
<a href="abstract_service.cfm?abstract_service_id=#d.complementary_id#&#tr.fwx#">
<img src="img/edit.gif"/>
</a>
</cfif>
<i>Эта услуга предлагается дополнительно к основной при формировании спецификации</i>
</div>
</div>
<div class="tr">
<div class="th">Кол-во по умолчанию</div>
<div class="td">
<input type="text" name="quantity" id="quantity" value="#d.quantity#" size="2" class="r"/>
<i>В каком количестве предлагать на каждый экземпляр основной услуги</i>
</div>
</div>
<div class="tr">
<div class="th">Сортировка</div>
<div class="td">
<input type="text" name="sort" id="sort" value="#d.sort#" size="2" class="r"/>
<i>Целое число - порядок, в котором Компонент будет выводиться в составе данной услуги. Рекомендуется ставить через 100, чтобы потом удобнее было тасовать</i>
</div>
</div>
<div class="tr">
<div class="th">Описание</div>
<div class="td">
<textarea name="descr" rows="10" cols="100">#request.htm2plain(d.descr)#</textarea>
</div>
</div>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'DD.MM.YYYY')# #timeFormat(d.dt_created,'HH:MM')#
#qDecoration.creator# <cfif len(qDecoration.creator_shortname)>(#qDecoration.creator_shortname#)</cfif>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Изменено
#dateFormat(d.dt_updated,'DD.MM.YYYY')# #timeFormat(d.dt_updated,'HH:MM')#
#qDecoration.updater# <cfif len(qDecoration.updater_shortname)>(#qDecoration.updater_shortname#)</cfif>
</div>
</div>
</div>
</cfoutput>
<layout:page section="footer"/>

View File

@ -0,0 +1,72 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_detail entity="abstract_service_complementary" pageInfoOut="pageInfo"/>
<cfparam name="abstract_service_complementary_id" type="integer"/>/***use case: составное имя неоднозначно читается*/
<d:del
entity="#pageInfo.entity#"
confirmMessage="Удалить дополнительную услугу?"
denyMessage="Удаление данной дополнительной услуги невозможно (ситуация не предусмотрена)."
accessObj="#pageInfo.entity#"
status="status"
output="markup">
<d:del_condition field="abstract_service_complementary_id" value="#abstract_service_complementary_id#" cfsqltype="cf_sql_integer"/>
</d:del>
<m:dispatch_detail
usePRG="Yes"
pageInfo=#pageInfo#
id="#abstract_service_complementary_id#"
status=#status#
trackOut="tr"
idAttributesOut="id"
/>
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.abstract_service
,c.abstract_service as complementary_service
,a.abstract_service_id
,c.abstract_service_id as complementary_id
,a.code
,c.code as complementary_code
,g.area_code
,gc.area_code as complementary_area_code
from abstract_service_complementary cs
left outer join abstract_service a on (cs.abstract_service_id=a.abstract_service_id)
left outer join area g on (a.area_id=g.area_id)
left outer join abstract_service c on (cs.complementary_id=c.abstract_service_id)
left outer join area gc on (c.area_id=gc.area_id)
where cs.abstract_service_complementary_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#abstract_service_complementary_id#" null=#!isNumeric(d.abstract_service_complementary_id)#/>
</cfquery>
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Удаление дополнительной абстрактной услуги
#qDecoration.complementary_service#
#request.skuCode(qDecoration.complementary_area_code, qDecoration.complementary_code)#
[#abstract_service_complementary_id#]
для абстрактной услуги
#qDecoration.complementary_service#
#request.skuCode(qDecoration.area_code, qDecoration.code)#
</cfoutput>
</layout:attribute>
<layout:attribute name="controls">&nbsp;</layout:attribute>
</layout:page>
<cfoutput>#markup#</cfoutput>
<layout:page section="footer"/>

69
abstract_service_del.cfm Normal file
View File

@ -0,0 +1,69 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_detail entity="abstract_service" pageInfoOut="pageInfo"/>
<cfparam name="abstract_service_id" type="integer"/>
<d:del
entity="#pageInfo.entity#"
confirmMessage="Удалить абстрактную услугу?"
denyMessage="Удаление данной абстрактной услуги невозможно (есть конкретные услуги)."
accessObj="#pageInfo.entity#"
status="status"
output="markup">
<d:dependency entity="service" title="Конкретные услуги">
<d:dependency_field key>s.service_id</d:dependency_field>
<d:dependency_field title="Характеристика">m.modifier</d:dependency_field>
<d:dependency_from>
service s
left outer join modifier m on (s.modifier_id=m.modifier_id)
</d:dependency_from>
<d:dependency_condition cfsqltype="cf_sql_integer" value='#abstract_service_id#'>s.abstract_service_id</d:dependency_condition>
<d:dependency_order_by>2 desc</d:dependency_order_by>
</d:dependency>
<d:del_condition field="abstract_service_id" value="#abstract_service_id#" cfsqltype="cf_sql_integer"/>
</d:del>
<m:dispatch_detail
usePRG="Yes"
pageInfo=#pageInfo#
id="#abstract_service_id#"
status=#status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<cfquery name="qDecoration" datasource="#request.DS#">
select a.code, a.abstract_service
FROM abstract_service a
where a.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#abstract_service_id#" null=#!isValid("integer", abstract_service_id)#/>
</cfquery>
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Удаление абстрактной услуги (номенклатурной позиции, строки каталога услуг)
#qDecoration.abstract_service#
<cfif abstract_service_id GT 0>
[#abstract_service_id#]
</cfif>
</cfoutput>
</layout:attribute>
<layout:attribute name="controls">&nbsp;</layout:attribute>
</layout:page>
<!---<cfdump var=#qDecoration#/>--->
<cfoutput>#markup#</cfoutput>
<layout:page section="footer"/>

136
abstract_service_filter.cfm Normal file
View File

@ -0,0 +1,136 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_filter entity="abstract_service" pageInfoOut="pageInfo" trackOut="tr"/>
<m:filter_settings target="#pageInfo.entity#_ls">
<!--- <m:filterparam filter=#filter# param="service_type_id" ftype="numeric" compare="EQ" field="a.service_type_id" default=""/> --->
<m:filterparam filter=#filter# param="abstract_service" ftype="string" compare="LIKE%" field="a.abstract_service" default=""/>
<m:filterparam filter=#filter# param="code" ftype="string" compare="LIKE%" field="a.code" default=""/>
<!---<m:filterparam filter=#filter# param="area_id" ftype="numeric" compare="EQ" field="a.area_id" default=""/>--->
<m:filterparam filter=#filter# param="area_id_list" ftype="numeric" list="Yes" expression="(a.area_id in (?))" default=""/>
<m:filterparam filter=#filter# param="area" ftype="string" compare="LIKE%" field="g.area" default=""/>
<m:filterparam filter=#filter# param="area_code" ftype="string" compare="LIKE%" field="g.area_code" default=""/>
<!--- <m:filterparam filter=#filter# param="payment_periodicity_id" ftype="numeric" compare="EQ" field="b.payment_periodicity_id" default=""/> --->
<m:filterparam filter=#filter# param="status_id" ftype="numeric" compare="EQ" field="a.status_id" default=""/>
</m:filter_settings>
<cfif isDefined("resetAndClose") or isDefined("saveAndClose")>
<cflocation url="#tr.backUrl#" addtoken="No"/>
</cfif>
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title"><cfoutput>Каталог услуг - фильтр</cfoutput></layout:attribute>
</layout:page>
<!---<script type="text/javascript"/>
$(document).ready(function() {
try {
$("#customer_id").searchable({maxMultiMatch: 50});
$("#service_manager_id").searchable({maxMultiMatch: 50});
} catch (e) {alert(e)}
});
</script>--->
<cfoutput>
<input type="hidden" name="track" value="#tr.self#"/>
<div class="detail">
<div class="tr">
<div class="th"></div>
<div class="td">
<button type="button" name="reset" onClick="document.location.href='#request.thisPage#?reset=yes&track=#tr.self#'">#i18("Очистить","Clear")#</button>
</div>
</div>
<div class="tr">
<div class="th">#i18("Номенклатура","Service")#</div>
<div class="td">
<input type="text" name="abstract_service" value="#abstract_service#" size="50"/>
<i>#i18("по вхождению подстроки","by substring")#</i>
</div>
</div>
<div class="tr">
<div class="th">#i18("Код услуги","Service Code")#</div>
<div class="td">
<input type="text" name="code" value="#code#" size="20"/>
<i>#i18("по вхождению подстроки","by substring")#</i>
</div>
</div>
<div class="tr">
<div class="th">#i18("Статус","Status")#</div>
<div class="td" style="vertical-align:top;">
<cfquery name="qStatus" datasource="#request.DS#">
select status_id, status
from status
order by status_id
</cfquery>
<c:combo
query=#qStatus#
combo="status_id"
id="status_id"
key="status_id"
displayf="##status##"
selected=#status_id#
empty=""
/>
</div>
</div>
<div class="tr">
<div class="th">#i18("Группа каталога","Catalog Group")#</div>
<div class="td" style="vertical-align:top;">
<cfquery name="qArea" datasource="#request.DS#">
select g.area_id, g.area, g.area_code
from area g
order by g.area_code
</cfquery>
<c:combo
query=#qArea#
combo="area_id_list"
id="area_id"
key="area_id"
displayf="##area_code## ##area##"
selected=#area_id_list#
empty=""
multiple="multiple"
size="7"
/>
<div style="display:inline-block; vertical-align:top; line-height:2em;">
#i18("Код","Code")#
<input type="text" name="area_code" value="#area_code#" size="10"/>
<br/>
#i18("Группа","Group")#
<input type="text" name="area" value="#area#" size="20"/>
<br/>
<i>#i18("по вхождению подстроки","by substring")#</i>
</div>
</div>
</div>
</div><!--- detail --->
</cfoutput>
<layout:page section="footer" closeForm="Yes"/>
<!--- <cfdump var=#filter#> --->

164
abstract_service_ls.cfm Normal file
View File

@ -0,0 +1,164 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_ls entity="abstract_service" 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.abstract_service_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_INTEGER">a.abstract_service_id</d:field>
<d:field title="Код группы">g.area_code</d:field>
<d:field title="Группа">g.analytic_code</d:field>
<d:field title="Группа">g.area</d:field>
<d:field>a.area_id</d:field>
<d:field title="Номенклатура (RUS)">a.abstract_service</d:field>
<d:field title="Номенклатура (ENG)">a.abstract_service_en</d:field>
<d:field title="Код">a.code</d:field>/***use case: составное поле. А как сортировать*/
<d:field title="Статус">a.status_id</d:field>
<d:field title="Статус">s.status</d:field>
<d:field title="Ед. изм.">m.measure</d:field>
<d:field title="Ед. изм.">m.measure_short</d:field>
<d:field title="Ответственный">a.manager_id</d:field>
<d:field title="">u.login</d:field>
<d:field title="">u.firstname</d:field>
<d:field title="">u.middlename</d:field>
<d:field title="Ответственный">u.lastname</d:field>
<d:field title="Email ответственного">u.email</d:field>
<d:field title="">a.descr</d:field>
<d:field title="Коммерческие примечания">a.commercial_note</d:field>
<!--- <d:field title="Провайдер" cfSqlType="CF_SQL_INTEGER">(select count(*) from abstract_service_provider sp where sp.abstract_service_id=a.abstract_service_id) as provider_count</d:field> --->
<!---https://habr.com/ru/post/200120/--->
<!---<d:field title="Провайдеры">
/*MSSQL*/STUFF(CAST((
select [text()] = ', ' || "provider"
from abstract_service_provider sp
join provider p on (sp.provider_id=p.provider_id)
where sp.abstract_service_id=a.abstract_service_id
FOR XML PATH(''), TYPE) AS VARCHAR(MAX)), 1, 2, '')
as providers
</d:field>--->
<!--- <d:field title="Провайдеры">
/*PostgreSQL*/(select STRING_AGG(p.provider,', ')
from abstract_service_provider sp
join provider p on (sp.provider_id=p.provider_id)
where sp.abstract_service_id=a.abstract_service_id
)as providers
</d:field> --->
<!---<d:field title="Периодичность">p.payment_periodicity</d:field>--->
<d:field title="Компон.">(select count(*) from abstract_service_param_class ac where ac.abstract_service_id=a.abstract_service_id) as param_count</d:field>
<d:field title="Класс характеристики">c.modifier_class</d:field>
<d:field>a.modifier_class_id</d:field>
<d:field title="Вариан." cfSqlType="CF_SQL_INTEGER">(select count(*) from service s where s.abstract_service_id=a.abstract_service_id) as service_count</d:field>
<d:field title="Доп.усл.">(select count(*) from abstract_service_complementary ac where ac.abstract_service_id=a.abstract_service_id) as complementary_count</d:field>
<d:field title="Документов" cfSqlType="CF_SQL_INTEGER">(select count(*) from abstract_service_doc d where d.abstract_service_id=a.abstract_service_id) as doc_count</d:field>
</d:field_set>
from abstract_service a
left outer join modifier_class c on (a.modifier_class_id=c.modifier_class_id)
left outer join area g on (a.area_id=g.area_id)
left outer join measure m on (a.measure_id=m.measure_id)
left outer join status s on (a.status_id=s.status_id)
left outer join usr u on (a.manager_id=u.usr_id)
<!---left outer join payment_periodicity p on (b.payment_periodicity_id=p.payment_periodicity_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">
<cfrethrow/>
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
</cfcatch>
</cftry>
<cfquery name="qCountTotal" datasource="#request.DS#">
select count(*) as cnt from abstract_service 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:page>
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
<layout:grid_summary
recordCount=#qRead.recordCount#
totalCount=#qCountTotal.cnt#
footerOut="gridFooter"
excelLink="Yes"
jsonLink="Yes"
/>
<table class="worktable">
<thead>
<layout:grid_head titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray#>
<th width="1%">
<c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/>
</th>
<th width="1%"></th>
<th width="7%"><layout:column_head name="analytic_code"/></th>
<th width="2%"><layout:column_head name="code"/></th>
<th width="15%"><layout:column_head name="abstract_service"/></th>
<th width="3%"><layout:column_head name="measure_short"/></th>
<th width="2%"><layout:column_head name="param_count"/></th>
<th width="15%"><layout:column_head name="modifier_class"/></th>
<th width="2%"><layout:column_head name="service_count"/></th>
<th width="2%"><layout:column_head name="complementary_count"/></th>
<th width="2%"><layout:column_head name="lastname"/></th>
<th width="3%"><layout:column_head name="status"/></th>
<th width="1%"></th>
</layout:grid_head>
</thead>
<cfoutput query="qRead" maxrows=#pageInfo.recordsPerPage# startrow=#pageInfo.nStart#>
<tr>
<td class="c">
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# id=#qRead[pageInfo.entity&'_id'][currentRow]# fwx=#tr.fwx#/>
</td>
<td class="c"><cfif doc_count GT 0><img src="img/paperclip.gif" title="#doc_count# док."/></cfif></td>
<td><a href="area.cfm?area_id=#area_id#&#tr.fwx#">#analytic_code# #area#</a></td>
<td>#request.skuCode(area_code,code)#</td>
<td><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">#abstract_service#</a></td>
<td class="c">#measure_short#</td>
<td class="c"><cfif param_count GT 0>#param_count#</cfif></td>
<td><a href="modifier_class.cfm?modifier_class_id=#modifier_class_id#&#tr.fwx#">#modifier_class#</a></td>
<td class="c"><cfif service_count GT 0>#service_count#</cfif></td>
<td class="c"><cfif complementary_count GT 0>#complementary_count#</cfif></td>
<td class="c"><cfif manager_id GT 0><a href="mailto:#email#">#lastname# #firstname# #middlename#</a></cfif></td>
<td>#status#</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# id=#qRead[pageInfo.entity&'_id'][currentRow]# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>

View File

@ -0,0 +1,277 @@
<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="plain2HtmClean">
<cfargument name="s" type="string"/>
<cfreturn request.plain2htm(request.cleanHtm(s))/>
</cffunction>
<cffunction name="cleanInput">
<cfargument name="s" type="string"/>
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="abstract_service_param_class" key="abstract_service_param_class_id" pageInfoOut="pageInfo"/>
<d:bean readonly=#!pageInfo.writePermitted()# table="#pageInfo.entity#" datasource="#request.DS#" output="d" status="status">
<d:param field="abstract_service_param_class_id" type="integer" key autoincrement/>
<d:param field="abstract_service_id" type="integer" required/>
<d:param field="param_class_id" type="integer" forNull=""/>
<d:param field="is_multiple" type="bit" init="0" default="0"/>
<d:param field="sort" type="integer" forNull=""/>
<d:param field="descr" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<d:param field="updater_id" type="integer" value="#request.usr_id#" />
<d:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<d:param field="dt_updated" type="timestamp" value="#Now()#"/>
</d:bean>
<!--- <cfdump var=#form#/>
<cfdump var=#d#/> --->
<m:dispatch_detail
usePRG="No"<!---*** --->
pageInfo=#pageInfo#
id="#d.abstract_service_param_class_id#"
status=#pageInfo.status#
trackOut="tr"
idAttributesOut="id"
/>
<cfquery name="qAbstractService" datasource="#request.DS#">
select
a.abstract_service
,a.abstract_service_id
,a.code
from abstract_service a
where a.abstract_service_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_id#" null=#!isNumeric(d.abstract_service_id)#/>
</cfquery>
<!---*** Имена запросов ниже по тексту переопределяются--->
<cfquery name="qParamClass" datasource="#request.DS#">
select p.param_class, m.measure_id, m.measure
from param_class p
left outer join measure m on m.measure_id=p.measure_id
where param_class_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.param_class_id#" null=#!isNumeric(d.param_class_id)#/>
</cfquery>
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.login as creator, a.shortname as creator_shortname, m.login as updater, m.shortname as updater_shortname
from #pageInfo.entity# e
left outer join usr a on (e.creator_id=a.usr_id)
left outer join usr m on (e.updater_id=m.usr_id)
where e.#pageInfo.key#=<cfqueryparam attributeCollection=#id#/>
</cfquery>
</m:silent><!---
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Компонент [#d.abstract_service_param_class_id#]
<cfif d.param_class_id GT 0>
<b>#qParamClass.param_class#</b> [#d.param_class_id#]
</cfif>
абстрактной услуги
<cfif d.abstract_service_id GT 0>
<b>#qAbstractService.abstract_service#</b> [#d.abstract_service_id#]
</cfif>
</cfoutput>
</layout:attribute>
</layout:page>
<cfif status.errorState GT 0>
<cfoutput><div class="err">#status.errorMessage#</div></cfoutput>
</cfif>
<cfoutput>
<input type="hidden" name="abstract_service_param_class_id" value="#d.abstract_service_param_class_id#"/>
<input type="hidden" name="abstract_service_id" value="#d.abstract_service_id#"/>
<!--- <input type="hidden" name="param_class_id" value="#d.param_class_id#"/> --->
<input type="hidden" name="track" value="#tr.self#"/>
<input type="hidden" name="pass" value=""/><!--- pass marker to prevent save on submit --->
<div class="detail">
<div class="tr">
<div class="th">Абстрактная услуга</div>
<div class="td">
<a href="abstract_service.cfm?abstract_service_id=#qAbstractService.abstract_service_id#&#tr.fwx#">#qAbstractService.code# <b>#qAbstractService.abstract_service#</b> </a>
</div>
</div>
<div class="tr">
<div class="th">Компонент</div>
<div class="td">
<cfquery name="qList" datasource="#request.DS#">
select c.param_class_id, c.param_class, m.measure_short
from param_class c
left outer join measure m on (c.measure_id=m.measure_id)
order by 2
</cfquery>
<c:combo
query=#qList#
combo="param_class_id"
id="param_class_id"
key="param_class_id"
selected="#d.param_class_id#"
displayf="##param_class## ##measure_short##"
empty=""
class=""
<!--- onchange="documen t.getElementById('param_id').selectedIndex=0; /*document.getElementById('base_price').value='';*/ --->
onchange="submit();"
/>
<cfif d.param_class_id GT 0>
<a href="param_class.cfm?param_class_id=#d.param_class_id#&#tr.fwx#">
<img src="img/edit.gif"/>
</a>
</cfif>
<a href="param_class.cfm?param_class_id=-1&#tr.fwx#">
<img src="img/add.gif"/>
</a>
<cfif d.param_class_id GT 0>
Единица измерения:
<b><cfif qParamClass.measure_id GT 0>#qParamClass.measure#<cfelse>(нет)</cfif></b>
</cfif>
<i>Вариант компонента либо фиксируется в варианте услуги, либо выбирается при формировании спецификации</i>
</div>
</div>
<div class="tr">
<div class="th">Множественный</div>
<div class="td">
<input type="checkbox" name="is_multiple" id="is_multiple" value="1"<cfif d.is_multiple> checked</cfif> />
<i>Если отметка стоит, то для экземпляра услуги можно выбирать несколько вариантов компонента, например, несколько типов диска</i>
</div>
</div>
<div class="tr">
<div class="th">Сортировка</div>
<div class="td">
<input type="text" name="sort" id="sort" value="#d.sort#" size="2"/>
<i>Целое число - порядок, в котором Компонент будет выводиться в составе данной услуги. Рекомендуется ставить через 100, чтобы потом удобнее было тасовать</i>
</div>
</div>
<div class="tr">
<div class="th">Описание</div>
<div class="td">
<textarea name="descr" rows="10" cols="100">#request.htm2plain(d.descr)#</textarea>
</div>
</div>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'DD.MM.YYYY')# #timeFormat(d.dt_created,'HH:MM')#
#qDecoration.creator# <cfif len(qDecoration.creator_shortname)>(#qDecoration.creator_shortname#)</cfif>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Изменено
#dateFormat(d.dt_updated,'DD.MM.YYYY')# #timeFormat(d.dt_updated,'HH:MM')#
#qDecoration.updater# <cfif len(qDecoration.updater_shortname)>(#qDecoration.updater_shortname#)</cfif>
</div>
</div>
</div>
Это шаблон для компонента экземпляра услуги (строки спецификации). Если в компонентах услуги определен Компонент, а не конкретный вариант компонента, то нужно присвоить цены всем компонентам этого класса, которые актуальны для данной услуги. Это требуется не только для назначения цен, но и для ограничения списка возможных вариантов выбора компонента для данной услуги. *** Может быть, вместо "компонент" нужно ввести термин "тип компонента", потому что это не экземпляр. Например, Компонент - дисковое пространство, а компонент - дисковое пространство SSD, это уточнение класса компонента, но не конкретный объем на конкретном СХД, и даже не конкретная дисковая квота в рамках контракта (спецификации)
<br/>
</cfoutput>
<layout:page section="extension" closeForm="Yes"/>
<cfif d.abstract_service_param_class_id GT 0>
<h4>Реализации (конкретные параметры вариантов услуг), использующих данный компонент</h4>
<cfquery name="qServiceParam" datasource="#request.DS#">
select
ac.abstract_service_param_class_id
,g.area_code
,s.abstract_service_id
,s.service_id
,a.abstract_service
,a.code
,sp.service_param_id
,ac.param_class_id
,pc.param_class
,p.param_id
,p.param
,p.code as param_code
,p.sort
,s.modifier_id /*всегда берем ключ от той таблицы, к которой присоединяем - если нарушена ссылка, останется больше информации*/
,m.modifier
,a.modifier_class_id
,mc.modifier_class
,m.code as modifier_code
,u.measure_short
from abstract_service_param_class ac
left outer join param_class pc on (ac.param_class_id=pc.param_class_id)
left outer join service_param sp on (ac.abstract_service_param_class_id=sp.abstract_service_param_class_id)
left outer join param p on (ac.param_class_id=p.param_class_id AND sp.param_id=p.param_id)/***условие выглядит избыточно жестким, сразу из класса и экземпляра, а зачем*/
left outer join service s on (sp.service_id=s.service_id)
left outer join abstract_service a on (s.abstract_service_id=a.abstract_service_id) /*** тут снова развилка, можно взять из шаблона, а можно из экземпляра... нельзя ли устранить неоднозначность*/
left outer join area g on (a.area_id=g.area_id)
left outer join modifier m on (s.modifier_id=m.modifier_id)
/*** тут еще можно присоединить класс модификатора, и тоже варианты - из шаблона или экземпляра... но экземпляр бывает пустым*/
left outer join modifier_class mc on (mc.modifier_class_id=m.modifier_class_id) /*кажется, в данном случае правильно по шаблону*/
left outer join measure u on (pc.measure_id=u.measure_id)/***единица измерения из класса может быть переопределена - может, здесь вообще без нее обойтись... цены-то нет. А в цене единица должна быть зафиксирована*/
where ac.abstract_service_param_class_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.abstract_service_param_class_id#"/>
order by p.sort, ac.abstract_service_param_class_id
</cfquery>
<!---<cfdump var=#qServiceParam#/>--->
<cfoutput>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th></th>
<th>ID</th>
<th>Вариант услуги</th>
<th>Код</th>
<th>Компонент</th>
<th>Ед.изм.</th>
<th>Сортировка</th>
</tr>
</thead>
<cfoutput query="qServiceParam">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="service_param" id=#service_param_id# fwx=#tr.fwx#/>
</td>
<td>#service_param_id#</td>
<td><a href="service.cfm?service_id=#service_id#&#tr.fwx#">#abstract_service# #modifier#</a></td>
<td>
<a href="service_param.cfm?service_param_id=#service_param_id#&#tr.fwx#"/>#request.skuCode(area_code, code, modifier_code, param_code)#</a>
</td>
<td>
<cfif param_id GT 0><a href="param_class.cfm?param_class_id=#param_class_id#&#tr.fwx#">#param_class#</a><cfif len(param)>: <a href="param.cfm?param_id=#param_id#&#tr.fwx#">#param#</a></cfif></cfif>
</td>
<td class="c">#measure_short#</td>
<td class="c">#sort#</td>
</tr>
</cfoutput>
</table>
<!---
При формировании спецификации доступны только компоненты (компоненты, параметры), для которых указаны базовые цены. Термин не вполне корректный, точнее было бы - вариант компонента.
--->
</cfif>
<layout:page section="footer"/>

View File

@ -0,0 +1,90 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_detail entity="abstract_service_param_class" pageInfoOut="pageInfo"/>
<cfparam name="abstract_service_param_class_id" type="integer"/><!--- /***use case: составное имя неоднозначно читается*/ --->
<d:del
entity="#pageInfo.entity#"
confirmMessage="Удалить компонент абстрактной услуги?"
denyMessage="Удаление данного компонента невозможно (существуют зависимые объекты)."
accessObj="#pageInfo.entity#"
status="status"
output="markup">
<!---*** эту же зависимость можно построить по составному ключу? --->
<d:dependency entity="service_param" title="Параметры конкретных услуг">
<d:dependency_field key>service_param_id</d:dependency_field>
<d:dependency_field title="Код">a.code</d:dependency_field>
<d:dependency_field title="Абстрактная услуга">a.abstract_service</d:dependency_field>
<d:dependency_field title="Класс характеристики">c.modifier_class</d:dependency_field>
<d:dependency_field title="Характеристика">m.modifier</d:dependency_field>
<d:dependency_field title="Компонент">pc.param_class</d:dependency_field>
<d:dependency_field title="Компонент">p.param</d:dependency_field>
<d:dependency_from>
service_param sp
left outer join service s on (sp.service_id=s.service_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 c on (m.modifier_class_id=c.modifier_class_id)
left outer join param p on (sp.param_id=p.param_id)
left outer join param_class pc on (p.param_class_id=pc.param_class_id)
</d:dependency_from>
<d:dependency_condition cfsqltype="cf_sql_integer" value='#abstract_service_param_class_id#'>sp.abstract_service_param_class_id</d:dependency_condition>
<d:dependency_order_by>1 desc</d:dependency_order_by>
</d:dependency>
<d:del_condition field="abstract_service_param_class_id" value="#abstract_service_param_class_id#" cfsqltype="cf_sql_integer"/>
</d:del>
<m:dispatch_detail
usePRG="Yes"
pageInfo=#pageInfo#
id="#abstract_service_param_class_id#"
status=#status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<cfquery name="qDecoration" datasource="#request.DS#">
select
ac.abstract_service_id, a.abstract_service, a.code
,g.area, g.area_code, g.analytic_code
,ac.param_class_id, c.param_class
FROM abstract_service_param_class ac
left outer join abstract_service a on (ac.abstract_service_id=a.abstract_service_id)
left outer join area g on (ac.abstract_service_id=a.abstract_service_id)
left outer join param_class c on (ac.param_class_id=c.param_class_id)
where ac.abstract_service_param_class_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#abstract_service_param_class_id#" null=#!isValid("integer", abstract_service_param_class_id)#/>
</cfquery>
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Удаление компонента абстрактной услуги
#qDecoration.abstract_service#
(#qDecoration.code#)
#qDecoration.param_class#
<cfif abstract_service_param_class_id GT 0>
[#abstract_service_param_class_id#]
</cfif>
</cfoutput>
</layout:attribute>
<layout:attribute name="controls">&nbsp;</layout:attribute>
</layout:page>
<!---<cfdump var=#qDecoration#/>--->
<!--- <i>компонент абстрактной услуги - это (абстрактный) компонент. У конкретной услуги - конкретные компоненты (варианты), у абстрактной услуги - классы параметров</i> --->
<cfoutput>#markup#</cfoutput>
<layout:page section="footer"/>

270
abstract_service_rpt.cfm Normal file
View File

@ -0,0 +1,270 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_ls entity="abstract_service" accessObject="abstract_service_rpt" 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.abstract_service_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_INTEGER">a.abstract_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="Catalog Group">g.area_en</d:field>
<d:field title="Статус">u.status</d:field>
<d:field title="Status">u.status_en</d:field>
<d:field title=#i18("Код услуги","Service Code")#>a.code</d:field>
<d:field title=#i18("Номенклатура (RUS)","Service (RUS)")#>a.abstract_service</d:field>
<d:field title=#i18("Номенклатура (ENG)","Service (ENG)")#>a.abstract_service_en</d:field>
<d:field title="Ед.изм.">m.measure_short</d:field>
<d:field title="Measure">m.measure_short_en</d:field>
<d:field title="Провайдер" cfSqlType="CF_SQL_INTEGER">(select count(*) from abstract_service_provider sp where sp.abstract_service_id=a.abstract_service_id) as provider_count</d:field>
<d:field title="Провайдеры">
CAST(
(
select coalesce(p.provider,'') as provider /*null does not produce an attribute*/
from abstract_service_provider sp
join provider p on (sp.provider_id=p.provider_id)
where sp.abstract_service_id=a.abstract_service_id
FOR XML AUTO, TYPE, ROOT('providers')
)
AS VARCHAR(MAX))
as providers
</d:field>
<d:field title="Providers">
CAST(
(
select coalesce(p.provider_en, '') as provider /*NB!*/
from abstract_service_provider sp
join provider p on (sp.provider_id=p.provider_id)
where sp.abstract_service_id=a.abstract_service_id
FOR XML AUTO, TYPE, ROOT('providers')
)
AS VARCHAR(MAX))
as providers_en
</d:field>
<d:field title="Периодичность">p.payment_periodicity</d:field>
<d:field title="Periodicity">p.payment_periodicity_en</d:field>
<d:field title=#i18("Код","Code")#>b.budget_code</d:field>
<d:field title="Бюджетная статья">b.budget</d:field>
<d:field title="Budget Item">b.budget_en</d:field>
<d:field title="Тип">st.service_type</d:field>
<d:field title="Type">st.service_type_en</d:field>
<d:field title=#i18("Класс характеристики","Characteristic class")#>mc.modifier_class</d:field>
<d:field title=#i18("Вариантов","Variants")# cfSqlType="CF_SQL_INTEGER">(select count(*) from service s where s.abstract_service_id=a.abstract_service_id) as service_count</d:field>
<d:field title=#i18("Документы","Documents")# cfSqlType="CF_SQL_INTEGER">(select count(*) from abstract_service_doc d where d.abstract_service_id=a.abstract_service_id) as doc_count</d:field>
<d:field title=#i18("Документы","Documents")# >
CAST(
(
select abstract_service_doc_id, abstract_service_doc, fname, contenttype, dt_created
from abstract_service_doc d
where d.abstract_service_id=a.abstract_service_id
FOR XML AUTO, TYPE, ROOT('docs')
)
AS VARCHAR(MAX))
as docs
</d:field>
</d:field_set>
from abstract_service a
join service_type st on (a.service_type_id=st.service_type_id)
join status u on (a.status_id=u.status_id)
left outer join modifier_class mc on (a.modifier_class_id=mc.modifier_class_id)
left outer join area g on (a.area_id=g.area_id)
left outer join budget b on (a.budget_id=b.budget_id)
left outer join measure m on (a.measure_id=m.measure_id)
left outer join payment_periodicity p on (b.payment_periodicity_id=p.payment_periodicity_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 abstract_service 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>#i18("Каталог","Catalog")#</b> </cfoutput>
</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"
/>
<cffunction name="formatProviders" output="true">
<cfargument name="providers"/>
<cfif len(ARGUMENTS.providers)>
<cftry>
<cfset providerCollection=xmlParse(ARGUMENTS.providers)/>
<cfloop array=#providerCollection.providers.XmlChildren# index="d">
<p style="margin:.5em 0;">
#d.XmlAttributes.provider#
</p>
</cfloop>
<cfcatch type="ANY">#cfcatch.message# #cfcatch.detail#</cfcatch>
</cftry>
</cfif>
</cffunction>
<cfset request.formatProviders=formatProviders/>
<!---NB CALLER.tr.fwx! --->
<cffunction name="formatDocs" output="true">
<cfargument name="docs"/>
<cfif len(docs)>
<cftry>
<cfset docsCollection=xmlParse(docs)/><!---<cfdump var=#docsCollection#/>--->
<cfloop array=#docsCollection.docs.XmlChildren# index="d"> <!---<cfdump var=#d.XmlAttributes#/>--->
<p style="line-height:1.8em;">
<a href="doc_get.cfm?entity=abstract_service&doc_id=#d.XmlAttributes.abstract_service_doc_id#" title="открыть (#d.XmlAttributes.contenttype#)" target="_blank">
<m:contenttype_icon contenttype=#d.XmlAttributes.contenttype#/>
</a>
<a href="doc.cfm?entity=abstract_service&doc_id=#d.XmlAttributes.abstract_service_doc_id#&#CALLER.tr.fwx#" title="редактировать атрибуты"><cfif len(d.XmlAttributes.abstract_service_doc)>#d.XmlAttributes.abstract_service_doc#<cfelse>#d.XmlAttributes.abstract_fname#</cfif> (#dateFormat(d.XmlAttributes.dt_created,'DD.MM.YYYY')#)</a>
</p>
</cfloop>
<cfcatch type="ANY">#cfcatch.message# #cfcatch.detail#</cfcatch>
</cftry>
</cfif>
</cffunction>
<cfset request.formatDocs=formatDocs/>
<!---*** очень осторожно: используется Dynamic Evaluation! --->
<c:table query=#qRead# recordsPerPage=#pageInfo.recordsPerPage# nStart=#pageInfo.nStart# titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray# class="worktable wide">
<c:column width="1%" field="area_code"/>
<c:column width="5%" field="area" lang="ru"/><c:column width="5%" field="area_en" lang="en"/>
<c:column width="3%" field="status" lang="ru"/><c:column width="3%" field="status_en" lang="en"/>
<c:column width="3%" field="service_type" lang="ru"/><c:column width="3%" field="service_type_en" lang="en"/>
<c:column width="15%" field="abstract_service"><c:td><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#CALLER.tr.fwx#">#abstract_service#</a></c:td></c:column>
<c:column width="15%" field="abstract_service_en"><c:td><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#CALLER.tr.fwx#">#abstract_service_en#</a></c:td></c:column>
<c:column width="5%" field="code"><c:td><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#CALLER.tr.fwx#">#code#</a></c:td></c:column>
<c:column width="2%" field="measure_short" lang="ru"/><c:column width="2%" field="measure_short_en" lang="en"/>
<c:column width="15%" field="provider_count" lang="ru">
<c:th>Провайдеры</c:th>
<c:td>#request.formatProviders(providers)#<!---<pre>#replace(replace(providers,'<','&lt;', 'ALL'),'>','&gt;', 'ALL')#</pre>---></c:td>
</c:column>
<c:column width="15%" field="provider_count" lang="en">
<c:th>Providers</c:th>
<c:td>#request.formatProviders(providers_en)#<!---<pre>#replace(replace(providers_en,'<','&lt;', 'ALL'),'>','&gt;', 'ALL')#</pre>---></c:td>
</c:column>
<c:column width="20%" field="doc_count">
<c:td>#request.formatDocs(docs)#</c:td>
</c:column>
</c:table>
<!--- <table class="worktable">
<thead>
<layout:grid_head titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray#>
<th width="1%"></th>
<th width="3%"><layout:column_head name="area_code"/></th>
<th width="10%"><layout:column_head name="area"/></th>
<th width="3%"><layout:column_head name="status"/></th>
<th width="5%"><layout:column_head name="service_type"/></th>
<th width="10%"><layout:column_head name="abstract_service"/></th>
<th width="2%"><layout:column_head name="code"/></th>
<th width="2%"><layout:column_head name="measure_short"/></th>
<th width="5%"><layout:column_head name="provider_count"/></th>
<th width="15%"><layout:column_head name="doc_count"/></th>
</layout:grid_head>
</thead>
<cfoutput query="qRead" maxrows=#pageInfo.recordsPerPage# startrow=#pageInfo.nStart#>
<tr>
<td class="c">
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# id=#qRead[pageInfo.entity&'_id'][currentRow]# fwx=#tr.fwx#/>
</td>
<td>#area_code#</td>
<td>#area#</td>
<td>#status#</td>
<td class="c">#service_type#</td>
<td>#abstract_service#</td>
<td>#code#</td>
<td class="c">#measure_short#</td>
<td>
<cfif len(providers)>
<cftry>
<cfset providerCollection=xmlParse(providers)/>
<cfloop array=#providerCollection.providers.XmlChildren# index="d">
<p style="margin:.5em 0;">
#d.XmlAttributes.provider#
</p>
</cfloop>
<cfcatch type="ANY">#cfcatch.message# #cfcatch.detail#</cfcatch>
</cftry>
</cfif>
</td>
<td>
<cfif len(docs)>
<cftry>
<cfset docsCollection=xmlParse(docs)/>
<cfloop array=#docsCollection.docs.XmlChildren# index="d">
<p style="line-height:1.8em;">
<a href="doc_get.cfm?entity=abstract_service&doc_id=#d.XmlAttributes.abstract_service_doc_id#" title="открыть (#d.XmlAttributes.contenttype#)" target="_blank">
<m:contenttype_icon contenttype=#d.XmlAttributes.contenttype#/>
</a>
<a href="doc.cfm?entity=abstract_service&doc_id=#d.XmlAttributes.abstract_service_doc_id#&#tr.fwx#" title="редактировать атрибуты"><cfif len(d.XmlAttributes.abstract_service_doc)>#d.XmlAttributes.abstract_service_doc#<cfelse>#d.XmlAttributes.abstract_fname#</cfif> (#dateFormat(d.XmlAttributes.dt_created,'DD.MM.YYYY')#)</a>
</p>
</cfloop>
<cfcatch type="ANY">#cfcatch.message# #cfcatch.detail#</cfcatch>
</cftry>
</cfif>
</td>
</tr>
</cfoutput>
</table>--->
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>

200
area.cfm Normal file
View File

@ -0,0 +1,200 @@
<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="plain2HtmClean">
<cfargument name="s" type="string"/>
<cfreturn request.plain2htm(request.cleanHtm(s))/>
</cffunction>
<cffunction name="cleanInput">
<cfargument name="s" type="string"/>
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="area" key="area_id" pageInfoOut="pageInfo"/>
<d:bean readonly=#!pageInfo.writePermitted()# table="area" datasource="#request.DS#" output="d" status="status">
<d:param field="area_id" type="integer" key autoincrement/>
<d:param field="area_code" type="varchar" size="31" preprocessor=#cleanInput#/>
<d:param field="analytic_code" type="varchar" size="31" preprocessor=#cleanInput#/>
<d:param field="area" type="varchar" size="255" preprocessor=#cleanInput#/>
<d:param field="area_en" type="varchar" size="255" preprocessor=#cleanInput#/>
<d:param field="descr" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<d:param field="updater_id" type="integer" value="#request.usr_id#" />
<d:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<d:param field="dt_updated" type="timestamp" value="#Now()#"/>
</d:bean>
<m:dispatch_detail
usePRG="No"<!---*** --->
pageInfo=#pageInfo#
id="#d.area_id#"
status=#pageInfo.status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.login as creator, a.shortname as creator_shortname, m.login as updater, m.shortname as updater_shortname
from area g
left outer join usr a on (g.creator_id=a.usr_id)
left outer join usr m on (g.updater_id=m.usr_id)
where g.area_id=<cfqueryparam attributeCollection=#id#/>
</cfquery>
</m:silent><!---
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Группа каталога
<cfif d.area_id GT 0>
<b>#d.area#</b>
[#d.area_id#]
</cfif>
</cfoutput>
</layout:attribute>
</layout:page>
<cfif status.errorState GT 0>
<cfoutput><div class="err">#status.errorMessage#</div></cfoutput>
</cfif>
<cfoutput>
<input type="hidden" name="area_id" value="#d.area_id#"/>
<input type="hidden" name="track" value="#tr.self#"/>
<input type="hidden" name="pass" value=""/><!--- pass marker to prevent save on submit --->
<div class="detail">
<div class="tr">
<div class="th">ID</div>
<div class="td">
#d.area_id#
</div>
</div>
<div class="tr">
<div class="th">Код</div>
<div class="td">
<input type="text" name="area_code" value="#d.area_code#" size="70"/>
<i>используется для формирования кода услуги и кода sku</i>
</div>
</div>
<div class="tr">
<div class="th">Аналитический код</div>
<div class="td">
<input type="text" name="analytic_code" value="#d.analytic_code#" size="70"/>
</div>
</div>
<div class="tr">
<div class="th">Группа (RUS)</div>
<div class="td">
<input type="text" name="area" value="#d.area#" size="70"/>
</div>
</div>
<div class="tr">
<div class="th">Группа (ENG)</div>
<div class="td">
<input type="text" name="area_en" value="#d.area_en#" size="70"/>
</div>
</div>
<div class="tr">
<div class="th">Описание</div>
<div class="td">
<textarea name="descr" rows="10" cols="100">#request.htm2plain(d.descr)#</textarea>
</div>
</div>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'DD.MM.YYYY')# #timeFormat(d.dt_created,'HH:MM')#
#qDecoration.creator# <cfif len(qDecoration.creator_shortname)>(#qDecoration.creator_shortname#)</cfif>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Изменено
#dateFormat(d.dt_updated,'DD.MM.YYYY')# #timeFormat(d.dt_updated,'HH:MM')#
#qDecoration.updater# <cfif len(qDecoration.updater_shortname)>(#qDecoration.updater_shortname#)</cfif>
</div>
</div>
</div>
</cfoutput>
<layout:page section="extension" closeForm="Yes"/>
<cfif d.area_id GT 0>
<cfquery name="qAbstractService" datasource="#request.DS#">
select distinct
a.abstract_service_id
,a.code
,a.abstract_service
,(select count(*) from service s where s.abstract_service_id=a.abstract_service_id) as svc_cnt
,(select count(*) from abstract_service_param_class ac where ac.abstract_service_id=a.abstract_service_id) as param_cnt
from abstract_service a
where a.area_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.area_id#"/>
order by a.code, a.abstract_service
</cfquery>
<cfoutput>
<h4>Абстрактные услуги (#qAbstractService.recordCount#)</h4>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th></th>
<th>Код услуги</th>
<th>Абстрактная услуга</th>
<th>Вариантов</th>
<th>Компонентов</th>
<th></th>
</tr>
</thead>
<cfoutput query="qAbstractService">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="abstract_service" id=#abstract_service_id# fwx=#tr.fwx#/>
</td>
<td>
<cfif abstract_service_id GT 0><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">#code#</a></cfif>
</td>
<td>
<cfif abstract_service_id GT 0><a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">#abstract_service#</a></cfif>
</td>
<td class="c">
<cfif svc_cnt GT 0>#svc_cnt#</cfif>
</td>
<td class="c">
<cfif param_cnt GT 0>#param_cnt#</cfif>
</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="abstract_service" id=#abstract_service_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
</cfif>
<layout:page section="footer"/>

67
area_del.cfm Normal file
View File

@ -0,0 +1,67 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_detail entity="area" pageInfoOut="pageInfo"/>
<cfparam name="area_id" type="integer"/>
<d:del
entity="#pageInfo.entity#"
confirmMessage="Удалить группу услуг?"
denyMessage="Удаление данной группы невозможно (используется абстрактными услугами)."
accessObj="#pageInfo.entity#"
status="status"
output="markup">
<d:dependency entity="service" title="Абстрактные услуги">
<d:dependency_field key>a.abstract_service_id</d:dependency_field>
<d:dependency_field title="Код услуги">a.code</d:dependency_field>
<d:dependency_field title="Абстрактная услуга">a.abstract_service</d:dependency_field>
<d:dependency_from>
abstract_service a
left outer join area g on (a.area_id=g.area_id)
</d:dependency_from>
<d:dependency_condition cfsqltype="cf_sql_integer" value='#area_id#'>g.area_id</d:dependency_condition>
<d:dependency_order_by>2</d:dependency_order_by>
</d:dependency>
<d:del_condition field="area_id" value="#area_id#" cfsqltype="cf_sql_integer"/>
</d:del>
<m:dispatch_detail
usePRG="Yes"
pageInfo=#pageInfo#
id="#area_id#"
status=#status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<cfquery name="qDecoration" datasource="#request.DS#">
select
m.area
from area m
where m.area_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#area_id#" null=#!isValid("integer", area_id)#/>
</cfquery>
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Удаление группы услуг
#qDecoration.area#
[#area_id#]
</cfoutput>
</layout:attribute>
<layout:attribute name="controls">&nbsp;</layout:attribute>
</layout:page>
<cfoutput>#markup#</cfoutput>
<layout:page section="footer"/>

145
area_ls.cfm Normal file
View File

@ -0,0 +1,145 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<cffunction name="hideNonPositive">
<cfargument name="a"/>
<cfreturn (a GT 0)? a : ""/>
</cffunction>
<m:prepare_ls entity="area" 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.area_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_INTEGER">m.area_id</d:field>
<d:field title="Код группы">m.area_code</d:field>
<d:field title="Аналитический код">m.analytic_code</d:field>
<d:field title="Группа (RUS)">m.area</d:field>
<d:field title="Группа (ENG)">m.area_en</d:field>
<d:field title="Абстр. услуг">(select count(*) from abstract_service a where a.area_id=m.area_id) as as_cnt</d:field>
<d:field title="Вариантов услуг">(select count(*) from abstract_service a join service s on (a.abstract_service_id=s.abstract_service_id) where a.area_id=m.area_id) as svc_cnt</d:field>
</d:field_set>
from area m
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 area 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_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 оно закопано в модуль, и аргументы называются по-разному... но мы хотим немного сэкономить и не обрабатывать весь резалтсет --->
<cfsavecontent variable="qRead.f_link_view_edit">
<a href="#pageInfo.entity#.cfm?#pageInfo.entity#_id=#area_id#&#tr.fwx#" name="#area_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_link_del">
<cfif pageInfo.writePermitted()><a href="#pageInfo.entity#_del.cfm?#pageInfo.entity#_id=#area_id#&#tr.fwx#" name="#area_id#" 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><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/></c:th>
<c:td field="f_link_view_edit" class="c"/>
<!--- <a href="#CALLER.pageInfo.entity#.cfm?#CALLER.pageInfo.entity#_id=#area_id#&#CALLER.tr.fwx#" name="#area_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a> --->
</c:column>
<c:column width="3%" field="area_id"/>
<c:column width="5%" field="area_code"/>
<c:column width="5%" field="analytic_code"/>
<c:column width="20%" field="area"/>
<c:column width="20%" field="area_en"/>
<c:column width="5%" field="as_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
<c:column width="5%" field="svc_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
<c:column width="1%" sortable="false">
<c:td field="f_link_del" class="c"/>
</c:column>
</c:table>
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>
<!---*** критика синтаксиса: CALLER в данном контексте выглядит ужасно. Когда применять #service_id#, когда ##service_id##
Может быть, стоит отказаться от пользовательского тега и обратиться к более ровному способу форматирования.
Например (явно плохая идея, но для примера) печатать таблицу, а потом ее парсить и переформатировать... некоторые это могли сделать на клиенте.
На самом деле все, что нужно нам из скоупа CALLER, уже определено в момент вызова тега, и мы можем заменить CALLER на <cfoutput>. Это тоже неуклюже. То есть тащить весь CALLER внутрь как бы избыточно (не говоря о том, что можно словить каких-то сложносочиненных глюков)
Сортировка должна происходить на сервере БД, иначе паджинатор бесполезен. Вытаскивать резалтсет на сервер приложений и там его сортировать выглядит очень плохим решением (еще глупее сортировать на клиенте). Для корректной сортировки нужно делать композицию колонок на сервере, что не очень хорошо, например, с нуллами надо обращаться осторожно (вот аргумент в пользу NOT NULL), и синтаксис становится зависим от диалекта SQL. Возможный вариант, если у нас композиция из 2 колонок, сортировать по обеим. Либо отказаться от сортировки по композитной колонке, что кажется проще всего.
Контекст query выглядит естественно, но эта простота вводит в заблуждение - на вид обычный синтаксис, а функции недоступны (паковать в реквест еще то удовольствие), контекст страницы недоступен, ищи его через CALLER - догадаться невозможно.
Можно передавать внутрь тега все, что может понадобиться - функции, переменные?
Можно придумать собственный синтаксис, заменяющий cfif
--->
<!--- тонкости
в примере ниже
Атрибуты тега вычисляются до вызова, в контексте вызывающей страницы, а содержимое обрабатывается самим тегом в его контексте (собственно, мы сказали ему так делать). Но при чтении исходника это совсем не очевидно и может порвать мозг.
Можно, конечно, обрабатывать исключение и подставлять контекст вызывающей страницы? Как заставить тег видеть контекст вызывающей страницы? Попробовал взять весь тег в cfoutput. В результате перестал видеть поля query. Откатился.
Печаль в том, что мы в одном месте (чего и хотели - чтобы рядом) получаем контекст вызывающей страницы и контекст query, поля которого хотим называть неквалифицированными именами.
Вариант: действуем в 2 прохода, сначала формируем структуру, а потом рендерим ее. В принципе, с учетом пагинации, может потреблять памяти меньше, чем сам query
<c:th><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/><cfoutput>#pageInfo.entity#</cfoutput>#pageInfo.entity#</c:th> --->
<!--- Хотелось бы:
чтобы контекст страницы был явно доступен во всех вложенных тегах. >> The custom tag's Caller scope is a reference to the calling page's Variables scope (добавить все из CALLER в Variables? А не зациклимся?
чтобы итератор работал прозрачно, как в cfoutput query
Как обойтись без динамического исполнения? Для всех форматтеров снаружи объявлять closure? нечитабельно.
Хотя читабельность простыней ниже - так себе
В общем, получается пока плохо
? полиморфизм i18(measure_short) - как бы избежать отдельной далекой декларации длинного списка похожих функций. Можно полю придать признак языка? Соглашение с суффиксами? Это уже какая-то морфология получается!
--->

121
area_ls1.cfm Normal file
View File

@ -0,0 +1,121 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_ls entity="area" 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.area_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_INTEGER">m.area_id</d:field>
<d:field title="Код группы">m.area_code</d:field>
<d:field title="Аналитический код">m.analytic_code</d:field>
<d:field title="Группа">m.area</d:field>
</d:field_set>
from area m
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 area 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:page>
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
<layout:grid_summary
recordCount=#qRead.recordCount#
totalCount=#qCountTotal.cnt#
footerOut="gridFooter"
excelLink="Yes"
jsonLink="Yes"
/>
<cfscript>
function uc(x) {return UCase(x);}
</cfscript>
<c:grid query=#qRead# titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray# class="worktable">
<c:column width="1%">
<c:th><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/></c:th>
<c:td>
<!---<c:link_view_edit canWrite="#CALLER.pageInfo.writePermitted()#" entity="#CALLER.pageInfo.entity#" id=#qRead.area_id# fwx="#CALLER.tr.fwx#"/>--->
<a href="#CALLER.pageInfo.entity#.cfm?#CALLER.pageInfo.entity#_id=#area_id#&#CALLER.tr.fwx#" name="#area_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a>
</c:td>
</c:column>
<c:column width="3%" lang="en">
<c:th field="area_id">rrrrrrr</c:th>
<c:td>(#area_id#)</c:td>
</c:column>
<c:column width="5%" field="area_code">_#area_code#_</c:column>
<c:column width="5%" field="area_code"></c:column>
<c:column width="5%" field="area_code"/>
<!---<c:column width="80%" field="area" formatter=#function (x) {return UCase(x)}#/>---><!---длинно--->
<c:column width="80%" field="area" formatter=#uc#/><!---если переиспользовать форматтер на той же странице, можно так--->
</c:grid>
<!--- <table class="worktable">
<thead>
<layout:grid_head titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray#>
<th width="1%">
<c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/>
</th>
<th width="3%"><layout:column_head name="area_id"/></th>
<th width="5%"><layout:column_head name="area_code"/></th>
<th width="80%"><layout:column_head name="area"/></th>
</layout:grid_head>
</thead>
<cfoutput query="qRead" maxrows=#pageInfo.recordsPerPage# startrow=#pageInfo.nStart#>
<tr>
<td class="c">
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# id=#qRead[pageInfo.entity&'_id'][currentRow]# fwx=#tr.fwx#/>
</td>
<td class="c">#area_id#</td>
<td>#area_code#</td>
<td>#area#</td>
</tr>
</cfoutput>
</table>--->
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>

200
builder.cfm Normal file
View File

@ -0,0 +1,200 @@
<!--- примитивный конструктор селектов, чтобы не набирать руками колонки --->
<!--- v0.1 2018.02.27 --->
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfparam name="obj" default=""/>
<cfparam name="ds" default="metadata"/>
<cfparam name="out" default="field_set,bean"/>
<!---<cfswitch expression=#ds#>
<cfcase value="metadata"><cfset request.ds="mms"/></cfcase>
<cfcase value="data"><cfset request.ds="ditcloud"/></cfcase>
<cfdefaultcase><cfset request.ds=""/></cfdefaultcase>
</cfswitch>--->
<cfquery name="qObj" datasource="#request.DS#">
select o.type, o.name from sys.objects o where o.type in ('U','V') order by o.type, o.name
</cfquery>
<!---<cfdump var=#qObj#/>--->
<cfquery name="qCol" datasource="#request.DS#">
select c.name, c.system_type_id, c.max_length, c.is_nullable, c.is_identity from sys.columns c join sys.objects o on (c.object_id=o.object_id) where o.name=<cfqueryparam cfsqltype="cf_sql_varchar" value="#obj#"/>
</cfquery>
<!---<cfdump var=#qCol#/>--->
<form action="" method="post">
<!--- <select name="ds" onchange="submit();">
<option <cfif #ds# EQ "data"> selected</cfif>>data</option>
<option <cfif #ds# EQ "metadata"> selected</cfif>>metadata</option>
</select>--->
<select name="obj">
<cfoutput query="qObj">
<option <cfif #obj# EQ #name#> selected</cfif> value="#name#">
<cfif #trim(qObj.type)# EQ 'U'>(table)<cfelseif #trim(qObj.type)# EQ 'V'>(view)<cfelse></cfif> #name#
</option>
</cfoutput>
</select>
<input type="checkbox" name="out_all" id="out_all" value="1" onchange="; for (var i=0, checkboxes=document.getElementsByName('out'), n=checkboxes.length; i < n ; i++) {checkboxes[i].checked = this.checked;}"/>
<label for="out_all">(все)</label>
<cfloop list="field_set,select,insert,update,bean,grid,detail" item="outformat">
<cfoutput>
<input type="checkbox" name="out" id="#outformat#" value="#outformat#"<cfif structKeyExists(form, "out")><cfif listFind(form.out,outformat)> checked</cfif></cfif>/>
<label for="#outformat#">#outformat#</label>
</cfoutput>
</cfloop>
<input type="submit" name="do" value="Сформировать"/>
</form>
<cfif structKeyExists(form, "do")>
<cfif structKeyExists(form, "out")>
<cfif listFind(form.out,"field_set")>
<pre>
select
&lt;d:field_set titleMapOut="titleMap" lengthOut="fieldCount"&gt;<cfoutput query="qCol">
&lt;d:field title="#name#"&gt;#name#&lt;/d:field&gt;</cfoutput>
&lt;/d:field_set&gt;
from <cfoutput>#obj#</cfoutput>
</pre>
</cfif>
<cfif listFind(form.out,"select")>
<cfset comma="No"/>
<pre>
select <cfoutput query="qCol">
<cfif comma>,<cfelse><cfset comma="Yes"/></cfif>#name#</cfoutput>
from <cfoutput>#obj#</cfoutput>
</pre>
</cfif>
<cfif listFind(form.out,"insert")>
<pre>
insert into <cfoutput>#obj#</cfoutput> (<cfset comma="No"/>
<cfoutput query="qCol"><cfif !is_identity><cfif comma>,<cfelse><cfset comma="Yes"/></cfif>#name#</cfif></cfoutput>
) values (<cfset comma="No"/><cfoutput query="qCol"><cfif !is_identity>
<cfif comma>,<cfelse><cfset comma="Yes"/></cfif>&lt;cfqueryparam cfsqltype="cf_sql_#fieldType(system_type_id)#" value="###name###"/&gt;</cfif></cfoutput>
)
</pre>
</cfif>
<cfif listFind(form.out,"update")>
<cfset comma="No"/>
<pre>
update <cfoutput>#obj#</cfoutput> set <cfoutput query="qCol"><cfif !is_identity>
<cfif comma>,<cfelse><cfset comma="Yes"/></cfif>#name#=&lt;cfqueryparam cfsqltype="cf_sql_#fieldType(system_type_id)#" value="###name###"/&gt;</cfif></cfoutput>
<cfoutput>where #obj#_id=&lt;cfqueryparam cfsqltype="cf_sql_integer" value="###obj#_id##" null=##!isNumeric(#obj#_id)##/&gt;</cfoutput>
</pre>
</cfif>
<cfif listFind(form.out,"bean")>
<pre>
&lt;d:bean readonly=#!pageInfo.writePermitted()# table="<cfoutput>#obj#</cfoutput>" datasource="#request.DS#" output="d" status="status"&gt;<cfoutput query="qCol">
<cfswitch expression=#name#>
<cfcase value="creator_id">&lt;d:param field="creator_id" type="integer" value="##request.usr_id##" skipUpdate/&gt;</cfcase>
<cfcase value="updater_id">&lt;d:param field="updater_id" type="integer" value="##request.usr_id##"/&gt;</cfcase>
<cfcase value="dt_created">&lt;d:param field="dt_created" type="timestamp" value="##Now()##" skipUpdate/&gt;</cfcase>
<cfcase value="dt_updated">&lt;d:param field="dt_updated" type="timestamp" value="##Now()##"/&gt;</cfcase>
<cfdefaultcase>&lt;d:param field="#name#" type="#fieldType(system_type_id)#"<cfif (system_type_id EQ 167) AND (max_length GT 0)> size="#max_length#" preprocessor=##cleanInput##</cfif><cfif (system_type_id EQ 167) AND (max_length LE 0)> preprocessor=##plain2HtmClean##</cfif><cfif "#name#" EQ "#obj#_id"> key autoincrement<cfelseif is_nullable AND listFind("127,104,106,62,59,36,56,108,52,41,58,61,189,48",system_type_id)> forNull=""</cfif><cfif system_type_id EQ 104> default="0" init="0"</cfif>/&gt;</cfdefaultcase>
</cfswitch></cfoutput>
&lt;/d:bean&gt;
</pre>
</cfif>
<cfif listFind(form.out,"grid")>
<pre>
&lt;table class="worktable"&gt;
&lt;thead&gt;
&lt;layout:grid_head titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray#&gt;
<cfoutput query="qCol">&lt;th&gt;&lt;layout:column_head name="#name#"/&gt;&lt;/th&gt;
</cfoutput>
&lt;/layout:grid_head&gt;
&lt;/thead&gt;
&lt;cfoutput query="qRead" maxrows="#pageInfo.recordsPerPage#" startrow="#pageInfo.nStart#"&gt;
&lt;tr&gt;
<cfoutput query="qCol">&lt;td class="c"&gt;##<cfif listFind("58,61,189",system_type_id)>dateFormat(#name#,'DD.MM.YYYY')<cfelse>#name#</cfif>##&lt;/td&gt;
</cfoutput>
&lt;/tr&gt;
&lt;/cfoutput&gt;
&lt;/table&gt;
</pre>
</cfif>
<cfif listFind(form.out,"detail")>
<pre>
&lt;div class="detail"&gt;
<cfoutput query="qCol"><cfif "#name#" NEQ "#obj#_id">
&lt;div class="tr"&gt;
&lt;div class="th"&gt;#name#&lt;/div&gt;
&lt;div class="td"&gt;<cfif ((system_type_id EQ 167) AND (max_length GT 0)) OR listFind("127,106,62,59,36,56,108,52,41,58,61,189,48",system_type_id)>&lt;input type="text" name="#name#" id="#name#" value="<cfelseif ((system_type_id EQ 167) AND (max_length LE 0))>&lt;textarea rows="5" cols="70" name="#name#" id="#name#"&gt;<cfelseif system_type_id EQ 104>&lt;input type="checkbox" name="#name#" id="name" value="1"&lt;cfif (</cfif><!---
--->##<cfif listFind("58,61,189",system_type_id)>dateFormat(d.#name#,'DD.MM.YYYY')<cfelse>d.#name#</cfif>##<cfif ((system_type_id EQ 167) AND (max_length GT 0)) OR listFind("127,106,62,59,36,56,108,52,41,58,61,189,48",system_type_id)>"/&gt;<cfelseif ((system_type_id EQ 167) AND (max_length LE 0))>&lt;/textarea&gt;<cfelseif system_type_id EQ 104> GT 0)&gt; checked&lt;/cfif&gt;/&gt;</cfif><!---
--->&lt;/div&gt;
&lt;/div&gt;
</cfif></cfoutput>
&lt;/div&gt;
</pre>
</cfif>
</cfif>
</cfif>
<cffunction name="fieldType" output="No">
<cfargument name="xtype"/>
<cfswitch expression=#xtype#>
<cfcase value="127"><cfreturn "bigint"/></cfcase>
<cfcase value="104"><cfreturn "integer"/></cfcase><!---bit--->
<cfcase value="175"><cfreturn "char"/></cfcase>
<cfcase value="40"><cfreturn "date"/></cfcase>
<cfcase value="106"><cfreturn "decimal"/></cfcase>
<cfcase value="62"><cfreturn "double"/></cfcase><!---float--cf_sql_double--->
<cfcase value="59"><cfreturn "float"/></cfcase><!---real--cf_sql_float--->
<cfcase value="36"><cfreturn "idstamp"/></cfcase><!---uniqueidentifier--->
<cfcase value="56"><cfreturn "integer"/></cfcase>
<cfcase value="108"><cfreturn "numeric"/></cfcase>
<!---<cfcase value="59"><cfreturn "real"/></cfcase>--->
<cfcase value="52"><cfreturn "smallint"/></cfcase>
<cfcase value="41"><cfreturn "time"/></cfcase>
<cfcase value="58,61,189"><cfreturn "timestamp"/></cfcase><!---smalldatetime,datetime,timestamp--->
<cfcase value="48"><cfreturn "tinyint"/></cfcase>
<cfcase value="165"><cfreturn "varbinary"/></cfcase>
<cfcase value="167,231"><cfreturn "varchar"/></cfcase>
<cfdefaultcase><cfreturn "varchar"/></cfdefaultcase>
</cfswitch>
</cffunction>
<!---
CF_SQL_BIGINT
CF_SQL_BIT
CF_SQL_CHAR
CF_SQL_BLOB
CF_SQL_CLOB
CF_SQL_DATE
CF_SQL_DECIMAL
CF_SQL_DOUBLE
CF_SQL_FLOAT
CF_SQL_IDSTAMP
CF_SQL_INTEGER
CF_SQL_LONGVARCHAR
CF_SQL_MONEY
CF_SQL_MONEY4
CF_SQL_NUMERIC
CF_SQL_REAL
CF_SQL_REFCURSOR
CF_SQL_SMALLINT
CF_SQL_TIME
CF_SQL_TIMESTAMP
CF_SQL_TINYINT
CF_SQL_VARCHAR
--->

145
catalog_tree.cfm Normal file
View File

@ -0,0 +1,145 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_ls entity="param" 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.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="titleMap" lengthOut="fieldCount">
<d:field title="area_id" cfSqlType="CF_SQL_INTEGER">g.area_id</d:field>
<d:field title="area" cfSqlType="CF_SQL_VARCHAR">g.area</d:field>
<d:field title="area_code" cfSqlType="CF_SQL_VARCHAR">g.area_code</d:field>
<d:field title="analytic_code" cfSqlType="CF_SQL_VARCHAR">g.analytic_code</d:field>
<d:field title="abstract_service_id" cfSqlType="CF_SQL_INTEGER">a.abstract_service_id</d:field>
<d:field title="abstract_service" cfSqlType="CF_SQL_VARCHAR">a.abstract_service</d:field>
<d:field title="abstract_service_code" cfSqlType="CF_SQL_VARCHAR">a.code as abstract_service_code</d:field>
<d:field title="service_id" cfSqlType="CF_SQL_INTEGER">s.service_id</d:field>
<d:field title="modifier" cfSqlType="CF_SQL_VARCHAR">m.modifier</d:field>
<d:field title="modifier_code" cfSqlType="CF_SQL_VARCHAR">m.code as modifier_code</d:field>
<d:field title="abstract_service_param_class_id" cfSqlType="CF_SQL_INTEGER">ac.abstract_service_param_class_id</d:field>
<d:field title="param_class_id" cfSqlType="CF_SQL_VARCHAR">pc.param_class_id</d:field>
<d:field title="param_class" cfSqlType="CF_SQL_VARCHAR">pc.param_class</d:field>
<d:field title="is_multiple" cfSqlType="CF_SQL_VARCHAR">ac.is_multiple</d:field>
<d:field title="service_param_id" cfSqlType="CF_SQL_INTEGER">sp.service_param_id</d:field>
<d:field title="param_id" cfSqlType="CF_SQL_INTEGER">p.param_id</d:field>
<d:field title="param" cfSqlType="CF_SQL_VARCHAR">p.param</d:field>
<d:field title="param_short" cfSqlType="CF_SQL_VARCHAR">p.param_short</d:field>
<d:field title="param_code" cfSqlType="CF_SQL_VARCHAR">p.code as param_code</d:field>
</d:field_set>
from area g
left outer join abstract_service a on (g.area_id=a.area_id)
left outer join service s on (a.abstract_service_id=s.abstract_service_id)
left outer join modifier m on (s.modifier_id=m.modifier_id)
left outer join abstract_service_param_class ac on (a.abstract_service_id=ac.abstract_service_id)
left outer join param_class pc on (ac.param_class_id=pc.param_class_id)
left outer join service_param sp on (s.service_id=sp.service_id AND ac.abstract_service_param_class_id=sp.abstract_service_param_class_id)
left outer join param p on (sp.param_id=p.param_id)
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
order by g.analytic_code, a.code, m.code, s.service_id, ac.abstract_service_param_class_id, p.sort, p.code, p.param_id
</cfquery>
<!--- <cfdump var=#qRead#/> --->
<cfcatch type="database">
<cfrethrow/>
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
</cfcatch>
</cftry>
<cfquery name="qCountTotal" datasource="#request.DS#">
select count(*) as cnt from param 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>
<!--- <cfdump var=#qRead#/> --->
<div style="padding:1em;font-size:170%;">
<cfoutput query="qRead" group="area_id">
<div style="font-size:90%;border:1px solid ##bbb;margin:.5em;">
<a href="area.cfm?area_id=#area_id#&#tr.fwx#" style="display:block;width:100%;padding-left:.5em;line-height:1.6em;background:##ccc;">
#analytic_code# <b>#area#</b> (#area_code#)
</a>
<cfoutput group="abstract_service_id">
<cfif abstract_service_id GT 0>
<div style="padding-left:2em;font-size:90%;">
<a href="abstract_service.cfm?abstract_service_id=#abstract_service_id#&#tr.fwx#">
<img src="img/asvc.jpg" width="13" height="13"/>
#abstract_service# [#abstract_service_id#] (#area_code#.#abstract_service_code#)
</a>
<cfoutput group="service_id">
<cfif service_id GT 0>
<div style="padding-left:2em;font-size:90%;">
<a href="service.cfm?service_id=#service_id#&#tr.fwx#">
<img src="img/svc.jpg" width="16" height="16"/>
#abstract_service#:#modifier# [#service_id#](#area_code#.#abstract_service_code#.#modifier_code#)
</a>
<cfoutput group="abstract_service_param_class_id">
<cfif abstract_service_param_class_id GT 0>
<div style="padding-left:2em;font-size:90%;">
<img src="img/a-piece.png" width="13" height="13"/>
<a href="abstract_service_param_class.cfm?abstract_service_param_class_id=#abstract_service_param_class_id#&#tr.fwx#">#param_class# [#abstract_service_param_class_id#]</a>
<cfoutput group="service_param_id">
<cfif service_param_id GT 0>
<div style="padding-left:2em;font-size:90%;">
<img src="img/piece.png" width="13" height="13"/>
<a href="service_param.cfm?service_param_id=#service_param_id#&#tr.fwx#">#param# [#service_param_id#](#area_code#.#abstract_service_code#.#modifier_code#.#param_code#)</a>
</div>
</cfif>
</cfoutput>
</div>
</cfif>
</cfoutput>
</div>
</cfif>
</cfoutput>
</div>
</cfif>
</cfoutput>
</div>
</cfoutput>
</div>
</cfif>
<layout:page section="footer"/>

193
contract.cfm Normal file
View File

@ -0,0 +1,193 @@
<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="plain2HtmClean">
<cfargument name="s" type="string"/>
<cfreturn request.plain2htm(request.cleanHtm(s))/>
</cffunction>
<cffunction name="cleanInput">
<cfargument name="s" type="string"/>
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="contract" accessObject="" key="contract_id" pageInfoOut="pageInfo"/>
<d:bean readonly=#!pageInfo.writePermitted()# table="contract" datasource="#request.DS#" output="d" status="pageInfo.status">
<d:param field="contract_id" type="integer" key autoincrement/>
<d:param field="contragent_id" type="integer"/>
<d:param field="contract" type="varchar" size="255" preprocessor=#cleanInput#/>
<d:param field="dt_contract" type="timestamp" format="yyyy-MM-dd" preprocessor=#cleanInput# forNull="" init="#Now()#"/><!--- !!! Important yyyy-MM-dd NOT YYYY-MM-DD --->
<d:param field="descr" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<d:param field="updater_id" type="integer" value="#request.usr_id#" />
<d:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<d:param field="dt_updated" type="timestamp" value="#Now()#"/>
</d:bean>
<m:dispatch_detail
usePRG="No"<!---*** --->
pageInfo=#pageInfo#
id="#d.contract_id#"
status=#pageInfo.status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.login as creator, a.shortname as creator_shortname, m.login as updater, m.shortname as updater_shortname
from contract g
left outer join usr a on (g.creator_id=a.usr_id)
left outer join usr m on (g.updater_id=m.usr_id)
where g.contract_id=<cfqueryparam attributeCollection=#id#/>
</cfquery>
</m:silent><!---
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Договор
<cfif d.contract_id GT 0>
<b>#d.contract#</b>
[#d.contract_id#]
</cfif>
</cfoutput>
</layout:attribute>
</layout:page>
<!--- <cfif status.errorState GT 0>
<cfoutput><div class="err">#status.errorMessage#</div></cfoutput>
</cfif> --->
<cfoutput>
<input type="hidden" name="contract_id" value="#d.contract_id#"/>
<input type="hidden" name="track" value="#tr.self#"/>
<input type="hidden" name="pass" value=""/><!--- pass marker to prevent save on submit --->
<div class="detail">
<div class="tr">
<div class="th">ID</div>
<div class="td">
#d.contract_id#
</div>
</div>
<div class="tr">
<div class="th">Номер договора</div>
<div class="td">
<input type="text" name="contract" value="#d.contract#" size="70"/>
</div>
</div>
<div class="tr">
<div class="th">Дата договора</div>
<div class="td">
<input type="date" name="dt_contract" id="dt_contract" value="#dateFormat(d.dt_contract,"YYYY-MM-DD")#"/>
<button type="button" onclick="document.getElementById('dt_contract').value='#DateFormat(Now(), 'YYYY-MM-DD')#';">Сегодня</button>
</div>
</div>
<div class="tr">
<div class="th">Контрагент</div>
<div class="td">
<cfquery name="qList">
select c.contragent_id, c.contragent
from contragent c
order by 2
</cfquery>
<c:combo
query=#qList#
combo="contragent_id" id="contragent_id" key="contragent_id"
selected="#d.contragent_id#"
displayf="##contragent##"
class=""
/>
</div>
</div>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'YYYY-MM-DD')# #timeFormat(d.dt_created,'HH:MM')#
#qDecoration.creator# <cfif len(qDecoration.creator_shortname)>(#qDecoration.creator_shortname#)</cfif>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Изменено
#dateFormat(d.dt_updated,'YYYY-MM-DD')# #timeFormat(d.dt_updated,'HH:MM')#
#qDecoration.updater# <cfif len(qDecoration.updater_shortname)>(#qDecoration.updater_shortname#)</cfif>
</div>
</div>
</div>
</cfoutput>
<layout:page section="extension" closeForm="No"/>
<cfif d.contract_id GT 0>
<cfquery name="qSpecification">
select
s.specification_id
,s.specification
,(select count(*) from specification_item i where i.specification_id=s.specification_id) as item_cnt
from specification s
where s.contract_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.contract_id#"/>
order by 1
</cfquery>
<cfoutput>
<h4>Спецификации (#qSpecification.recordCount#)</h4>
</cfoutput>
<cfif pageInfo.writePermitted()>
<cfoutput>
<cfset addUrl="specification.cfm?specification_id=-1&contract_id=#d.contract_id#&#tr.fwx#"/>
<button type="button" class="maincontrol" onclick="document.location.href='#addUrl#'">
<a href="#addUrl#">Создать</a>
</button>
</cfoutput>
</cfif>
<table class="worktable">
<thead>
<tr>
<th></th>
<th>Номер спецификации</th>
<th>Строк</th>
<th></th>
</tr>
</thead>
<cfoutput query="qSpecification">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="specification" id=#specification_id# fwx=#tr.fwx#/>
</td>
<td>#specification#</td>
<td class="c">
<cfif item_cnt GT 0>#item_cnt#</cfif>
</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="specification" id=#specification_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
</cfif>
<layout:page section="extension" closeForm="Yes"/> <!--- *** правильно так? --->
<layout:page section="footer"/>

116
contract_ls.cfm Normal file
View File

@ -0,0 +1,116 @@
<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="contract" 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_INTEGER">d.contract_id</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="Номер договора">d.contract</d:field>
<d:field title="Дата договора">d.dt_contract</d:field>
<d:field title="Описание">d.descr</d:field>
<d:field title="Соглашений">(select count(*) from agreement s where s.contract_id=d.contract_id) as spec_cnt</d:field>
</d:field_set>
from contract d
join contragent c on (d.contragent_id=c.contragent_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 contract 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_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 оно закопано в модуль, и аргументы называются по-разному... но мы хотим немного сэкономить и не обрабатывать весь резалтсет --->
<cfsavecontent variable="qRead.f_link_view_edit">
<a href="#pageInfo.entity#.cfm?#pageInfo.entity#_id=#contract_id#&#tr.fwx#" name="#contract_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_link_del">
<cfif pageInfo.writePermitted()><a href="#pageInfo.entity#_del.cfm?#pageInfo.entity#_id=#contract_id#&#tr.fwx#" name="#contract_id#" 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><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/></c:th>
<c:td field="f_link_view_edit" class="c"/>
<!--- <a href="#CALLER.pageInfo.entity#.cfm?#CALLER.pageInfo.entity#_id=#contract_id#&#CALLER.tr.fwx#" name="#contract_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a> --->
</c:column>
<c:column width="2%" field="contract_id"><c:td class="r"/></c:column>
<c:column width="10%" field="contragent"/>
<c:column width="10%" field="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="15%" field="descr"/>
<c:column width="2%" field="spec_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
<c:column width="1%" sortable="false">
<c:td field="f_link_del" class="c"/>
</c:column>
</c:table>
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>

243
contragent.cfm Normal file
View File

@ -0,0 +1,243 @@
<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="plain2HtmClean">
<cfargument name="s" type="string"/>
<cfreturn request.plain2htm(request.cleanHtm(s))/>
</cffunction>
<cffunction name="cleanInput">
<cfargument name="s" type="string"/>
<cfreturn htmlEditFormat(s)/>
</cffunction>
<m:prepare_detail entity="contragent" accessObject="" key="contragent_id" pageInfoOut="pageInfo"/>
<d:bean readonly=#!pageInfo.writePermitted()# table="contragent" datasource="#request.DS#" output="d" status="pageInfo.status">
<d:param field="contragent_id" type="integer" key autoincrement/>
<d:param field="contragent" type="varchar" size="255" preprocessor=#cleanInput#/>
<d:param field="is_provider" type="bool" init="0" default="0"/>
<d:param field="descr" type="varchar" preprocessor=#plain2HtmClean#/>
<d:param field="external_uid" type="guid" forNull=""/>
<d:param field="external_code" type="varchar" size="255"/>
<d:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<d:param field="updater_id" type="integer" value="#request.usr_id#" />
<d:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<d:param field="dt_updated" type="timestamp" value="#Now()#"/>
</d:bean>
<m:dispatch_detail
usePRG="No"<!---*** --->
pageInfo=#pageInfo#
id="#d.contragent_id#"
status=#pageInfo.status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<cfquery name="qDecoration" datasource="#request.DS#">
select
a.login as creator, a.shortname as creator_shortname, m.login as updater, m.shortname as updater_shortname
from contragent g
left outer join usr a on (g.creator_id=a.usr_id)
left outer join usr m on (g.updater_id=m.usr_id)
where g.contragent_id=<cfqueryparam attributeCollection=#id#/>
</cfquery>
</m:silent><!---
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Контрагент
<cfif d.contragent_id GT 0>
<b>#d.contragent#</b>
[#d.contragent_id#]
</cfif>
</cfoutput>
</layout:attribute>
</layout:page>
<!--- <cfif status.errorState GT 0>
<cfoutput><div class="err">#status.errorMessage#</div></cfoutput>
</cfif>
--->
<cfoutput>
<input type="hidden" name="contragent_id" value="#d.contragent_id#"/>
<input type="hidden" name="track" value="#tr.self#"/>
<input type="hidden" name="pass" value=""/><!--- pass marker to prevent save on submit --->
<div class="detail">
<div class="tr">
<div class="th">ID</div>
<div class="td">
#d.contragent_id#
</div>
</div>
<div class="tr">
<div class="th">Наименование</div>
<div class="td">
<input type="text" name="contragent" value="#d.contragent#" size="70"/>
</div>
</div>
<div class="tr">
<div class="th">Провайдер</div>
<div class="td">
<input type="checkbox" name="is_provider" value="1"<cfif d.is_provider GT 0> checked</cfif>/>
</div>
</div>
<div class="tr">
<div class="th">Внешний UID</div>
<div class="td">
<input type="text" name="external_uid" value="#d.external_uid#" size="70"/><i>Company UID из Элмы</i>
</div>
</div>
<div class="tr">
<div class="th">WZ</div>
<div class="td">
<input type="text" name="external_code" value="#d.external_code#" size="7"/><i></i>
</div>
</div>
<div class="tr">
<div class="th">Описание</div>
<div class="td">
<textarea name="descr" rows="10" cols="100">#request.htm2plain(d.descr)#</textarea>
</div>
</div>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'YYYY-MM-DD')# #timeFormat(d.dt_created,'HH:MM')#
#qDecoration.creator# <cfif len(qDecoration.creator_shortname)>(#qDecoration.creator_shortname#)</cfif>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Изменено
#dateFormat(d.dt_updated,'YYYY-MM-DD')# #timeFormat(d.dt_updated,'HH:MM')#
#qDecoration.updater# <cfif len(qDecoration.updater_shortname)>(#qDecoration.updater_shortname#)</cfif>
</div>
</div>
</div>
</cfoutput>
<layout:page section="extension" closeForm="Yes"/>
<cfif d.contragent_id GT 0>
<cfquery name="qContract">
select
d.contract_id
,d.contract
,d.dt_contract
,(select count(*) from specification s where s.contract_id=d.contract_id) as spec_cnt
,(select count(distinct resource_realm_id) from resource_realm_access a where a.contract_id=d.contract_id) as res_realm_cnt
from contract d
where d.contragent_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.contragent_id#"/>
order by 1
</cfquery>
<cfoutput>
<h4>Договоры (#qContract.recordCount#)</h4>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th><c:link_add canWrite=#pageInfo.writePermitted()# entity="contract" id="#contragent_id#" extra="contragent_id=#d.contragent_id#" fwx=#tr.fwx#/></th>
<th>Номер договора</th>
<th>Дата договора</th>
<th>Спецификаций</th>
<th>Ресурсных платформ</th>
<th></th>
</tr>
</thead>
<cfoutput query="qContract">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="contract" id=#contract_id# fwx=#tr.fwx#/>
</td>
<td>#contract#</td>
<td class="c">
#dateFormat(dt_contract,'YYYY-MM-DD')#
</td>
<td class="c">
<cfif spec_cnt GT 0>#spec_cnt#</cfif>
</td>
<td class="c">
<cfif res_realm_cnt GT 0>#res_realm_cnt#</cfif>
</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="contract" id=#contract_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
</cfif>
<i>Доступ к ресурсным платформам предоставляется на уровне договора</i>
<cfif d.contragent_id GT 0>
<cfquery name="qUsr">
select
u.usr_id
,u.login
,u.firstname
,u.lastname
,u.middlename
,u.email
,u.idp_usr_uid
from usr u
where u.contragent_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#d.contragent_id#"/>
order by 1
</cfquery>
<cfoutput>
<h4>Пользователи (#qContract.recordCount#)</h4>
</cfoutput>
<table class="worktable">
<thead>
<tr>
<th></th>
<th>Логин</th>
<th>Ф.И.О.</th>
<th>e-mail</th>
<th>IDP user UID</th>
<th></th>
</tr>
</thead>
<cfoutput query="qUsr">
<tr>
<td>
<c:link_view_edit canWrite=#pageInfo.writePermitted()# entity="usr" id=#usr_id# fwx=#tr.fwx#/>
</td>
<td>#login#</td>
<td>#lastname# #firstname# #middlename#</td>
<td>#email#</td>
<td>#idp_usr_uid#</td>
<td class="c">
<c:link_del canWrite=#pageInfo.writePermitted()# entity="usr" id=#usr_id# fwx=#tr.fwx#/>
</td>
</tr>
</cfoutput>
</table>
</cfif>
<layout:page section="footer"/>

121
contragent_ls.cfm Normal file
View File

@ -0,0 +1,121 @@
<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="contragent" 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.contragent_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_INTEGER">c.contragent_id</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="Описание">c.descr</d:field>
<d:field title="Внешний UID">c.external_uid</d:field>
<d:field title="WZ">c.external_code</d:field>
<d:field title="Провайдер">c.is_provider</d:field>
<d:field title="Контрактов">(select count(*) from contract d where d.contragent_id=c.contragent_id) as contract_cnt</d:field>
<d:field title="Спецификаций">(select count(*) from specification s join contract d on (s.contract_id=d.contract_id) where d.contragent_id=c.contragent_id) as spec_cnt</d:field>
<d:field title="Пользователей">(select count(*) from usr u where u.contragent_id=c.contragent_id) as usr_cnt</d:field>
</d:field_set>
from contragent c
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 contragent 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_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 оно закопано в модуль, и аргументы называются по-разному... но мы хотим немного сэкономить и не обрабатывать весь резалтсет --->
<cfsavecontent variable="qRead.f_link_view_edit">
<a href="#pageInfo.entity#.cfm?#pageInfo.entity#_id=#contragent_id#&#tr.fwx#" name="#contragent_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a>
</cfsavecontent>
<cfsavecontent variable="qRead.f_link_del">
<cfif pageInfo.writePermitted()><a href="#pageInfo.entity#_del.cfm?#pageInfo.entity#_id=#contragent_id#&#tr.fwx#" name="#contragent_id#" 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><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/></c:th>
<c:td field="f_link_view_edit" class="c"/>
<!--- <a href="#CALLER.pageInfo.entity#.cfm?#CALLER.pageInfo.entity#_id=#contragent_id#&#CALLER.tr.fwx#" name="#contragent_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a> --->
</c:column>
<c:column width="3%" field="contragent_id"/>
<c:column width="10%" field="contragent"/>
<c:column width="5%" field="is_provider" formatter=#function(b){return b?"ПРОВАЙДЕР":"";}#><c:td class="c"/></c:column>
<c:column width="15%" field="descr"/>
<c:column width="10%" field="external_uid"/>
<c:column width="5%" field="external_code"/>
<c:column width="2%" field="usr_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
<c:column width="2%" field="contract_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
<c:column width="2%" field="spec_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
<c:column width="1%" sortable="false">
<c:td field="f_link_del" class="c"/>
</c:column>
</c:table>
<cfoutput>#gridFooter#</cfoutput>
</cfif>
<layout:page section="footer"/>

165
doc.cfm Normal file
View File

@ -0,0 +1,165 @@
<cfsilent></cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="m" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
<cfparam name="entity"/>
<cfparam name="doc_id" type="integer"/>
<!--- validate entity to prevent sql injection--->
<cfmodule template="mod/attach_support.cfm" entity="#entity#" output="entitySpec"/>
<m:prepare_detail entity="#entity#_doc" pageInfoOut="pageInfo"/>
<!--- осторожно, в странице entity, а в pageInfo entity_doc! --->
<cfset pageInfo.formEncType="multipart/form-data"/>
<m:upload field="doc" output="attach"/>
<cfset "#entity#_doc_id"=#doc_id#/>
<m:bean readonly=#!pageInfo.writePermitted()# table="#pageInfo.entity#" datasource="#request.ds#" output="d" status="status" meta="m">
<m:param field="#entity#_doc_id" type="integer" key autoincrement />
<m:param field="#entity#_doc" type="varchar" size="255"/>
<cfif attach.ok>
<m:param field="doc" type="varbinary" value=#attach.binaryData#/>
<m:param field="contenttype" type="varchar" size="255" value=#attach.contenttype#/>
<m:param field="fname" type="varchar" size="255" value=#attach.filename#/>
<cfelse>
<m:param field="contenttype" type="varchar" size="255" readonly/>
<m:param field="fname" type="varchar" size="255" readonly/>
</cfif>
<m:param field="creator_id" type="integer" value="#request.usr_id#" skipUpdate/>
<m:param field="updater_id" type="integer" value="#request.usr_id#" />
<m:param field="dt_created" type="timestamp" value="#Now()#" skipUpdate/>
<m:param field="dt_updated" type="timestamp" value="#Now()#"/>
</m:bean>
<cfset doc_id=d["#entity#_doc_id"]/>
<m:dispatch_detail
usePRG="No"
pageInfo=#pageInfo#
data=#d#
status=#status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- #entity# is validated --->
<cfquery name="qAttributes" datasource="#request.DS#">
select
d.#entity#_id as entity_id, d.#entity#_doc as title, datalength(d.doc) as doc_size, d.contenttype, d.fname,
a.login as creator, a.shortname as creator_name, u.login as modifier, u.shortname as modifier_name
from #entity#_doc d
left outer join usr a on (d.creator_id=a.usr_id)
left outer join usr u on (d.updater_id=u.usr_id)
where d.#entity#_doc_id=<cfqueryparam attributeCollection=#id#/>
</cfquery>
<cfquery name="qEntity" datasource="#request.DS#">
#entitySpec.selectHead#
where d.#entity#_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#qAttributes.entity_id# null=#!isValid("integer", qAttributes.entity_id)#/>
</cfquery>
<!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
Документ
<cfoutput query="qAttributes">
<b><cfif len(title)>#title#<cfelse>#fname#</cfif></b>
<cfif len(contenttype)>(#contenttype#)</cfif>
</cfoutput>
<cfoutput query="qEntity">
<b><cfset Evaluate("WriteOutput('#entitySpec.format#')")/></b>
</cfoutput>
</layout:attribute>
</layout:page>
<cfoutput>
<input type="hidden" name="doc_id" value="#doc_id#">
<input type="hidden" name="entity" value="#entity#">
<input type="hidden" name="track" value="#tr.self#"/>
<div class="detail">
<div class="tr">
<div class="th">Название документа</div>
<div class="td">
<input type="text" name="#entity#_doc" value="#qAttributes.title#" size="63" maxlength="255" style="width:100%">
</div>
</div>
<cfif doc_id GT 0>
<div class="tr">
<div class="th">Имя файла</div>
<div class="td">
#qAttributes.fname#
<a href="doc_get.cfm?entity=#entity#&doc_id=#doc_id#" target="_blank"><img src="img/view.gif" title="просмотр (в новом окне)"/></a>
<a href="doc_get.cfm?entity=#entity#&doc_id=#doc_id#&action=download"><img src="img/download.png" title="скачать"/></a>
</div>
</div>
<div class="tr">
<div class="th">Content Type</div>
<div class="td">
#qAttributes.contenttype#
<m:contenttype_icon contenttype=#qAttributes.contenttype#/>
</div>
</div>
<div class="tr">
<div class="th">Размер</div>
<div class="td">
#qAttributes.doc_size# байт
</div>
</div>
</cfif>
<cfif pageInfo.writePermitted()>
<div class="tr">
<div class="th">Заменить файл</div>
<div class="td">
<input type="file" name="doc"/>
</div>
</div>
</cfif>
<div class="tr">
<div class="th">Создано</div>
<div class="td">
#dateFormat(d.dt_created,'DD.MM.YYYY')# #timeFormat(d.dt_created,'HH:MM')#
#qAttributes.creator# <cfif len(qAttributes.creator_name)>(#qAttributes.creator_name#)</cfif>
<i>Дата и время первоначальной загрузки</i>
</div>
</div>
<div class="tr">
<div class="th">Изменен</div>
<div class="td">
#dateFormat(d.dt_updated,'DD.MM.YYYY')# #timeFormat(d.dt_updated,'HH:MM')#
#qAttributes.modifier# <cfif len(qAttributes.modifier_name)>(#qAttributes.modifier_name#)</cfif>
</div>
</div>
</div>
</cfoutput>
<layout:page section="extension" closeForm="Yes"/>
<cfif listFind(d.contenttype, "image","/") EQ 1><!--- preview --->
<cfoutput><img src="doc_get.cfm?entity=#entity#&doc_id=#doc_id#" style="max-width:100%;"/></cfoutput>
</cfif>
<layout:page section="footer"/>

101
doc_del.cfm Normal file
View File

@ -0,0 +1,101 @@
<!---<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="m" taglib="lib/bean"/>
<cfimport prefix="layout" taglib="layout"/>
<cfparam name="entity" type="string"/>
<cfparam name="doc_id" type="integer"/>
<cfmodule template="mod/attach_support.cfm" entity="#entity#"/>
<m:track
thisUrl="#request.thisPage#?entity=#entity#&doc_id=#doc_id#"
defaultBackUrl="#entity#_ls.cfm"/>
<m:del
entity="#entity#"
keyName="doc_id,entity"
checkQuery="select 0 as chk"
displayQuery="select m.#entity#_doc as doc_title, m.contenttype, m.fname
from #entity#_doc m
where m.#entity#_doc_id='#doc_id#'"
deleteQuery="delete from #entity#_doc where #entity#_doc_id='#doc_id#'"
displayMessage="Удаление вложения <b>##doc_title##</b> ##fname## (##contenttype##)"
confirmMessage="Удалить вложение?"
denyMessage="Удаление вложения невозможно (ситуация не предусмотрена)"
backURL="#tr.backUrl#"
accessObj=""
track="#tr.self#"/>
<layout:page section="extension" closeForm="Yes"/>
<layout:page section="footer"/>
--->
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_detail entity="abstract_service_doc" pageInfoOut="pageInfo"/>
<cfparam name="entity" type="string"/>
<cfparam name="doc_id" type="integer"/>
<cfmodule template="mod/attach_support.cfm" entity="#entity#"/><!---*** this check prevents sql injection--->
<!---Внимание, "entity" используется в 2 смыслах!--->
<d:del
entity="#pageInfo.entity#"
confirmMessage="Удалить документ?"
denyMessage="Удаление данного документа невозможно (ситуация не предусмотрена)."
accessObj="#pageInfo.entity#"
status="status"
output="markup">
<!---*** не работает: queryString="entity=#entity#&doc_id=#doc_id#"--->
<d:del_condition field="doc_id" expression="#entity#_doc_id" value="#doc_id#" cfsqltype="cf_sql_integer"/>
</d:del>
<m:dispatch_detail
usePRG="No"
pageInfo=#pageInfo#
id="#doc_id#"
status=#status#
trackOut="tr"
idAttributesOut="id"
/>
<!--- decoration --->
<!---*** sql injection id prevented by attach_support check--->
<cfquery name="qDecoration" datasource="#request.DS#">
select d.#entity#_doc as doc_name, d.fname, a.abstract_service, a.code
from #entity#_doc d
join #entity# a on (d.abstract_service_id=a.abstract_service_id)
where d.#entity#_doc_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#doc_id#" null=#!isValid("integer", doc_id)#/>
</cfquery>
</m:silent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput>
Удаление документа
<b>#qDecoration.doc_name#(#qDecoration.fname#)</b> [#doc_id#]
абстрактной услуги
<b>
#qDecoration.code#
#qDecoration.abstract_service#
</b>
</cfoutput>
</layout:attribute>
<layout:attribute name="controls">&nbsp;</layout:attribute>
</layout:page>
<!---<cfdump var=#qDecoration#/>--->
<cfoutput><input type="hidden" name="entity" value="#entity#"/></cfoutput>
<cfoutput>#markup#</cfoutput>
<layout:page section="footer"/>

29
doc_get.cfm Normal file
View File

@ -0,0 +1,29 @@
<cfsilent>
<cfimport prefix="m" taglib="mod"/>
<cfimport prefix="m" taglib="mod/bean"/>
<cfimport prefix="layout" taglib="layout"/>
<cfparam name="entity"/>
<cfparam name="doc_id" type="integer"/>
<cfparam name="action" default=""/>
<!--- validate entity to prevent sql injection--->
<cfmodule template="mod/attach_support.cfm" entity="#entity#"/>
<cfset errMsg=""/>
<cftry>
<!---Проверяем параметр на корректность, и все равно стремно --->
<cfquery name="qRead" datasource="#request.DS#">
select d.doc, d.fname, d.contenttype
from #entity#_doc d
where #entity#_doc_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#doc_id#"/>
</cfquery>
<cfcatch type="Any">
<cfset errMsg="#CFCATCH.Message#. #CFCATCH.Detail#"/>
</cfcatch>
</cftry>
</cfsilent><cfif len(errMsg)><cfoutput>#errMsg#</cfoutput><cfelse>
<cfswitch expression=#action#><cfcase value="download"><cfheader name="Content-Disposition" value='attachment; filename="#qRead.fname#"'/><cfcontent type="#qRead.contenttype#" variable=#qRead.doc#/></cfcase><cfdefaultcase><cfheader name="Content-Disposition" value='inline; filename="#qRead.fname#"'/><cfcontent type="#qRead.contenttype#" variable=#qRead.doc#/></cfdefaultcase></cfswitch></cfif>

37
etc/db/postgres.txt Normal file
View File

@ -0,0 +1,37 @@
create table if not exists: не заменяет декларацию... затупил, не догадался
drop table if exists;
14:04 17.04.2023
ERROR: operator does not exist: uuid = character varying
Использовать для POSTGRESQL UUID: CF GUID+CF_SQL_OTHER
Ошибка при записи в базу данных. ERROR: column "is_payg" is of type bit but expression is of type boolean Подсказка: You will need to rewrite or cast the expression. Позиция: 723 То же самое работает для abstract_service_param_class.cfm ???
Очень странная разница: в abstract_service_param_class.cfm числа в d возвращаются как числа, а в tariff как строки
Ошибка: в БД нужно boolean, а в форме bit (транслируется в cf_sql_bit)
Теперь проблема с датой - добавил формат, ок. timestamp для Postgre работает
Message ERROR: invalid input syntax for type uuid: ""
Где: unnamed portal parameter $1 = ''
SQL select count(*) as cnt
from service_tariff
where 1=1
AND service_tariff_guid=
DatabaseName PostgreSQL
DatabaseVersion 15.1
DriverName PostgreSQL JDBC Driver
DriverVersion 42.6.0
Datasource svc
Stacktrace The Error Occurred in
D:\wwwroot\svc3\lib\data\bean.cfm: line 94
- и как это работает для INT? ответ: <cfif !keyInvalid> (а у нас other... когда был idstam, все было однозначно, но с Postgre почему-то idstamp не работает - "Использовать для POSTGRESQL UUID: CF GUID+CF_SQL_OTHER" - вероятно, надо сделать свои типы и маппинг чуть сложнее, чем cf_sql_#type#)
ошибка в dispatch_detail.cfm, рассчитанном на целочисленный id
для idstamp
ERROR: operator does not exist: uuid = character
Подсказка: No operator matches the given name and argument types. You might need to add explicit type casts.
Позиция: 96
для other
ERROR: invalid input syntax for type uuid: ""
Где: unnamed portal parameter $1 = ''
Но! в соседнем шаблоне tariff.cfm "other" работает, и в этом раньше работало - разница была в вызове, в одном случае было пустая строка, в другом отсутствовал параметр

238
etc/db/service_catalog.sql Normal file
View File

@ -0,0 +1,238 @@
/*Êàòàëîã óñëóã
Ïîääåðæêà êîìïîçèòíûõ óñëóã
Ïîääåðæêà âàðèàòèâíîñòè óñëóãè
Ïîääåðæêà âàðèàòèâíîñòè ïàðàìåòðà
Ïðàéñ-ëèñò
*/
-- ìîæíî äîáàâèòü áàçîâûå åäèíèöû è ïåðåñ÷åò
if exists (select * from sysobjects where name='measure') drop table measure
create table measure (
measure_id int identity PRIMARY KEY NOT NULL
,measure varchar(255) NOT NULL
,measure_short varchar(9) NOT NULL
,measure_short_en varchar(9) NULL
,descr varchar(MAX) NULL
)
go
insert into measure (measure, measure_short) values ('øòóêà','øò.')
insert into measure (measure, measure_short) values ('êèëîâàòò','êÂò')
insert into measure (measure, measure_short) values ('êèëîâàòò-÷àñ','êÂò-÷')
insert into measure (measure, measure_short) values ('ãèãàãåðö','ÃÃö')
insert into measure (measure, measure_short) values ('ãèãàáàéò','ÃÁàéò')
insert into measure (measure, measure_short) values ('10000 øò.','10òûñ.øò.')
go
if exists (select * from sysobjects where name='service_type') drop table service_type
create table service_type (
service_type_id int PRIMARY KEY NOT NULL
,service_type varchar(255) NOT NULL
)
go
insert into service_type (service_type_id, service_type) values (1,'èíñòàëëÿöèîííàÿ')
insert into service_type (service_type_id, service_type) values (2,'ïåðèîäè÷åñêàÿ') -- ïåðèîä ôèêñèðóåòñÿ â êîíòðàêòå, ïî óìîë÷àíèþ ìåñÿö
insert into service_type (service_type_id, service_type) values (3,'òàðèôèöèðóåìàÿ')
go
-- âàðèàíò âûáèðàåòñÿ èç ãðóïïû. Ýòî, ñêîðåå, íå ñåìàíòèêà ïðåäìåòíîé îáëàñòè, à èñêóññòâåííàÿ êîíñòðóêöèÿ
-- âàðèàíò çàäàåòñÿ îïðåäåëÿþùåé õàðàêòåðèñòèêîé, êîòîðàÿ ìîæåò êîìáèíèðîâàòü íåñêîëüêî óñëîâèé
if exists (select * from sysobjects where name='modifier_class') drop table modifier_class
create table modifier_class (
modifier_class_id int identity PRIMARY KEY NOT NULL
,modifier_class varchar(255) NOT NULL
,descr varchar(MAX) NULL
)
go
-- çíà÷åíèå ìîäèôèêàòîðà
if exists (select * from sysobjects where name='modifier') drop table modifier
create table modifier (
modifier_id int identity PRIMARY KEY NOT NULL
,modifier_class_id int NOT NULL
,modifier varchar(255) NOT NULL
,modifier_en varchar(255) NULL
,descr varchar(MAX) NULL
)
go
--alter table modifier add modifier_en varchar(255) NULL
-- ýêâèâàëåíò íîìåíêëàòóðû â 1Ñ
if exists (select * from sysobjects where name='abstract_service') drop table abstract_service
create table abstract_service (
abstract_service_id int identity PRIMARY KEY NOT NULL
,abstract_service varchar(255) NOT NULL
,service_type_id INT NOT NULL
,modifier_class_id INT NULL -- migrated from service (no support for multiple modifier classes)
,code varchar(31) NOT NULL
,version int NOT NULL
,descr varchar(MAX) NULL
)
go
/*
-- ïðèøëîñü âûäåëèòü ýòó ñóùíîñòü
-- âåðîÿòíî, äëÿ áîëüøèíñòâà íîìåíêëàòóð îíà íå íóæíà (ïðèäåòñÿ äîáàâëÿòü òðèâèàëüíóþ),
-- äîñòàòî÷íî ìèãðàöèè àòðèáóòà modifier_class_id â abstract_service
if exists (select * from sysobjects where name='service_class') drop table service_class
create table service_class (
service_class_id int identity PRIMARY KEY NOT NULL
,abstract_service_id int NOT NULL
,modifier_class_id INT NULL
--,service_class varchar(255) NOT NULL -- íå èñïîëüçóåòñÿ
,descr varchar(MAX) NULL
)
go
*/
-- êîíêðåòíûé âàðèàíò ñåðâèñà
-- â 1Ñ ðåàëèçóåòñÿ ËÈÁÎ ôîðìîé êîìïîíîâêè, ËÈÁÎ ìîäèôèêàöèåé íîìåíêëàòóðû
-- ìîäèôèêàòîð îòíîñèòñÿ ê ôîðìå êîìïîíîâêè
-- ôîðìà êîìïîíîâêè åñòü äëÿ ëþáîé êîíêðåòíîé êîìïëåêñíîé (êîìïîçèòíîé) íîìåíêëàòóðû, îíà îïðåäåëÿåò ñîñòàâ ïàðàìåòðîâ
-- ïðè ýòîì îíà ñâÿçûâàåòñÿ ëèáî ñ íîìåíêëàòóðîé, ëèáî ñ êîíêðåòíîé ðåàëèçàöèåé íîìåíêëàòóðû
if exists (select * from sysobjects where name='service') drop table service
create table service (
service_id int identity PRIMARY KEY NOT NULL
,abstract_service_id int NOT NULL
,modifier_id INT NULL
--,service varchar(255) NOT NULL -- íå èñïîëüçóåòñÿ
,descr varchar(MAX) NULL
,measure_id int NULL --*** ìèãðèðîâàòü â àáñòðàêòíóþ óñëóãó?
,precision int NULL
,base_price decimal(15,4) NULL
,CONSTRAINT UK_abstract_service_modifier UNIQUE(abstract_service_id, modifier_id)
)
go
--alter table service add measure_id int NULL
--alter table service add precision int NULL
--alter table service add base_price decimal(15,4) NULL
--alter table service add CONSTRAINT UK_abstract_service_modifier UNIQUE(abstract_service_id, modifier_id)
-- íàäî ïðîâåðÿòü, ïàðàìåòðû äëÿ âàðèàíòà ðåàëèçàöèè âñåãäà ñîáñòâåííûå, ëèáî øàðÿòñÿ
-- áóäåò ïîíÿòíî ïðè âûãðóçêå
if exists (select * from sysobjects where name='param_class') drop table param_class
create table param_class (
param_class_id int identity PRIMARY KEY NOT NULL
,param_class varchar(255) NOT NULL
,measure_id int NULL
/*,precision int NULL
,show_in_spec bit NOT NULL*/
,descr varchar(MAX) NULL
)
go
if exists (select * from sysobjects where name='param') drop table param
create table param (
param_id int identity PRIMARY KEY NOT NULL
,param_class_id int NULL--NOT NULL
,param varchar(255) NOT NULL
,measure_id int NULL -- overrides param_class.measure
,precision int NULL -- *** âèäèìî, ïîñòóïèòü, êàê ñ åäèíèöåé èçìåðåíèÿ, â param_class.precision øàáëîí
--,show_in_spec bit NOT NULL default 1
,base_price decimal(15,4) NULL -- Íà ñàìîì äåëå áàçîâûå öåíû îòäåëüíî, ýòî îáåñïå÷èâàåò âåðñèîííîñòü ïðàéñ-ëèñòà
,descr varchar(MAX) NULL
)
--alter table param add base_price decimal(15,4) NULL
--alter table param add measure_id int NULL
go
-- ñîñòàâ ïàðàìåòðîâ, ýêâèâàëåíò òàáëè÷íîé ÷àñòè ôîðìû êîìïîíîâêè
-- øàáëîí
-- â ñåðâèñå äîëæíû áûòü ïëåéñõîëäåðû äëÿ ïàðàìåòðîâ, îïðåäåëÿåìûõ ïðè ôîðìèðîâàíèè ñïåöèôèêàöèè è ôèêñèðîâàííûå ïàðàìåòðû
-- ìîæíî ñäåëàòü 2 òàáëèöû: øàáëîí ïàðàìåòðîâ è öåíû ïàðàìåòðîâ
-- ïðè ýòîì çàïèñè äëÿ ïðîñòûõ ïàðàìåòðîâ áóäóò äóáëèðîâàòüñÿ 1:1, à äëÿ âàðèàòèâíûõ 1:n
if exists (select * from sysobjects where name='service_param') drop table service_param
create table service_param (
service_param_id int identity PRIMARY KEY NOT NULL
,service_id int NOT NULL -- FK
--,modifier_id int NULL -- FK êîíòåêñò âàðèàíòà
,param_class_id int NULL -- êîíêðåòíûé ïàðàìåòð ìîæåò âûáèðàòüñÿ ïðè ââîäå ñïåöèôèêàöèè. Â 1Ñ ýòî ðåøàåòñÿ òàê: åñëè ó ïàðàìåòðà åñòü ïîòîìêè, âûáîð â ñïåöèôèêàöèè
,param_id int NULL
--,base_price decimal(15,4) NULL -- Íàñëåäîâàòü îò ïàðàìåòðà. Íà ñàìîì äåëå áàçîâûå öåíû îòäåëüíî, ýòî îáåñïå÷èâàåò âåðñèîííîñòü ïðàéñ-ëèñòà
,descr varchar(MAX) NULL
,CONSTRAINT CK_param_xor_class CHECK (((param_class_id IS NULL) AND NOT (param_id IS NULL)) OR ((param_id IS NULL) AND NOT (param_class_id IS NULL)))
-- óäàëèòü îãðàíè÷åíèå, â êîíòåêñòå óñëóãè äîëæíû áûòü çàäàíû òàêæå öåíû êîíêðåòíûõ ïàðàìåòðîâ
-- alter table service_param drop CONSTRAINT CK_param_xor_class
)
go
-- åñëè â service_param óêàçàí êîíêðåòíûé ïàðàìåòð, òî îòíîøåíèå 1:1, åñëè êëàññ - òî 1:n
-- â äàëüíåéøåì ìîæíî ñäåëàòü âåðñèîííîñòü öåí
-- íå òîëüêî öåíû, íî è âàðèàíòû âûáîðà äëÿ àáñòðàêòíûõ ïàðàìåòðîâ
if exists (select * from sysobjects where name='service_param_price') drop table service_param_price
create table service_param_price (
service_param_price_id int identity PRIMARY KEY NOT NULL
,service_param_id int NOT NULL -- FK, äëÿ êîíêðåòíûõ ïàðàìåòðîâ 1:1. Êàê ýòî çàùèòèòü îãðàíè÷åíèÿìè, íå ïðèäóìàë
--,param_class_id int NOT NULL
,param_id int NOT NULL
,base_price decimal(15,4) NULL -- Íàñëåäîâàòü îò ïàðàìåòðà, äëÿ óäîáñòâà. Íà ñàìîì äåëå áàçîâûå öåíû äîëæíû âåñòèñü îòäåëüíî, ýòî îáåñïå÷èâàåò âåðñèîííîñòü ïðàéñ-ëèñòà
CONSTRAINT UK_service_param_price UNIQUE (service_param_id, param_id)
)
go
if exists (select * from sysobjects where name='specification') drop table specification
create table specification (
specification_id int identity PRIMARY KEY NOT NULL
,specification varchar(255) NOT NULL
,descr varchar(MAX) NULL
)
go
if exists (select * from sysobjects where name='specification_item') drop table specification_item
create table specification_item (
specification_item_id int identity PRIMARY KEY NOT NULL
,specification_id int NOT NULL
,service_id int NOT NULL
--,modifier_id int NULL
,specification_item varchar(1023) NOT NULL -- èìÿ äëÿ ïå÷àòè
,quantity decimal(15,4) NULL
,price decimal(15,4) NULL -- äëÿ êîìïîçèòíûõ ñåðâèñîâ ðàñ÷åò ïî ïàðàìåòðàì
)
go
--alter table specification_item alter column specification_item varchar (1023) NOT NULL
if exists (select * from sysobjects where name='specification_item_param') drop table specification_item_param
create table specification_item_param (
specification_item_param_id int identity PRIMARY KEY NOT NULL
,specification_item_id int NOT NULL
,service_param_id int NOT NULL -- åñëè ïàðàìåòð êîíêðåòíûé, òî param_id îòñþäà
,param_id int NULL -- åñëè â ñåðâèñå çàäàí òîëüêî êëàññ ïàðàìåòðà, òî çäåñü íàäî êîíêðåòèçèðîâàòü *** Ìîæíî äåíîðìàëèçîâàòü, âñåãäà ïîìåùàÿ ñþäà çíà÷åíèå
,quantity decimal(15,4) NULL
,price decimal(15,4) NULL
)
go
----------------------------------------
--9:00 24.09.2020
-- ýòî íå ÖÎÄû, à ïëîùàäêè
if exists (select * from sysobjects where name='site') drop table site
create table site (
site_id int identity PRIMARY KEY NOT NULL
,site varchar(255) NOT NULL
,descr varchar(MAX) NULL
)
go
insert into site(site) values('ÖÎÄ ÌÌÒÑ-9')
insert into site(site) values('ÖÎÄ ÌÌÒÑ-10')
insert into site(site) values('ÖÎÄ Êóð÷àòîâñêèé')
insert into site(site) values('ÖÎÄ Îñòàïîâñêèé')
insert into site(site) values('ÖÎÄ Óäîìëÿ')
insert into site(site) values('ÖÎÄ Åêàòåðèíáóðã')
insert into site(site) values('ÖÎÄ Àäëåð')
insert into site(site) values('ÖÎÄ NORD')
insert into site(site) values('ÖÎÄ OST')
go

8
etc/db/set_env.cmd Normal file
View File

@ -0,0 +1,8 @@
REM set Windows env
setx datasource_svc_class org.postgresql.Driver /M
setx datasource_svc_connectionString jdbc:postgresql://localhost:5432/svc /M
setx datasource_svc_username postgres /M
setx datasource_svc_password encrypted:8ea2101f286dfcf2947cb2162e927cb769b3f845b6d4c57ef2ae89463d72d97842a2228c7ba562a24ee8eaf728350ab6 /M
setx datasource_svc_connectionLimit 5 /M
pause

409
etc/db/spec.sql Normal file
View File

@ -0,0 +1,409 @@
/*Ñïåöèôèêàöèè ñ âåðñèîííîñòüþ
*/
-- ìîæíî äîáàâèòü áàçîâûå åäèíèöû è ïåðåñ÷åò
drop table if exists measure CASCADE;
create table measure (
measure_id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY NOT NULL
,measure varchar(255) NOT NULL
,measure_short varchar(9) NOT NULL
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
);
insert into measure (measure, measure_short) values ('øòóêà','øò.');
insert into measure (measure, measure_short) values ('êèëîâàòò','êÂò');
insert into measure (measure, measure_short) values ('êèëîâàòò-÷àñ','êÂò-÷');
insert into measure (measure, measure_short) values ('ãèãàãåðö','ÃÃö');
insert into measure (measure, measure_short) values ('ãèãàáàéò','ÃÁàéò');
insert into measure (measure, measure_short) values ('10000 øò.','10òûñ.øò.');
drop table if exists contragent CASCADE;
create table contragent (
contragent_id int GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY
,contragent varchar(255) NULL
,descr text NULL -- comments
,is_provider bool NOT NULL DEFAULT false
,external_uid uuid NULL
,external_code varchar(255) NULL --WZ
,dt_created timestamptz NOT NULL default CURRENT_TIMESTAMP -- âðåìÿ çàïèñè ïî ÷àñàì ñåðâåðà ÁÄ
,creator_id int NULL -- èäåíòèôèêàòîð ïîëüçîâàòåëÿ, ñîçäàâøåãî çàïèñü
,dt_updated timestamptz NOT NULL default CURRENT_TIMESTAMP
,updater_id int NULL -- èäåíòèôèêàòîð ïîëüçîâàòåëÿ, îáíîâèâøåãî çàïèñü
);
ALTER TABLE contragent OWNER TO dbo;
-- äàííûå äëÿ òåñòèðîâàíèÿ
insert into contragent (contragent, is_provider) values ('NUBES', true); -- ïðåäïîëàãàåòñÿ, ÷òî ïðîâàéäåð òîëüêî îäèí, íî ýòî íå ïîääåðæèâàåòñÿ îãðàíè÷åíèÿìè
insert into contragent (contragent) values
('Ðîãà è Êîïûòà ÎÎÎ')
,('Ëþòèê ÇÀÎ')
;
drop table if exists contract CASCADE;
create table contract (
contract_id int GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY
,contragent_id int NOT NULL
,contract varchar(255) NULL -- íîìåð êîíòðàêòà
,dt_contract timestamptz NOT NULL
,is_closed bool NOT NULL default false
,dt_closed timestamptz NULL -- äàòà çàâåðøåíèÿ êîíòðàêòà
,descr text NULL -- comments
,dt_created timestamptz NOT NULL default CURRENT_TIMESTAMP --
,creator_id int NULL -- èäåíòèôèêàòîð ïîëüçîâàòåëÿ, ñîçäàâøåãî çàïèñü
,dt_updated timestamptz NOT NULL default CURRENT_TIMESTAMP --
,updater_id int NULL -- èäåíòèôèêàòîð ïîëüçîâàòåëÿ, îáíîâèâøåãî çàïèñü
);
ALTER TABLE contract OWNER TO dbo;
insert into contract (contragent_id,contract,dt_contract) values (2,'test',CURRENT_TIMESTAMP);
-- ñîãëàøåíèå îáåñïå÷èâàåò ÿâíóþ ïðèêëàäíóþ âåðñèîííîñòü
drop table if exists agreement CASCADE;
create table agreement (
--agreement_id int GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY
--,
contract_id int NOT NULL
,agreement_version int NOT NULL
,agreement varchar(255) NULL -- íàçâàíèå ñîãëàøåíèÿ
,dt_agreement timestamptz NOT NULL -- ôîðìàëüíàÿ äàòà, íå ñâÿçàíà ñ âåðñèîííîñòüþ (ìîæåò áûòü, ïîðÿäîê)
,is_actual boolean NOT NULL -- ñ÷èòàåì, ÷òî íà äîãîâîð 1 äåéñòâóþùåå ñîãëàøåíèå - êîòîðûå äî íåãî, òå óñòàðåëè, êîòîðûå ïîñëå, òå â ïðîåêòå
,descr text NULL
,dt_created timestamptz NOT NULL default CURRENT_TIMESTAMP --
,creator_id int NULL -- èäåíòèôèêàòîð ïîëüçîâàòåëÿ, ñîçäàâøåãî çàïèñü
,dt_updated timestamptz NOT NULL default CURRENT_TIMESTAMP --
,updater_id int NULL -- èäåíòèôèêàòîð ïîëüçîâàòåëÿ, îáíîâèâøåãî çàïèñü
,CONSTRAINT PK_agreement PRIMARY KEY (contract_id, agreement_version)
);
ALTER TABLE agreement OWNER TO dbo;
insert into agreement (contract_id,agreement_version,dt_agreement,is_actual) values (1,0,CURRENT_TIMESTAMP,true);
-- øàïêà ñïåöèôèêàöèè, íå âåðñèîííàÿ (íå òåìïîðàëüíàÿ)
drop table if exists specification CASCADE;
create table specification (
specification_id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY NOT NULL
,specification varchar(255) NOT NULL
,contract_id int NOT NULL
,descr text NULL
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
);
ALTER TABLE specification OWNER TO dbo;
insert into specification (specification,contract_id) values ('first spec',1);
-- íà ñîãëàøåíèå äîëæíà áûòü îäíà àêòóàëüíàÿ âåðñèÿ ñïåöèôèêàöèè
drop table if exists specification_version CASCADE;
create table specification_version (
specification_id int
,agreement_version int NOT NULL -- FK agreement
,descr text NULL
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
,CONSTRAINT PK_specification_version PRIMARY KEY (specification_id, agreement_version)
);
ALTER TABLE specification_version OWNER TO dbo;
-- ñòðîêà ñïåöèôèêàöèè
drop table if exists specification_item CASCADE;
create table specification_item (
specification_item_uid uuid NOT NULL PRIMARY KEY DEFAULT gen_random_uuid() -- êëþ÷ ñòðîêè
,specification_id int NOT NULL --FK
,svc_id int NOT NULL --immutable
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
);
ALTER TABLE specification_item OWNER TO dbo;
-- âåðñèÿ ñòðîêè ñïåöèôèêàöèè (âåðñèîííîñòü áåðåòñÿ îò ñïåêè)
drop table if exists specification_item_version CASCADE;
create table specification_item_version (
specification_item_uid uuid NOT NULL -- êëþ÷ ñòðîêè
,agreement_version int NOT NULL -- ÂÀÆÍÎ: åñëè ñòðîêà íå ðåäàêòèðîâàëàñü - âåðñèÿ áóäåò ñòàðîé (ýêîíîìèì âåðñèé, *** íî ìîæíî ñäåëàòü òàáëèöó, ñîáèðàþùóþ âåðñèè ñòðîê)
,dt_from timestamptz NULL
,dt_to timestamptz NULL
,specification_item_version varchar(1023) NOT NULL -- èìÿ äëÿ ïå÷àòè
,quantity decimal(15,4) NULL
,price decimal(15,4) NULL
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
,CONSTRAINT PK_specification_item_version PRIMARY KEY (specification_item_uid, agreement_version)
);
ALTER TABLE specification_item OWNER TO dbo;
-- ïàðàìåòð (êîìïîíåíò) ñîáñòâåííîé âåðñèîííîñòè íå èìååò, ïðè ñîçäàíèè íîâîé âåðñèè ñòðîêè êëîíèðóåòñÿ
drop table if exists specification_item_param CASCADE;
create table specification_item_param (
specification_item_param_id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY NOT NULL
,specification_item_uid uuid NOT NULL
,agreement_version int NOT NULL
,service_param_id int NOT NULL
,quantity decimal(15,4) NULL
,price decimal(15,4) NULL
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
);
ALTER TABLE specification_item_param OWNER TO dbo;
drop table if exists svc CASCADE;
CREATE TABLE svc (
svc_id integer NOT NULL,
svc character varying(255),
descr text,
dt_created timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
creator_id integer,
dt_updated timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater_id integer,
is_production_ready boolean DEFAULT false NOT NULL,
code character varying(255),
man text,
svc_short character varying(255),
resource_realm_type_id integer,
version character varying(255),
orchestrator_name character varying(255),
sort integer
);
ALTER TABLE svc OWNER TO dbo;
INSERT INTO svc VALUES (92, 'k8s_mongodb', '', '2024-09-09 12:53:00.022+03', 3, '2024-09-09 12:53:00.022+03', 3, false, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (95, 'NodeJS - ñåðâåð ïðèëîæåíèé', 'Îáðàç: node:16', '2024-12-10 17:57:41.06+03', 3, '2025-03-07 18:12:53.508+03', 3, true, '', 'Îáðàç: node:16', 'nodejs', 3, '0.0.6', 'Node', NULL);
INSERT INTO svc VALUES (50, 'Nextcloud - ïëàòôîðìà ñîâìåñòíîé ðàáîòû', 'Ðåñóðñíàÿ ïëàòôîðìà: k8s. Àâòîìàòèçàöèÿ: helm chart', '2024-09-09 12:51:27.551+03', 3, '2025-02-28 18:11:26.017+03', 3, true, '', 'Ðåñóðñíàÿ ïëàòôîðìà: k8s. Àâòîìàòèçàöèÿ: helm chart', 'nextcloud', 3, '0.0.3', 'Nextcloud', NULL);
INSERT INTO svc VALUES (21, 'Âèðòóàëüíûé ÄÖ äëÿ VM (vc_vdc)', 'Âèðòóàëüíûé ÄÖ â Cloud Director. Òðåáóåò íàëè÷èå Îðãàíèçàöèè', '2024-04-08 10:59:07.350806+03', NULL, '2025-02-12 15:42:07.821+03', 10, false, '', 'Âèðòóàëüíûé ÄÖ â Cloud Director. Òðåáóåò íàëè÷èå Îðãàíèçàöèè', '', NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (26, 'vApp äëÿ VM (vc_vapp)', 'Ïàïêà â êëàóä äèðåêòîðå. Äëÿ óñòàíîâêè íóæåí vc_nsxt', '2024-12-23 14:54:46.277+03', 3, '2025-02-12 15:42:46.017+03', 10, false, '', 'Ïàïêà â êëàóä äèðåêòîðå. Äëÿ óñòàíîâêè íóæåí vc_nsxt', '', NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (111, 'DNS-çàïèñü', '', '2024-09-17 14:22:05.028+03', 11, '2025-02-28 16:45:10.351+03', 3, true, '', '', 'dnsrecord', 4, '0.0.4', 'Records', NULL);
INSERT INTO svc VALUES (13, 'S3 áàêåò (s3_bucket)', 'Òðåáóåò íàëè÷èÿ ó÷åòíîé çàïèñì S3<br/>Ðåñóðñíàÿ ïëàòôîðìà: Ceph', '2024-12-11 23:19:43.469+03', 3, '2025-02-28 16:43:49.758+03', 3, true, '', 'Òðåáóåò íàëè÷èÿ ó÷åòíîé çàïèñì S3<br/>Ðåñóðñíàÿ ïëàòôîðìà: Ceph', 's3bucket', 1, '0.0.3', 'Bucket', NULL);
INSERT INTO svc VALUES (20, 'Îðãàíèçàöèÿ äëÿ VM â Cloud Director (vc_organization)', 'Îðãàíèçàöèÿ â êëàóä äèðåêòîðå', '2024-04-08 10:59:07.350806+03', NULL, '2025-02-12 15:41:57.046+03', 10, false, '', 'Îðãàíèçàöèÿ â êëàóä äèðåêòîðå', '', NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (12, 'S3 - ó÷åòíàÿ çàïèñü', 'S3 account, ðåñóðñíàÿ ïëàòôîðìà CEPH (S3 CEPH). Íàñòðîåí ñáîð ìåòðèê, àâòîìàòèçàöèÿ áèëëèíãà â ðàçðàáîòêå', '2024-04-08 10:59:07.350806+03', NULL, '2025-02-28 16:42:41.829+03', 3, true, '', 'S3 account, ðåñóðñíàÿ ïëàòôîðìà CEPH (S3 CEPH). Íàñòðîåí ñáîð ìåòðèê, àâòîìàòèçàöèÿ áèëëèíãà â ðàçðàáîòêå', 's3', 1, '1.0.0', 'Ceph', NULL);
INSERT INTO svc VALUES (32, 'PostgreSQL íà ÂÌ (vc_vm_postgresql_std)', 'Ñåðâèñ íàñòðîéêè PostgreSQL äëÿ âèðòóàëüíîé ìàøèíû.<br/>Òðåáóåò íàëè÷èÿ ÂÌ<br/><br/>Âåðñèÿ Postgre - 17', '2024-08-05 12:47:46.275+03', 3, '2025-02-12 15:42:55.441+03', 10, false, '', 'Ñåðâèñ íàñòðîéêè PostgreSQL äëÿ âèðòóàëüíîé ìàøèíû.<br/>Òðåáóåò íàëè÷èÿ ÂÌ<br/><br/>Âåðñèÿ Postgre - 17', '', NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (100, 'tenantOpenwhisk', 'Äîáàâëåíèå è óäàëåíèÿ ïîëüçîâàòåëÿ äëÿ ðàáîòû ñ Openwhisk', '2024-09-12 13:43:55.166+03', 3, '2024-12-26 13:06:02.166+03', 3, false, '', 'Äîáàâëåíèå è óäàëåíèÿ ïîëüçîâàòåëÿ äëÿ ðàáîòû ñ Openwhisk', NULL, NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (25, 'Âíåøíèé IP àäðåñ äëÿ VM (vc_external_ip)', 'Ñîçäàíèå external Ip â Cloud Director. <br/>Òðåáóåò íàëè÷èå óñëóãè', '2024-12-12 16:32:45.488+03', 3, '2025-02-28 16:47:42.541+03', 3, true, '', 'Ñîçäàíèå external Ip â Cloud Director. <br/>Òðåáóåò íàëè÷èå óñëóãè', 'vcexternalip', 2, '0.0.2', 'Ip', NULL);
INSERT INTO svc VALUES (96, 'pgAdmin - êîíñîëü äëÿ PostgreSQL', '', '2024-12-10 18:28:43.874+03', 3, '2025-02-28 17:48:10.242+03', 3, true, '', '', 'pgadmin', 3, '0.0.2', 'Pgadmin', NULL);
INSERT INTO svc VALUES (110, 'DNS-çîíà', '', '2024-09-16 18:52:52.357+03', 11, '2025-02-28 16:45:17.753+03', 3, true, '', '', 'dnszone', 4, '0.0.3', 'Zones', NULL);
INSERT INTO svc VALUES (99, 'k8s_gitea', '', '2025-02-28 17:18:32.548+03', 3, '2025-02-28 17:43:41.652+03', 3, true, '', '', '', 3, '0.0.1', 'Gitea', NULL);
INSERT INTO svc VALUES (82, 'Harbor Registry (registry_k8s)', 'Harbor Registry. Ðåñóðñíàÿ ïëàòôîðìà: k8s. Àâòîìàòèçàöèÿ: helm chart. Àâòîðèçàöèÿ: keycloak', '2024-09-09 12:52:04.345+03', 3, '2025-02-28 18:09:50.071+03', 3, true, '', 'Harbor Registry. Ðåñóðñíàÿ ïëàòôîðìà: k8s. Àâòîìàòèçàöèÿ: helm chart. Àâòîðèçàöèÿ: keycloak', 'harbor', 3, '0.0.2', 'Registry', NULL);
INSERT INTO svc VALUES (2, 'k8sTemplate', '', '2025-02-28 17:06:21.371+03', 3, '2025-02-28 17:06:48.617+03', 3, false, '', '', '', 3, '0.0.1', 'Template', NULL);
INSERT INTO svc VALUES (23, 'VM â Cloud Director (vc_vm)', 'Âèðòóàëüíàÿ ìàøèíà áåç êàêèõ-ëèáî îñîáåííîñòåé. <br/>Äàííàÿ óñëóãà çàïóñêàåò vc_ip äëÿ âûäà÷è áåëîãî àäðåñà è ïîäêëþ÷åíèÿ ê ÂÌ', '2024-08-02 12:53:13.869+03', 3, '2025-02-12 15:42:20.771+03', 10, false, '', 'Âèðòóàëüíàÿ ìàøèíà áåç êàêèõ-ëèáî îñîáåííîñòåé. <br/>Äàííàÿ óñëóãà çàïóñêàåò vc_ip äëÿ âûäà÷è áåëîãî àäðåñà è ïîäêëþ÷åíèÿ ê ÂÌ', '', NULL, NULL, NULL, NULL);
INSERT INTO svc VALUES (91, 'Redis In-Memory DB Cluster on k8s', 'Redis êëàñòåð. Ïîä êåøè. <br/>Ðåñóðñíàÿ ïëàòôîðìà: k8s. <br/>Àâòîìàòèçàöèÿ: k8s operator<br/>port 6379', '2024-09-09 12:52:49.473+03', 3, '2025-03-07 11:39:36.69+03', 3, true, '', '', 'redis', 3, '0.0.3', 'Redis', NULL);
INSERT INTO svc VALUES (81, 'Apache Superset - àíàëèòè÷åñêèé ñåðâåð (superset_k8s)', 'Apache Superset êàê ñåðâèñ. <br/>Ðåñóðñíàÿ ïëàòôîðìà: k8s. <br/>Àâòîìàòèçàöèÿ: k8s operator.<br/>Àâòîðèçàöèÿ: 2FA keycloak (äëÿ äîìåííîãî ëîãèíà @mgmt.nubes.ru)', '2024-09-09 12:51:49.122+03', 3, '2025-02-28 18:09:54.127+03', 3, true, '', 'Apache Superset êàê ñåðâèñ. <br/>Ðåñóðñíàÿ ïëàòôîðìà: k8s. <br/>Àâòîìàòèçàöèÿ: k8s operator.<br/>Àâòîðèçàöèÿ: 2FA keycloak (äëÿ äîìåííîãî ëîãèíà @mgmt.nubes.ru)', 'superset', 3, '0.0.1', 'Superset', NULL);
INSERT INTO svc VALUES (22, 'Ñåòåâûå àäàïòåðû äëÿ VM (vc_nsxt)', '', '2024-04-08 10:59:07.350806+03', NULL, '2025-02-28 17:19:33.266+03', 3, false, '', '', '', NULL, '', '', NULL);
INSERT INTO svc VALUES (93, 'RabbitMQ - ñåðâåð î÷åðåäåé (rabbitmq_k8s)', 'RabbitMQ', '2024-09-09 12:53:09.059+03', 3, '2025-03-07 11:39:29.483+03', 3, true, '', '', 'rabbitmq', 3, '0.0.3', 'Rabbitmq', NULL);
INSERT INTO svc VALUES (90, 'PostgreSQL RDBMS Cluster', 'PostgreSQL êëàñòåð. Ðåñóðñíàÿ ïëàòôîðìà: k8s. Àâòîìàòèçàöèÿ: k8s operator.<br/>Àâòîìàòè÷åñêîå ðåçåðâíîå êîïèðîâàíèå, ðó÷íîå âîññòàíîâëåíèå.', '2024-09-09 12:52:34.457+03', 3, '2025-03-12 10:36:06.529+03', 3, true, '', 'PostgreSQL êëàñòåð. Ðåñóðñíàÿ ïëàòôîðìà: k8s. Àâòîìàòèçàöèÿ: k8s operator.<br/>Àâòîìàòè÷åñêîå ðåçåðâíîå êîïèðîâàíèå, ðó÷íîå âîññòàíîâëåíèå.', 'postgres', 3, '0.0.5', 'Pgsql', NULL);
INSERT INTO svc VALUES (98, 'k8s_simple_http_container', '', '2025-02-28 17:18:40.813+03', 3, '2025-02-28 17:43:48.248+03', 3, true, '', '', 'http', 3, '0.0.3', 'SimpleHttpContainer', NULL);
INSERT INTO svc VALUES (94, 'Lucee - ñåðâåð ïðèëîæåíèé', 'Îáðàç: lucee/lucee:latest', '2024-12-10 16:53:24.068+03', 3, '2025-03-10 10:13:04.713+03', 3, true, '', 'Îáðàç: lucee/lucee:latest', 'lucee', 3, '0.0.9', 'Lucee', NULL);
INSERT INTO svc VALUES (1, 'dummy service', 'Áîëâàíêà äëÿ òåñòîâ', '2024-04-19 19:10:30.206+03', 3, '2025-04-30 19:00:08.473+03', 10, true, '', '', 'dummy', 7, '', 'dummy', NULL);
INSERT INTO svc VALUES (112, 'grafana_tenant', '', '2025-03-12 12:30:15.669+03', 3, '2025-04-28 18:40:23.781+03', 10, false, '', '', 'tenant', 6, '0.0.2', 'Tenant', NULL);
ALTER TABLE ONLY svc
ADD CONSTRAINT PK_svc PRIMARY KEY (svc_id);
-------------------------------------------------------------------------
-- IAM
-------------------------------------------------------------------------
-- usr is normally shared view
drop table if exists usr;
create table usr(
usr_id int GENERATED BY DEFAULT AS IDENTITY(START WITH 11) PRIMARY KEY NOT NULL
,firstname varchar(255) NULL
,middlename varchar(255) NULL
,lastname varchar(255) NOT NULL
,login varchar(255) NOT NULL
,password varchar(255) NULL -- changed from varbinary for postgre and Argon2
,email varchar(255) NOT NULL
,phone_cell varchar(50) NULL
,descr text NULL
,settings text NULL
,locked boolean NOT NULL CONSTRAINT DF_usr_locked DEFAULT(false)
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
,fullname varchar GENERATED ALWAYS AS ((lastname||rtrim(' '||coalesce(firstname,'')))||rtrim(' '||coalesce(middlename,''))) STORED
,shortname varchar GENERATED ALWAYS AS (replace((lastname||rtrim(' '||coalesce(left(firstname,(1))||'.','')))||rtrim(' '||coalesce(left(middlename,(1))||'.','')),' .','')) STORED
);
create unique index UX_login on usr(login);
insert into usr (usr_id,firstname,middlename,lastname,login,password,email,phone_cell)
values (2,'','','Àíîíèìíûé ïîëüçîâàòåëü','anonymous',null,'',null);
insert into usr (usr_id,firstname,middlename,lastname,login,password,email,phone_cell)
values (10,'Ñåðãåé','Þðüåâè÷','Ìèùóê','smishchuk','$argon2id$v=19$m=500,t=3,p=4$d37RBdizC3rwQfINGSoQmg$Bwvr1f+RQf9hpXwV58sgUYzYpupp7iUzfUBACGApT80','msyu@mail.ru',null);
------------------------------
drop table if exists obj;
create table obj ( --
obj varchar(63) NOT NULL PRIMARY KEY
,descr text NULL -- ïðèìå÷àíèÿ
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
);
drop table if exists role;
create table role ( --
role_id int /*identity*/ NOT NULL PRIMARY KEY
,role varchar(255) NOT NULL
,descr text NULL -- ïðèìå÷àíèÿ
,creator_id int NULL
,updater_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_updated timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
);
insert into role (role_id,role) values (1,'Àäìèíèñòðàòîð');
insert into role (role_id,role) values (2,'×èòàòåëü'); -- òîëüêî ÷òåíèå îãðàíè÷åííîãî ñïèñêà ýêðàíîâ
drop table if exists usr_role;
create table usr_role ( --
role_id int NOT NULL
,usr_id int NOT NULL
,CONSTRAINT PK_usr_role primary key (usr_id, role_id)
,creator_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
);
insert into usr_role (role_id,usr_id) values (2,2);
insert into usr_role (role_id,usr_id) values (1,10);
drop table if exists acl;
create table acl(
obj varchar(63) NOT NULL
,role_id int NOT NULL
,permission int NOT NULL -- 1=READ 2=WRITE
,creator_id int NULL
,modifier_id int NULL
,dt_created timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà çàïèñè
,dt_modified timestamp NOT NULL default CURRENT_TIMESTAMP -- äàòà ïîñëåäíåé ìîäèôèêàöèè
,CONSTRAINT PK_acl PRIMARY KEY (obj, role_id)
);
/* insert into obj (obj,descr) values ('abstract_service','Àáñòðàêòíàÿ óñëóãà êàòàëîãà');
insert into obj (obj,descr) values ('price','Ïðàéñ-ëèñò áàçîâûé');
insert into obj (obj,descr) values ('service','Óñëóãà (ðàçâåðíóòûé êàòàëîã)');
insert into obj (obj,descr) values ('abstract_service_rpt','Êàòàëîã');
insert into obj (obj,descr) values ('price_rpt','Ïðàéñ-ëèñò: óñëóãà ñ ïàðàìåòðîì');
insert into obj (obj,descr) values ('export','Îò÷åòû ýêñïîðòà');
insert into obj (obj,descr) values ('modifier_class','Êëàññ õàðàêòåðèñòèêè');
insert into obj (obj,descr) values ('modifier','Õàðàêòåðèñòèêà');
insert into obj (obj,descr) values ('param_class','Êëàññ ïàðàìåòðà');
insert into obj (obj,descr) values ('param','Ïàðàìåòð');
insert into obj (obj,descr) values ('measure','Åäèíèöà èçìåðåíèÿ');
insert into obj (obj,descr) values ('site','Òàðèôíàÿ çîíà');
insert into obj (obj,descr) values ('provider','Ïîñòàâùèê (ÄÇÎ)');
insert into obj (obj,descr) values ('area','Ãðóïïà êàòàëîãà');
insert into obj (obj,descr) values ('service_param','Ïàðàìåòð êîíêðåòíîé óñëóãè');
insert into obj (obj,descr) values ('specification','Ñïåöèôèêàöèÿ');
insert into obj (obj,descr) values ('specification_item','Ñòðîêà ñïåöèôèêàöèè');
insert into obj (obj,descr) values ('specification_item_param','Ðåñóðñ ñòðîêè ñïåöèôèêàöèè (ýêçåìïëÿðà óñëóãè)');
insert into obj (obj,descr) values ('usr','Ïîëüçîâàòåëü');
insert into obj (obj,descr) values ('acl','Ïðàâà äîñòóïà');
insert into obj (obj,descr) values ('service_param_price','Öåíà êîìïîíåíòà');
insert into obj (obj,descr) values ('service_price','Öåíà óñëóãè');
insert into obj (obj,descr) values ('abstract_service_complementary','Äîïîëíèòåëüíàÿ óñëóãà'); */
/* --÷èòàòåëü
insert into acl(obj,role_id,permission) values ('abstract_service',2,1);
insert into acl(obj,role_id,permission) values ('price',2,1);
insert into acl(obj,role_id,permission) values ('service',2,1);
insert into acl(obj,role_id,permission) values ('abstract_service_rpt',2,1);
insert into acl(obj,role_id,permission) values ('abstract_service_doc',2,1);
insert into acl(obj,role_id,permission) values ('price_rpt',2,1);
insert into acl(obj,role_id,permission) values ('modifier_class',2,1);
insert into acl(obj,role_id,permission) values ('modifier',2,1);
insert into acl(obj,role_id,permission) values ('param_class',2,1);
insert into acl(obj,role_id,permission) values ('param',2,1);
insert into acl(obj,role_id,permission) values ('measure',2,1);
insert into acl(obj,role_id,permission) values ('site',2,1);
insert into acl(obj,role_id,permission) values ('provider',2,1);
insert into acl(obj,role_id,permission) values ('area',2,1);
insert into acl(obj,role_id,permission) values ('specification',2,1);
insert into acl(obj,role_id,permission) values ('specification_item',2,1);
insert into acl(obj,role_id,permission) values ('specification_item_param',2,1);
insert into acl(obj,role_id,permission) values ('service_param',2,1);
insert into acl(obj,role_id,permission) values ('abstract_service_param_class',2,1);
insert into acl(obj,role_id,permission) values ('service_param_price',2,1);
insert into acl(obj,role_id,permission) values ('service_price',2,1);
insert into acl(obj,role_id,permission) values ('abstract_service_complementary',2,1);
--àäìèí
insert into acl(obj,role_id,permission) values ('abstract_service',1,2);
insert into acl(obj,role_id,permission) values ('price',1,2);
insert into acl(obj,role_id,permission) values ('service',1,2);
insert into acl(obj,role_id,permission) values ('abstract_service_rpt',1,2);
insert into acl(obj,role_id,permission) values ('abstract_service_doc',1,2);
insert into acl(obj,role_id,permission) values ('price_rpt',1,2);
insert into acl(obj,role_id,permission) values ('export',1,2);
insert into acl(obj,role_id,permission) values ('modifier_class',1,2);
insert into acl(obj,role_id,permission) values ('modifier',1,2);
insert into acl(obj,role_id,permission) values ('param_class',1,2);
insert into acl(obj,role_id,permission) values ('param',1,2);
insert into acl(obj,role_id,permission) values ('measure',1,2);
insert into acl(obj,role_id,permission) values ('site',1,2);
insert into acl(obj,role_id,permission) values ('provider',1,2);
insert into acl(obj,role_id,permission) values ('area',1,2);
insert into acl(obj,role_id,permission) values ('specification',1,2);
insert into acl(obj,role_id,permission) values ('specification_item',1,2);
insert into acl(obj,role_id,permission) values ('specification_item_param',1,2);
insert into acl(obj,role_id,permission) values ('usr',1,2);
insert into acl(obj,role_id,permission) values ('acl',1,2);
insert into acl(obj,role_id,permission) values ('service_param',1,2);
insert into acl(obj,role_id,permission) values ('abstract_service_param_class',1,2);
insert into acl(obj,role_id,permission) values ('service_param_price',1,2);
insert into acl(obj,role_id,permission) values ('service_price',1,2);
insert into acl(obj,role_id,permission) values ('abstract_service_complementary',1,2); */

30
etc/spec.txt Normal file
View File

@ -0,0 +1,30 @@
2025-06-02
можно отметить, что тут смешаны версионность допника и темпоральность строки
Можно сделать таблицу, собирающую версии строк, чтобы не искать каждый раз (а может, нам не нужен снапшот на произвольную дату? или версию допника - вот, я уже запутался)
в сервисе нет единиц измерения у меня
31.05.2025
Спецификация относится к договору. В принципе, в договоре может быть несколько спецификаций, но поддерживать это не кажется безусловно нужным. Каждая новая действующая версия спецификации относится к доп соглашению (возможно для договора ввести нулевой допник). Возможно, для редактирования захочется ввести редакторскую версионность, эту мы не рассматриваем.
Для обсуждения версионности важно, что мы имеем дело с услугами, которые длятся (в отличие от них, для продажи товаров, видимо, имеет смысл только тривиальная редакторская версионность, не имеющая отношения к учету).
Спецификация состоит из номенклатурных позиций с ценой, количеством, датой начала и окончания действия, уникальным ключом строки. Ключ строки может соотноситься 1 к 1 с объектом биллинга для индивидуальных объектов (облачный пул) или 1 ко многим для счетных объектов (ip адрес). Включение разнородных объектов, отличающихся модификаторами (соответственно, кодами) или значениями параметров, не поддерживается.
Версионность спецификации поддерживает: добавление, удаление, изменение строки (почти тоже самое, что услуги) . При добавлении или удалении услуги обязательный атрибут - дата начала или завершения оказания услуги (обе даты имеют смысл "включительно": первый и последний день оказания услуги). Дата начала/завершения может быть какой угодно (хоть через 5 лет, мы не реализуем проверок), но с одним ограничением: даты в цепочке версий строки должны быть последовательными (монотонными), дата завершения не меньше даты начала, дата начала следующей версии не меньше даты завершения предыдущей версии.
Добавленная услуга получает уникальный ключ строки. Ключ удаленной услуги (строки) дискардится. Видимо, есть разные похожие сценарии: удалить услугу (вместе со строкой) с некоторой даты, обнулить количество с некоторой даты, завершить обслуживание с некоторой даты. Разница будет видна, когда дойдем до модификации.
Разница между строкой и инстансом услуги, возможно, нуждается в пояснении. Когда мы редактируем строку, мы подразумеваем, что за ней могут стоять индивидуальные инстансы. Например, при расширении вычислительного пула мы говорим про конкретный пул (в том числе имеющий уникальный идентификатор) , а не просто докидываем куда-то гигабайт или рублей. В случае со счетными объектами обычно подразумевается, что при увеличении количества объекты добавляются к множеству, при уменьшении - убираются из него (строго говоря, это не так - увеличение просто значит, что добавили больше, чем убрали, причем поменяться могли все элементы). Счетные объекты (те же стойки) обычно имеют индивидуальность: у каждого стойко-места свой номер, но это обычно отражается не в спецификации, а в ТУ (возможно, это связано с тем, что индивидуальность элемента не влияет на взаиморасчеты, только количество). Может быть, это не важно.
При изменении строки не может меняться номенклатура. Может меняться количество, параметры (компоненты) композитной услуги, цена (или частные цены компонентов). Чтобы не путаться: дата начала/окончания меняться не может, это не обычный прикладной атрибут, а "драйвер" версионности. Иначе говоря, при изменении строки меняются только числовые значения (можно, наверно, менять примечания и пользовательские названия они на учет не влияют)
Модификация строки нетривиальна по сравнению с созданием и удалением. Когда мы меняем строку, мы создаем новую версию, завершая действие прежней версии некоторым числом и создавая новую версию (непременно) более поздним числом (чаще всего следующим днем, пропуск мы, скорее всего, не захотим поддерживать: это может несколько усложнить формирование счетов... но паузу можно оформить периодом с нулевым количеством).
Таким образом, спецификация содержит версии строк, которые на любую дату составляют актуальную картину, причем на любую дату актуально не более одной версии каждой строки. За расчетный период могут быть актуальными несколько вариантов строки, логических препятствий для этого нет (может быть, этого придется избегать, чтобы исключить противоречия при формировании счетов). Строки не удаляются, а закрываются некоторой датой.
Редактирование (включая возможность двигать даты начала/окончания) в некоторый момент замораживается, и строку нельзя уже поменять задним числом (условия уточнить). Может быть, необходим будет механизм компенсирующих проводок для корректировки задним числом.
Таким образом, мы семантически объединяем даты начала/окончания оказания услуги и даты актуальности версий строк (чтобы не усложнять, и они кажутся очень близкими по смыслу).
Возобновления оказания услуги, наверное, предусматривать не надо: достаточно создать новую строку спецификации с теми же реквизитами и новым уникальным ключом строки - тогда можно рассчитывать на непрерывность цепочек версий (это ограничение выглядит успокаивающим, но непонятно, так ли оно полезно или необходимо). ВременнАя монотонность цепочек версий, напротив, кажется совершенно обязательной.
Номера версий строк монотонны (реализация может позволить наличие пропусков оно логически ничему не противоречит)
Теперь что такое версия спецификации и откуда берется номер версии спецификации. Предлагается считать версией спецификации снапшот версий строк, последовательность таких снапшотов соответствует истории спецификации.
Каждая версия спецификации вносит изменения: строка добавилась, строка удалилась, строка изменилась. Строки, которые не менялись, просто остаются в кумулятивном представлении, и отсутствуют в дифференциальном представлении. Измененная строка в кумулятивном представлении выглядит как «стало вот так с такой даты», а в дифференциальном «изменилось на столько с такой даты».
Если нам нужно 2 раза поменять некоторую строку (скажем, с 15 и 20 числа месяца) нам придется выпустить 2 версии спецификации: формат не предусматривает замножение строк. Вероятно, 2 версии спецификации, в свою очередь, потребуют 2 дополнительных соглашений (кажется, в структуре доп соглашения, даже если предусмотрено несколько спецификаций, то это не версии одной спецификации). Впрочем, не припомню практической необходимости в таких изысках.
Может быть, тут не хватает вопросов, на которые должна отвечать модель, но мне она пока кажется информационно полной и не сильно противоречивой.

127
export.cfm Normal file
View File

@ -0,0 +1,127 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:filter_settings target="export" markerList="sc_onyma_service,sc_service_param_price_service_rcode">
<m:filterparam filter=#filter# param="abstract_service_id" ftype="numeric" list="Yes" expression="(s.abstract_service_id in (?))" default=""/>
<m:filterparam filter=#filter# param="dt_from" ftype="date" expression="(a.dt_status >=? AND a.status_id in (1,2))" default=""/>
<m:filterparam filter=#filter# param="dt_to" ftype="date" expression="(a.dt_status <=? AND a.status_id in (1,2))" default=""/>
</m:filter_settings>
<!---router--->
<cfif structKeyExists(FORM,"sc_onyma_service")>
<cflocation url="sc_onyma_service.cfm"/>
</cfif>
<cfif structKeyExists(FORM,"sc_service_param_price_service_rcode")>
<cflocation url="sc_service_param_price_service_rcode.cfm"/>
</cfif>
<m:prepare_ls entity="" pageInfoOut="pageInfo" trackOut="tr"/>
</m:silent><!---
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
---><!---
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput><b>#i18("Экспорт","Export")#</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>
<cfoutput>
<form action="" method="post" >
<!--- <cfparam name="abstract_service_id" type="string" default=""/><!---list--->--->
<fieldset style="margin:1em; padding:1em; font-size:110%">
<legend>С фильтром по услугам</legend>
<div class="detail">
<div class="tr">
<div class="th">Коды услуг</div>
<div class="td">
<cfquery name="qAbstractService" datasource="#request.DS#">
select
abstract_service_id, abstract_service, code
from abstract_service a
where 1=1
order by a.code
</cfquery>
<c:combo
query=#qAbstractService#
combo="abstract_service_id"
id="abstract_service_id"
key="abstract_service_id"
displayf="##code## ##abstract_service##"
selected=#abstract_service_id#
empty=""
multiple="multiple"
size="10"
/>
<i>(множественное выделение)</i>
</div>
</div>
<div class="tr">
<div class="th">С</div>
<div class="td">
<input type="text" name="dt_from" id="dt_from" value="#dateFormat(dt_from,'DD.MM.YYYY')#"/>
<button type="button" onclick="document.getElementById('dt_from').value='#DateFormat(Now(), 'DD.MM.YYYY')#';">Сегодня</button>
<i>по дате присвоения статуса "Проект" или "Активна"</i>
</div>
</div>
<div class="tr">
<div class="th">По</div>
<div class="td">
<input type="text" name="dt_to" id="dt_to" value="#dateFormat(dt_to,'DD.MM.YYYY')#"/>
<button type="button" onclick="document.getElementById('dt_to').value='#DateFormat(Now(), 'DD.MM.YYYY')#';">Сегодня</button>
<i>по дате присвоения статуса "Проект" или "Активна"</i>
</div>
</div>
<div class="tr">
<div class="th"></div>
<div class="td">
<button name="sc_onyma_service" style="font-size:110%; cursor:pointer; font-weight:bold;">SC_onyma_service</button>
</div>
</div>
<div class="tr">
<div class="th"></div>
<div class="td">
<button name="sc_service_param_price_service_rcode" style="font-size:110%; cursor:pointer; font-weight:bold;">SC_service_param_price_Service_Rcode</button>
</div>
</div>
</div>
</fieldset>
</form>
</cfoutput>
<fieldset style="margin:1em; padding:1em; font-size:110%;line-height:2em;">
<legend>Без фильтра</legend>
<!--- <a href="sc_onyma_service.cfm">SC_onyma_service</a><br/>--->
<a href="sc_service_param_price.cfm" class="button" style="font-weight:bold; margin-left:10em;">SC_service_param_price</a><br/>
<a href="sc_rcode.cfm" class="button" style="font-weight:bold; margin-left:10em;">SC_Rcode</a><br/>
<!--- <a href="sc_service_param_price_service_rcode.cfm">SC_service_param_price_Service_Rcode</a><br/>--->
</fieldset>
</cfif>
<layout:page section="footer"/>

46
export1.cfm Normal file
View File

@ -0,0 +1,46 @@
<cfsilent>
<cfimport prefix="m" taglib="lib"/>
<cfimport prefix="c" taglib="lib/controls"/>
<cfimport prefix="d" taglib="lib/data"/>
<cfimport prefix="layout" taglib="layout"/>
</cfsilent><m:silent silent="No">
<m:prepare_filter entity="export" pageInfoOut="pageInfo" trackOut="tr" lsPage="."/>
<m:filter_settings target="export">
<m:filterparam filter=#filter# param="service_type_id" ftype="numeric" compare="EQ" field="a.service_type_id" default=""/>
<m:filterparam filter=#filter# param="abstract_service" ftype="string" compare="LIKE%" field="a.abstract_service" default=""/>
<m:filterparam filter=#filter# param="code" ftype="string" compare="LIKE%" field="a.code" default=""/>
</m:filter_settings>
</m:silent><!---
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
---><!---
---><layout:page section="header" pageInfo=#pageInfo#>
<layout:attribute name="title">
<cfoutput><b>#i18("Экспорт","Export")#</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="padding:2em; font-size:110%">
<a href="sc_onyma_service.cfm">SC_onyma_service</a><br/>
<a href="sc_service_param_price.cfm">SC_service_param_price</a><br/>
<a href="sc_rcode.cfm">SC_Rcode</a><br/>
<a href="sc_service_param_price_service_rcode.cfm">SC_service_param_price_Service_Rcode</a><br/>
</div>
</cfif>
<layout:page section="footer"/>

BIN
img/Arrow-Left-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
img/Arrow-left-icon (1).png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

47
img/DataLime.svg Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW X8 -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="78.6273mm" height="70.4009mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 37746 33797"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
<![CDATA[
.fil3 {fill:none}
.fil2 {fill:#D7F372}
.fil4 {fill:#FEFEFE;fill-rule:nonzero}
.fil5 {fill:#638328;fill-rule:nonzero}
.fil1 {fill:url(#id1)}
.fil0 {fill:url(#id2)}
]]>
</style>
<clipPath id="id0">
<path d="M20432 0c8718,-38 15581,2266 15458,9209 -25,787 -197,745 -1206,434 -5376,-1662 -8578,-3016 -12410,-6248 -1067,-900 -1945,-1797 -2743,-2837 -478,-648 -8,-545 901,-558zm-18416 19428c1785,-4186 2803,-6725 6956,-9214 1814,-1088 3728,-1795 5744,-2401 5011,-1469 9917,-953 14495,540 1697,562 2833,1208 4123,2158 602,450 989,178 1872,-71 402,-113 1572,-529 1912,-305 933,615 -675,1120 -1291,1389 -1798,785 -1256,251 -1265,1780 -43,7030 -7302,11174 -13250,12374 -3409,688 -7029,1146 -9343,1499 -5916,900 -5060,-1185 -9071,-2819 -937,-381 -2531,-341 -2879,-1361 -223,-655 1540,-2751 1997,-3569z"/>
</clipPath>
<linearGradient id="id1" gradientUnits="userSpaceOnUse" x1="-740.954" y1="15224.8" x2="37478.6" y2="11458.4">
<stop offset="0" style="stop-opacity:1; stop-color:#C6C517"/>
<stop offset="1" style="stop-opacity:1; stop-color:#E7D900"/>
</linearGradient>
<linearGradient id="id2" gradientUnits="userSpaceOnUse" x1="-442.19" y1="20004.6" x2="37830.6" y2="16055.8">
<stop offset="0" style="stop-opacity:1; stop-color:#89A423"/>
<stop offset="1" style="stop-opacity:1; stop-color:#638429"/>
</linearGradient>
</defs>
<g id="Layer_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<path class="fil0" d="M22767 31689l-14060 2085c-2226,330 -4572,-2956 -6349,-3695 -1559,-649 -1653,-822 -1915,-2004 -266,-1196 -259,-3137 -401,-4460 -150,-1391 203,-1130 973,-2123 591,-795 964,-1292 1359,-2228 1413,-3396 2313,-5352 5285,-7695 3781,-2753 8236,-4067 12877,-4299 774,-89 484,-275 112,-747 -812,-1079 -1165,-2747 -1381,-4068 -68,-416 -308,-2197 198,-2372 228,-79 1093,72 1388,100 101,9 200,16 301,22 1094,51 2280,-41 2615,-17 4852,417 10503,1550 11899,7016 226,935 209,1325 200,2255 -2,142 -8,1026 126,1086 215,97 947,-1057 1467,133 110,344 145,764 169,1126 8,120 17,237 29,356 91,880 115,1755 53,2638 -23,319 -23,817 -223,1077 -611,795 -1576,1292 -2268,2065 -435,506 -635,1974 -834,2703 -720,2633 -1869,4361 -3594,4590l-7936 1054 -90 5402z"/>
<path class="fil1" d="M20432 0c8718,-38 15581,2266 15458,9209 -25,787 -197,745 -1206,434 -5376,-1662 -8578,-3016 -12410,-6248 -1067,-900 -1945,-1797 -2743,-2837 -478,-648 -8,-545 901,-558zm-18416 19428c1785,-4186 2803,-6725 6956,-9214 1814,-1088 3728,-1795 5744,-2401 5011,-1469 9917,-953 14495,540 1697,562 2833,1208 4123,2158 602,450 989,178 1872,-71 402,-113 1572,-529 1912,-305 933,615 -675,1120 -1291,1389 -1798,785 -1256,251 -1265,1780 -43,7030 -7302,11174 -13250,12374 -3409,688 -7029,1146 -9343,1499 -5916,900 -5060,-1185 -9071,-2819 -937,-381 -2531,-341 -2879,-1361 -223,-655 1540,-2751 1997,-3569z"/>
<g style="clip-path:url(#id0)">
<g id="_3107826610240">
<path id="1" class="fil2" d="M32620 15645c91,-46 98,-37 3,-91 -66,80 -20,59 -3,91zm-9180 173l399 13 94 3 24 -102c121,-34 39,27 76,-81l-104 -24c-76,-2 -129,-55 -130,-59 -3,-10 -11,-11 -18,-15l-68 -4c-94,14 -151,38 -213,69l-167 12 -8 120 12 65 103 3zm3362 -16369c31,57 -35,35 43,50 123,23 4,11 64,-18 -27,-64 39,-43 -41,-56 -131,-22 -7,-12 -66,24zm10290 3584c-14,-80 10,-36 -56,-77 -2,4 -94,5 -19,84 51,53 74,-7 75,-7zm2277 11808c100,-46 108,-71 4,-122 -65,81 -40,56 -4,122zm-598 -13384c72,-96 70,-72 -25,-113 -75,90 -74,70 25,113zm-486 7658c-47,-62 -81,7 -83,7 65,99 -66,22 64,80 3,-6 100,22 19,-87zm-14361 -9918c35,-131 44,-89 -39,-138 -4,7 -53,-26 -31,67 27,121 -23,26 70,71zm13953 15010c7,-87 -6,-35 -58,-63 -74,84 -46,57 -4,129 45,-22 53,54 62,-66zm1320 -15163c106,-113 26,-91 4,-126 -51,29 -67,-45 -62,71 4,73 20,40 58,55zm2646 15025c-2,-2 9,-68 -88,-57 -109,12 -37,7 -73,64 105,50 64,60 161,-7zm-292 -3726c48,-52 47,-33 49,-171 -84,-2 -93,-38 -195,78 -83,11 -33,-18 -92,47l115 91c47,-29 48,-35 123,-45zm-2986 3302c-113,22 -40,12 -65,57 182,135 184,-23 184,-24 -10,-6 19,-60 -119,-33zm-1300 1033c-76,-44 -26,-43 -193,-4 18,157 33,163 111,169 166,12 14,18 79,-36l3 -129zm-28 818c-15,-28 43,-120 -226,-46 35,72 -28,65 93,92 164,37 124,-39 133,-46zm-7887 -16516l182 4c21,-158 -15,-177 -161,-176l-21 172zm1556 1675l148 114c99,86 124,57 174,-16 -50,-145 -12,-36 -146,-105 -44,-243 65,-253 -76,-325 -82,93 -25,15 -43,187 -15,145 -10,6 -57,145zm-16717 6826c58,-32 47,42 53,-46 7,-83 4,-30 -50,-59l-24 38c3,61 -11,24 21,67zm-1336 -2651c25,-6 44,9 63,-22 77,-123 10,-42 -8,-80 -80,40 -47,5 -55,102zm-4579 -6954l-112 -3 26 95c101,-38 42,50 86,-92zm7494 3833c33,-24 94,21 33,-122 -79,33 -49,-52 -62,48 -20,150 -16,19 29,74zm14390 12465c-110,-30 -18,-3 -62,20 24,35 -18,154 116,33 -22,-35 -5,-40 -54,-53zm-16336 1107c44,-72 -19,-62 -22,-69 -108,42 -55,-27 -72,102 120,-4 51,36 94,-33zm-15555 -8727c0,-1 54,27 19,-104 -41,1 -53,-32 -83,34 -36,76 49,66 64,70zm29578 -7130c115,91 90,22 123,-26 -55,-41 62,-61 -72,-36 -85,16 -30,37 -51,62zm-15613 10133c8,-12 163,46 3,-107 -158,125 -4,106 -3,107zm19829 6238c-113,-3 -59,-5 -148,25 75,104 35,82 146,96l2 -121zm-1810 -750c-9,127 22,73 56,93 13,-18 98,-37 6,-177 -40,23 -55,-4 -62,84zm-22909 -1701c110,-49 103,-21 88,-170l-170 17 -8 103 29 61 61 -11zm17260 -7459c57,-32 46,52 67,-70 25,-145 -10,-61 -33,-93 -62,23 -49,-63 -69,61 -24,151 20,79 35,102zm6292 8218c-86,10 -54,14 -87,55 20,17 25,52 112,48 130,-7 69,-26 89,-71 -34,-23 -5,-44 -114,-32zm-18726 -12582l138 126c48,-78 33,-47 37,-156 -115,-27 -88,-44 -175,30zm5425 2089c112,8 43,39 121,-26l69 -111c-57,-38 50,-12 -63,-36 -108,-23 -8,-17 -111,3l-16 170zm199 -5155c68,-15 102,32 91,-91 -10,-106 -55,-86 -91,-103 -91,200 -13,173 0,194zm-4498 9344c44,-116 -2,-63 -8,-78 -188,-98 -154,47 -70,159 12,-9 44,9 78,-81zm-14595 -8298l-37 -85 -225 -25c13,84 -5,39 37,90 11,13 11,8 29,27 101,111 -29,62 100,79 134,17 77,-16 96,-28l0 -58zm16516 14224c-51,-40 -1,-28 -113,-50 -41,-8 -243,-20 -290,67 61,129 108,18 237,86 55,29 -10,50 104,69 198,32 132,-42 146,-52 -49,-181 23,-57 -89,-111l5 -9zm-15097 58c48,-69 44,-72 16,-145 -273,51 -22,42 -250,167 31,-165 -35,-99 -48,-114l-10 228 209 8 83 -144zm10508 -4775c26,-191 49,60 -34,-54 -80,69 -76,58 -4,123 52,-55 25,22 38,-69zm2333 -7579c33,-5 125,10 56,-109 -99,52 -45,-60 -56,109zm-3430 -2611c31,53 -29,36 45,50 112,21 9,9 62,-17 -23,-52 62,-39 -40,-56 -76,-13 -10,-11 -67,23zm-5194 1548c20,-171 28,-57 -48,-102 -23,40 -71,-39 -25,67 24,53 -2,25 73,35zm2622 14176c16,-129 5,-16 -32,-67 -96,48 -105,68 -4,128 34,-41 21,52 36,-61zm20631 -662c17,-119 -2,-25 -34,-66 -97,47 -110,67 -4,121 35,-34 24,49 38,-55zm-26456 -15122c101,69 78,57 133,-25 -30,-22 47,-55 -72,-37 -124,19 -29,27 -61,62zm-3047 11843c12,19 -43,82 103,51 57,-13 47,-31 63,-80 -75,-40 -83,-41 -168,-21l2 50zm590 1476c-68,85 -67,86 -5,161 100,-47 96,-110 5,-161zm9676 2249c132,-45 120,-6 96,-144 -185,-46 -50,-16 -91,31 11,22 4,32 23,36 49,12 16,9 52,-9 -39,-41 -1,-18 -75,-27 -8,6 -42,26 -44,28 -15,11 -32,39 -36,33 -3,-7 -12,13 -19,19l7 24c-83,-5 -17,-34 -119,21l-151 150c-7,14 -26,96 -30,118 184,-1 47,-2 195,-98 58,-38 107,-51 184,-77l17 -88 -9 -17zm-10949 -16354c55,-82 68,-123 -24,-178 -4,5 -49,-31 -45,89 4,131 35,74 69,89zm5381 2060c95,56 114,57 192,-23 -73,-75 -188,-91 -192,23zm4150 14183c1,-1 64,-22 50,-106 -19,-117 0,-36 -73,-72 -30,39 -121,103 23,178zm17483 -2004c-59,-80 -103,-72 -188,-35 18,24 -70,68 84,81 141,12 94,-39 104,-46zm-13680 -1675c141,42 169,46 247,-29 -37,-39 -45,-69 -145,-59 -99,10 -73,22 -102,88zm-8064 1221l-36 23c-90,81 -54,49 -56,120 261,25 188,-170 188,-171 -115,-7 34,-13 -60,2l-36 26c7,17 -3,42 39,48 3,1 16,-4 19,-4 5,0 15,-7 23,-10 -39,-35 6,-19 -81,-34zm8633 -1952c-7,-10 54,-79 -137,-26 9,87 13,131 90,196 33,-28 19,-1 55,-52 24,-33 -22,88 23,-39 49,-141 4,-71 -31,-79l-78 -1 25 81 53 -80zm-7088 2769c-11,-74 -88,-139 -148,-163l-43 119 162 129c15,-21 48,44 29,-85zm-7692 303l-2 61 261 28c11,-216 -161,-128 -259,-89zm39584 -10253c14,28 -26,64 65,64 135,1 27,20 78,-60 -44,-33 11,-44 -75,-39 -129,8 -18,-2 -68,35zm419 750c28,-36 34,52 41,-69 10,-164 -9,-60 -36,-101 -30,17 -56,-27 -71,73 -20,138 30,78 66,97zm3066 2473c55,-72 68,-95 66,-198 -92,-19 -136,-38 -155,50 -18,87 89,148 89,148zm2396 -3620c57,42 -52,30 106,49 159,20 20,7 113,-14 -22,-95 28,-126 -112,-132 -102,-5 -86,13 -107,97zm-718 4372l-51 -56c213,-116 92,-238 -70,-239 -152,-1 -176,38 -165,195l14 39c15,128 95,141 227,140l45 -79zm-11882 -7680c96,59 33,27 76,3l-58 -18c-3,-8 -12,11 -18,15zm-21198 15445c35,43 20,47 60,29 5,-2 14,-15 22,-22l-82 -7zm5007 1132l97 3 -6 -58c-40,-60 5,-36 -76,-65 -35,-12 -55,0 -88,1l5 117 68 2zm19326 -14421l-61 0c-35,54 -28,-70 -32,67 -4,136 11,60 30,93 73,-19 31,14 65,-50 146,-35 47,16 96,-68 -57,-55 15,-32 -98,-42zm-8429 13335c39,-6 206,-169 -164,-173 -70,95 -80,76 -102,170l266 3zm14571 -9261c47,74 57,123 127,4 -116,-124 -105,-20 -127,-4zm909 -1194c55,84 170,131 199,-23 -26,-14 -10,-39 -115,-26 -57,8 -60,10 -84,49zm271 2163c-1,-1 34,-56 -85,-37 -107,17 -28,-8 -84,61 38,68 -52,70 107,81 68,5 70,-17 106,-46 -12,-97 2,-33 -44,-59l-117 15 83 62c43,-50 20,-9 34,-77zm2227 -30c105,19 81,28 165,-11 -16,-86 -60,-131 -144,-155 -48,81 -43,60 -21,166zm-680 -1938c36,-37 13,13 35,-54 59,-184 69,-195 19,-219 -7,-2 -19,-13 -22,-4 -3,7 -75,-30 -95,109 -15,102 -6,135 63,168zm-7887 -1031c174,9 174,-15 198,-181l-195 0 -3 181zm-434 -3677c0,-132 -97,-207 -219,-204 -14,163 61,224 219,204zm9067 10670l-228 -20c15,143 32,200 191,182 20,-35 15,-15 29,-68 0,-1 7,-80 8,-94zm-11458 -8654l180 15c41,-77 53,-78 67,-187l-240 -2 -7 174zm-13484 -1787c67,65 -100,40 38,31 70,-5 24,3 66,-28 -77,-64 98,-40 -43,-30 -87,6 4,-25 -61,27zm15318 6420c8,8 -37,96 94,3 -76,-59 111,-37 -40,-27 -71,5 -10,-11 -54,24zm-4361 -5494c0,-176 44,-57 -80,-98 19,109 -24,65 80,98zm5777 11913c-52,-67 -18,-71 -104,-32 75,108 -101,-50 19,46 3,3 11,10 15,12 122,59 35,-5 70,-26zm452 -9192c-16,-105 17,-46 -64,-89 -51,58 -31,28 -37,112l0 24c139,141 57,117 171,135l19 -142 -89 -40zm1300 -184c26,36 -55,67 176,58 3,-16 70,-189 -107,-115 -68,28 -31,-2 -69,57zm-6645 5321c35,-145 -23,-89 -32,-106 -123,17 -84,-60 -108,72 -22,127 47,87 73,100 61,-30 38,56 67,-66zm12539 -5533c161,1 121,36 140,-122 -54,-35 -31,-46 -160,-30 -8,73 -19,77 20,152zm-7898 4642l158 -3 13 -151 -160 -4 -11 158zm-17042 -7038c56,111 45,115 104,4 -52,-38 -53,-32 -104,-4zm9439 14921c154,-74 34,-104 32,-108 -148,63 -33,108 -32,108zm-15492 -14617c77,-131 38,-84 -75,-106 31,146 -22,74 75,106zm2595 5412c115,-55 112,-64 4,-122 -16,20 -39,-42 -33,60 3,61 1,30 29,62zm3716 -5475c14,118 -32,80 92,86 38,-95 6,-127 -92,-86zm-11754 7101c6,-101 5,-86 -98,-105 -13,127 -2,118 98,105zm5801 -8233c54,-27 68,45 62,-68 -3,-75 -27,-45 -58,-61 -2,3 -85,14 -4,129zm-10835 7881c-39,-69 -44,-121 -135,-4 60,52 -67,23 67,40 113,15 27,-3 68,-36zm25397 -740c-39,10 -173,13 -98,95 96,105 86,-47 98,-95zm-2065 8351c-44,-72 23,-10 -75,-89 -65,-51 0,-9 -75,-42l-42 107 31 161c92,9 87,6 142,-32l19 -105zm-14954 -14214c87,52 55,48 150,6 -45,-139 -121,-139 -150,-6zm2674 8592c-160,2 -83,47 -93,81l164 16c3,-66 28,-97 -71,-97zm-12857 -11651c60,116 145,73 198,6 -88,-66 -119,-55 -198,-6zm14730 9603c8,31 -35,70 85,81 110,11 71,-14 85,-76 -83,-43 -68,-37 -170,-5zm-1945 -4959c-114,-51 -60,-57 -140,3l-4 58c93,64 166,73 228,-21 -41,-48 23,-26 -84,-40l-116 0c37,83 -28,35 83,68 54,-39 15,12 33,-68zm1791 10456c-76,-57 -141,-72 -205,22 16,13 16,57 118,48 109,-8 68,-30 87,-70zm6791 -1117c36,-46 36,70 46,-94 8,-128 -24,-68 -40,-87 -41,17 -64,-27 -71,84 -7,141 28,77 65,97zm-19845 -1831c156,4 126,-56 115,-191 -148,46 -119,6 -115,191zm28588 2560c110,14 138,-57 145,-166l-129 10c-85,158 -16,155 -16,156zm-24535 1960c-95,25 -67,45 -80,133 123,4 100,21 190,-35 -15,-82 23,-133 -110,-98zm-1340 -12555c34,-29 35,29 35,-82 -176,-85 -220,125 -198,245 233,90 139,21 170,-18l-9 -56 2 -89zm-138 10191c7,-3 15,-9 19,-11 187,-98 143,-30 160,-133 -81,-49 -97,-61 -235,49 -9,7 -14,11 -18,14l-10 -4 3 8c-6,4 -7,6 -36,40 48,43 -12,16 62,44 104,41 37,-1 55,-7zm8367 -12746l142 -3 17 -140c-107,-42 -56,-44 -174,-39 -39,107 -19,70 15,182zm13541 9864c19,-155 31,-118 -58,-202l-114 -68 -18 135c5,4 38,33 47,42 111,117 -30,57 143,93zm988 4753c45,-102 30,10 23,-135l-34 -127c-82,44 -10,4 -55,41l-47 40c-59,65 -45,-8 -44,128 63,55 64,54 157,53zm12225 -12623c69,-36 48,37 60,-51 11,-77 1,-29 -27,-74 -74,34 -47,-58 -61,47 -12,85 -16,23 28,78zm-541 532c79,-38 56,43 72,-73 18,-134 -33,-95 -37,-102 -62,28 -51,-64 -71,68 -26,164 18,78 36,107zm3249 -2408c42,-47 40,67 48,-70 9,-158 -18,-67 -43,-99 -62,25 -63,-61 -81,69 -20,138 47,86 76,100zm1303 9111c11,10 -39,54 99,53 166,-1 78,-27 103,-76 -9,-7 35,-50 -103,-50 -165,1 -70,41 -99,73zm-491 -3647c91,-9 105,-16 198,-88 -55,-161 -128,-160 -199,-171 8,167 44,104 1,259zm-24692 -3316c89,44 53,43 105,-26 -38,-27 54,-78 -66,-29 -4,1 -13,8 -16,10l-23 45zm13671 13200c-34,-129 31,-90 -104,-104 13,123 -20,66 104,104zm-2531 -392c-27,-46 15,-108 -118,-32 19,31 -50,43 47,68 133,33 20,3 71,-36zm7334 520c-76,-6 -56,36 -71,58 59,45 -67,20 67,36 129,15 17,4 69,-31 -26,-54 52,-54 -65,-63zm-2346 -1174c-22,-102 14,-11 -61,-51 -44,43 -78,-66 -39,94 19,78 18,22 64,42 41,-48 53,-4 36,-85zm-2672 1531c-126,3 -69,18 -100,66 34,27 41,99 222,7 -23,-40 -10,-76 -122,-73zm2389 -1391c-144,-10 -215,11 -139,175l166 10 -27 -185zm-13510 -6878c31,-55 21,-40 3,-86 -56,59 -65,-88 -32,42 34,130 -97,-14 29,44zm11036 7899c51,38 -7,20 62,28 135,17 -25,23 42,-24 -37,-35 4,-24 -62,-33 -161,-23 46,-43 -42,29zm-26597 -10879c62,73 10,58 96,32 -17,-44 72,-25 -23,-45 -72,-14 -23,-8 -73,13zm24877 10019c-13,-82 1,-14 -47,-36 -75,86 -26,63 26,92 24,-39 30,7 21,-56zm-13301 -13607c15,-24 58,33 23,-60 -25,-65 14,-8 -49,-43 -39,74 -63,63 26,103zm-1474 10770c72,-89 63,-70 -26,-109 -101,108 -21,86 26,109zm2490 -9768c5,-7 104,11 5,-148 -44,51 -53,-76 -44,73 6,81 4,33 39,75zm-455 582l45 -26c-21,-110 32,-69 -101,-93 -6,111 -40,72 56,119zm-2645 4875c5,-126 -3,-96 -98,-104 -11,117 -39,123 98,104zm-15387 -7335c18,35 -39,43 62,61 137,25 73,-13 98,-27 -5,-10 32,-155 -160,-34zm3775 14905c-5,113 34,83 37,87 96,-48 93,-123 5,-181 -22,29 -35,-53 -42,94zm16124 -7293c1,0 19,130 175,5 -14,-31 12,-58 -77,-63 -125,-7 -71,37 -98,58zm4169 4706c36,-17 59,39 73,-89 14,-124 -31,-78 -39,-88 -47,21 -58,-27 -69,83 -13,129 26,80 35,94zm-14149 1449c-78,-12 -84,28 -88,128l195 -3c-12,-79 -17,-110 -107,-125zm-10285 -377c144,13 156,25 270,-28 -59,-65 -141,-121 -249,-121l-21 149zm30877 -12750c85,40 49,47 105,-26 -20,-16 24,-117 -105,26zm-4545 -547c57,-82 74,-71 -25,-119 -65,93 -66,76 25,119zm6390 36c29,-122 42,-90 -84,-116 14,175 -38,71 84,116zm5154 2987c-1,45 -19,42 30,111 107,-34 39,71 81,-92 -1,-4 -13,-87 -13,-87 -16,-49 -13,-36 -31,-65 -83,37 -49,-29 -67,133zm-7078 -529c164,-26 122,59 107,-100 -108,-4 -71,-31 -107,100zm1289 -911c4,-125 47,-86 -67,-119 -93,100 -38,96 67,119zm2389 12606c-126,16 -58,-23 -117,61 78,102 120,95 117,-61zm-6679 -14484c93,-49 101,-26 33,-126 -50,15 -41,-45 -66,34 -45,140 4,62 33,92zm-6632 -463c15,26 -10,57 69,74 138,32 72,-15 95,-30 -35,-82 47,-48 -65,-68 -29,-6 -93,19 -99,24zm9162 3323c39,-11 64,56 82,-82 14,-103 -25,-89 -47,-113 -98,45 -81,123 -35,195zm11121 7323c77,-41 52,57 68,-98 6,-49 -11,-65 -20,-97 -60,22 -76,-44 -92,91 -17,134 36,91 44,104zm-6944 6433l64 2c35,-109 52,-107 -11,-201 -29,8 -65,-56 -82,91 -8,64 4,48 29,108zm-9851 -12707c33,-80 14,-192 -50,-252 -80,-76 -14,-26 -117,-47 51,222 26,39 90,163 44,86 -28,59 77,136zm17007 11129c-5,-4 -12,-10 -18,-14l-82 -58c-96,106 -9,225 150,201 10,-144 19,-76 -50,-129zm-14523 -7357l6 118 177 17 4 -157c-119,-17 -93,-25 -187,22zm1634 621c122,-10 52,43 137,-39 82,-80 30,-20 53,-141l-179 10 -11 170zm4069 -5651l169 46c4,-99 16,-85 -35,-146 -85,-102 -17,-50 -154,-73l20 173zm10176 12053c-10,-85 13,-6 -49,-52 -38,41 -37,-9 -30,69 9,97 -12,14 55,43 37,-56 37,58 24,-60zm-8682 -13172c37,61 -40,39 51,54 69,12 24,3 66,-21 -13,-32 49,-134 -117,-33zm2107 1274c32,-19 113,33 33,-122 -78,35 -50,-47 -63,48 -17,129 -11,23 30,74zm-2180 -3663l-108 -3c2,174 -2,49 42,106 98,-52 42,59 66,-103zm10237 6623c21,-30 58,43 35,-71 -21,-101 17,-22 -68,-66 -52,93 -66,71 33,137zm-4681 8279c36,-113 -28,-91 -30,-94 -79,34 -36,-30 -61,65 -8,29 10,72 15,95 50,-25 47,25 76,-66zm1712 -10475c91,-11 72,27 106,-40 54,-109 -37,-81 -62,-94l-37 44c-16,57 -18,8 -7,90zm-2158 653c14,19 -16,66 79,65 118,-2 32,5 75,-60 -18,-16 33,-129 -154,-5zm-9161 -4516c140,63 104,33 149,-46 -10,-8 40,-74 -77,-47 -186,44 -11,10 -72,93zm14791 10390c-148,-15 -74,13 -105,64 54,49 -82,47 102,53 102,4 98,-46 99,-47 -19,-29 7,-60 -96,-70zm-7396 -6688c36,71 -84,46 67,61 7,-6 18,-26 21,-20l74 -89c49,-90 34,-58 -1,-120 -66,20 -27,3 -73,42 -4,4 -10,10 -14,14 -4,4 -10,10 -14,14 -5,5 -12,11 -16,16l-35 33 -9 49zm3325 -2979c18,41 -50,73 94,76 129,2 71,-21 95,-70 -6,-6 38,-52 -90,-53 -164,-1 -55,12 -99,47zm-4326 1161l115 0c21,-126 29,-84 -30,-190 -116,49 -118,87 -85,190zm5264 1728c3,-4 48,17 51,-93 3,-169 -3,-47 -45,-100 -39,16 -76,-51 -89,107 -7,77 16,64 83,86zm3737 8908c127,-174 17,-185 6,-201 -65,17 -98,-21 -96,100 3,114 51,86 90,101zm-578 -7651c-69,-84 28,-32 -83,-63 -47,-14 -89,-4 -137,1 12,162 117,193 220,62zm-10792 -2729c100,-7 112,56 202,-184l-175 3 -27 181zm11216 4612c69,-72 57,-54 46,-178l-200 -7c-4,7 -10,9 -11,18l-76 95c135,22 67,-7 160,87l81 -15zm-25274 1701c77,60 7,56 87,3 -48,-47 101,-40 -34,-29 -73,6 -3,-17 -53,26zm-2320 -4177c8,14 14,124 93,3 -55,-40 95,-28 -36,-22 -55,3 -22,-1 -57,19zm3531 6166c27,41 -51,47 54,45 61,-2 16,-6 40,-42 -34,-25 -1,-17 -55,-23 -3,0 -17,14 -19,7 -3,-7 -13,9 -20,13zm9742 -9188c141,-30 64,23 96,-75 -192,-10 -27,10 -96,75zm-816 7909c14,-101 12,5 -30,-35 -126,99 -4,94 -3,96 46,-55 21,17 33,-61zm4718 4713c-57,112 -6,23 20,71 19,-13 146,-53 23,-91 -70,-21 -30,-5 -43,20zm-8122 -431c-16,-86 16,-10 -58,-43 -83,124 13,93 34,107 35,-58 47,63 24,-64zm17489 -3007c175,99 121,19 148,5 -163,-141 -131,-17 -148,-5zm-22342 4930c132,-4 153,38 191,-77l-183 -33c-126,37 -56,-3 -107,63 48,51 -83,44 99,47zm12980 -12068c-5,14 -15,15 -16,31 -2,16 -12,19 -13,27 -6,30 -6,60 -4,92l176 14 5 -153 -148 -11zm3361 -432c36,-54 25,-37 3,-87 -60,72 -60,-95 -28,43 33,144 -77,-37 25,44zm-4106 70c11,-16 62,31 29,-65 -27,-79 22,-7 -54,-51 -28,44 -74,-63 -27,70 23,65 -11,17 52,46zm4107 -1014c84,-42 48,57 62,-54 19,-151 13,-10 -29,-78 -90,38 -52,-66 -66,48 -12,105 -22,20 33,84zm5309 -1291c25,-37 79,60 36,-83 -31,-104 27,-9 -60,-59 -32,47 -83,-71 -36,83 27,91 -22,17 60,59zm1248 6583c63,-42 37,35 61,-54 36,-132 -10,-66 -27,-91 -56,21 -39,-53 -66,42 -50,177 2,67 32,103zm-3412 -2551c58,-28 78,64 72,-75 -4,-112 -22,-47 -68,-70 0,1 -117,-7 -4,145zm-290 -1225c21,58 -53,43 42,70 192,56 47,8 103,-36 -35,-66 28,-44 -52,-65 -126,-33 -82,23 -93,31zm-5356 -3095l-18 46c15,128 58,97 106,82 112,-34 73,-59 86,-77 -19,-13 -52,-43 -84,-53l-90 2zm8115 7257c60,-74 70,111 51,-115 -8,-93 -53,-79 -74,-92 -6,7 -48,-10 -51,93 -7,206 -25,60 74,114zm-358 -3417c71,-45 53,62 74,-83 25,-183 -18,-80 -39,-116 -80,37 -60,-87 -83,79 -26,191 22,83 48,120zm-17157 14c84,70 -122,41 42,30 72,-5 22,6 65,-27 -62,-52 99,-38 -41,-29 -76,5 -12,-10 -66,26zm5328 -1528c64,-38 48,39 53,-51 7,-103 14,-24 -49,-60 -33,49 -32,66 -4,111zm-27615 8986c78,-37 55,63 54,-88 -92,2 -45,-22 -73,27 -47,84 8,41 19,61zm32764 3684c-10,-69 1,-14 -45,-37 -107,108 -16,75 26,101 17,-36 27,-9 19,-64zm-6438 -13319c1,0 47,9 52,-34 12,-113 25,-18 -49,-67 -15,24 -88,9 -3,101zm-2549 -1315c-17,8 -170,44 -28,87 58,17 34,0 42,-20 45,-117 9,-15 -14,-67zm4500 3122c50,-16 41,47 55,-34 13,-73 3,-24 -22,-71 -54,37 -107,11 -33,105zm100 11390c59,41 -62,18 67,32 141,16 7,10 72,-28 -141,-125 -131,-11 -139,-4zm5906 333c26,-38 129,23 33,-116 -108,38 -98,26 -33,116zm-36586 -127c129,-18 2,10 67,-35 -65,-124 -157,-104 -185,26 57,9 59,18 118,9zm29127 1316c73,-30 40,-35 106,4 -33,22 14,19 -51,22 -116,5 -14,2 -55,-26zm-38 58l179 5 2 -117 -181 -1 0 113zm-23361 -15949c1,-1 61,10 45,-97 -16,-103 8,-32 -68,-78 -13,20 -65,-31 -41,104 21,124 2,35 64,71zm7079 11660c-101,8 -43,-8 -107,52 -56,54 -46,20 -62,107l176 18 -7 -177zm27110 -785c-83,-43 -52,-52 -103,26 49,34 -62,39 59,24 76,-9 15,3 44,-50zm-1211 -2487c86,-45 122,22 33,-115 -52,20 -45,-52 -59,40 -13,86 -25,15 26,75zm849 -5816c135,-10 77,32 107,-104 -166,22 -89,-39 -107,104zm-8045 -1393l59 -2c61,-97 37,-142 -53,-191 -5,7 -123,39 -6,193zm-12585 2344c3,-126 9,-31 -32,-70 -25,25 -18,13 -37,64l39 57 30 -51zm21445 8401c-173,28 -5,162 -5,162 17,-23 34,53 35,-88 2,-133 2,-16 -30,-74zm-7726 -10714c54,-16 48,46 60,-34 14,-86 9,-15 -27,-73 -49,31 -121,-28 -33,107zm2226 -437c29,-40 52,53 35,-69 -15,-105 -2,-34 -59,-73 -14,17 -58,-43 -43,72 17,126 -14,33 67,70zm-13381 14473c-108,-44 -32,2 -69,25 153,144 93,45 120,32 -37,-65 17,-30 -51,-57zm-16107 -2399c103,-46 70,-13 61,-117 -96,10 -54,-27 -90,34 -46,78 29,83 29,83zm6804 -10029c-8,-5 -18,-24 -24,-15l-95 -9c0,144 -25,145 119,124l0 -100c-90,37 -68,-13 -76,69 108,-5 13,38 76,-69zm-11048 7103c11,-112 26,21 -39,-41l8 93c60,-55 22,37 31,-52zm6 -5040c76,71 -99,41 38,30 70,-5 11,13 56,-27 -53,-44 90,-32 -36,-25 -65,4 -11,-8 -58,22zm701 2991c38,31 32,40 85,3 -102,-100 -85,-3 -85,-3zm38576 5668c152,93 87,13 102,3 -42,-43 17,-22 -57,-32l-45 29z"/>
<path class="fil2" d="M22443 33531c91,-46 99,-37 3,-91 -65,80 -19,59 -3,91zm-9179 174l399 12 94 3 23 -102c121,-33 40,27 77,-81l-104 -24c-77,-2 -129,-55 -130,-59 -3,-10 -12,-11 -18,-15l-68 -4c-94,14 -152,38 -213,70l-167 11 -9 121 13 64 103 4zm3362 -16370c31,57 -35,35 43,50 123,23 4,11 64,-17 -27,-65 39,-44 -41,-57 -132,-21 -7,-12 -66,24zm10290 3584c-14,-80 9,-36 -56,-77 -3,4 -94,6 -19,84 51,53 74,-6 75,-7zm2277 11808c100,-46 108,-71 3,-122 -64,81 -39,56 -3,122zm-598 -13384c72,-96 69,-72 -26,-113 -75,90 -73,70 26,113zm-487 7658c-46,-62 -80,7 -82,7 65,99 -67,22 63,80 4,-5 100,22 19,-87zm-14360 -9918c34,-131 44,-88 -39,-138 -4,7 -53,-26 -32,67 28,121 -23,26 71,71zm13953 15010c6,-87 -6,-35 -58,-63 -75,84 -46,57 -4,130 44,-23 53,54 62,-67zm1319 -15162c106,-114 26,-92 4,-127 -51,29 -67,-45 -61,71 4,73 20,40 57,56zm2647 15024c-2,-2 8,-68 -88,-57 -109,12 -38,7 -73,64 105,50 64,60 161,-7zm-293 -3726c49,-51 48,-33 50,-171 -85,-2 -93,-38 -195,78 -83,12 -33,-18 -93,47l116 91c47,-29 48,-34 122,-45zm-2986 3302c-112,22 -39,12 -64,57 182,135 183,-23 184,-23 -10,-7 18,-61 -120,-34zm-1299 1033c-77,-44 -27,-43 -194,-4 19,157 34,164 112,169 166,12 14,18 78,-36l4 -129zm-29 818c-14,-28 44,-120 -225,-46 34,72 -28,65 93,92 164,37 124,-39 132,-46zm-7886 -16516l181 4c22,-158 -15,-177 -160,-176l-21 172zm1555 1675l149 114c98,86 124,57 174,-16 -50,-145 -13,-36 -146,-105 -44,-243 65,-253 -76,-325 -82,93 -26,15 -43,187 -15,145 -11,7 -58,145zm-16716 6826c57,-32 46,42 53,-46 6,-83 4,-30 -50,-59l-24 38c3,61 -12,24 21,67zm-1337 -2651c26,-6 45,9 64,-22 76,-123 9,-42 -9,-80 -79,40 -46,5 -55,102zm-4578 -6954l-112 -3 26 95c100,-38 42,50 86,-92zm7494 3833c33,-24 94,21 33,-122 -79,33 -50,-52 -63,48 -20,150 -15,19 30,74zm14390 12465c-111,-30 -19,-3 -63,20 25,35 -17,155 117,33 -23,-35 -5,-39 -54,-53zm-16337 1107c45,-72 -18,-62 -21,-68 -108,41 -55,-28 -72,101 119,-4 51,36 93,-33zm-15554 -8727c0,0 54,27 19,-104 -42,1 -53,-32 -84,34 -35,76 50,66 65,70zm29578 -7130c115,91 90,22 123,-26 -55,-41 62,-61 -72,-36 -85,16 -31,37 -51,62zm-15614 10133c9,-12 164,46 4,-107 -159,125 -4,106 -4,107zm19830 6238c-114,-3 -59,-5 -148,25 75,104 35,82 145,96l3 -121zm-1810 -750c-9,127 22,73 56,93 12,-18 98,-37 5,-177 -39,23 -54,-4 -61,84zm-22909 -1701c109,-48 103,-21 88,-170l-170 17 -8 103 28 61 62 -11zm17260 -7459c57,-31 46,52 67,-70 25,-145 -11,-61 -33,-93 -63,23 -49,-63 -69,61 -24,151 20,79 35,102zm6292 8218c-87,10 -54,14 -87,55 20,17 25,52 112,48 129,-7 69,-26 89,-70 -34,-24 -5,-45 -114,-33zm-18726 -12582l138 126c48,-78 33,-47 37,-155 -115,-28 -88,-44 -175,29zm5425 2089c111,8 43,39 121,-26l69 -111c-57,-37 50,-12 -63,-36 -108,-23 -9,-17 -111,3l-16 170zm198 -5155c69,-15 103,32 92,-91 -10,-106 -55,-86 -92,-103 -90,200 -13,173 0,194zm-4497 9344c43,-116 -3,-63 -8,-78 -188,-98 -155,47 -70,159 12,-9 44,9 78,-81zm-14595 -8298l-38 -84 -224 -26c12,84 -6,39 36,90 11,13 12,8 29,28 102,110 -28,62 101,78 134,18 76,-16 96,-27l0 -59zm16516 14224c-52,-40 -1,-28 -113,-50 -42,-8 -243,-19 -291,67 61,129 109,18 238,86 55,29 -10,50 104,69 197,32 132,-42 145,-52 -48,-181 24,-57 -88,-111l5 -9zm-15098 58c48,-69 45,-72 17,-145 -274,51 -23,42 -250,167 30,-165 -35,-99 -48,-113l-11 227 209 8 83 -144zm10508 -4775c27,-191 50,60 -34,-54 -79,69 -75,58 -4,123 52,-55 26,22 38,-69zm2333 -7579c33,-5 126,10 57,-109 -99,52 -45,-60 -57,109zm-3429 -2611c31,53 -29,36 45,50 112,21 8,9 62,-17 -23,-52 62,-39 -41,-56 -76,-13 -10,-11 -66,23zm-5194 1548c20,-171 28,-57 -49,-102 -23,40 -71,-39 -24,67 24,53 -2,25 73,35zm2621 14176c16,-129 6,-16 -31,-67 -97,48 -106,68 -4,128 34,-41 21,52 35,-61zm20632 -662c16,-119 -2,-25 -34,-66 -97,47 -111,67 -4,122 35,-34 23,48 38,-56zm-26456 -15122c101,69 77,57 133,-25 -31,-22 47,-55 -73,-37 -124,19 -29,27 -60,62zm-3048 11843c12,19 -42,82 104,51 57,-12 47,-31 63,-80 -76,-39 -83,-41 -168,-21l1 50zm591 1476c-69,86 -68,86 -5,161 100,-47 96,-110 5,-161zm9675 2249c133,-45 121,-5 97,-144 -185,-45 -50,-16 -91,31 11,22 3,32 23,36 48,12 16,9 52,-9 -40,-40 -1,-18 -75,-27 -8,6 -43,27 -44,28 -15,11 -33,39 -36,33 -3,-7 -13,13 -19,19l7 24c-84,-5 -18,-34 -119,21l-151 150c-8,14 -26,96 -31,118 184,-1 48,-2 196,-98 58,-38 107,-51 184,-77l16 -87 -9 -18zm-10948 -16354c55,-82 67,-123 -24,-178 -4,5 -50,-31 -46,89 4,132 36,74 70,89zm5381 2060c95,56 114,57 192,-23 -74,-75 -188,-91 -192,23zm4150 14183c1,-1 63,-22 50,-106 -19,-117 0,-36 -74,-72 -29,39 -120,103 24,178zm17482 -2004c-59,-80 -103,-72 -188,-35 18,24 -69,68 85,81 140,12 94,-39 103,-46zm-13680 -1675c142,42 170,46 247,-29 -36,-39 -44,-68 -144,-58 -99,9 -73,21 -103,87zm-8064 1221l-36 23c-90,81 -54,49 -55,120 261,25 188,-170 188,-171 -115,-6 33,-13 -60,2l-37 26c8,17 -2,42 39,48 4,1 17,-4 20,-4 4,0 15,-7 22,-10 -39,-35 7,-19 -81,-34zm8634 -1952c-7,-10 54,-79 -138,-26 10,87 13,131 91,196 33,-28 19,-1 54,-52 25,-33 -21,88 23,-39 49,-141 5,-71 -30,-79l-79 -1 26 81 53 -80zm-7088 2769c-11,-74 -89,-139 -148,-163l-44 119 162 129c15,-21 49,45 30,-85zm-7692 303l-2 61 260 28c12,-216 -160,-128 -258,-89zm39584 -10253c14,28 -26,64 64,64 136,1 28,20 79,-60 -44,-33 10,-44 -75,-38 -129,7 -19,-3 -68,34zm419 750c28,-36 34,52 41,-69 10,-164 -9,-60 -36,-101 -30,17 -56,-27 -71,73 -20,138 30,78 66,97zm3065 2473c56,-72 68,-95 66,-198 -91,-19 -135,-38 -154,50 -19,87 88,148 88,148zm2397 -3620c57,42 -53,30 105,50 159,19 21,7 114,-15 -23,-95 27,-126 -112,-132 -103,-5 -87,13 -107,97zm-719 4372l-51 -56c213,-116 93,-238 -69,-239 -152,-1 -176,38 -165,195l14 39c14,128 95,141 226,140l45 -79zm-11881 -7680c95,59 33,27 75,3l-58 -18c-2,-8 -11,11 -17,15zm-21198 15445c35,43 20,47 60,29 5,-2 14,-15 21,-22l-81 -7zm5007 1132l96 3 -5 -58c-40,-60 5,-36 -76,-65 -36,-12 -55,0 -88,1l4 117 69 2zm19325 -14421l-61 0c-35,54 -27,-70 -32,67 -4,136 12,61 31,94 73,-20 31,13 65,-51 145,-35 46,16 95,-68 -56,-55 16,-32 -98,-42zm-8429 13335c40,-6 207,-169 -164,-173 -69,95 -80,76 -101,170l265 3zm14572 -9261c47,74 56,123 127,4 -117,-124 -105,-20 -127,-4zm909 -1194c54,84 169,131 199,-23 -27,-13 -10,-39 -116,-25 -56,7 -60,9 -83,48zm271 2163c-1,-1 33,-56 -85,-37 -108,17 -29,-7 -85,61 38,68 -51,70 108,81 68,5 70,-17 106,-46 -12,-97 2,-33 -44,-59l-117 16 83 62c42,-51 19,-10 34,-78zm2226 -30c105,20 81,29 165,-11 -16,-86 -60,-131 -144,-155 -47,81 -42,60 -21,166zm-680 -1938c37,-37 13,14 35,-54 59,-183 70,-195 20,-219 -8,-1 -19,-13 -23,-4 -2,7 -74,-30 -94,109 -15,102 -7,135 62,168zm-7886 -1031c174,9 174,-15 198,-181l-195 0 -3 181zm-435 -3677c1,-132 -96,-207 -218,-204 -14,163 61,224 218,204zm9068 10670l-229 -20c16,143 33,200 192,182 19,-35 15,-15 28,-68 1,-1 7,-80 9,-94zm-11458 -8654l179 16c42,-78 53,-79 68,-188l-240 -2 -7 174zm-13484 -1787c67,65 -101,40 38,31 69,-5 24,3 66,-28 -78,-63 97,-40 -43,-30 -88,6 4,-25 -61,27zm15318 6420c8,8 -38,96 94,3 -76,-59 111,-37 -40,-27 -71,5 -10,-11 -54,24zm-4361 -5494c0,-176 44,-57 -80,-98 19,110 -24,65 80,98zm5776 11913c-52,-67 -17,-71 -103,-32 75,108 -101,-50 18,46 3,3 12,10 15,12 123,59 36,-5 70,-26zm452 -9192c-15,-105 18,-46 -63,-89 -52,58 -31,28 -37,112l0 24c138,141 57,117 171,135l18 -141 -89 -41zm1300 -184c26,36 -55,67 177,58 3,-16 69,-189 -108,-115 -67,28 -30,-2 -69,57zm-6644 5321c34,-145 -23,-89 -32,-106 -123,17 -85,-60 -108,72 -22,127 47,87 73,100 61,-30 38,56 67,-66zm12539 -5533c161,1 121,36 140,-122 -54,-35 -31,-46 -161,-30 -7,73 -19,77 21,152zm-7899 4642l158 -3 14 -151 -161 -4 -11 158zm-17041 -7038c56,111 45,115 103,4 -51,-38 -52,-32 -103,-4zm9438 14921c155,-74 35,-103 33,-108 -148,63 -33,108 -33,108zm-15491 -14617c76,-131 38,-84 -75,-106 30,146 -22,74 75,106zm2595 5412c114,-55 112,-64 4,-122 -17,20 -39,-42 -33,60 3,62 0,30 29,62zm3715 -5475c14,118 -32,80 93,86 37,-95 5,-127 -93,-86zm-11753 7101c5,-101 4,-86 -99,-104 -13,126 -1,117 99,104zm5801 -8233c54,-27 68,45 62,-68 -4,-75 -27,-45 -58,-61 -3,3 -85,14 -4,129zm-10835 7881c-39,-69 -44,-121 -135,-4 59,52 -68,23 66,40 114,15 28,-3 69,-36zm25397 -740c-39,10 -173,13 -98,95 96,105 85,-47 98,-95zm-2065 8351c-44,-72 23,-10 -75,-89 -65,-51 0,-9 -75,-42l-43 107 31 161c93,9 88,6 142,-32l20 -105zm-14954 -14214c87,52 55,48 150,6 -45,-139 -121,-139 -150,-6zm2674 8593c-160,1 -84,46 -93,80l164 16c3,-66 28,-97 -71,-96zm-12857 -11652c59,116 145,73 198,6 -89,-66 -119,-55 -198,-6zm14729 9603c9,31 -34,70 86,81 110,11 71,-13 85,-75 -84,-44 -68,-38 -171,-6zm-1945 -4959c-113,-51 -59,-57 -140,3l-3 59c93,63 166,72 228,-22 -42,-48 23,-26 -85,-40l-115 0c37,83 -28,35 82,68 55,-38 15,12 33,-68zm1792 10456c-77,-56 -141,-72 -205,23 16,12 15,56 118,47 109,-8 68,-30 87,-70zm6791 -1117c36,-46 36,70 46,-94 7,-128 -25,-68 -41,-87 -41,17 -64,-27 -70,84 -8,141 28,77 65,97zm-19845 -1831c156,4 126,-56 115,-191 -148,47 -119,6 -115,191zm28588 2560c110,14 138,-57 145,-166l-129 10c-85,158 -17,155 -16,156zm-24536 1960c-95,25 -67,45 -79,133 122,4 100,21 190,-35 -16,-82 22,-133 -111,-98zm-1339 -12555c34,-29 35,29 35,-82 -176,-85 -220,125 -198,245 232,90 139,21 169,-18l-8 -56 2 -89zm-138 10191c6,-3 15,-9 19,-11 187,-98 143,-30 160,-133 -81,-49 -97,-61 -235,49 -9,7 -15,11 -19,14l-10 -4 4 8c-6,4 -7,6 -36,41 47,43 -13,15 61,44 105,40 38,-2 56,-8zm8367 -12746l142 -3 16 -140c-106,-42 -55,-43 -174,-39 -38,108 -18,70 16,182zm13540 9864c20,-155 32,-118 -57,-201l-114 -69 -18 135c4,4 38,33 46,42 112,117 -30,57 143,93zm988 4753c45,-102 30,10 24,-135l-34 -127c-82,44 -11,4 -56,41l-47 40c-58,65 -44,-8 -43,128 63,55 64,54 156,53zm12226 -12623c69,-36 48,37 60,-51 10,-77 0,-29 -27,-74 -74,34 -47,-58 -62,47 -11,85 -16,23 29,78zm-541 532c79,-38 56,43 72,-73 18,-134 -33,-95 -37,-102 -62,28 -51,-64 -72,68 -25,164 18,78 37,107zm3249 -2408c42,-47 39,67 47,-70 10,-158 -17,-67 -42,-99 -63,25 -63,-60 -82,69 -19,138 47,86 77,100zm1303 9111c11,10 -39,54 99,53 165,-1 78,-27 103,-76 -9,-7 34,-50 -103,-50 -165,1 -71,41 -99,73zm-492 -3647c92,-9 106,-16 198,-88 -55,-161 -128,-160 -198,-171 8,167 44,104 0,259zm-24691 -3316c88,44 53,43 105,-26 -39,-27 54,-78 -66,-29 -4,1 -13,8 -16,10l-23 45zm13670 13200c-33,-129 32,-90 -103,-104 13,123 -21,66 103,104zm-2530 -391c-27,-47 15,-109 -119,-33 20,31 -50,44 47,68 133,33 20,3 72,-35zm7333 519c-75,-6 -55,36 -70,58 59,45 -67,20 67,36 128,15 17,5 68,-31 -26,-54 53,-54 -65,-63zm-2346 -1174c-21,-102 14,-11 -60,-51 -44,43 -78,-66 -39,94 19,78 18,22 64,42 41,-48 52,-4 35,-85zm-2671 1531c-126,3 -69,18 -100,67 33,26 41,98 222,6 -23,-40 -11,-75 -122,-73zm2389 -1391c-144,-10 -216,11 -140,175l167 10 -27 -185zm-13510 -6878c31,-55 21,-40 2,-86 -55,59 -65,-88 -31,42 34,130 -97,-14 29,44zm11036 7899c51,38 -7,20 62,28 135,17 -26,24 42,-24 -37,-35 3,-24 -62,-33 -162,-23 46,-43 -42,29zm-26597 -10879c61,73 10,58 96,32 -17,-44 72,-25 -24,-45 -72,-14 -22,-8 -72,13zm24876 10019c-12,-82 2,-14 -47,-36 -75,86 -25,63 27,92 24,-39 30,7 20,-56zm-13300 -13607c15,-24 58,33 23,-60 -25,-65 14,-8 -49,-43 -39,74 -64,63 26,103zm-1474 10770c72,-89 63,-70 -26,-109 -102,108 -21,86 26,109zm2490 -9768c5,-7 104,11 5,-148 -45,51 -53,-76 -44,73 5,81 3,34 39,75zm-455 582l45 -26c-21,-109 31,-69 -102,-93 -6,111 -39,73 57,119zm-2646 4875c5,-126 -2,-96 -98,-104 -10,117 -38,124 98,104zm-15387 -7335c19,35 -38,43 63,61 137,25 73,-13 97,-27 -4,-10 32,-155 -160,-34zm3776 14905c-5,113 33,83 36,87 97,-48 94,-123 6,-180 -22,28 -35,-54 -42,93zm16124 -7293c1,0 19,130 175,5 -14,-31 11,-58 -77,-63 -125,-7 -71,37 -98,58zm4168 4706c37,-17 60,39 74,-88 13,-125 -31,-79 -39,-89 -47,21 -58,-27 -69,83 -13,129 25,80 34,94zm-14149 1449c-77,-12 -83,28 -88,128l196 -3c-13,-79 -18,-110 -108,-125zm-10285 -377c145,13 156,25 271,-27 -60,-66 -141,-122 -250,-121l-21 148zm30878 -12750c85,40 49,48 105,-26 -21,-16 24,-117 -105,26zm-4545 -547c57,-82 74,-71 -26,-119 -64,93 -65,76 26,119zm6389 36c29,-122 43,-90 -83,-116 14,175 -39,72 83,116zm5155 2988c-2,44 -19,42 29,111 108,-35 40,70 81,-93 0,-4 -13,-87 -13,-87 -15,-49 -13,-36 -31,-65 -82,38 -49,-29 -66,134zm-7078 -530c164,-26 121,59 106,-100 -107,-4 -71,-31 -106,100zm1288 -911c5,-125 48,-86 -66,-119 -93,100 -38,96 66,119zm2390 12606c-127,16 -58,-23 -117,61 77,102 120,95 117,-61zm-6680 -14484c93,-49 102,-26 33,-126 -50,15 -40,-45 -66,34 -44,140 5,62 33,92zm-6631 -463c15,26 -10,57 69,75 138,31 72,-16 95,-31 -35,-82 47,-48 -66,-68 -28,-5 -93,19 -98,24zm9161 3323c39,-11 65,56 83,-82 13,-103 -26,-89 -48,-112 -98,44 -81,122 -35,194zm11122 7323c77,-41 52,57 68,-98 5,-49 -11,-64 -20,-96 -60,21 -77,-45 -93,90 -16,134 36,91 45,104zm-6944 6433l64 2c34,-109 52,-107 -11,-201 -30,8 -66,-56 -83,91 -7,64 4,48 30,108zm-9852 -12707c33,-80 15,-192 -49,-252 -81,-76 -14,-26 -117,-47 50,222 25,40 89,163 45,86 -28,59 77,136zm17007 11129c-5,-4 -12,-10 -17,-14l-83 -58c-95,106 -8,225 151,201 10,-144 18,-76 -51,-129zm-14522 -7357l6 118 177 17 4 -157c-119,-17 -94,-25 -187,22zm1633 621c122,-9 53,43 137,-39 83,-80 31,-20 54,-141l-180 10 -11 170zm4070 -5651l169 46c4,-99 16,-85 -35,-146 -85,-102 -17,-49 -154,-73l20 173zm10175 12053c-9,-85 14,-6 -49,-52 -37,41 -36,-9 -29,69 9,97 -12,14 55,43 36,-56 37,58 23,-60zm-8682 -13171c38,60 -39,38 51,53 70,12 25,3 66,-21 -12,-32 50,-133 -117,-32zm2108 1273c32,-19 113,33 33,-122 -78,35 -51,-47 -63,49 -17,128 -11,22 30,73zm-2180 -3663l-109 -3c3,174 -2,49 43,106 98,-52 42,59 66,-103zm10237 6624c21,-31 58,42 35,-72 -21,-101 16,-22 -69,-66 -51,93 -65,71 34,138zm-4681 8278c35,-113 -29,-91 -30,-94 -79,35 -36,-30 -61,65 -8,30 9,72 15,95 49,-25 47,25 76,-66zm1712 -10475c90,-11 72,27 105,-40 54,-109 -36,-81 -61,-94l-37 44c-16,57 -18,8 -7,90zm-2159 653c14,19 -15,66 80,65 117,-2 32,5 75,-60 -19,-16 33,-129 -155,-5zm-9160 -4516c140,63 103,33 149,-46 -10,-8 40,-74 -77,-47 -186,44 -11,10 -72,93zm14791 10390c-149,-15 -74,13 -105,64 54,49 -82,47 102,53 102,4 97,-46 99,-47 -19,-29 7,-60 -96,-70zm-7396 -6688c36,71 -84,46 66,62 8,-7 18,-27 22,-21l74 -89c49,-90 34,-58 -1,-120 -66,20 -27,3 -73,42 -5,4 -10,10 -14,14 -5,4 -11,10 -15,14 -4,5 -11,12 -16,16l-35 34 -8 48zm3324 -2979c19,41 -49,73 95,76 129,2 70,-21 95,-70 -7,-6 38,-52 -90,-53 -165,-1 -56,12 -100,47zm-4325 1161l115 0c20,-126 28,-84 -30,-190 -117,49 -118,87 -85,190zm5264 1728c2,-3 48,17 50,-92 4,-170 -3,-48 -44,-101 -39,16 -77,-51 -90,107 -6,77 17,64 84,86zm3736 8908c128,-174 17,-185 7,-200 -65,16 -98,-21 -96,99 2,114 50,86 89,101zm-577 -7651c-69,-84 28,-31 -83,-63 -48,-14 -90,-4 -138,1 13,162 117,193 221,62zm-10793 -2729c100,-7 113,56 202,-184l-174 3 -28 181zm11216 4612c69,-72 58,-54 46,-178l-199 -7c-4,7 -10,9 -12,18l-76 95c135,22 68,-7 161,87l80 -15zm-25273 1701c76,60 6,56 86,3 -47,-47 102,-40 -34,-29 -72,6 -2,-17 -52,26zm-2321 -4177c9,14 14,125 94,3 -55,-40 95,-28 -36,-22 -55,3 -22,-1 -58,19zm3532 6166c27,41 -52,47 54,45 61,-2 15,-6 40,-42 -34,-25 -1,-17 -55,-23 -4,0 -17,14 -19,7 -3,-7 -13,9 -20,13zm9741 -9188c141,-29 65,23 97,-75 -192,-10 -27,11 -97,75zm-816 7909c15,-101 13,5 -29,-35 -126,99 -5,94 -3,96 46,-55 21,17 32,-61zm4719 4713c-57,112 -6,24 19,71 20,-12 147,-53 24,-91 -71,-21 -31,-5 -43,20zm-8123 -431c-15,-86 16,-10 -58,-43 -82,124 13,93 35,107 35,-58 46,63 23,-64zm17490 -3007c175,100 121,20 148,5 -164,-141 -131,-17 -148,-5zm-22342 4930c132,-4 153,38 190,-77l-182 -33c-126,37 -57,-3 -107,63 47,51 -83,44 99,47zm12980 -12068c-5,14 -15,15 -17,31 -2,16 -11,19 -13,27 -5,31 -5,60 -3,92l176 14 5 -153 -148 -11zm3361 -432c36,-54 25,-37 3,-87 -60,72 -60,-95 -28,43 33,144 -77,-37 25,44zm-4106 70c11,-16 62,31 29,-65 -28,-79 21,-7 -55,-51 -27,44 -74,-63 -27,70 23,65 -11,17 53,46zm4107 -1014c83,-42 48,57 62,-54 19,-151 12,-10 -29,-78 -91,38 -53,-66 -66,49 -13,104 -23,19 33,83zm5309 -1291c25,-37 79,60 36,-83 -31,-103 26,-8 -61,-59 -32,47 -82,-71 -36,83 28,92 -21,17 61,59zm1248 6583c63,-42 37,35 61,-54 35,-132 -11,-66 -27,-91 -56,21 -40,-53 -67,42 -50,177 3,67 33,103zm-3413 -2551c58,-28 79,64 73,-75 -5,-112 -22,-47 -68,-70 -1,1 -117,-7 -5,145zm-289 -1224c21,57 -53,42 41,69 192,56 47,8 104,-36 -35,-66 27,-44 -52,-65 -126,-33 -82,23 -93,32zm-5357 -3096l-17 46c15,129 58,97 106,82 112,-34 72,-59 86,-77 -20,-13 -52,-43 -84,-53l-91 2zm8116 7257c60,-74 70,111 51,-114 -8,-94 -53,-80 -74,-93 -6,8 -48,-10 -52,93 -7,206 -24,60 75,114zm-359 -3417c72,-45 54,62 74,-83 26,-183 -17,-80 -38,-116 -80,37 -61,-87 -83,79 -26,191 21,83 47,120zm-17157 14c85,70 -121,41 43,30 71,-4 21,6 65,-27 -62,-52 98,-38 -42,-29 -76,5 -12,-10 -66,26zm5329 -1528c63,-38 47,39 53,-51 6,-102 14,-24 -50,-60 -32,49 -31,66 -3,111zm-27615 8986c78,-36 55,63 54,-88 -92,3 -46,-22 -73,28 -47,83 8,40 19,60zm32764 3684c-10,-69 0,-14 -45,-36 -107,107 -16,74 26,100 17,-35 26,-9 19,-64zm-6439 -13319c1,0 48,9 52,-33 12,-114 25,-19 -48,-68 -16,24 -89,9 -4,101zm-2549 -1315c-16,8 -169,44 -28,87 59,17 35,0 43,-20 45,-117 8,-15 -15,-67zm4501 3122c50,-16 41,47 55,-34 13,-73 3,-24 -23,-71 -53,37 -106,11 -32,105zm100 11390c59,41 -62,18 66,32 141,16 8,10 73,-28 -142,-125 -131,-11 -139,-4zm5906 333c25,-38 129,23 33,-116 -109,38 -98,26 -33,116zm-36586 -127c129,-18 2,10 67,-34 -65,-125 -157,-104 -185,25 57,9 59,18 118,9zm29127 1317c73,-31 40,-35 105,3 -33,22 15,19 -51,22 -115,5 -13,3 -54,-25zm-38 57l179 5 2 -117 -181 -1 0 113zm-23361 -15949c1,-1 61,10 45,-96 -16,-104 8,-33 -69,-78 -13,19 -64,-32 -40,103 21,124 1,35 64,71zm7078 11660c-100,8 -43,-8 -106,52 -56,54 -46,20 -62,107l175 18 -7 -177zm27110 -785c-82,-43 -51,-52 -102,26 49,34 -62,39 58,24 76,-9 15,3 44,-50zm-1210 -2487c86,-45 122,22 32,-114 -51,19 -45,-53 -58,39 -14,86 -25,15 26,75zm849 -5816c135,-10 76,32 106,-104 -166,22 -89,-39 -106,104zm-8045 -1393l58 -2c62,-97 37,-142 -52,-191 -5,7 -124,39 -6,193zm-12585 2344c3,-126 9,-31 -32,-70 -26,25 -18,13 -37,64l38 57 31 -51zm21445 8402c-173,27 -5,161 -5,161 16,-23 33,53 35,-88 2,-133 2,-16 -30,-73zm-7726 -10715c54,-16 48,46 60,-34 13,-86 8,-15 -27,-73 -49,31 -122,-28 -33,107zm2226 -437c29,-40 52,53 35,-69 -16,-105 -3,-34 -60,-73 -13,17 -57,-43 -42,72 16,126 -15,33 67,70zm-13381 14473c-109,-44 -32,2 -69,25 153,144 93,45 120,33 -37,-65 17,-30 -51,-58zm-16107 -2399c103,-46 70,-13 61,-117 -97,10 -54,-27 -90,34 -46,78 29,83 29,83zm6804 -10029c-8,-5 -18,-24 -24,-15l-96 -9c1,144 -24,145 120,124l0 -100c-90,37 -68,-13 -76,69 108,-5 13,38 76,-69zm-11049 7103c12,-112 26,21 -38,-41l7 93c60,-55 22,37 31,-52zm7 -5040c76,71 -99,41 37,30 71,-5 11,13 56,-27 -52,-44 90,-32 -35,-25 -65,4 -11,-8 -58,22zm700 2992c39,30 32,39 86,2 -102,-100 -86,-3 -86,-2zm38577 5667c152,93 87,13 102,3 -42,-43 16,-22 -58,-32l-44 29z"/>
</g>
</g>
<path class="fil3" d="M20432 0c8718,-38 15581,2266 15458,9209 -25,787 -197,745 -1206,434 -5376,-1662 -8578,-3016 -12410,-6248 -1067,-900 -1945,-1797 -2743,-2837 -478,-648 -8,-545 901,-558zm-18416 19428c1785,-4186 2803,-6725 6956,-9214 1814,-1088 3728,-1795 5744,-2401 5011,-1469 9917,-953 14495,540 1697,562 2833,1208 4123,2158 602,450 989,178 1872,-71 402,-113 1572,-529 1912,-305 933,615 -675,1120 -1291,1389 -1798,785 -1256,251 -1265,1780 -43,7030 -7302,11174 -13250,12374 -3409,688 -7029,1146 -9343,1499 -5916,900 -5060,-1185 -9071,-2819 -937,-381 -2531,-341 -2879,-1361 -223,-655 1540,-2751 1997,-3569z"/>
<path class="fil4" d="M10113 32164l548 -85c566,-87 655,-815 655,-1696 0,-1108 -152,-1559 -630,-1485l-573 89 0 3177zm-872 -3711l1541 -239c770,-120 1425,167 1425,1818l0 225c0,1013 -203,2283 -1374,2464l-1592 246 0 -4514z"/>
<path class="fil4" d="M14753 30269l-349 -2047 -421 2167 770 -120zm-922 -2527l1171 -182 1019 4358 -943 146 -216 -1141 -987 152 -274 1218 -935 145 1165 -4696z"/>
<polygon class="fil4" points="17968,31617 17096,31752 17096,27924 16014,28092 16014,27404 19050,26934 19050,27622 17968,27790 "/>
<path class="fil5" d="M24269 30700l88 -3885 -824 115 -106 4640 2357 -329 17 -755 -1532 214zm2552 396l105 -4640 -824 115 -106 4640 825 -115zm3488 -5112l-525 1811c-157,575 -298,1154 -410,1687l-17 3c-83,-518 -193,-1044 -319,-1586l-423 -1679 -1020 143 -395 4680 752 -105 124 -1798c41,-577 85,-1269 109,-1855l17 -3c87,553 207,1162 334,1668l432 1780 624 -87 566 -1950c157,-539 327,-1176 462,-1748l17 -3c-16,472 -6,1216 3,1822l37 1793 785 -109 -139 -4606 -1014 142zm2380 3547l29 -1291 1399 -196 16 -730 -1398 196 25 -1123 1483 -207 17 -748 -2307 322 -106 4640 2396 -334 17 -749 -1571 220z"/>
<path class="fil4" d="M21036 29298l-350 -2048 -420 2166 770 -118zm-923 -2529l1172 -182 1019 4359 -943 145 -217 -1141 -986 152 -274 1218 -936 145 1165 -4696z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 40 KiB

BIN
img/Knob-Left-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
img/a-piece.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
img/add.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
img/alarm-arrow-up-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
img/arr_dn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

BIN
img/arr_dn1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

BIN
img/arr_dn2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

BIN
img/arr_up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

BIN
img/arr_up1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

BIN
img/arr_up2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

BIN
img/arrow-left-icon (2).png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
img/asvc.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
img/complex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

BIN
img/component.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

16
img/component.svg Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#555555;}
</style>
<g>
<path class="st0" d="M476.7,88.3h-88.3c0-48.8-39.5-88.3-88.3-88.3s-88.3,39.5-88.3,88.3h-88.3c-19.5,0-35.3,15.8-35.3,35.3v88.3
C39.5,211.9,0,251.4,0,300.1s39.5,88.3,88.3,88.3v88.3c0,19.5,15.8,35.3,35.3,35.3h123.6v-35.3c0-29.3,23.7-53,53-53s53,23.7,53,53
V512h123.6c19.5,0,35.3-15.8,35.3-35.3V353.1h-35.3c-29.3,0-53-23.7-53-53s23.7-53,53-53H512V123.6
C512,104.1,496.2,88.3,476.7,88.3z M388.4,300.1c0,48.8,39.5,88.3,88.3,88.3v88.3h-88.3c0-31.5-16.8-60.7-44.1-76.5
c-27.3-15.8-61-15.8-88.3,0c-27.3,15.8-44.1,44.9-44.1,76.5h-88.3V353.1H88.3c-29.3,0-53-23.7-53-53s23.7-53,53-53h35.3V123.6
h123.6V88.3c0-29.3,23.7-53,53-53s53,23.7,53,53v35.3h123.6v88.3C427.9,211.9,388.4,251.4,388.4,300.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
img/deer.bk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
img/deer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
img/del.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

BIN
img/del16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

BIN
img/del2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
img/dit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
img/dit_m.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/dit_m1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1023 B

BIN
img/edit.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

BIN
img/edit.gif.bk Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

16
img/json.svg Normal file
View File

@ -0,0 +1,16 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
<polyline points="14 2 14 8 20 8" />
<path d="M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1" />
<path d="M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1" />
</svg>

After

Width:  |  Height:  |  Size: 498 B

BIN
img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
img/logo0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
img/mimetype/document.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

BIN
img/mimetype/excel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

BIN
img/mimetype/ficon_pptx.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

BIN
img/mimetype/html.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

BIN
img/mimetype/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 B

BIN
img/mimetype/image_.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

BIN
img/mimetype/pdf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

BIN
img/mimetype/powerpoint.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

BIN
img/mimetype/text.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

BIN
img/mimetype/word.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

BIN
img/minus.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 B

BIN
img/new.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 B

BIN
img/ok.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

BIN
img/paperclip.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

BIN
img/piece.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

BIN
img/portlet_dot.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

BIN
img/redmult.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

BIN
img/redmult16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
img/sarrow.bk.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

BIN
img/sarrow.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

BIN
img/save.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

BIN
img/search.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

BIN
img/search_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

BIN
img/simple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

BIN
img/svc.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
img/up.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 B

BIN
img/view.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 B

BIN
img/xls.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

174
inc/functions.cfm Normal file
View File

@ -0,0 +1,174 @@
<cfscript>
/* Все глобальные функции экспортированы в request scope */
function plain2htm(s) {
return replace(replace(s, chr(13),'',"ALL"),chr(10),'<br/>', "ALL");
}
request.plain2htm = plain2htm;
function htm2plain(s) {
return replaceNoCase(s, '<br/>', '#chr(13)##chr(10)#', "ALL");
}
request.htm2plain = htm2plain;
function cleanHtm(s) {
return replaceList(s, '<,>,"', '&lt;,&gt;,&quot;');
}
request.cleanHtm = cleanHtm;
function clean4CDATA(s) {
LF = chr(10);
return replaceNoCase(replaceList(s, '[,]', '&91;,&93;'),"<br>",LF,"ALL");
}
request.clean4CDATA = clean4CDATA;
function numFmt(num, decimalPlaces = 0){
var sFormat = ",";
if (decimalPlaces GT 0) {sFormat = sFormat & "." & repeatString("0", decimalPlaces);}
return replace(NumberFormat(num, sFormat), ",", " ", "ALL");
}
request.numFmt = numFmt;
function nFmt(num, decimalPlaces = 2){
if (num EQ 0) return "";
return numFmt(num, decimalPlaces);
}
request.nFmt = nFmt;
function dateFmt(date, sFormat = 'DD.MM.YYYY'){
return dateFormat(date, sFormat);
}
request.dateFmt = dateFmt;
function dateTimeFmt(date, sDateFormat = 'DD.MM.YYYY', sTimeFormat='HH:MM'){
return dateFormat(date, sDateFormat) & ' ' & timeFormat(date, sTimeFormat);
}
request.dateTimeFmt = dateTimeFmt;
function timeFmt(date, sFormat = 'HH:MM'){
return timeFormat(date, sFormat);
}
request.timeFmt = timeFmt;
function usrAuthenticated() {
return request.usr_id GT 0 AND NOT (request.usr_id EQ request.ANONYMOUS_USR_ID);
}
request.usrAuthenticated = usrAuthenticated;
function filterOn(filter) {
return (isStruct(filter) AND NOT structIsEmpty(filter));
}
request.filterOn = filterOn;
function stripWhiteSpace(sNumber) {
return reReplace(sNumber, "[[:space:]]", "", "ALL");
}
request.stripWhiteSpace = stripWhiteSpace;
/*
// never used
function cleanNumber(sNumber) {
var s = reReplace(sNumber, "[[:space:]]", "", "ALL");
if ( find(",", s) ) { //watch argument order!!!
// assume Russian format with decimal comma and spaces for thousand separator
return replace(s, ",", ".");
} else {
// assume English format with decimal point and commas for thousand separator
return replace(s, ",", "", "ALL");
}
}
request.cleanNumber = cleanNumber;
*/
/*https://cflib.org/udf/queryColumnToArray*/
/**
* Takes a selected column of data from a query and converts it into an array.
*
* @param query The query to scan. (Required)
* @param column The name of the column to return data from. (Required)
* @return Returns an array.
* @author Peter J. Farrell (pjf@maestropublishing.com)
* @version 1, July 22, 2005
*/
function queryColumnToArray(qry, column) {
var arr = arrayNew(1);
var ii = "";
var loop_len = arguments.qry.recordcount;
for (ii=1; ii lte loop_len; ii=ii+1) {
arrayAppend(arr, arguments.qry[arguments.column][ii]);
}
return arr;
}
request.queryColumnToArray = queryColumnToArray;
/* ************************************* */
function loginPasswordPolicyCheck(usr_id, login, passwd, passwd2) {
msg = "";
// для старого логина длина не проверяется, все равно ничего не поделаешь
if (NOT(usr_id GT 0) AND len(login) LE 3) {
msg="Слишком короткий логин (минимальная длина логина 3 символа)";
} else {
if (passwd NEQ passwd2) {
msg="Пароль и подтверждение не совпадают";
} else {
if (len(passwd) LT "8") msg="Слишком короткий пароль (минимальная длина пароля 8 символов)";
}
}
return msg;
}
request.loginPasswordPolicyCheck = loginPasswordPolicyCheck;
function i18(label,label_en=label) {
//примитивная 2-язычная версия
if (request.language EQ 'en') {
return label_en;
} else {
return label;
};
}
request.i18 = i18;
function passwordHashCreate(password) {
return GenerateArgon2Hash('#ARGUMENTS.password#', 'argon2id', 1, 16000, 2);
}
request.passwordHashCreate = passwordHashCreate;
function passwordHashCheck(password, passwordHash) {
/*dirty hack for Lucee 6*/
try {
return evaluate("Argon2CheckHash('#ARGUMENTS.password#', ARGUMENTS.passwordHash, 'argon2id')");
} catch(e) {} // for lucee 5 compatibility
return evaluate("Argon2CheckHash('#ARGUMENTS.password#', ARGUMENTS.passwordHash)"); //lucee 6
}
request.passwordHashCheck = passwordHashCheck;
function skuCode(area_code="", abstract_service_code="") {
var s="#arguments[1]#.#arguments[2]#";
if (arrayLen(arguments) GE 3) {
if (len(arguments[3]) GT 0) {
s="#s#.#arguments[3]#";
} else {
s="#s#.0";
};
};
if (arrayLen(arguments) GE 4) {
if (len(arguments[4]) GT 0) {
s="#s#.#arguments[4]#"
}
};
if (arrayLen(arguments) GE 5) {
var pricingModelSuffix=arguments[5];
s="#s#-#pricingModelSuffix#";
}
return s;
}
request.skuCode = skuCode;
function roundSafe(a, precision) {
return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a;
}
request.roundSafe = roundSafe;
</cfscript>

51
inc/menu.cfm Normal file
View File

@ -0,0 +1,51 @@
<cfimport prefix="m" taglib="../lib"/>
<cfimport prefix="c" taglib="../lib/controls"/>
<cfparam name="ATTRIBUTES.fwx" default=""/>
<cfparam name="ATTRIBUTES.thisUrl" default=""/>
<cfset i18=request.i18/>
<!---<style>ul#mainmenu li.menu-item-noaction a.inline{display:inline;}</style>--->
<cfoutput>
<ul id="mainmenu">
<cfif request.usrAuthenticated()></cfif>
<li class="menu-title">Реестры</li>
<c:menu_item acl="" page="contract_ls.cfm" label="Договоры"/>
<c:menu_item acl="" page="specification_ls.cfm" label="Спецификации"/>
<li class="menu-title">Справочники</li>
<c:menu_item acl="" page="svc_ls.cfm" label="Сервисы"/>
<c:menu_item acl="" page="contragent_ls.cfm" label="Контрагенты"/>
<c:menu_item acl="" page="measure_ls.cfm" label="Единицы измерения"/>
<!--- <c:menu_item acl="usr" page="usr_ls.cfm" label=#i18("Пользователи", "Users")#/> --->
<li class="menu-title">"Пользователь"</li>
<cfif request.usrAuthenticated()>
<cfquery name="qUsr" datasource="#request.DS#">
select shortname/*, login, firstname, middlename, lastname*/
from usr
where usr_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#request.usr_id#/>
</cfquery>
<li class="menu-item-noaction">#qUsr.shortname#</li> <!---#request.usr_id#--->
<c:menu_item acl="" page="password.cfm" queryString="#ATTRIBUTES.fwx#" label="Смена пароля"/>
<c:menu_item acl="" page="logout.cfm" queryString="target_page=#URLEncodedFormat(ATTRIBUTES.thisUrl)#" label="Выход"/>
<cfelse>
<c:menu_item acl="" page="saml/login.cfm" queryString="target_page=#URLEncodedFormat(ATTRIBUTES.thisUrl)#" label="Вход через WebSSO"/>
<c:menu_item acl="" page="login.cfm" queryString="#ATTRIBUTES.fwx#" label="Вход"/>
<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"/>

1
index.cfm Normal file
View File

@ -0,0 +1 @@
<cflocation url="specification_ls.cfm" addtoken="No"/>

4
js/jquery.min.js vendored Normal file
View File

@ -0,0 +1,4 @@
/*! jQuery v1.7.1 jquery.com | jquery.org/license */
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);

View File

@ -0,0 +1,3 @@
/* JQuery Searchable DropDown Plugin | Copyright (c) 2012 xhaggi */
/*modidfed 14.11.2016|18.01.2018 by msyu - display:inline-block, padding-top: 0 for chrome; BUG: maxListSize IS IGNORED, use instead maxMultiMatch; chrome highlighted position correction;*/
(function($){var B=register("searchable");B.defaults={maxListSize:100,maxMultiMatch:50,exactMatch:false,wildcards:true,ignoreCase:true,warnMultiMatch:"top {0} matches ...",warnNoMatch:"no matches ...",latency:200,zIndex:"auto"};B.execute=function(g,h){var j=null;var k=null;var l=null;if($.browser.msie&&parseInt(jQuery.browser.version)<7)return this;if(this.nodeName!="SELECT"||this.size>1)return this;var m=$(this);var n={index:-1,options:null};var o="lang";var p=false;$.browser.chrome=/chrome/.test(navigator.userAgent.toLowerCase());if($.browser.chrome)$.browser.safari=false;if($.meta){g=$.extend({},options,m.data())}var q=$("<div/>");var r=$("<div/>");var t=$("<input/>");var u=$("<select/>");var x=$("<option>"+g.warnMultiMatch.replace(/\{0\}/g,g.maxMultiMatch)+"</option>").attr("disabled","true");var y=$("<option>"+g.warnNoMatch+"</option>").attr("disabled","true");var z={option:function(a){return $(u.get(0).options[a])},selected:function(){return u.find(":selected")},selectedIndex:function(a){if(a>-1)u.get(0).selectedIndex=a;return u.get(0).selectedIndex},size:function(a){u.attr("size",Math.max(2,Math.min(a,20)))},reset:function(){if((m.get(0).selectedIndex-1)==m.data("index"))return;var a=m.get(0).selectedIndex;var b=m.get(0).length;var c=Math.floor(g.maxMultiMatch/2);var d=Math.max(1,(a-c));var e=Math.min(b,Math.max(g.maxMultiMatch,(a+c)));var f=a-d;u.empty();this.size(e-d);for(var i=d;i<e;i++)u.append($(m.get(0).options[i]).clone().attr(o,i-1));if(e>g.maxMultiMatch)u.append(x);u.get(0).selectedIndex=f}};draw();var A=false;r.mouseover(function(){A=true});r.mouseout(function(){A=false});u.mouseover(function(){A=true});u.mouseout(function(){A=false});t.click(function(e){if(!p)enable(e,true);else disable(e,true)});t.blur(function(e){if(!A&&p)disable(e,true)});m.keydown(function(e){if(e.keyCode!=9&&!e.shiftKey&&!e.ctrlKey&&!e.altKey)t.click()});m.click(function(e){u.focus()});u.click(function(e){if(z.selectedIndex()<0)return;disable(e)});u.focus(function(e){t.focus()});u.blur(function(e){if(!A)disable(e,true)});u.mousemove(function(e){if($.browser.opera&&parseFloat(jQuery.browser.version)>=9.8)return true;var a=Math.floor(parseFloat(/([0-9\.]+)px/.exec(z.option(0).css("font-size"))));var b=4;if($.browser.opera)b=2.5;if($.browser.safari)b=3;if($.browser.chrome)b=3.4;a+=a/b;z.selectedIndex(Math.floor((e.pageY-u.offset().top+this.scrollTop)/a))});r.click(function(e){t.click()});t.keyup(function(e){if(jQuery.inArray(e.keyCode,new Array(9,13,16,33,34,35,36,38,40))>-1)return true;l=$.trim(t.val().toLowerCase());clearSearchTimer();j=setTimeout(searching,g.latency)});t.keydown(function(e){if(e.keyCode==9){disable(e)}if(e.shiftKey||e.ctrlKey||e.altKey)return;switch(e.keyCode){case 13:disable(e);m.focus();break;case 27:disable(e,true);m.focus();break;case 33:if(z.selectedIndex()-u.attr("size")>0){z.selectedIndex(z.selectedIndex()-u.attr("size"))}else{z.selectedIndex(0)}synchronize();break;case 34:if(z.selectedIndex()+u.attr("size")<u.get(0).options.length-1){z.selectedIndex(z.selectedIndex()+u.attr("size"))}else{z.selectedIndex(u.get(0).options.length-1)}synchronize();break;case 38:if(z.selectedIndex()>0){z.selectedIndex(z.selectedIndex()-1);synchronize()}break;case 40:if(z.selectedIndex()<u.get(0).options.length-1){z.selectedIndex(z.selectedIndex()+1);synchronize()}break;default:return true}return false});function draw(){m.css("text-decoration","none");m.width(m.outerWidth());m.height(m.outerHeight());q.css("position","relative");/*msyu*/q.css("display","inline-block");q.css("margin","0");/*/msyu*/q.css("width",m.outerWidth());if($.browser.msie)q.css("z-index",h);r.css({"position":"absolute","top":0,"left":0,"width":m.outerWidth(),"height":m.outerHeight(),/*msyu*/"background-color":"#BBEE55","opacity":"0.2"/*/msyu*/});t.attr("type","text");t.hide();t.height(m.outerHeight());t.css({"position":"absolute","top":0,"left":0,"margin":"0px","padding":"0px","outline-style":"none","border-style":"solid","border-bottom-style":"none","border-color":"transparent","background-color":"transparent"});var a=new Array();a.push("border-left-width");a.push("border-top-width");a.push("font-size");a.push("font-stretch");a.push("font-variant");a.push("font-weight");a.push("color");a.push("text-align");a.push("text-indent");a.push("text-shadow");a.push("text-transform");a.push("padding-left");a.push("padding-top");for(var i=0;i<a.length;i++)t.css(a[i],m.css(a[i]));if($.browser.msie&&parseInt(jQuery.browser.version)<8){t.css("padding","0px");t.css("padding-left","3px");t.css("border-left-width","2px");t.css("border-top-width","3px")}else if($.browser.chrome){t.height(m.innerHeight());t.css("text-transform","none");t.css("padding-left",parseFloatPx(t.css("padding-left"))+3);t.css("padding-top",/*2*/0)}else if($.browser.safari){t.height(m.innerHeight());t.css("padding-top",2);t.css("padding-left",3);t.css("text-transform","none")}else if($.browser.opera){t.height(m.innerHeight());var b=parseFloatPx(m.css("padding-left"));t.css("padding-left",b==1?b+1:b);t.css("padding-top",0)}else if($.browser.mozilla){t.css("padding-top","0px");t.css("border-top","0px");t.css("padding-left",parseFloatPx(m.css("padding-left"))+3)}else{t.css("padding-left",parseFloatPx(m.css("padding-left"))+3);t.css("padding-top",parseFloatPx(m.css("padding-top"))+1)}var c=parseFloatPx(m.css("padding-left"))+parseFloatPx(m.css("padding-right"))+parseFloatPx(m.css("border-left-width"))+parseFloatPx(m.css("border-left-width"))+23;t.width(m.outerWidth()-c);var w=m.css("width");var d=m.outerWidth();m.css("width","auto");d=d>m.outerWidth()?d:m.outerWidth();m.css("width",w);u.hide();z.size(m.get(0).length);u.css({"position":"absolute","top":m.outerHeight(),"left":0,"width":d,"border":"1px solid #333","font-weight":"normal","padding":0,"background-color":m.css("background-color"),"text-transform":m.css("text-transform")});var e=/^\d+$/.test(m.css("z-index"))?m.css("z-index"):1;if(g.zIndex&&/^\d+$/.test(g.zIndex))e=g.zIndex;r.css("z-index",(e).toString(10));t.css("z-index",(e+1).toString(10));u.css("z-index",(e+2).toString(10));m.wrap(q);m.after(r);m.after(t);m.after(u)};function enable(e,s,v){if(m.attr("disabled"))return false;m.prepend("<option />");if(typeof v=="undefined")p=!p;z.reset();synchronize();store();if(s)u.show();t.show();t.focus();t.select();m.get(0).selectedIndex=0;if(typeof e!="undefined")e.stopPropagation()};function disable(e,a){p=false;m.find(":first").remove();clearSearchTimer();t.hide();u.hide();if(typeof a!="undefined")restore();populate();if(typeof e!="undefined")e.stopPropagation()};function clearSearchTimer(){if(j!=null)clearTimeout(j)};function populate(){if(z.selectedIndex()<0||z.selected().get(0).disabled)return;m.get(0).selectedIndex=parseInt(u.find(":selected").attr(o));m.change();m.data("index",new Number(m.get(0).selectedIndex))};function synchronize(){if(z.selectedIndex()>-1&&!z.selected().get(0).disabled)t.val(u.find(":selected").text());else t.val(m.find(":selected").text())};function store(){n.index=z.selectedIndex();n.options=new Array();for(var i=0;i<u.get(0).options.length;i++)n.options.push(u.get(0).options[i])};function restore(){u.empty();for(var i=0;i<n.options.length;i++)u.append(n.options[i]);z.selectedIndex(n.index);z.size(n.options.length)};function escapeRegExp(a){var b=["/",".","*","+","?","|","(",")","[","]","{","}","\\","^","$"];var c=new RegExp("(\\"+b.join("|\\")+")","g");return a.replace(c,"\\$1")};function searching(){if(k==l){j=null;return}var a=0;k=l;u.hide();u.empty();var b=escapeRegExp(l);if(g.exactMatch)b="^"+b;if(g.wildcards){b=b.replace(/\\\*/g,".*");b=b.replace(/\\\?/g,".")}var c=null;if(g.ignoreCase)c="i";l=new RegExp(b,c);for(var i=1;i<m.get(0).length&&a<g.maxMultiMatch;i++){if(l.length==0||l.test(m.get(0).options[i].text)){var d=$(m.get(0).options[i]).clone().attr(o,i-1);if(m.data("index")==i)d.text(m.data("text"));u.append(d);a++}}if(a>=1){z.selectedIndex(0)}else if(a==0){u.append(y)}if(a>=g.maxMultiMatch){u.append(x)}z.size(a);u.show();j=null};function parseFloatPx(a){try{a=parseFloat(a.replace(/[\s]*px/,""));if(!isNaN(a))return a}catch(e){}return 0};return};function register(d){var e=$[d]={};$.fn[d]=function(b){b=$.extend(e.defaults,b);var c=this.size();return this.each(function(a){e.execute.call(this,b,c-a)})};return e}})(jQuery);

33
layout/attribute.cfm Normal file
View File

@ -0,0 +1,33 @@
<cfsilent>
<!---Замещает любую переменную (*** небезопасно) тега layout:page --->
<!---Тег layout:page проглатывает собственный контент, и вместо него после закрытия выводит разметку на основании атрибутов (при открытии тега он формирует переменные - фрагменты разметки - по шаблону) и вложенных тегов layout:attribute (которые по закрытии тега на самом деле перезаписывают переменные в layout:page).
Вложенные теги удобны, чтобы передавать читабельную разметку, а не строку в кавычках.--->
<cfparam name="ATTRIBUTES.name"/><!---имя переменной layout:page, чаще всего title, controls--->
<!--- ATTRIBUTES.value --->
<cfparam name="ATTRIBUTES.append" default=""/><!---before,after--->
<cfif thisTag.executionMode IS "end">
<cfassociate basetag="cf_page"/>
<cfset layoutTemplate=getBaseTagData('cf_page',1)/>
<cfif structKeyExists(ATTRIBUTES, "value")>
<cfset value=ATTRIBUTES.value/>
<cfelse>
<cfset value=thisTag.generatedContent/>
</cfif>
<!---ниже в комментариях предполагается, что мы меняем фрагмент разметки, например, controls, но на самом деле это может быть любая переменная тега layout:page--->
<cfif structKeyExists(layoutTemplate,"#ATTRIBUTES.name#") AND lcase(ATTRIBUTES.append) EQ "before">
<!---дописать в начало фрагмента разметки с именем name, сгенерированного layout:page, например, controls--->
<cfset "layoutTemplate.#ATTRIBUTES.name#" = value & layoutTemplate["#ATTRIBUTES.name#"]/>
<cfelseif structKeyExists(layoutTemplate,"#ATTRIBUTES.name#") AND lcase(ATTRIBUTES.append) EQ "after">
<!---дописать в конец фрагмента разметки с именем name,, сгенерированного layout:page, например, controls--->
<cfset "layoutTemplate.#ATTRIBUTES.name#" = layoutTemplate["#ATTRIBUTES.name#"] & value/>
<cfelse>
<!---заменить фрагмент разметки с именем name, сгенерированный layout:page--->
<cfset "layoutTemplate.#ATTRIBUTES.name#"= value/>
</cfif>
<cfset thisTag.generatedContent=""/>
</cfif>
</cfsilent>

Some files were not shown because too many files have changed in this diff Show More