feat: implement advanced bidirectional field referencing and cross-module path resolution

- Core Logic Enhancements:
    - Implement bidirectional field referencing between <FIELDS>, <LAYOUT>, and <TITLES> tags in .frml files, enabling seamless navigation from definitions to usages and vice versa.
    - Add robust support for AJAX-OPTION field mapping:
        - SRC attribute: Links to field definitions within defs/ajax.xml datasets.
        - TARGET attribute: Links to local field definitions within the same form.
    - Implement global grid resolution: GRID-ID now searches across the current file and all recursively included files (<INCLUDE>).
    - Enhance deep recursive search for fields/sections within nested tags like <SECTION>, <ROW>, and <FIELD-LIST>.

- Path Resolution & Helpers (DynFormPathUtils):
    - Added support for module-relative paths starting with # (mapping to view/frm/).
    - Added support for cross-module paths starting with / (mapping to WEB-INF/app/module/{module}/view/frm/).
    - Implemented auto-correction for common keyboard typos (Thai 'ิ' instead of /).
    - Added specialized helpers for locating ajax.xml and included files within the framework's structure.

- Smart Completion Enhancements:
    - Added context-aware completion for TARGET and SRC fields in AJAX update-fields.
    - Enabled global GRID-ID completion by scanning all included resources.
    - Improved dataset completion to include both local and AJAX-defined datasets.

- Test Resources:
    - Added a comprehensive set of real-world examples (bdgt04, bdgt05, bdgt06) in DevResources/full-examples/ to validate complex cross-module and master-detail scenarios.
This commit is contained in:
2026-04-10 12:56:04 +07:00
parent da049ea016
commit f705cd11b9
99 changed files with 20379 additions and 30 deletions

View File

@@ -0,0 +1,263 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT_BUDGET_ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_BUDGET_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,BGM_CODE,PBDG_ID</KEYFIELDS>
<SQL>
<SELECT>
SELECT :PROJ_ID PROJ_ID
, ACTT.ACM_CODE
, ACTT.ACM_NAME
, ACTT.ACM_SEQ
, ACTT.NODE_LEVEL
, ACTT.MAIN_NODE
, ACTT.ACM_UNIT
, ACTT.ACM_START_YEAR
, ACTT.ACM_END_YEAR
, ACTT.NODE_TYPE
, PBGI.PBDG_ID
, PBGI.BGM_CODE
, PBGI.PBGI_QTY
, PBGI.PBGI_COST
, PBGI.PBGI_FREQ
, PBGI.PBGI_ASSET_TYPE
, PBGI.PBGI_REPLACE
, PBGI.PBGI_ADDITION
, PBGI.PBGI_ACQUIRE
, PBGI.PBGI_TOTAL
, PBGI.PBGI_REASON
</SELECT>
<FROM>
FROM BGT.V_ACTIVITY_TREE ACTT
INNER JOIN ( SELECT DISTINCT ACM.ACM_CODE
FROM BUD.ACTIVITY_M ACM
INNER JOIN BUD.ACTIVITY_CTRL_H ACH ON ACM.ACM_CODE = ACH.ACH_CODE
START WITH ACM.ACM_CODE IN (SELECT PBGI.PBDG_ID ACM_CODE FROM PROJECT_BUDGET_ITEMS PBGI WHERE PROJ_ID = :PROJ_ID)
CONNECT BY PRIOR ACH.ACH_CTRL_CODE = ACH.ACH_CODE) FLTR ON FLTR.ACM_CODE = ACTT.ACM_CODE
LEFT OUTER JOIN BGT.PROJECT_BUDGET_ITEMS PBGI ON PBGI.PBDG_ID = ACTT.ACM_CODE
</FROM>
<ORDER>ORDER BY ACTT.ACM_SEQ</ORDER>
</SQL>
<SAVE-FILTER>
<FIELD NAME="NODE_TYPE" VALUE="[C,P]" ACTION="EXCLUDE"/>
</SAVE-FILTER>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="TEXT" LABEL="รหัสอ้างอิงโครงการ" WIDTH="32"/>
<FIELD NAME="PBDG_ID" TYPE="TEXT" LABEL="รหัสงบประมาณโครงการ" WIDTH="32" FORM-NAME="ACM_CODE"/>
<FIELD NAME="BGM_CODE" TYPE="TEXT" LABEL="รหัสหมวดงบประมาณ" WIDTH="20"/>
<FIELD NAME="PBGI_QT_01" TYPE="NUMBER" LABEL="จำนวนไตรมาส 1" WIDTH="15"/>
<FIELD NAME="PBGI_QT_02" TYPE="NUMBER" LABEL="จำนวนไตรมาส 2" WIDTH="15"/>
<FIELD NAME="PBGI_QT_03" TYPE="NUMBER" LABEL="จำนวนไตรมาส 3" WIDTH="15"/>
<FIELD NAME="PBGI_QT_04" TYPE="NUMBER" LABEL="จำนวนไตรมาส 4" WIDTH="15"/>
<FIELD NAME="PBGI_QTY" TYPE="NUMBER" LABEL="จำนวน" WIDTH="10"/>
<FIELD NAME="PBGI_COST" TYPE="NUMBER" LABEL="ราคาต่อหน่วย" WIDTH="15"/>
<FIELD NAME="PBGI_FREQ" TYPE="NUMBER" LABEL="ความถี่/จำนวนครั้ง" WIDTH="10"/>
<FIELD NAME="PBGI_ASSET_TYPE" TYPE="TEXT" LABEL="ประเภทสินทรัพย์" WIDTH="10"/>
<FIELD NAME="PBGI_REPLACE" TYPE="NUMBER" LABEL="ทดแทนของเดิม" WIDTH="10"/>
<FIELD NAME="PBGI_ADDITION" TYPE="NUMBER" LABEL="เพิ่มเติม" WIDTH="10"/>
<FIELD NAME="PBGI_ACQUIRE" TYPE="NUMBER" LABEL="จัดหาใหม่" WIDTH="10"/>
<FIELD NAME="PBGI_TOTAL" TYPE="NUMBER" LABEL="รวมเป็นเงิน" WIDTH="15"/>
<FIELD NAME="PBGI_REASON" TYPE="TEXT" LABEL="เหตุผลความจำเป็น" WIDTH="4000"/>
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-CONST-BUDGET">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID" DETAIL-FIELDS="PROJ_ID"/>
<UNIQ-CHECK CHECK-FIELDS="ACM_CODE" MESSAGE="pctbi.const_code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT_BUDGET_ITEMS" EDIT="Y" DELETE="Y" CLASS="table-primary">
<KEYFIELDS>PROJ_ID,BGM_CODE</KEYFIELDS>
<TITLES>
<ROW>
<FIELD NAME="ACM_CODE" LABEL="pctbi.const_code" WIDTH="10em" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="ACM_NAME" LABEL="pctbi.const_name" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BUDGET_INFO" LABEL="pctbi.budget" ALIGN="center" COLS-SPAN="3"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_QTY" LABEL="pctbi.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pctbi.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pctbi.total" WIDTH="8em" ALIGN="right"/>
</ROW>
</TITLES>
<FIELDS>
<FIELD NAME="PBDG_ID" LABEL="pctbi.const_code" WIDTH="15em" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="ACM_NAME" LABEL="pctbi.const_name" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
<COMMAND-BUTTONS>
<BUTTONS-FILTER>
<EDIT><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></EDIT>
<DELETE><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></DELETE>
<VIEW><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></VIEW>
</BUTTONS-FILTER>
</COMMAND-BUTTONS>
</FIELDS>
<FOOTER SHOW="Y"/>
<SCRIPT>
<INITIALIZE>
<![CDATA[
(ctx)=> {
ctx.sum_of = {};
console.log("init grid-budget");
const fieldFormat = (field,value,row) => {
if (row["node_type"] === "D" || field === "pbgi_total") {
return formatNumber(value, 0);
} else {
return "";
}
}
const summary = (field, data) => {
let total = 0;
for (const row of data) {
total += (+row[field])||0;
}
ctx.sum_of[field] = total;
if (ctx.$dataGrid && ctx.$dataGrid.load && !ctx.$dataGrid.reload) {
ctx.$dataGrid.reload = true;
for (let id=data.length-1; id>=0; id--) {
let row = data[id];
if (row["node_type"] === "C") {
let grpTotal = 0;
let mainNode = row["acm_code"];
let nodes = [];
let dataNode = $$("main_node="+mainNode,data);
if (dataNode) {
nodes.push(dataNode);
for (let node of nodes.flat()) {
grpTotal += +node[field];
}
data[id][field] = grpTotal;
}
}
}
ctx.$dataGrid.load(data);
ctx.$dataGrid.reload = false;
}
return formatNumber(total,0);
}
const fieldList = ["pbgi_qty","pbgi_cost","pbgi_total"];
for (let field of fieldList) {
let column = $$(`field=${field}`,ctx.gridColumn.flat());
column.formatter = (value,row) => {
return fieldFormat(field, value, row);
}
column.footerFormatter = (data)=>{
return summary(field,data);
}
}
ctx.option.rowStyle = function (row, index) {
if (row["node_type"] === "C") {
return {classes : `group-level-${row["node_level"]}`};
}
return {}; // Default style for other rows
}
}
]]>
</INITIALIZE>
</SCRIPT>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT_BUDGET_ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="PBDG_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="ACM_CODE" INPUTTYPE="HIDDEN"/>
<FIELD NAME="BGM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="ACM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="VACM_CODE" CAPTION="pctbi.const_code" INPUTTYPE="TEXT" REQUIRE="Y" READONLY="Y"/>
<FIELD NAME="ACM_CODE" CAPTION="pctbi.const_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-ACTIVITY-04" VALUE-FIELD="ACM_CODE" TEXT-FIELD="ACM_NAME" PARAMETERS="DV_YEAR=PROJ_YEAR,STM_CODE=STM_CODE">
<UPDATE-FIELDS>
<FIELD SRC="ACM_CODE" TARGET="VACM_CODE"/>
<FIELD SRC="ACM_CODE" TARGET="PBDG_ID"/>
<FIELD SRC="ACM_NAME" TARGET="ACM_NAME"/>
<FIELD SRC="ACM_UNIT" TARGET="PBGI_UNIT"/>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
console.log("call formater with ", data);
return $(`<div class="d-flex flex-row gap-1"><label class="flex-column text-nowrap col-3">[${data.acm_code}]</label> : <label>${data.acm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="VBGM_CODE" CAPTION="pwbg.bgm_code" INPUTTYPE="TEXT" READONLY="Y"/>
<FIELD NAME="BGM_CODE" CAPTION="pwbg.bgm_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-BUDGET-04" VALUE-FIELD="BGM_CODE" TEXT-FIELD="BGM_NAME">
<UPDATE-FIELDS>
<FIELD SRC="BGM_CODE" TARGET="VBGM_CODE"></FIELD>
<FIELD SRC="BGM_NAME" TARGET="BGM_NAME"></FIELD>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
console.log("call formater with ", data);
return $(`<div class="d-flex flex-row gap-1"><label class="flex-column text-nowrap col-3">[${data.bgm_code}]</label> : <label>${data.bgm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="PBGI_UNIT" CAPTION="pctbi.unit" INPUTTYPE="TEXT" DATATYPE="TEXT" READONLY="Y"/>
<FIELD NAME="PBGI_QTY" CAPTION="pctbi.qty" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_COST" CAPTION="pctbi.cost" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_TOTAL" CAPTION="pctbi.total" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" READONLY="Y"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="VACM_CODE" LAYOUT_WIDTH="6"/>
<FIELD NAME="ACM_CODE" LAYOUT_WIDTH="16"/>
</ROW>
<ROW ID="ROW-BUDGET-DATA">
<FIELD NAME="PBGI_QTY" LAYOUT_WIDTH="3" OFFSET="6"/>
<FIELD NAME="PBGI_UNIT" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_COST" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_TOTAL" LAYOUT_WIDTH="3"/>
</ROW>
<ROW>
<FIELD NAME="VBGM_CODE" LAYOUT_WIDTH="4" OFFSET="6"/>
<FIELD NAME="BGM_CODE" LAYOUT_WIDTH="12"/>
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 350px"></div>]]>
</ROW>
</LAYOUT>
<SCRIPT>
<INITIALIZE><![CDATA[
console.log("sum budget value");
let budgetField = $$("input.budget-data");
const sumBudget = ()=>{
$$("PBGI_TOTAL").setValue(budgetField.multiply());
}
budgetField.on("change",sumBudget);
]]></INITIALIZE>
</SCRIPT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT_BUDGET_ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_BUDGET_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,BGM_CODE,PBDG_ID</KEYFIELDS>
<SQL>
<SELECT>SELECT BGTT.BGM_CODE
, BGTT.BGM_NAME
, BGTT.BGM_UNIT
, BGTT.BGM_UNIT_RATE
, BGTT.NODE_LEVEL
, BGTT.BGM_SEQ
, BGTT.EXP_TYPE
, BGTT.MAIN_NODE
, BGTT.NODE_TYPE
, PBGI.PBGI_QTY
, PBGI.PBGI_COST
, PBGI.PBGI_FREQ
, PBGI.PBGI_ASSET_TYPE
, PBGI.PBGI_REPLACE
, PBGI.PBGI_ADDITION
, PBGI.PBGI_ACQUIRE
, PBGI.PBGI_TOTAL
, PBGI.PBGI_REASON
</SELECT>
<FROM>
FROM BGT.V_BUDGET_TREE BGTT
INNER JOIN (SELECT DISTINCT BGDM.BGM_CODE
FROM BUD.BUDGET_M BGDM
INNER JOIN BUD.BUDGET_M BGDH ON BGDM.BGM_CODE = BGDH.BGM_CODE
START WITH BGDM.BGM_CODE IN (SELECT PBGI.BGM_CODE FROM BGT.PROJECT_BUDGET_ITEMS PBGI WHERE PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID)
CONNECT BY PRIOR BGDH.BGM_MAIN_NODE = BGDH.BGM_CODE) FLTR ON FLTR.BGM_CODE = BGTT.BGM_CODE
LEFT OUTER JOIN BGT.PROJECT_BUDGET_ITEMS PBGI ON PBGI.BGM_CODE = BGTT.BGM_CODE
</FROM>
<ORDER>ORDER BY BGTT.BGM_SEQ</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="TEXT" LABEL="รหัสอ้างอิงโครงการ" WIDTH="32"/>
<FIELD NAME="PBDG_ID" TYPE="TEXT" LABEL="รหัสงบประมาณโครงการ" WIDTH="32"/>
<FIELD NAME="BGM_CODE" TYPE="TEXT" LABEL="รหัสหมวดงบประมาณ" WIDTH="20"/>
<FIELD NAME="PBGI_QT_01" TYPE="NUMBER" LABEL="จำนวนไตรมาส 1" WIDTH="15"/>
<FIELD NAME="PBGI_QT_02" TYPE="NUMBER" LABEL="จำนวนไตรมาส 2" WIDTH="15"/>
<FIELD NAME="PBGI_QT_03" TYPE="NUMBER" LABEL="จำนวนไตรมาส 3" WIDTH="15"/>
<FIELD NAME="PBGI_QT_04" TYPE="NUMBER" LABEL="จำนวนไตรมาส 4" WIDTH="15"/>
<FIELD NAME="PBGI_QTY" TYPE="NUMBER" LABEL="จำนวน" WIDTH="10"/>
<FIELD NAME="PBGI_COST" TYPE="NUMBER" LABEL="ราคาต่อหน่วย" WIDTH="15"/>
<FIELD NAME="PBGI_FREQ" TYPE="NUMBER" LABEL="ความถี่/จำนวนครั้ง" WIDTH="10"/>
<FIELD NAME="PBGI_ASSET_TYPE" TYPE="TEXT" LABEL="ประเภทสินทรัพย์" WIDTH="10"/>
<FIELD NAME="PBGI_REPLACE" TYPE="NUMBER" LABEL="ทดแทนของเดิม" WIDTH="10"/>
<FIELD NAME="PBGI_ADDITION" TYPE="NUMBER" LABEL="เพิ่มเติม" WIDTH="10"/>
<FIELD NAME="PBGI_ACQUIRE" TYPE="NUMBER" LABEL="จัดหาใหม่" WIDTH="10"/>
<FIELD NAME="PBGI_TOTAL" TYPE="NUMBER" LABEL="รวมเป็นเงิน" WIDTH="15"/>
<FIELD NAME="PBGI_REASON" TYPE="TEXT" LABEL="เหตุผลความจำเป็น" WIDTH="4000"/>
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-EQUIPT-BUDGET">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID,PBDG_ID" DETAIL-FIELDS="PROJ_ID,PBDG_ID"/>
<UNIQ-CHECK CHECK-FIELDS="BGM_CODE" MESSAGE="pwbg.bgm_code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT_BUDGET_ITEMS" EDIT="Y" DELETE="Y" CLASS="table-primary">
<KEYFIELDS>PROJ_ID,BGM_CODE</KEYFIELDS>
<TITLES>
<ROW>
<FIELD NAME="BGM_CODE" LABEL="pbgz.bgm_code" WIDTH="10em" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_NAME" LABEL="pbgz.bgm_name" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_BUTGETS" LABEL="pbgz.budget" ALIGN="center" COLS-SPAN="5"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_FREQ" LABEL="pbgz.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_ACQUIRE" LABEL="pbgz.acquire" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
</ROW>
</TITLES>
<FIELDS>
<FIELD NAME="BGM_CODE" LABEL="pwbg.bgm_code" WIDTH="15em" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="BGM_NAME" LABEL="pwbg.bgm_name" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="PBGI_FREQ" LABEL="pbgz.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_ACQUIRE" LABEL="pbgz.acquire" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
<COMMAND-BUTTONS>
<BUTTONS-FILTER>
<EDIT><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></EDIT>
<DELETE><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></DELETE>
<VIEW><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></VIEW>
</BUTTONS-FILTER>
</COMMAND-BUTTONS>
</FIELDS>
<FOOTER SHOW="Y"/>
<SCRIPT>
<INITIALIZE>
<![CDATA[
(ctx)=> {
ctx.sum_of = {};
console.log("init grid-budget");
const fieldFormat = (field,value,row) => {
if (row["node_type"] === "D" || field === "pbgi_total") {
return formatNumber(value, 0);
} else {
return "";
}
}
const summary = (field, data) => {
let total = 0;
for (const row of data) {
total += (+row[field])||0;
}
ctx.sum_of[field] = total;
if (ctx.$dataGrid && ctx.$dataGrid.load && !ctx.$dataGrid.reload) {
ctx.$dataGrid.reload = true;
for (let id=data.length-1; id>=0; id--) {
let row = data[id];
if (row["node_type"] === "C") {
let grpTotal = 0;
let mainNode = row["bgm_code"];
let nodes = [];
nodes.push($$("main_node="+mainNode,data));
for (let node of nodes.flat()) {
grpTotal += +node[field];
}
data[id][field] = grpTotal;
}
}
ctx.$dataGrid.load(data);
ctx.$dataGrid.reload = false;
}
return formatNumber(total,0);
}
const fieldList = ["pbgi_freq","pbgi_qty","pbgi_acquire","pbgi_cost","pbgi_total"];
for (let field of fieldList) {
let column = $$(`field=${field}`,ctx.gridColumn.flat());
column.formatter = (value,row) => {
return fieldFormat(field, value, row);
}
column.footerFormatter = (data)=>{
return summary(field,data);
}
}
ctx.option.rowStyle = function (row, index) {
if (row["node_type"] === "C") {
return {classes : `group-level-${row["node_level"]}`};
}
return {}; // Default style for other rows
}
}
]]>
</INITIALIZE>
</SCRIPT>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT_BUDGET_ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="PBDG_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="BGM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="VBGM_CODE" CAPTION="pwbg.bgm_code" INPUTTYPE="TEXT" READONLY="Y"/>
<FIELD NAME="BGM_CODE" CAPTION="pwbg.bgm_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-BUDGET-03" VALUE-FIELD="BGM_CODE" TEXT-FIELD="BGM_NAME">
<UPDATE-FIELDS>
<FIELD SRC="BGM_CODE" TARGET="VBGM_CODE"></FIELD>
<FIELD SRC="BGM_NAME" TARGET="BGM_NAME"></FIELD>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
console.log("call formater with ", data);
return $(`<div><label class="offset-${data.node_level}">[${data.bgm_code}]</label> : <label>${data.bgm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="PBGI_FREQ" CAPTION="pbgz.freq" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_QTY" CAPTION="pbgz.qty" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_ACQUIRE" CAPTION="pbgz.acquire" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_COST" CAPTION="pbgz.cost" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_TOTAL" CAPTION="pbgz.total" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" READONLY="Y"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="VBGM_CODE" LAYOUT_WIDTH="6"/>
<FIELD NAME="BGM_CODE" LAYOUT_WIDTH="16"/>
</ROW>
<ROW ID="ROW-BUDGET-DATA">
<FIELD NAME="PBGI_FREQ" LAYOUT_WIDTH="3" OFFSET="6"/>
<FIELD NAME="PBGI_QTY" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_ACQUIRE" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_COST" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_TOTAL" LAYOUT_WIDTH="3"/>
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 350px"></div>]]>
</ROW>
</LAYOUT>
<SCRIPT>
<INITIALIZE><![CDATA[
console.log("sum budget value");
let budgetField = $$("input.budget-data");
const sumBudget = ()=>{
$$("PBGI_TOTAL").setValue(budgetField.multiply());
}
budgetField.on("change",sumBudget);
]]></INITIALIZE>
</SCRIPT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT_BUDGET_ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_BUDGET_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,BGM_CODE,PBDG_ID</KEYFIELDS>
<SQL>
<SELECT>SELECT BGTT.BGM_CODE
, BGTT.BGM_NAME
, BGTT.BGM_UNIT
, BGTT.BGM_UNIT_RATE
, BGTT.NODE_LEVEL
, BGTT.BGM_SEQ
, BGTT.EXP_TYPE
, BGTT.MAIN_NODE
, BGTT.NODE_TYPE
, PBGI.PBGI_QTY
, PBGI.PBGI_FREQ
, PBGI.PBGI_COST
, PBGI.PBGI_ACQUIRE
, PBGI.PBGI_TOTAL
</SELECT>
<FROM>
FROM BGT.V_BUDGET_TREE BGTT
INNER JOIN (SELECT DISTINCT BGDM.BGM_CODE
FROM BUD.BUDGET_M BGDM
INNER JOIN BUD.BUDGET_M BGDH ON BGDM.BGM_CODE = BGDH.BGM_CODE
START WITH BGDM.BGM_CODE IN (SELECT PBGI.BGM_CODE FROM BGT.PROJECT_BUDGET_ITEMS PBGI WHERE PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID)
CONNECT BY PRIOR BGDH.BGM_MAIN_NODE = BGDH.BGM_CODE) FLTR ON FLTR.BGM_CODE = BGTT.BGM_CODE
LEFT OUTER JOIN BGT.PROJECT_BUDGET_ITEMS PBGI ON PBGI.BGM_CODE = BGTT.BGM_CODE AND PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID
</FROM>
<ORDER>ORDER BY BGTT.BGM_SEQ</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="TEXT" LABEL="รหัสอ้างอิงโครงการ" WIDTH="32"/>
<FIELD NAME="PBDG_ID" TYPE="TEXT" LABEL="รหัสงบประมาณโครงการ" WIDTH="32"/>
<FIELD NAME="BGM_CODE" TYPE="TEXT" LABEL="รหัสหมวดงบประมาณ" WIDTH="20"/>
<FIELD NAME="PBGI_FREQ" TYPE="NUMBER" LABEL="จำนวนครั้ง" WIDTH="10"/>
<FIELD NAME="PBGI_QTY" TYPE="NUMBER" LABEL="จำนวนคน" WIDTH="10"/>
<FIELD NAME="PBGI_ACQUIRE" TYPE="NUMBER" LABEL="จำนวนชั่วโมง" WIDTH="10"/>
<FIELD NAME="PBGI_COST" TYPE="NUMBER" LABEL="อัตรา" WIDTH="15"/>
<FIELD NAME="PBGI_TOTAL" TYPE="NUMBER" LABEL="รวมเป็นเงิน" WIDTH="15"/>
<FIELD NAME="PBGI_REASON" TYPE="TEXT" LABEL="เหตุผลความจำเป็น" WIDTH="4000"/>
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-WORK-BUDGET">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID,PBDG_ID" DETAIL-FIELDS="PROJ_ID,PBDG_ID"/>
<UNIQ-CHECK CHECK-FIELDS="BGM_CODE" MESSAGE="pwbg.bgm_code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT_BUDGET_ITEMS" EDIT="Y" DELETE="Y" CLASS="table-primary">
<KEYFIELDS>PROJ_ID,BGM_CODE</KEYFIELDS>
<TITLES>
<ROW>
<FIELD NAME="BGM_CODE" LABEL="pbgz.bgm_code" WIDTH="10em" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_NAME" LABEL="pbgz.bgm_name" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_BUTGETS" LABEL="pbgz.budget" ALIGN="center" COLS-SPAN="5"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_FREQ" LABEL="pbgz.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_ACQUIRE" LABEL="pbgz.acquire" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
</ROW>
</TITLES>
<FIELDS>
<FIELD NAME="BGM_CODE" LABEL="pwbg.bgm_code" WIDTH="15em" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="BGM_NAME" LABEL="pwbg.bgm_name" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="PBGI_FREQ" LABEL="pbgz.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_ACQUIRE" LABEL="pbgz.acquire" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
<COMMAND-BUTTONS>
<BUTTONS-FILTER>
<EDIT><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></EDIT>
<DELETE><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></DELETE>
<VIEW><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></VIEW>
</BUTTONS-FILTER>
</COMMAND-BUTTONS>
</FIELDS>
<FOOTER SHOW="Y"/>
<SCRIPT>
<INITIALIZE>
<![CDATA[
(ctx)=> {
ctx.sum_of = {};
console.log("init grid-budget");
const fieldFormat = (field,value,row) => {
if (row["node_type"] === "D" || field === "pbgi_total") {
return formatNumber(value, 0);
} else {
return "";
}
}
const summary = (field, data) => {
let total = 0;
for (const row of data) {
total += (+row[field])||0;
}
ctx.sum_of[field] = total;
if (ctx.$dataGrid && ctx.$dataGrid.load && !ctx.$dataGrid.reload) {
ctx.$dataGrid.reload = true;
for (let id=data.length-1; id>=0; id--) {
let row = data[id];
if (row["node_type"] === "C") {
let grpTotal = 0;
let mainNode = row["bgm_code"];
let nodes = [];
nodes.push($$("main_node="+mainNode,data));
for (let node of nodes.flat()) {
grpTotal += +node[field];
}
data[id][field] = grpTotal;
}
}
ctx.$dataGrid.load(data);
ctx.$dataGrid.reload = false;
}
return formatNumber(total,0);
}
const fieldList = ["pbgi_freq","pbgi_qty","pbgi_acquire","pbgi_cost","pbgi_total"];
for (let field of fieldList) {
let column = $$(`field=${field}`,ctx.gridColumn.flat());
column.formatter = (value,row) => {
return fieldFormat(field, value, row);
}
column.footerFormatter = (data)=>{
return summary(field,data);
}
}
ctx.option.rowStyle = function (row, index) {
if (row["node_type"] === "C") {
return {classes : `group-level-${row["node_level"]}`};
}
return {}; // Default style for other rows
}
}
]]>
</INITIALIZE>
</SCRIPT>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT_BUDGET_ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="PBDG_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="BGM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="VBGM_CODE" CAPTION="pwbg.bgm_code" INPUTTYPE="TEXT" READONLY="Y"/>
<FIELD NAME="BGM_CODE" CAPTION="pwbg.bgm_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-BUDGET-02" VALUE-FIELD="BGM_CODE" TEXT-FIELD="BGM_NAME">
<UPDATE-FIELDS>
<FIELD SRC="BGM_CODE" TARGET="VBGM_CODE"></FIELD>
<FIELD SRC="BGM_NAME" TARGET="BGM_NAME"></FIELD>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
console.log("call formater with ", data);
return $(`<div><label class="offset-${data.node_level}">[${data.bgm_code}]</label> : <label>${data.bgm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="PBGI_FREQ" CAPTION="pbgz.freq" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_QTY" CAPTION="pbgz.qty" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_ACQUIRE" CAPTION="pbgz.acquire" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_COST" CAPTION="pbgz.cost" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_TOTAL" CAPTION="pbgz.total" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" READONLY="Y"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="VBGM_CODE" LAYOUT_WIDTH="6"/>
<FIELD NAME="BGM_CODE" LAYOUT_WIDTH="16"/>
</ROW>
<ROW ID="ROW-BUDGET-DATA">
<FIELD NAME="PBGI_FREQ" LAYOUT_WIDTH="3" OFFSET="6"/>
<FIELD NAME="PBGI_QTY" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_ACQUIRE" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_COST" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_TOTAL" LAYOUT_WIDTH="3"/>
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 350px"></div>]]>
</ROW>
</LAYOUT>
<SCRIPT>
<INITIALIZE><![CDATA[
console.log("sum budget value");
let budgetField = $$("input.budget-data");
const sumBudget = ()=>{
$$("PBGI_TOTAL").setValue(budgetField.multiply());
}
budgetField.on("change",sumBudget);
]]></INITIALIZE>
</SCRIPT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,272 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT_BUDGET_ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_BUDGET_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,BGM_CODE,PBDG_ID</KEYFIELDS>
<SQL>
<SELECT>SELECT BGTT.BGM_CODE
, BGTT.BGM_NAME
, BGTT.BGM_UNIT
, BGTT.BGM_UNIT_RATE
, BGTT.NODE_LEVEL
, BGTT.BGM_SEQ
, BGTT.EXP_TYPE
, BGTT.MAIN_NODE
, BGTT.NODE_TYPE
, PBGI.PBGI_QTY
, PBGI.PBGI_FREQ
, PBGI.PBGI_COST
, PBGI.PBGI_TOTAL
</SELECT>
<FROM>
FROM BGT.V_BUDGET_TREE BGTT
INNER JOIN (SELECT DISTINCT BGDM.BGM_CODE
FROM BUD.BUDGET_M BGDM
INNER JOIN BUD.BUDGET_M BGDH ON BGDM.BGM_CODE = BGDH.BGM_CODE
START WITH BGDM.BGM_CODE IN (SELECT PBGI.BGM_CODE FROM BGT.PROJECT_BUDGET_ITEMS PBGI WHERE PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID)
CONNECT BY PRIOR BGDH.BGM_MAIN_NODE = BGDH.BGM_CODE) FLTR ON FLTR.BGM_CODE = BGTT.BGM_CODE
LEFT OUTER JOIN BGT.PROJECT_BUDGET_ITEMS PBGI ON PBGI.BGM_CODE = BGTT.BGM_CODE AND PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID
</FROM>
<ORDER>ORDER BY BGTT.BGM_SEQ</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="TEXT" LABEL="รหัสอ้างอิงโครงการ" WIDTH="32"/>
<FIELD NAME="PBDG_ID" TYPE="TEXT" LABEL="รหัสงบประมาณโครงการ" WIDTH="32"/>
<FIELD NAME="BGM_CODE" TYPE="TEXT" LABEL="รหัสหมวดงบประมาณ" WIDTH="20"/>
<FIELD NAME="PBGI_FREQ" TYPE="NUMBER" LABEL="จำนวนครั้ง" WIDTH="10"/>
<FIELD NAME="PBGI_QTY" TYPE="NUMBER" LABEL="จำนวนคน" WIDTH="10"/>
<FIELD NAME="PBGI_COST" TYPE="NUMBER" LABEL="อัตรา" WIDTH="15"/>
<FIELD NAME="PBGI_TOTAL" TYPE="NUMBER" LABEL="รวมเป็นเงิน" WIDTH="15"/>
<FIELD NAME="PBGI_REASON" TYPE="TEXT" LABEL="เหตุผลความจำเป็น" WIDTH="4000"/>
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-WORK-BUDGET">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID,PBDG_ID" DETAIL-FIELDS="PROJ_ID,PBDG_ID"/>
<UNIQ-CHECK CHECK-FIELDS="BGM_CODE" MESSAGE="pwbg.bgm_code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT_BUDGET_ITEMS" EDIT="Y" DELETE="Y" ADD="Y" CLASS="table-primary">
<KEYFIELDS>PROJ_ID,BGM_CODE</KEYFIELDS>
<TITLES>
<ROW>
<FIELD NAME="BGM_CODE" LABEL="plcbg.bgm_code" WIDTH="10em" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_NAME" LABEL="plcbg.bgm_name" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_BUTGETS" LABEL="plcbg.budget" ALIGN="center" COLS-SPAN="4"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_QTY" LABEL="plcbg.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_FREQ" LABEL="plcbg.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="plcbg.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="plcbg.total" WIDTH="8em" ALIGN="right"/>
</ROW>
</TITLES>
<FIELDS>
<FIELD NAME="BGM_CODE" LABEL="pwbg.bgm_code" WIDTH="15em" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="BGM_NAME" LABEL="pwbg.bgm_name" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="PBGI_QTY" LABEL="plcbg.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_FREQ" LABEL="plcbg.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="plcbg.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="plcbg.total" WIDTH="8em" ALIGN="right"/>
<COMMAND-BUTTONS>
<BUTTONS-FILTER>
<EDIT><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></EDIT>
<DELETE><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></DELETE>
<VIEW><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></VIEW>
</BUTTONS-FILTER>
</COMMAND-BUTTONS>
</FIELDS>
<FOOTER SHOW="Y"/>
<SCRIPT>
<INITIALIZE>
<![CDATA[
(ctx)=> {
ctx.sum_of = {};
console.log("init grid-budget");
const fieldFormat = (field,value,row) => {
return (row["node_type"] === "D" || field === "pbgi_total") ? formatNumber(value, 0) : "";
}
const summary = (field, data) => {
let total = 0;
for (const row of data) {
if (row["node_type"] === "D") {
total += (strToFloat(row[field])) || 0;
}
}
ctx.sum_of[field] = total;
if (ctx.$dataGrid && ctx.$dataGrid.load && !ctx.$dataGrid.reload) {
ctx.$dataGrid.reload = true;
for (let id=data.length-1; id>=0; id--) {
let row = data[id];
if (row["node_type"] === "C") {
let grpTotal = 0;
let mainNode = row["bgm_code"];
let nodes = [];
nodes.push($$("main_node="+mainNode,data));
for (let node of nodes.flat()) {
grpTotal += +node[field];
}
data[id][field] = grpTotal;
}
}
ctx.$dataGrid.load(data);
ctx.$dataGrid.reload = false;
}
return formatNumber(total,0);
}
const fieldList = ["pbgi_freq","pbgi_qty","pbgi_cost","pbgi_total"];
for (let field of fieldList) {
let column = $$(`field=${field}`,ctx.gridColumn.flat());
column.formatter = (value,row) => {
return fieldFormat(field, value, row);
}
column.footerFormatter =function (data) {
return summary(field,data);
}
}
ctx.option.rowStyle = function (row, index) {
if (row["node_type"] === "C") {
return {classes : `group-level-${row["node_level"]}`};
}
return {}; // Default style for other rows
}
}
]]>
</INITIALIZE>
</SCRIPT>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT_BUDGET_ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="PBDG_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="BGM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="NODE_TYPE" INPUTTYPE="HIDDEN" VALUE="D"/>
<FIELD NAME="VBGM_CODE" CAPTION="pwbg.bgm_code" INPUTTYPE="TEXT" READONLY="Y"/>
<FIELD NAME="BGM_CODE" CAPTION="pwbg.bgm_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-BUDGET-02-BDGT" VALUE-FIELD="BGM_CODE" TEXT-FIELD="BGM_NAME">
<UPDATE-FIELDS>
<FIELD SRC="BGM_CODE" TARGET="VBGM_CODE"></FIELD>
<FIELD SRC="BGM_NAME" TARGET="BGM_NAME"></FIELD>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
return $(`<div><label class="offset-${data.node_level}">[${data.bgm_code}]</label> : <label>${data.bgm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="PBGI_QTY" CAPTION="plcbg.qty" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_FREQ" CAPTION="plcbg.freq" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_COST" CAPTION="plcbg.cost" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_TOTAL" CAPTION="plcbg.total" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" READONLY="Y"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="VBGM_CODE" LAYOUT_WIDTH="6"/>
<FIELD NAME="BGM_CODE" LAYOUT_WIDTH="16"/>
</ROW>
<ROW ID="ROW-BUDGET-DATA">
<FIELD NAME="PBGI_QTY" LAYOUT_WIDTH="3" OFFSET="6"/>
<FIELD NAME="PBGI_FREQ" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_COST" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_TOTAL" LAYOUT_WIDTH="3"/>
</ROW>
<ROW TYPE="CONTENT" CLASS="bootstrap-table bootstrap5">
<![CDATA[
<div class="fixed-table-container fixed-table-header col-24">
<table class="col-24 no-padding table table-bordered table-hover with-command">
<thead class="table-primary">
<tr>
<th style="text-align: center; vertical-align: middle; width: 3em; " rowspan="2" data-field="bgm_code">
<div class="th-inner ">No</div>
</th>
<th style="text-align: center; vertical-align: middle; " rowspan="2" data-field="bgm_name">
<div class="th-inner ">รายการกิจกรรม</div>
</th>
<th style="text-align: center; " colspan="4">
<div class="th-inner ">งบประมาณ</div>
<div class="fht-cell"></div>
</th>
<th class="operate-header" style="text-align: center; width: 90px; " rowspan="2" data-field="grid-operate">
<button type="button" id="add-btn-gridGRID_BUDGET" class="btn btn-primary btn-round white data-grid-add-btn w-75"><i class="fa fa-plus"></i></button>
</th>
</tr>
<tr>
<th style="text-align: center; width: 5em; " data-field="pbgi_freq" data-not-first-th="">
<div class="th-inner ">หน่วย/คน</div>
</th>
<th style="text-align: center; width: 5em; " data-field="pbgi_qty">
<div class="th-inner ">ครั้ง/คืน</div>
</th>
<th style="text-align: center; width: 6em; " data-field="pbgi_cost">
<div class="th-inner ">อัตรา</div>
</th>
<th style="text-align: center; width: 8em; " data-field="pbgi_total">
<div class="th-inner ">รวมเป็นเงิน</div>
</th>
</tr>
</thead>
<tbody>
<tr data-index="1">
<td class="" style="text-align: right; vertical-align: middle;">
<div class="col">1</div>
</td>
<td class="" style="text-align: left; vertical-align: middle;">
<div class="col">กิจกรรมย่อย 1</div>
</td>
<td class="" style="text-align: right; ">5</td>
<td class="" style="text-align: right; ">10</td>
<td class="" style="text-align: right; ">200</td>
<td class="" style="text-align: right; ">10,000</td>
<td class="operate-header" style="text-align: center; width: 90px;">
<div class="d-flex flex-row gap-1 justify-content-center width-100">
<button type="button" class="btn btn-grid-command btn-warning btn-edit" title="Edit "><i class="fa fa-edit white"></i></button>
<button type="button" class="btn btn-grid-command btn-danger btn-delete" title="Delete "><i class="fa fa-trash-alt white"></i></button>
<button type="button" class="btn btn-grid-command btn-primary btn-view" title="View "><i class="fa fa-file-alt white"></i></button>
</div>
</td>
</tr>
<tr data-index="1">
<td class="" colspan="8"><div style="height: 200px"></div></td>
</tr>
</tbody>
</table>
]]>
</ROW>
</LAYOUT>
<SCRIPT>
<INITIALIZE><![CDATA[
console.log("sum budget value");
let budgetField = $$("input.budget-data");
const sumBudget = ()=>{
$$("PBGI_TOTAL").setValue(budgetField.multiply());
}
budgetField.on("change",sumBudget);
]]></INITIALIZE>
</SCRIPT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT_BUDGET_ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_BUDGET_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,BGM_CODE,PBDG_ID</KEYFIELDS>
<SQL>
<SELECT>SELECT BGTT.BGM_CODE
, BGTT.BGM_NAME
, BGTT.BGM_UNIT
, BGTT.BGM_UNIT_RATE
, BGTT.NODE_LEVEL
, BGTT.BGM_SEQ
, BGTT.EXP_TYPE
, BGTT.MAIN_NODE
, BGTT.NODE_TYPE
, PBGI.PBGI_QTY
, PBGI.PBGI_FREQ
, PBGI.PBGI_COST
, PBGI.PBGI_ACQUIRE
, PBGI.PBGI_TOTAL
</SELECT>
<FROM>
FROM BGT.V_BUDGET_TREE BGTT
INNER JOIN (SELECT DISTINCT BGDM.BGM_CODE
FROM BUD.BUDGET_M BGDM
INNER JOIN BUD.BUDGET_M BGDH ON BGDM.BGM_CODE = BGDH.BGM_CODE
START WITH BGDM.BGM_CODE IN (SELECT PBGI.BGM_CODE FROM BGT.PROJECT_BUDGET_ITEMS PBGI WHERE PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID)
CONNECT BY PRIOR BGDH.BGM_MAIN_NODE = BGDH.BGM_CODE) FLTR ON FLTR.BGM_CODE = BGTT.BGM_CODE
LEFT OUTER JOIN BGT.PROJECT_BUDGET_ITEMS PBGI ON PBGI.BGM_CODE = BGTT.BGM_CODE AND PBGI.PROJ_ID = :PROJ_ID AND PBGI.PBDG_ID = :PBDG_ID
</FROM>
<ORDER>ORDER BY BGTT.BGM_SEQ</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="TEXT" LABEL="รหัสอ้างอิงโครงการ" WIDTH="32"/>
<FIELD NAME="PBDG_ID" TYPE="TEXT" LABEL="รหัสงบประมาณโครงการ" WIDTH="32"/>
<FIELD NAME="BGM_CODE" TYPE="TEXT" LABEL="รหัสหมวดงบประมาณ" WIDTH="20"/>
<FIELD NAME="PBGI_FREQ" TYPE="NUMBER" LABEL="จำนวนครั้ง" WIDTH="10"/>
<FIELD NAME="PBGI_QTY" TYPE="NUMBER" LABEL="จำนวนคน" WIDTH="10"/>
<FIELD NAME="PBGI_ACQUIRE" TYPE="NUMBER" LABEL="จำนวนชั่วโมง" WIDTH="10"/>
<FIELD NAME="PBGI_COST" TYPE="NUMBER" LABEL="อัตรา" WIDTH="15"/>
<FIELD NAME="PBGI_TOTAL" TYPE="NUMBER" LABEL="รวมเป็นเงิน" WIDTH="15"/>
<FIELD NAME="PBGI_REASON" TYPE="TEXT" LABEL="เหตุผลความจำเป็น" WIDTH="4000"/>
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-WORK-BUDGET">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID,PBDG_ID" DETAIL-FIELDS="PROJ_ID,PBDG_ID"/>
<UNIQ-CHECK CHECK-FIELDS="BGM_CODE" MESSAGE="pwbg.bgm_code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT_BUDGET_ITEMS" EDIT="N" DELETE="N" CLASS="table-primary">
<KEYFIELDS>PROJ_ID,BGM_CODE</KEYFIELDS>
<TITLES>
<ROW>
<FIELD NAME="BGM_CODE" LABEL="pbgz.bgm_code" WIDTH="10em" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_NAME" LABEL="pbgz.bgm_name" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_BUTGETS" LABEL="pbgz.budget" ALIGN="center" COLS-SPAN="5"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_FREQ" LABEL="pbgz.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_ACQUIRE" LABEL="pbgz.acquire" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
</ROW>
</TITLES>
<FIELDS>
<FIELD NAME="BGM_CODE" LABEL="pwbg.bgm_code" WIDTH="15em" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="BGM_NAME" LABEL="pwbg.bgm_name" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[ (value,row,idx)=>{return $(`<div class="col offset-${row["node_level"]}">${value}</div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="PBGI_FREQ" LABEL="pbgz.freq" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QTY" LABEL="pbgz.qty" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_ACQUIRE" LABEL="pbgz.acquire" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_COST" LABEL="pbgz.cost" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pbgz.total" WIDTH="8em" ALIGN="right"/>
<COMMAND-BUTTONS>
<BUTTONS-FILTER>
<EDIT><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></EDIT>
<DELETE><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></DELETE>
<VIEW><![CDATA[({$ctx,row})=>{return row["node_type"] !== "C"}]]></VIEW>
</BUTTONS-FILTER>
</COMMAND-BUTTONS>
</FIELDS>
<FOOTER SHOW="Y"/>
<SCRIPT>
<INITIALIZE>
<![CDATA[
(ctx)=> {
ctx.sum_of = {};
console.log("init grid-budget");
const fieldFormat = (field,value,row) => {
if (row["node_type"] === "D" || field === "pbgi_total") {
return formatNumber(value, 0);
} else {
return "";
}
}
const summary = (field, data) => {
let total = 0;
for (const row of data) {
total += (+row[field])||0;
}
ctx.sum_of[field] = total;
if (ctx.$dataGrid && ctx.$dataGrid.load && !ctx.$dataGrid.reload) {
ctx.$dataGrid.reload = true;
for (let id=data.length-1; id>=0; id--) {
let row = data[id];
if (row["node_type"] === "C") {
let grpTotal = 0;
let mainNode = row["bgm_code"];
let nodes = [];
nodes.push($$("main_node="+mainNode,data));
for (let node of nodes.flat()) {
grpTotal += +node[field];
}
data[id][field] = grpTotal;
}
}
ctx.$dataGrid.load(data);
ctx.$dataGrid.reload = false;
}
return formatNumber(total,0);
}
const fieldList = ["pbgi_freq","pbgi_qty","pbgi_acquire","pbgi_cost","pbgi_total"];
for (let field of fieldList) {
let column = $$(`field=${field}`,ctx.gridColumn.flat());
column.formatter = (value,row) => {
return fieldFormat(field, value, row);
}
column.footerFormatter = (data)=>{
return summary(field,data);
}
}
ctx.option.rowStyle = function (row, index) {
if (row["node_type"] === "C") {
return {classes : `group-level-${row["node_level"]}`};
}
return {}; // Default style for other rows
}
}
]]>
</INITIALIZE>
</SCRIPT>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT_BUDGET_ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="PBDG_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="BGM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="VBGM_CODE" CAPTION="pwbg.bgm_code" INPUTTYPE="TEXT" READONLY="Y"/>
<FIELD NAME="BGM_CODE" CAPTION="pwbg.bgm_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-BUDGET-02" VALUE-FIELD="BGM_CODE" TEXT-FIELD="BGM_NAME">
<UPDATE-FIELDS>
<FIELD SRC="BGM_CODE" TARGET="VBGM_CODE"></FIELD>
<FIELD SRC="BGM_NAME" TARGET="BGM_NAME"></FIELD>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
console.log("call formater with ", data);
return $(`<div><label class="offset-${data.node_level}">[${data.bgm_code}]</label> : <label>${data.bgm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="PBGI_FREQ" CAPTION="pbgz.freq" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_QTY" CAPTION="pbgz.qty" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_ACQUIRE" CAPTION="pbgz.acquire" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_COST" CAPTION="pbgz.cost" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" CLASS-NAME="budget-data"/>
<FIELD NAME="PBGI_TOTAL" CAPTION="pbgz.total" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" READONLY="Y"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="VBGM_CODE" LAYOUT_WIDTH="6"/>
<FIELD NAME="BGM_CODE" LAYOUT_WIDTH="16"/>
</ROW>
<ROW ID="ROW-BUDGET-DATA">
<FIELD NAME="PBGI_FREQ" LAYOUT_WIDTH="3" OFFSET="6"/>
<FIELD NAME="PBGI_QTY" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_ACQUIRE" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_COST" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_TOTAL" LAYOUT_WIDTH="3"/>
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 350px"></div>]]>
</ROW>
</LAYOUT>
<SCRIPT>
<INITIALIZE><![CDATA[
console.log("sum budget value");
let budgetField = $$("input.budget-data");
const sumBudget = ()=>{
$$("PBGI_TOTAL").setValue(budgetField.multiply());
}
budgetField.on("change",sumBudget);
]]></INITIALIZE>
</SCRIPT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT-STTGYS-ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_STTGYS_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,PSTG_CODE,PSTI_GROUP</KEYFIELDS>
<SQL>
<SELECT>
SELECT PSTI.PROJ_ID
, PSTI.PSTG_CODE
, PSTI.PSTI_GROUP
, RFGP.RFC_DESC GROUP_DESC
, PSTI.PSTI_CODE
, RFCI.RFC_DESC ITEM_DESC
, PSTI_DETAIL
</SELECT>
<FROM>FROM PROJECT_STTGYS_ITEMS PSTI
INNER JOIN BGT.REFER_CODE RFGP ON RFGP.RFG_GRP='STG-ITEMS' AND RFC.RFC_CODE=STTG.PSTI_CODE
INNER JOIN BGT.REFER_CODE RFCI ON RFC.RFG_GRP=PSTI.PSTI_GROUP AND RFC.RFC_CODE=STTG.PSTI_CODE
</FROM>
<ORDER>ORDER BY PSTI_GROUP, PSTI_CODE</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="VARCHAR" WIDTH="50" LABEL="project.id" />
<FIELD NAME="PSTG_CODE" TYPE="VARCHAR" WIDTH="20" LABEL="pstg.code" />
<FIELD NAME="PSTI_GROUP" TYPE="VARCHAR" WIDTH="15" LABEL="psti.group" />
<FIELD NAME="PSTI_CODE" TYPE="VARCHAR" WIDTH="15" LABEL="psti.code" />
<FIELD NAME="PSTI_DETAIL" TYPE="VARCHAR" WIDTH="250" LABEL="psti.detail" />
<FIELD NAME="CREATE_BY" TYPE="VARCHAR" WIDTH="50" LABEL="sys.create_by" />
<FIELD NAME="CREATE_TIME" TYPE="DATE" WIDTH="0" LABEL="sys.create_time" />
<FIELD NAME="UPDATE_BY" TYPE="VARCHAR" WIDTH="50" LABEL="sys.update_by" />
<FIELD NAME="UPDATE_TIME" TYPE="DATE" WIDTH="0" LABEL="sys.update_time" />
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-PROJECT-STTGYS-ITEMS">
<MASTER-DATA DATASET-ID="DS-PROJECT-STTGYS" MASTER-FIELDS="PROJ_ID,PSTG_CODE" DETAIL-FIELDS="PROJ_ID,PSTG_CODE"/>
<UNIQ-CHECK CHECK-FIELDS="PSTI_GROUP" MESSAGE="psti.group duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT-STTGYS-ITEMS" EDIT="Y" DELETE="Y" ADD="Y">
<FIELDS>
<FIELD NAME="$itemno" LABEL="no" ALIGN="right" WIDTH="5em"/>
<FIELD NAME="GROUP_DESC" LABEL="psti.group" WIDTH="10em" ALIGN="left" />
<FIELD NAME="ITEM_DESC" LABEL="psti.code" ALIGN="left" />
</FIELDS>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT-STTGYS-ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN" />
<FIELD NAME="PSTG_CODE" INPUTTYPE="HIDDEN" />
<FIELD NAME="GROUP_DESC" INPUTTYPE="HIDDEN" />
<FIELD NAME="ITEM_DESC" INPUTTYPE="HIDDEN" />
<FIELD NAME="PSTI_GROUP" CAPTION="psti.group" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-STTGY-GROUP-02" VALUE-FIELD="RFC_CODE" TEXT-FIELD="RFC_DESC" PARAMETERS="RFG_GRP=PSTI_GROUP" CHILD-FIELD="PSTI_CODE" ON-EMPTY="LOAD-ALL">
<UPDATE-FIELDS>
<FIELD TARGET="GROUP_DESC" SRC="RFC_DESC"/>
</UPDATE-FIELDS>
</AJAX-OPTION>
</FIELD>
<FIELD NAME="PSTI_CODE" CAPTION="psti.code" INPUTTYPE="COMBOBOX" REQUIRE="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-STTGY-ITEMS-02" VALUE-FIELD="RFC_CODE" TEXT-FIELD="RFC_DESC" PARAMETERS="RFG_GRP=PSTI_GROUP">
<UPDATE-FIELDS>
<FIELD TARGET="ITEM_DESC" SRC="RFC_DESC"/>
</UPDATE-FIELDS>
</AJAX-OPTION>
</FIELD>
<FIELD NAME="PSTI_DETAIL" CAPTION="psti.detail" INPUTTYPE="TEXTAREA" ROWS="3" />
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="PSTI_GROUP" LAYOUT_WIDTH="6"/>
<FIELD NAME="PSTI_CODE" LAYOUT_WIDTH="18" />
</ROW>
<ROW>
<FIELD NAME="PSTI_DETAIL" LAYOUT_WIDTH="18" OFFSET="6" />
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 200px"></div>]]>
</ROW>
</LAYOUT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT-STTGYS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_STTGYS</TABLENAME>
<KEYFIELDS>PROJ_ID,PSTG_CODE</KEYFIELDS>
<SQL>
<SELECT>
SELECT STTG.PROJ_ID
, STTG.PSTG_CODE
, RFC.RFC_DESC PSTG_DESC
, STTG.PSTG_CONCEPT
</SELECT>
<FROM>FROM PROJECT_STTGYS STTG
INNER JOIN BGT.REFER_CODE RFC ON RFC.RFG_GRP='STG-MAIN' AND RFC.RFC_CODE=STTG.PSTG_CODE
</FROM>
<ORDER>ORDER BY PSTG_CODE</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="VARCHAR" WIDTH="50" LABEL="project.id" />
<FIELD NAME="PSTG_CODE" TYPE="VARCHAR" WIDTH="20" LABEL="pstg.code" />
<FIELD NAME="PSTG_CONCEPT" TYPE="VARCHAR" WIDTH="500" LABEL="pstg.concept" />
<FIELD NAME="CREATE_BY" TYPE="VARCHAR" WIDTH="50" LABEL="sys.create_by" />
<FIELD NAME="CREATE_TIME" TYPE="DATE" WIDTH="0" LABEL="sys.create_time" />
<FIELD NAME="UPDATE_BY" TYPE="VARCHAR" WIDTH="50" LABEL="sys.update_by" />
<FIELD NAME="UPDATE_TIME" TYPE="DATE" WIDTH="0" LABEL="sys.update_time" />
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-PROJECT-STTGYS">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID" DETAIL-FIELDS="PROJ_ID"/>
<UNIQ-CHECK CHECK-FIELDS="PSTG_CODE" MESSAGE="pstg.code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT-STTGYS" EDIT="Y" DELETE="Y" ADD="Y">
<FIELDS>
<FIELD NAME="$itemno" LABEL="no" ALIGN="right" WIDTH="5em"/>
<FIELD NAME="PSTG_CODE" LABEL="pstg.code" WIDTH="12em" ALIGN="center" />
<FIELD NAME="PSTG_DESC" LABEL="pstg.desc" ALIGN="left" />
</FIELDS>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT-STTGYS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN" />
<FIELD NAME="PSTG_CODE" CAPTION="pstg.desc" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<LIST-OPTION TABLE="BGT.REFER_CODE" TEXT="#RFC_DESC" VALUE="RFC_CODE" FILTER="RFG_GRP='STG-MAIN'" FIRSTLIST="@{CAPTION}"/>
</FIELD>
<FIELD NAME="PSTG_CONCEPT" CAPTION="pstg.concept" INPUTTYPE="TEXTAREA" ROWS="2" />
<FIELD NAME="GRID-STTGYS-ITEMS" INPUTTYPE="DATA-GRID" GRID-ID="GRID-PROJECT-STTGYS-ITEMS" CAPTION="psti.header"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="PSTG_CODE" LAYOUT_WIDTH="16" OFFSET="4" />
</ROW>
<SECTION>
<HEADER CLASS="form-section-header col-24 mg-b-n30 mg-t-16 border-top-1">
<![CDATA[<h4 class="ml-3 col-24">@M{pstg.header}</h4>]]>
</HEADER>
<ROW>
<FIELD NAME="GRID-STTGYS-ITEMS" LAYOUT_WIDTH="20" OFFSET="4"/>
</ROW>
</SECTION>
<ROW>
<FIELD NAME="PSTG_CONCEPT" LAYOUT_WIDTH="16" OFFSET="4" />
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 200px"></div>]]>
</ROW>
</LAYOUT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>

View File

@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-PROJECT_BUDGET_ITEMS">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECT_BUDGET_ITEMS</TABLENAME>
<KEYFIELDS>PROJ_ID,BGM_CODE,PBDG_ID</KEYFIELDS>
<SQL>
<SELECT>SELECT PROJ_ID
, PBDG_ID
, BGM_CODE
, BUD.GET_BUDGET (BGM_CODE) BGM_NAME
, PBGI_QT_01
, PBGI_QT_02
, PBGI_QT_03
, PBGI_QT_04
, PBGI_QTY
, PBGI_COST
, PBGI_FREQ
, PBGI_ASSET_TYPE
, PBGI_REPLACE
, PBGI_ADDITION
, PBGI_ACQUIRE
, PBGI_TOTAL
, PBGI_REASON
</SELECT>
<FROM>FROM PROJECT_BUDGET_ITEMS</FROM>
<ORDER>ORDER BY PROJ_ID,BGM_CODE</ORDER>
</SQL>
<FIELDS>
<FIELD NAME="PROJ_ID" TYPE="TEXT" LABEL="รหัสอ้างอิงโครงการ" WIDTH="32"/>
<FIELD NAME="PBDG_ID" TYPE="TEXT" LABEL="รหัสงบประมาณโครงการ" WIDTH="32"/>
<FIELD NAME="BGM_CODE" TYPE="TEXT" LABEL="รหัสหมวดงบประมาณ" WIDTH="20"/>
<FIELD NAME="PBGI_QT_01" TYPE="NUMBER" LABEL="จำนวนไตรมาส 1" WIDTH="15"/>
<FIELD NAME="PBGI_QT_02" TYPE="NUMBER" LABEL="จำนวนไตรมาส 2" WIDTH="15"/>
<FIELD NAME="PBGI_QT_03" TYPE="NUMBER" LABEL="จำนวนไตรมาส 3" WIDTH="15"/>
<FIELD NAME="PBGI_QT_04" TYPE="NUMBER" LABEL="จำนวนไตรมาส 4" WIDTH="15"/>
<FIELD NAME="PBGI_QTY" TYPE="NUMBER" LABEL="จำนวน" WIDTH="10"/>
<FIELD NAME="PBGI_COST" TYPE="NUMBER" LABEL="ราคาต่อหน่วย" WIDTH="15"/>
<FIELD NAME="PBGI_FREQ" TYPE="NUMBER" LABEL="ความถี่/จำนวนครั้ง" WIDTH="10"/>
<FIELD NAME="PBGI_ASSET_TYPE" TYPE="TEXT" LABEL="ประเภทสินทรัพย์" WIDTH="10"/>
<FIELD NAME="PBGI_REPLACE" TYPE="NUMBER" LABEL="ทดแทนของเดิม" WIDTH="10"/>
<FIELD NAME="PBGI_ADDITION" TYPE="NUMBER" LABEL="เพิ่มเติม" WIDTH="10"/>
<FIELD NAME="PBGI_ACQUIRE" TYPE="NUMBER" LABEL="จัดหาใหม่" WIDTH="10"/>
<FIELD NAME="PBGI_TOTAL" TYPE="NUMBER" LABEL="รวมเป็นเงิน" WIDTH="15"/>
<FIELD NAME="PBGI_REASON" TYPE="TEXT" LABEL="เหตุผลความจำเป็น" WIDTH="4000"/>
</FIELDS>
</DATASET>
</DATASETS>
<DATA-GRIDS>
<DATA-GRID ID="GRID-WORK-BUDGET">
<MASTER-DATA DATASET-ID="DS-MASTER" MASTER-FIELDS="PROJ_ID,PBDG_ID" DETAIL-FIELDS="PROJ_ID,PBDG_ID"/>
<UNIQ-CHECK CHECK-FIELDS="BGM_CODE" MESSAGE="pwbg.bgm_code duplicate !"></UNIQ-CHECK>
<GRID-LIST DATAID="DS-PROJECT_BUDGET_ITEMS" EDIT="Y" DELETE="Y" CLASS="table-primary">
<KEYFIELDS>PROJ_ID,BGM_CODE</KEYFIELDS>
<TITLES>
<ROW>
<FIELD NAME="BGM_CODE" LABEL="pwbg.bgm_code" WIDTH="10em" ALIGN="center" ROWS-SPAN="2"/>
<FIELD NAME="BGM_NAME" LABEL="pwbg.bgm_name" ALIGN="left" ROWS-SPAN="2"/>
<FIELD NAME="BGM_QUOTERS" LABEL="pwbg.quoter" ALIGN="center" COLS-SPAN="4"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pwbg.total" WIDTH="6em" ALIGN="right" ROWS-SPAN="2"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_QT_01" LABEL="1" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_QT_02" LABEL="2" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_QT_03" LABEL="3" WIDTH="6em" ALIGN="right"/>
<FIELD NAME="PBGI_QT_04" LABEL="4" WIDTH="6em" ALIGN="right"/>
</ROW>
</TITLES>
<FIELDS>
<FIELD NAME="BGM_CODE" LABEL="pwbg.bgm_code" WIDTH="15em" ALIGN="center"/>
<FIELD NAME="BGM_NAME" LABEL="pwbg.bgm_name" ALIGN="left"/>
<FIELD NAME="PBGI_QT_01" LABEL="pwbg.quotr_01" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QT_02" LABEL="pwbg.quotr_02" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QT_03" LABEL="pwbg.quotr_03" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_QT_04" LABEL="pwbg.quotr_04" WIDTH="5em" ALIGN="right"/>
<FIELD NAME="PBGI_TOTAL" LABEL="pwbg.total" WIDTH="10em" ALIGN="right"/>
</FIELDS>
<FOOTER SHOW="Y"/>
<SCRIPT>
<INITIALIZE>
<![CDATA[
(ctx)=> {
ctx.sum_of = {};
console.log("init grid-budget");
const fieldFormat = (value) => {
return formatNumber(value, 0);
}
const summary = (field, data) => {
let total = 0;
for (const row of data) {
total += (+row[field])||0;
}
ctx.sum_of[field] = total;
return formatNumber(total,0);
}
const quoterFields = $$("field^pbgi_qt_",ctx.gridColumn.flat());
for (let field of quoterFields) {
field.formatter = fieldFormat;
let fieldName = field.field;
field.footerFormatter = (data)=>{
return summary(fieldName,data);
}
}
let fieldName = "pbgi_total";
$$("field=pbgi_total",ctx.gridColumn.flat()).formatter = fieldFormat;
$$("field=pbgi_total",ctx.gridColumn.flat()).footerFormatter = (data)=>{
return summary(fieldName,data);
};
}
]]>
</INITIALIZE>
</SCRIPT>
</GRID-LIST>
<GRID-EDITOR DATAID="DS-PROJECT_BUDGET_ITEMS">
<FIELDS>
<FIELD NAME="PROJ_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="PBDG_ID" INPUTTYPE="HIDDEN"/>
<FIELD NAME="BGM_NAME" INPUTTYPE="HIDDEN"/>
<FIELD NAME="VBGM_CODE" CAPTION="pwbg.bgm_code" INPUTTYPE="TEXT" READONLY="Y"/>
<FIELD NAME="BGM_CODE" CAPTION="pwbg.bgm_name" INPUTTYPE="COMBOBOX" REQUIRE="Y" EDIT-READONLY="Y">
<AJAX-OPTION URL="/api-data.jbx" DATASET="DS-BUDGET-01" VALUE-FIELD="BGM_CODE" TEXT-FIELD="BGM_NAME">
<UPDATE-FIELDS>
<FIELD SRC="BGM_CODE" TARGET="VBGM_CODE"></FIELD>
<FIELD SRC="BGM_NAME" TARGET="BGM_NAME"></FIELD>
</UPDATE-FIELDS>
</AJAX-OPTION>
<LIST-OPTION>
<FORMATTER><![CDATA[
(data) => {
console.log("call formater with ", data);
return $(`<div><label>[${data.bgm_code}]</label> : <label>${data.bgm_name}</label></div>`);
}
]]></FORMATTER>
</LIST-OPTION>
</FIELD>
<FIELD NAME="PBGI_QT_01" CAPTION="pwbg.quotr_01" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0"/>
<FIELD NAME="PBGI_QT_02" CAPTION="pwbg.quotr_02" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0"/>
<FIELD NAME="PBGI_QT_03" CAPTION="pwbg.quotr_03" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0"/>
<FIELD NAME="PBGI_QT_04" CAPTION="pwbg.quotr_04" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0"/>
<FIELD NAME="PBGI_TOTAL" CAPTION="pwbg.total" INPUTTYPE="TEXT" DATATYPE="NUMBER" DECIMAL="0" READONLY="Y"/>
</FIELDS>
<LAYOUT CLASS="block-layout-form">
<ROW>
<FIELD NAME="VBGM_CODE" LAYOUT_WIDTH="6"/>
<FIELD NAME="BGM_CODE" LAYOUT_WIDTH="16"/>
</ROW>
<ROW>
<FIELD NAME="PBGI_QT_01" LAYOUT_WIDTH="3" OFFSET="6"/>
<FIELD NAME="PBGI_QT_02" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_QT_03" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_QT_04" LAYOUT_WIDTH="3"/>
<FIELD NAME="PBGI_TOTAL" LAYOUT_WIDTH="3"/>
</ROW>
<ROW TYPE="CONTENT">
<![CDATA[<div style="height: 350px"></div>]]>
</ROW>
</LAYOUT>
<SCRIPT>
<INITIALIZE><![CDATA[
const quoterTotal = ()=>{
$$("PBGI_TOTAL").setValue($$("^PBGI_QT_").sum());
}
$$("^PBGI_QT_").on("change",quoterTotal);
]]></INITIALIZE>
</SCRIPT>
</GRID-EDITOR>
</DATA-GRID>
</DATA-GRIDS>
</FORMS>