<cfsilent>
<!--- v0.4---><!---9:50 06.10.2020--->
<!--- v0.5---><!---2024-12-11 15:10:07--->
<!--- DEL.CFM - унифицированный шаблон операции удаления записи --->
<cfimport prefix="m" taglib="../../lib"/>
<cfimport prefix="m" taglib="../../lib/controls"/>
</cfsilent><cfif thisTag.executionMode IS "end" OR !thisTag.hasEndTag><m:silent silent="No">



	<cfparam name="ATTRIBUTES.savemarker" type="string" default="delete"/>
	<cfparam name="ATTRIBUTES.readonly" type="boolean" default="No"/>

	<cfparam name="ATTRIBUTES.checkQuery" type="string" default="select 0 as chk"/> <!--- запрос проверки целостности. 
	Простая строка (параметр преобразуется до вызова тега). 
	Если можно удалять, должен вернуть 0 в поле chk --->
	<cfparam name="ATTRIBUTES.displayDependencies" type="boolean" default="Yes"/>
	<cfparam name="ATTRIBUTES.ignoreDependencies" type="boolean" default="No"/><!--- будем удалять, несмотря на наличие зависимостей Предположительно, мы примем меры в запросе удаления, или расчитываем на каскадное удаление. Имеет смысл, видимо, только в комбинации с displayDependencies=TRUE, иначе зачем описывать зависимости и потом их игнорировать.  --->
	<cfparam name="ATTRIBUTES.entity" type="string"/>
	<cfparam name="ATTRIBUTES.accessObj" type="string" default="#ATTRIBUTES.entity#"/> <!--- объект доступа, права к которому проверяем --->

	<cfparam name="ATTRIBUTES.deleteQuery" type="string" default=""/> <!--- запрос удаления *** надо бы параметризовать  --->
	<cfparam name="ATTRIBUTES.confirmMessage" type="string"/> <!--- текст для javascript:confirm() --->
	<cfparam name="ATTRIBUTES.denyMessage" type="string" default="Удаление невозможно, существуют зависимые записи."/> <!--- 
	сообщение о невозможности удаления записи (если проверка целостности говорит нельзя) --->

	<cfparam name="ATTRIBUTES.queryString" type="string" default=""/>
	<cfparam name="ATTRIBUTES.defaultBackUrl" type="string" default="#ATTRIBUTES.entity#_ls.cfm"/>
	<cfparam name="ATTRIBUTES.output" type="string" default=""/> 
	<cfparam name="ATTRIBUTES.status" type="string" default=""/>

	<cfparam name="thisTag.dependencies" type="array" default=#arrayNew(1)#/>
	<cfparam name="thisTag.conditions" type="array"/>
	

	<cfset "CALLER.#ATTRIBUTES.status#"=CreateObject("component","status").init(false,"","")/>

	<cfif len(ATTRIBUTES.queryString) EQ 0>
		<cfset i = 0 />
		<cfloop array=#thisTag.conditions# index="condition">
			<cfif i GT 0>
				<cfset ATTRIBUTES.queryString="#ATTRIBUTES.queryString#&"/>
			</cfif>
			<cfset i = i+1/>
			<cfset ATTRIBUTES.queryString="#ATTRIBUTES.queryString##condition.field#=#condition.value#"/>	
		</cfloop>
	</cfif>

	<m:track 
		thisURL="#request.thisPage#?#ATTRIBUTES.queryString#"
		defaultBackUrl="#ATTRIBUTES.defaultBackUrl#"
		output="tr"
	/>

	<cfquery name="qCheck" datasource="#request.DS#">
		#preserveSingleQuotes(ATTRIBUTES.checkQuery)#	
	</cfquery>

	<cfset sDenyMessage=""/>

	<cfoutput query="qCheck">
		<cfset sDenyMessage=evaluate("""#ATTRIBUTES.denyMessage#""")/>
	</cfoutput>	

	<!--- быстрая проверка --->
	<cfset dependentRecordsExist = false/> 
	<cfloop array=#thisTag.dependencies# index="dep">
		<cfif dep.query.recordCount GT 0>
			<cfset dependentRecordsExist = true/>
			<cfbreak/>
		</cfif>	
	</cfloop>		
		
	<!--- do delete --->	
	<m:ac obj="#ATTRIBUTES.accessObj#" act="#request.PERMISSION_WRITE#" output="writePermitted">

		<cfset doSave = false/>
		<cfif !ATTRIBUTES.readonly>
			<cfloop list=#ATTRIBUTES.savemarker# index="marker">
				<cfif structKeyExists(FORM,"#marker#")><!--- удаление можно делать только постом --->
					<cfset doSave = true/>
					<cfbreak/>
				</cfif>
			</cfloop>
		</cfif>
		
		<cfif doSave AND qCheck.chk EQ 0>
			<cftry>	<!--- <cfoutput> <cfset i = 0 />
						<cfloop list=#ATTRIBUTES.deleteQuery# delimiters="?" index="queryPart">
							
						<cfif i GT 0>								
								cfqueryparam 
									cfsqltype='#condition.cfsqltype#' 
									value='#condition.value#' 
									null='#condition.null#'/	
							</cfif><cfset i = i + 1/>*#queryPart#* #i# 
						</cfloop> 
						
					</cfoutput> --->

						
				<cfquery name="qDel" datasource="#request.DS#" result="result">
					
					<cfif len(ATTRIBUTES.deleteQuery)>
						<!--- запрос удаления должен быть сформулирован так, 
						чтобы условия удаления были в конце --->
						<cfset i = 0 />
						<cfloop list=#ATTRIBUTES.deleteQuery# delimiters="?" index="queryPart">							
							<cfif i GT 0>								
								<cfqueryparam 
									cfsqltype='#condition.cfsqltype#' 
									value='#condition.value#' 
									null='#condition.null#'/>	
							</cfif><cfset i = i + 1/>#queryPart#
						</cfloop> 
					<cfelse>
						delete from #ATTRIBUTES.entity# where /**/
						<cfset i = 0 />
						<cfloop array=#thisTag.conditions# index="condition">
							<cfif i GT 0> AND </cfif>
							<cfset i = i + 1/>
							#condition.expression#=<cfqueryparam 
									cfsqltype='#condition.cfsqltype#' 
									value='#condition.value#' 
									null='#condition.null#'/>	
						</cfloop>
					</cfif>
				</cfquery>
				
				<!--- *** неуклюжий костыль --->
				<cfset CALLER.saveAndClose = true/><!--- сигнал для закрытия экрана --->
				
				<cfcatch type="database">
					<cfset "CALLER.#ATTRIBUTES.status#.errorState"=true/>
					<cfset "CALLER.#ATTRIBUTES.status#.errorMessage"="Ошибка при обращении к базе данных. #cfcatch.message# #cfcatch.detail# #cfcatch.tagcontext[1].template# line #cfcatch.tagcontext[1].line#"/>
					<!--- <cfrethrow/> --->
				</cfcatch>
			</cftry>
		</cfif>
	</m:ac>

	<cfif !writePermitted><!--- перетирания cfcatch не будет --->
		<cfset "CALLER.#ATTRIBUTES.status#.errorState"=true/>
		<cfset "CALLER.#ATTRIBUTES.status#.errorMessage"="Ваших полномочий недостаточно для выполнения данной операции."/>
	</cfif>


	<!--- print output --->
	<cfsavecontent variable="markup">
	<cfoutput>
	
	<div class="container-fluid">
	<div class="row"> 
	
	<br>
	<form name="frmDel" action="#request.thisPage#" method="POST">
	<cfif NOT writePermitted>
		<!--- ситуация возможна при прямом заходе по URL. Надо высказать юзарю свое неодобрение. --->
		<!--- <h4 class="text-danger">Ваших полномочий недостаточно для выполнения данной операции.</h4>
		<br/> --->
		
	<cfelseif qCheck.chk GT 0>
		<h4 class="text-danger">#ATTRIBUTES.denyMessage#</h4>
		<br/>	
		
	<cfelseif dependentRecordsExist>
		<cfif ATTRIBUTES.displayDependencies>
			
			<h4 class="text-danger">#ATTRIBUTES.denyMessage#</h4>
			<br/>
			<cftry>
				<cfloop array=#thisTag.dependencies# index="dep">
					<cfif dep.query.recordCount GT 0>
					
						<h5>#dep.title#</h5>
						
						<cfif dep.showDetails>
						<table class="worktable">
							<thead>
								<tr>
									<th width="1%" class="c"></th>
									<cfloop array=#dep.fields# item="fld">
										<cfif len(fld.title)>
											<th>#fld.title#</th>
										</cfif>
									</cfloop>
									<th width="1%"></th>
								</tr>		
							</thead>
							
							<cfoutput query=#dep.query#>
								<cfset urlQueryString=""/>
								<cfloop array=#dep.keys# index="keyName">
									<cfif len(urlQueryString)> 
										<cfset urlQueryString="#urlQueryString#&"/><!---***--->
									</cfif>
									<cfset urlQueryString="#urlQueryString##keyName#=#dep.query[keyName][currentRow]#"/>
								</cfloop>
								<tr>
									<td>					
										<a href="#dep.page#?#urlQueryString#&#tr.fwx#" <!---class="far fa-edit"--->><img src="img/edit.gif"/></a>
									</td>
									<cfloop array=#dep.fields# item="fld">
										<cfif len(fld.title)>
											<td>
											<cfif isDefined("fld.formatter")>
											#fld.formatter(dep.query[fld.name][currentRow])#
											<cfelse>
											#dep.query[fld.name][currentRow]#
											</cfif>
											</td>
										</cfif>
									</cfloop> 
									<td>					
										<a href="#dep.delete_page#?#urlQueryString#&#tr.fwx#" <!---class="far fa-trash-alt text-danger"--->><img src="img/del.gif"/></a>
									</td>
								</tr>
							</cfoutput>			
						</table>
						<cfelse><!---dep.showDetails--->
							<cfoutput><p>#dep.denyMessage# (#dep.query.recordCount#)</p></cfoutput>	
						</cfif><!---dep.showDetails--->
					</cfif>
				</cfloop>
			<cfcatch type="any">
				<cfoutput>#cfcatch.message# #cfcatch.detail# #cfcatch.tagcontext[1].template# line #cfcatch.tagcontext[1].line#/></cfoutput><cfrethrow/>
			</cfcatch>
			</cftry>
		<cfelse><!---ATTRIBUTES.displayDependencies--->
			<cfoutput>#ATTRIBUTES.denyMessage#</cfoutput>
		</cfif><!---ATTRIBUTES.displayDependencies--->
	</cfif>	
	
	<cfif NOT dependentRecordsExist OR ATTRIBUTES.ignoreDependencies><!--- qCheck.chk GT 0 | dependentRecordsExist --->
		<cfif writePermitted>
			<input type="hidden" name="track" value="#tr.self#">
			<cfloop array=#thisTag.conditions# index="condition">
				<!---<input type="hidden" name="#condition.expression#" value="#evaluate('#condition.expression#')#"/>--->
				<input type="hidden" name="#condition.field#" value="#evaluate('#condition.field#')#"/><!--- по замыслу, берется из скоупа FORM (*** слишком неявно)--->
			</cfloop>
			<button type="submit" class="maincontrol btn btn-secondary" name="delete" onclick="if(!confirm('#evaluate("""#ATTRIBUTES.confirmMessage#""")#')) return false;">Удалить</button>
		</cfif>
	</cfif>	

	<button type="button" class="maincontrol btn btn-secondary" name="close" onclick="document.location.href='#tr.backURL#'">
		Закрыть
	</button>
	
<!--- 	<cfdump var=#dependentRecordsExist#/>
	<cfdump var=#ATTRIBUTES.ignoreDependencies#/>
	<cfdump var=#NOT dependentRecordsExist OR ATTRIBUTES.ignoreDependencies#/> --->
	
	</form>
	
	
	</div>
	</div>
	</cfoutput>
	</cfsavecontent>

</m:silent><cfif len(ATTRIBUTES.output)><cfset "CALLER.#ATTRIBUTES.output#" = #markup#/><cfelse>
	<cfoutput>#markup#</cfoutput>
</cfif></cfif>
<!--- пример монструозной конструкции Postgre для каскадного удаления --->
<!--- with 
inst as (
delete from instance 
where instance_uid='e283e337-0ddc-459c-88b8-57d1963b4a7d'
returning instance_uid
),
st as (
delete from instance_state 
where instance_uid in (select instance_uid from inst)
returning instance_state_uid
),
op as (
delete from instance_operation
where instance_uid in (select instance_uid from inst)
returning instance_operation_uid
),
par as (
delete from instance_operation_param
where instance_operation_uid in (select instance_operation_uid from op)
returning instance_operation_param_uid
),
cfs as (
delete from instance_operation_cfs_param
where instance_operation_uid in (select instance_operation_uid from op)
returning instance_operation_cfs_param_uid
)
select * from inst 
left outer join st on (inst.instance_uid=st.instance_uid)
left outer join op on (inst.instance_uid=op.instance_uid)
left outer join par on (op.instance_operation_uid=par.instance_operation_uid)
left outer join cfs on (op.instance_operation_uid=cfs.instance_operation_uid)
; --->
<!--- такой вопрос: точно ли будут задействованы все CTE, если я на них не сошлюсь? На месте оптимизатора я бы проигнорил незадействованные. Наверное, надо все включить в джойн для уверенности? --->