089 xl json dates, gpu fixes
This commit is contained in:
+2
-1
@@ -15,6 +15,7 @@
|
|||||||
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
|
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
|
||||||
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath())&'mod')/>
|
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath())&'mod')/>
|
||||||
<cfset this.timeZone = "Europe/Moscow"/><!--- для биллинга очень важен часовой пояс, поэтому ставим вручную в коде --->
|
<cfset this.timeZone = "Europe/Moscow"/><!--- для биллинга очень важен часовой пояс, поэтому ставим вручную в коде --->
|
||||||
|
<!--- <cfset this.serialization.json.date = "iso8601"/> --->
|
||||||
<cfset this.datasource = "dwh"/>
|
<cfset this.datasource = "dwh"/>
|
||||||
|
|
||||||
<cfset this.defaultdatasource = this.datasource/>
|
<cfset this.defaultdatasource = this.datasource/>
|
||||||
@@ -87,7 +88,7 @@
|
|||||||
|
|
||||||
<!--- global settings --->
|
<!--- global settings --->
|
||||||
<!--- *************************************************************************************************** --->
|
<!--- *************************************************************************************************** --->
|
||||||
<cfset request.APP_VERSION="0.00.087"/> <!--- *********************************************************** --->
|
<cfset request.APP_VERSION="0.00.089"/> <!--- *********************************************************** --->
|
||||||
<!--- *************************************************************************************************** --->
|
<!--- *************************************************************************************************** --->
|
||||||
<cfset request.STAND=getStand()/>
|
<cfset request.STAND=getStand()/>
|
||||||
<cfset request.RECORDS_PER_PAGE=500/>
|
<cfset request.RECORDS_PER_PAGE=500/>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
k.__name as contragent
|
k.__name as contragent
|
||||||
,k.id_klienta as wz
|
,k.id_klienta as wz
|
||||||
,k.__index as contragent_index
|
,k.__index as contragent_index
|
||||||
,d."_plannedDueDate" as _plannedDueDate
|
<!--- ,d."_plannedDueDate" as _plannedDueDate --->
|
||||||
,d."__createdAt"
|
,d."__createdAt"
|
||||||
,d."__index" as deal_index
|
,d."__index" as deal_index
|
||||||
,s.status
|
,s.status
|
||||||
@@ -131,12 +131,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tr">
|
<!--- <div class="tr">
|
||||||
<div class="th">_plannedDueDate</div>
|
<div class="th">_plannedDueDate</div>
|
||||||
<div class="td">#dateFormat(qDecoration._plannedDueDate,'YYYY-MM-DD')#
|
<div class="td">#dateFormat(qDecoration._plannedDueDate,'YYYY-MM-DD')#
|
||||||
Паразитное поле, не использовать в расчетах
|
Паразитное поле, не использовать в расчетах
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> --->
|
||||||
|
|
||||||
<div class="tr">
|
<div class="tr">
|
||||||
<div class="th">Статус</div>
|
<div class="th">Статус</div>
|
||||||
|
|||||||
+26
-8
@@ -8,21 +8,39 @@
|
|||||||
<m:prepare_ls entity="crm2cloud" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
|
<m:prepare_ls entity="crm2cloud" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
|
||||||
|
|
||||||
|
|
||||||
|
<cfset this.nullSupport = true/>
|
||||||
|
|
||||||
|
<cfquery name="qRead" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
|
||||||
<cfquery name="qGPU" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
|
select
|
||||||
select obj_uuid, obj_id, client_id as WZ, vcd, org, org_vdc, vcenter, gpu, dt_load, dt_load_ts, org_status, cluster as clus, is_template
|
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||||
|
<d:field>obj_uuid::text as obj_uuid</d:field>
|
||||||
|
<d:field>obj_id</d:field>
|
||||||
|
<d:field>client_id as WZ</d:field>
|
||||||
|
<d:field>vcd</d:field>
|
||||||
|
<d:field>org</d:field>
|
||||||
|
<d:field>org_vdc</d:field>
|
||||||
|
<d:field>vcenter</d:field>
|
||||||
|
<d:field>gpu::text as gpu</d:field>
|
||||||
|
<d:field cfSqlType="CF_SQL_TIMESTAMP">dt_load</d:field>
|
||||||
|
<d:field cfSqlType="CF_SQL_TIMESTAMP">dt_load_ts</d:field>
|
||||||
|
<d:field>org_status</d:field>
|
||||||
|
<d:field>cluster as clus</d:field>
|
||||||
|
<d:field cfSqlType="CF_SQL_BOOLEAN" formatter=#request.castToBoolSimple#>is_template</d:field>
|
||||||
|
<d:field cfSqlType="CF_SQL_BOOLEAN" formatter=#request.castToBoolSimple#>(1=1) as t1</d:field>
|
||||||
|
<d:field cfSqlType="CF_SQL_BOOLEAN" formatter=#request.castToBoolSimple#>(1=0) as t2</d:field>
|
||||||
|
<d:field cfSqlType="CF_SQL_BOOLEAN" formatter=#request.castToBoolSimple#>(1=null) as t3</d:field>
|
||||||
|
</d:field_set>
|
||||||
from gpu.vm
|
from gpu.vm
|
||||||
order by client_id
|
order by client_id
|
||||||
</cfquery>
|
</cfquery>
|
||||||
|
|
||||||
<!--- <cfdump var=#qGPU# abort=true/> --->
|
<!--- <cfdump var=#qRead# abort=true/> --->
|
||||||
|
|
||||||
<cfif isDefined("output_xls")>
|
<cfif isDefined("output_xls")>
|
||||||
<layout:xml qRead=#qCharge# titleMap=#titleMap# filename="#pageInfo.entity#.xml"/>
|
<layout:xml qRead=#qRead# titleMap=#titleMap# filename="#pageInfo.entity#.xml"/>
|
||||||
<cfabort/>
|
<cfabort/>
|
||||||
</cfif><cfif isDefined("output_json")>
|
</cfif><cfif isDefined("output_json")>
|
||||||
<layout:json qRead=#qCharge# titleMap=#titleMap# filename="#pageInfo.entity#.json"/>
|
<layout:json qRead=#qRead# titleMap=#titleMap# filename="#pageInfo.entity#.json"/>
|
||||||
<cfabort/>
|
<cfabort/>
|
||||||
</cfif><!---
|
</cfif><!---
|
||||||
---><layout:page section="header" pageInfo=#pageInfo#>
|
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||||
@@ -45,7 +63,7 @@ order by client_id
|
|||||||
|
|
||||||
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
||||||
</cfoutput>
|
</cfoutput>
|
||||||
<cfoutput><b>#qGPU.recordCount#</b></cfoutput>
|
<cfoutput><b>#qRead.recordCount#</b></cfoutput>
|
||||||
<table class="worktable">
|
<table class="worktable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -62,7 +80,7 @@ order by client_id
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<cfoutput query="qGPU">
|
<cfoutput query="qRead">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="contragent.cfm?wz=#WZ#&#tr.fwx#">#WZ#</a></td>
|
<td><a href="contragent.cfm?wz=#WZ#&#tr.fwx#">#WZ#</a></td>
|
||||||
<td>#obj_uuid#</td>
|
<td>#obj_uuid#</td>
|
||||||
|
|||||||
@@ -311,6 +311,29 @@ public string function formatJsonString(str) {
|
|||||||
}
|
}
|
||||||
request.formatJsonString = formatJsonString;
|
request.formatJsonString = formatJsonString;
|
||||||
//нужна еще функция, которая сериализует структуру как pretty printed json. См. https://github.com/bennadel/JsonSerializer.cfc (все не совсем просто, например, не заранее не определен формат даты)
|
//нужна еще функция, которая сериализует структуру как pretty printed json. См. https://github.com/bennadel/JsonSerializer.cfc (все не совсем просто, например, не заранее не определен формат даты)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hint Приводит поле резалтсета к булевому типу, пригодному для сериализации в json, вместо null возвращает false.
|
||||||
|
*/
|
||||||
|
boolean function castToBoolSimple(any x) {
|
||||||
|
if ( !structKeyExists( arguments, "x" ) || isNull( arguments.x ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 2. Handle empty strings, empty arrays, or empty structs
|
||||||
|
if ( isSimpleValue( arguments.x ) && trim( arguments.x ) == "" ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( isArray( arguments.x ) && arrayIsEmpty( arguments.x ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( isStruct( arguments.x ) && structIsEmpty( arguments.x ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 3. Fall back to standard CFML truthy evaluation
|
||||||
|
return isBoolean( arguments.x ) && arguments.x ? true : false;
|
||||||
|
}
|
||||||
|
request.castToBoolSimple=castToBoolSimple;
|
||||||
|
|
||||||
</cfscript>
|
</cfscript>
|
||||||
|
|
||||||
<cffunction name=structGetKey>
|
<cffunction name=structGetKey>
|
||||||
@@ -361,3 +384,5 @@ request.formatJsonString = formatJsonString;
|
|||||||
</cffunction>
|
</cffunction>
|
||||||
<cfset request.camel2snake = camel2snake/>
|
<cfset request.camel2snake = camel2snake/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+59
-4
@@ -67,7 +67,7 @@
|
|||||||
</cfloop>
|
</cfloop>
|
||||||
|
|
||||||
<cfset var outArray=arrayNew(1)/>
|
<cfset var outArray=arrayNew(1)/>
|
||||||
//copy fields to structure, renaming fields, this preserves data type
|
<!--- //copy fields to structure, renaming fields, this preserves data type --->
|
||||||
<cfloop query=#arguments.qry#>
|
<cfloop query=#arguments.qry#>
|
||||||
<cfset var structRow=structNew()/>
|
<cfset var structRow=structNew()/>
|
||||||
<cfloop index="i" from="1" to=#listLen(columnsOut)#>
|
<cfloop index="i" from="1" to=#listLen(columnsOut)#>
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
<cfset arrayAppend(outArray,structRow)/>
|
<cfset arrayAppend(outArray,structRow)/>
|
||||||
</cfloop>
|
</cfloop>
|
||||||
|
|
||||||
<cfreturn serializeJSON(outArray)/>
|
<cfreturn customJson(outArray)/>
|
||||||
<cfelse>
|
<cfelse>
|
||||||
<cfreturn serializeJSON(arguments.qry,"struct")/>
|
<cfreturn customJson(arguments.qry,"struct")/>
|
||||||
</cfif>
|
</cfif>
|
||||||
</cffunction>
|
</cffunction>
|
||||||
|
|
||||||
@@ -96,4 +96,59 @@
|
|||||||
type="application/json"
|
type="application/json"
|
||||||
/><cfoutput>#query2json(ATTRIBUTES.qRead,ATTRIBUTES.convertSnakeToCamel)#</cfoutput><!---
|
/><cfoutput>#query2json(ATTRIBUTES.qRead,ATTRIBUTES.convertSnakeToCamel)#</cfoutput><!---
|
||||||
,<cfoutput>"duration":"#(getTickCount()- msStartAt)#"</cfoutput>} --->
|
,<cfoutput>"duration":"#(getTickCount()- msStartAt)#"</cfoutput>} --->
|
||||||
<cfexit method="exittag"/>
|
<cfexit method="exittag"/>
|
||||||
|
|
||||||
|
<!--- *** еще добиться форматирования null, true, false
|
||||||
|
https://www.bennadel.com/blog/2165-returning-null-values-in-json-using-serializejson-and-coldfusion.htm
|
||||||
|
--->
|
||||||
|
<cfscript>
|
||||||
|
public string function customJson(required any data) {
|
||||||
|
return serializeJson(formatDatesToIso(arguments.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
private any function formatDatesToIso(required any input) {
|
||||||
|
// 1. Handle Dates (Strict verification using isValid and checking underlying type)
|
||||||
|
// Lucee dates are typically objects (java.util.Date / java.time).
|
||||||
|
// This prevents strings like "12345" or "Yes" from being treated as dates.
|
||||||
|
if (isDate(arguments.input) && (isObject(arguments.input) || !isValid("integer", arguments.input))) {
|
||||||
|
return dateTimeFormat(arguments.input, "iso8601");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Handle Structs (Preserve case-sensitivity using [:] syntax)
|
||||||
|
if (isStruct(arguments.input)) {
|
||||||
|
var newStruct = [Ordered: true]; // Lucee/CF literal for preserving key case
|
||||||
|
for (var key in arguments.input) {
|
||||||
|
newStruct[key] = formatDatesToIso(arguments.input[key]);
|
||||||
|
}
|
||||||
|
return newStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Handle Arrays
|
||||||
|
if (isArray(arguments.input)) {
|
||||||
|
var newArray = [];
|
||||||
|
for (var item in arguments.input) {
|
||||||
|
arrayAppend(newArray, formatDatesToIso(item));
|
||||||
|
}
|
||||||
|
return newArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Handle Queries
|
||||||
|
if (isQuery(arguments.input)) {
|
||||||
|
var queryArray = [];
|
||||||
|
var columns = arguments.input.getColumnNames(); // Returns correct case array
|
||||||
|
|
||||||
|
loop query="arguments.input" {
|
||||||
|
var rowStruct = [Ordered: true];
|
||||||
|
loop array="#columns#" index="col" {
|
||||||
|
// Safely grab cell using row coordinates
|
||||||
|
rowStruct[col] = formatDatesToIso(arguments.input[col][arguments.input.currentRow]);
|
||||||
|
}
|
||||||
|
arrayAppend(queryArray, rowStruct);
|
||||||
|
}
|
||||||
|
return queryArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Return everything else untouched (Strings, Numbers, Booleans, etc.)
|
||||||
|
return arguments.input;
|
||||||
|
}
|
||||||
|
</cfscript>
|
||||||
@@ -219,7 +219,7 @@ ORDER BY
|
|||||||
<td class="c<cfif NOT (status EQ "prod" OR status EQ "internal-test") AND isDate(dt_end_of_test) AND dt_end_of_test LE Now()> b err</cfif>">#dateFormat(dt_end_of_test,"YYYY-MM-DD")#</td>
|
<td class="c<cfif NOT (status EQ "prod" OR status EQ "internal-test") AND isDate(dt_end_of_test) AND dt_end_of_test LE Now()> b err</cfif>">#dateFormat(dt_end_of_test,"YYYY-MM-DD")#</td>
|
||||||
|
|
||||||
<td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
|
<td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
|
||||||
<td>#deal_status# [#status_id#]</td>
|
<td>#deal_status#<cfif len(status_id)> [#status_id#]</cfif></td>
|
||||||
|
|
||||||
<td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td>
|
<td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td>
|
||||||
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a> <cfif contract_id NEQ contract>(#contract_id#)</cfif> </td>
|
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a> <cfif contract_id NEQ contract>(#contract_id#)</cfif> </td>
|
||||||
|
|||||||
+3
-2
@@ -89,9 +89,10 @@ GPU-VM Power State: <b<cfif datediff("h",qGpuAge.dt_load, Now()) GT 24> class="e
|
|||||||
</b>
|
</b>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<a href="#request.thisPage#?output_xls" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
|
<a href="#request.thisPage#?output_xls&dt_start=#dateFormat(dt_start,'YYYY-MM-DD')#&dt_finish=#dateFormat(dt_finish,'YYYY-MM-DD')#" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
|
||||||
|
|
||||||
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
<a href="#request.thisPage#?output_json&dt_start=#dateFormat(dt_start,'YYYY-MM-DD')#&dt_finish=#dateFormat(dt_finish,'YYYY-MM-DD')#" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
||||||
|
<i>(перед выгрузкой отчета на произвольную дату просмотрите его в браузере)</i>
|
||||||
</cfoutput>
|
</cfoutput>
|
||||||
<table class="worktable">
|
<table class="worktable">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
Reference in New Issue
Block a user