169 lines
6.8 KiB
Plaintext
169 lines
6.8 KiB
Plaintext
<cfsetting showdebugoutput="no" enablecfoutputonly="true">
|
|
<cfheader name="Content-Type" value="application/json; charset=utf-8">
|
|
|
|
<cfparam name="url.contract_id" default="">
|
|
|
|
<cfset result = {ok: false, error: ""}>
|
|
|
|
<cftry>
|
|
<cfif NOT len(url.contract_id)>
|
|
<cfset result.error = "contract_id required">
|
|
<cfelse>
|
|
<!--- Берём два последних допника по дате --->
|
|
<cfquery name="sups" datasource="baza">
|
|
SELECT id, type, created_at
|
|
FROM supplements
|
|
WHERE contract_id = <cfqueryparam value="#url.contract_id#" cfsqltype="cf_sql_varchar">
|
|
ORDER BY created_at DESC
|
|
LIMIT 2
|
|
</cfquery>
|
|
|
|
<cfif sups.recordCount LT 2>
|
|
<cfset result.error = "need at least 2 supplements, found " & sups.recordCount>
|
|
<cfelse>
|
|
<cfset supNew = sups.id[1]>
|
|
<cfset supOld = sups.id[2]>
|
|
|
|
<!--- Читаем spec_rows для обоих --->
|
|
<cfquery name="rowsOld" datasource="baza">
|
|
SELECT row_num, name, price, qty, sum, date_start
|
|
FROM spec_rows
|
|
WHERE supplement_id = <cfqueryparam value="#supOld#" cfsqltype="cf_sql_varchar">
|
|
ORDER BY row_num
|
|
</cfquery>
|
|
|
|
<cfquery name="rowsNew" datasource="baza">
|
|
SELECT row_num, name, price, qty, sum, date_start
|
|
FROM spec_rows
|
|
WHERE supplement_id = <cfqueryparam value="#supNew#" cfsqltype="cf_sql_varchar">
|
|
ORDER BY row_num
|
|
</cfquery>
|
|
|
|
<!--- Индексация по row_num --->
|
|
<cfset oldByNum = {}>
|
|
<cfloop query="rowsOld">
|
|
<cfset oldByNum[rowsOld.row_num] = {
|
|
name: rowsOld.name,
|
|
price: rowsOld.price,
|
|
qty: rowsOld.qty,
|
|
sum: rowsOld.sum,
|
|
date_start: rowsOld.date_start
|
|
}>
|
|
</cfloop>
|
|
|
|
<cfset newByNum = {}>
|
|
<cfloop query="rowsNew">
|
|
<cfset newByNum[rowsNew.row_num] = {
|
|
name: rowsNew.name,
|
|
price: rowsNew.price,
|
|
qty: rowsNew.qty,
|
|
sum: rowsNew.sum,
|
|
date_start: rowsNew.date_start
|
|
}>
|
|
</cfloop>
|
|
|
|
<!--- Собираем все row_num --->
|
|
<cfset allNums = structKeyArray(oldByNum)>
|
|
<cfloop array="#structKeyArray(newByNum)#" index="n">
|
|
<cfif NOT structKeyExists(oldByNum, n)>
|
|
<cfset arrayAppend(allNums, n)>
|
|
</cfif>
|
|
</cfloop>
|
|
<cfset arraySort(allNums, "numeric")>
|
|
|
|
<!--- Сравниваем --->
|
|
<cfset changes = []>
|
|
<cfset fields = ["name", "price", "qty", "sum", "date_start"]>
|
|
|
|
<cfloop array="#allNums#" index="num">
|
|
<cfset inOld = structKeyExists(oldByNum, num)>
|
|
<cfset inNew = structKeyExists(newByNum, num)>
|
|
|
|
<cfif inOld AND NOT inNew>
|
|
<cfset arrayAppend(changes, {
|
|
row_num: num,
|
|
change_type: "deleted",
|
|
old_values: oldByNum[num],
|
|
new_values: {}
|
|
})>
|
|
<cfelseif NOT inOld AND inNew>
|
|
<cfset arrayAppend(changes, {
|
|
row_num: num,
|
|
change_type: "added",
|
|
old_values: {},
|
|
new_values: newByNum[num]
|
|
})>
|
|
<cfelse>
|
|
<cfset oldVals = oldByNum[num]>
|
|
<cfset newVals = newByNum[num]>
|
|
<cfset same = true>
|
|
<cfset changedFields = {}>
|
|
<cfloop array="#fields#" index="f">
|
|
<cfif structKeyExists(oldVals, f) AND structKeyExists(newVals, f)>
|
|
<cfset ov = oldVals[f]>
|
|
<cfset nv = newVals[f]>
|
|
<cfif toString(ov) NEQ toString(nv)>
|
|
<cfset same = false>
|
|
<cfset changedFields[f] = {old: ov, new: nv}>
|
|
</cfif>
|
|
<cfelseif structKeyExists(oldVals, f) OR structKeyExists(newVals, f)>
|
|
<cfset same = false>
|
|
<cfset changedFields[f] = {
|
|
old: structKeyExists(oldVals, f) ? oldVals[f] : "",
|
|
new: structKeyExists(newVals, f) ? newVals[f] : ""
|
|
}>
|
|
</cfif>
|
|
</cfloop>
|
|
|
|
<cfset arrayAppend(changes, {
|
|
row_num: num,
|
|
change_type: same ? "unchanged" : "changed",
|
|
old_values: oldVals,
|
|
new_values: newVals,
|
|
changed_fields: changedFields
|
|
})>
|
|
</cfif>
|
|
</cfloop>
|
|
|
|
<!--- Сохраняем в spec_history --->
|
|
<cfloop array="#changes#" index="ch">
|
|
<cfquery datasource="baza">
|
|
INSERT INTO spec_history (contract_id, supplement_id, row_num, change_type, old_values, new_values)
|
|
VALUES (
|
|
<cfqueryparam value="#url.contract_id#" cfsqltype="cf_sql_varchar">,
|
|
<cfqueryparam value="#supNew#" cfsqltype="cf_sql_varchar">,
|
|
<cfqueryparam value="#ch.row_num#" cfsqltype="cf_sql_integer">,
|
|
<cfqueryparam value="#ch.change_type#" cfsqltype="cf_sql_varchar">,
|
|
<cfqueryparam value="#serializeJSON(ch.old_values)#" cfsqltype="cf_sql_varchar">::jsonb,
|
|
<cfqueryparam value="#serializeJSON(ch.new_values)#" cfsqltype="cf_sql_varchar">::jsonb
|
|
)
|
|
</cfquery>
|
|
</cfloop>
|
|
|
|
<cfset result = {
|
|
ok: true,
|
|
contract_id: url.contract_id,
|
|
supplement_old: supOld,
|
|
supplement_new: supNew,
|
|
changes: changes,
|
|
summary: {
|
|
added: 0,
|
|
deleted: 0,
|
|
changed: 0,
|
|
unchanged: 0
|
|
}
|
|
}>
|
|
|
|
<cfloop array="#changes#" index="ch">
|
|
<cfset result.summary[ch.change_type] = result.summary[ch.change_type] + 1>
|
|
</cfloop>
|
|
</cfif>
|
|
</cfif>
|
|
|
|
<cfcatch>
|
|
<cfset result = {ok: false, error: cfcatch.message, detail: cfcatch.detail}>
|
|
</cfcatch>
|
|
</cftry>
|
|
|
|
<cfoutput>#serializeJSON(result)#</cfoutput>
|