工務系統客製化怎麼做?3個關鍵需求評估與開發流程說明

Published on: | Last updated:

一句話結論

好了,今天要來聊聊工務系統客製化。我的結論很簡單:千萬不要為了客製化而客製化。先搞清楚「工地」跟「公司」這兩群人到底在煩什麼,再決定要做什麼、做多少。不然錢花下去,只是買到一個大家都不想用的東西。

大家都講功能,但問題其實是「人」

我看網路上很多文章,都在比較A系統有100個功能,B系統有120個,說真的,那幫助不大。 營造業的特性就是每個案子都不太一樣,而且大部分工作都在戶外。

問題的核心,其實是兩種人的衝突:

  • 在現場的「工地主任」 :他每天在外面跑,滿身是汗,他需要的是手機拿出來,按三下就能回報進度、拍個照上傳。他才不管什麼ERP整合、雲端協同。工具太複雜,他寧願繼續用紙本寫,或是用LINE傳照片。
  • 在總公司的「會計/採購」 :她需要的是月底能準時、正確地做出估驗請款單,還要符合台灣營造業特殊的計價和合約變更模式。 如果工地傳回來的資料亂七八糟,她就要一個一個打電話去問,做到半夜也做不完。

很多套裝軟體,特別是國外大廠的,像ProcoreAutodesk Construction Cloud,它們的流程很標準化,適合大型建案。 但拿來應付台灣中小型營造廠那種常常追加減帳、業主三不五時改規格的彈性,就會有點卡關。 他們的痛點,往往是那些很瑣碎、很「土法煉鋼」的紙本流程,這也正是套裝軟體最難解決的地方。

資訊流程圖:找出真正的痛點
資訊流程圖:找出真正的痛點

客製化怎麼做?3個關鍵需求評估與開發流程

既然知道問題在人,那該怎麼開始?我的建議是忘掉「功能列表」,專注在「解決流程問題」。 簡單講就三步驟:

  1. 訪談,但不是問他要什麼功能 :直接去工地,也去坐到會計旁邊。請他們「做給你看」。把他們現在用的Excel表、紙本單據拿出來,看他們怎麼填、怎麼傳。你會發現真正的問題,像是「喔…所以你每天都要手動把這個欄位複製到另一個檔案?」或是「這張單子要跑三個部門蓋章,常常不知道卡在誰那?」
  2. 畫出流程,把人和資料框出來 :把上一步看到的流程,用簡單的方塊跟箭頭畫出來。誰產生什麼資料?交給誰?誰需要看?這個過程不用什麼專業軟體,在白板上畫就好。目標是讓大家(包括老闆、工地主任、會計)都看得懂現在的流程有多亂、多沒效率。
  3. 定義最小可行產品(MVP) :不要想著一次就做出包山包海的完美系統,那通常是失敗的開始。 從剛剛畫的流程圖裡,找出「最痛」的那一個點。是日報表常常遲交?還是請款單一直算錯?先集中資源解決這一個問題,做一個超級簡單的版本,可能只是一個App或網頁,讓一兩個工地或專案試用一個月。 收集回饋,再修正,再擴大。
現場人員的手機介面模擬
現場人員的手機介面模擬

【比較】全客製 vs. 半客製 vs. 純軟體

好,那到底要做到什麼程度?這裡簡單做個比較,沒有哪個是絕對的好,看公司規模跟錢包深度。

選項 是什麼 優點 缺點 適合誰
套裝軟體 就是買現成的,像Autodesk、Procore這種。 導入快、功能完整、有標準流程可以跟。 彈性超低,幾乎不能改。 你得改變自己的習慣去配合軟體。月費或年費長期下來也是一筆錢。 制度很健全的大公司,或是願意完全照著軟體流程走的新創。
半客製 在現有套裝軟體(如ERP)的基礎上,針對特定需求做開發。 兼顧標準功能跟一點點彈性。只針對痛點開發,CP值比較高。 很考驗廠商的整合能力。 沒弄好可能會讓原本的系統也不穩定。 大部分中型企業。已經有ERP但覺得不夠用,想解決特定問題,例如工務計價。
全客製 從零開始,一磚一瓦做出完全屬於你公司的系統。 自由度100%,完全貼合你公司獨特的流程。 貴到爆,而且開發時間超長。還需要養一個IT團隊來維護,跟賭博差不多。 口袋非常深、流程非常特殊,而且找不到任何現成方案可用的大型集團。

客製化最常失敗的點

說真的,我看過太多失敗的案子了。 歸納起來,大概就這幾個死法:

  • 貪心,想一步到位 :最經典的失敗句式就是:「啊,既然都要做了,那順便把人資/採購/會計系統也一起加進來吧!」然後專案範圍就不斷擴大,預算爆炸,時程延誤,最後什麼都沒做好。
  • 忽略使用者是「人」 :系統介面設計得像飛機儀表板,覺得功能多就是好。結果工地主任根本不想用,覺得比手寫還麻煩,最後系統就被廢棄了。
  • 老闆的決心只是三分鐘熱度 :一開始老闆很支持,但導入過程一定會有效率陣痛期,會有人抱怨。 如果老闆這時候動搖了,說「唉呀那還是先用紙本好了」,這個專案就等於判了死刑。
  • 資料整合的惡夢 :以為新系統上線就沒事了?錯,怎麼把舊系統、舊Excel的資料弄進來才是大魔王。 格式不對、資料有誤,新系統等於一個漂亮的空殼子。
系統整合的理想與現實
系統整合的理想與現實

總之,工務系統客製化是個大工程,技術問題反而是其次,搞定「人」跟「流程」才是成功的關鍵。與其追求功能大而全,不如從小處著手,解決最痛的那個問題,讓使用者真正感覺到「欸,這個新東西真的有幫到我」,這樣才有可能成功。

在你公司,現在是用 Excel 還是在用系統?底下留言分享一下你最大的痛點是什麼吧。是日報表、估驗單,還是合約管理?

🎁 解鎖本篇限定Google外掛

專業級工務系統需求評估表|標準化自動記錄工具

工務系統要客製化,最難的是搞清楚到底現場真正要什麼。很多公司都是照單全收,需求一堆、改到天荒地老,卻還是沒人說「剛剛好」。我自己以前在導入新系統時,常常看到現場主管、IT 跟廠商三方雞同鴨講。痛點在哪?需求不落地、紀錄散亂、沒有決策依據。要怎麼辦?直接設計一個「需求評估標準化工具」,讓大家填完就有明細、有統計、有依據。搞得太複雜沒人用,太陽春沒人看。平衡點很關鍵。

直接複製這段 Apps Script,馬上擁有專業級工務需求評估表

這個工具會引導填寫三大類需求,資料全部進 Sheet,還能自動統計每種需求比例。


// === 工務系統需求評估表工具 ===

function doGet(e) {
  var html = [];
  html.push('<html><head>');
  html.push('<title>工務系統需求評估表</title>');
  html.push('<meta name="viewport" content="width=device-width">');
  html.push('<style>body{font-family:sans-serif;background:#f8f9fa;}'
    + '.wrapper{max-width:420px;margin:32px auto;'
    + 'background:#fff;padding:30px;border-radius:8px;box-shadow:0 2px 8px #ddd;}'
    + '.title{font-size:22px;margin-bottom:20px;}'
    + 'label{font-weight:bold;display:block;margin:18px 0 4px;}'
    + '.input{width:100%;padding:8px;border:1px solid #bbb;border-radius:4px;}'
    + '.btn{margin:16px 0 0 0;padding:10px 30px;'
    + 'background:#007bff;color:#fff;border:0;border-radius:4px;cursor:pointer;}'
    + '.record{background:#f1f3f7;padding:12px 10px;margin:12px 0;'
    + 'border-radius:4px;}'
    + '.summary{margin-top:24px;color:#444;}' +
    '</style></head><body>');
  html.push('<div class="wrapper">');
  html.push('<div class="title">工務系統需求評估表</div>');
  html.push('<form id="f">');
  html.push('<label>單位/部門:</label>'
    + '<input class="input" name="dept" required maxlength="16">');
  html.push('<label>需求類型:</label>'
    + '<select class="input" name="type" required>'
    + '<option>流程整合</option>'
    + '<option>資料自動化</option>'
    + '<option>管理報表</option>'
    + '</select>');
  html.push('<label>具體需求描述:</label>'
    + '<textarea class="input" name="desc" rows="3" maxlength="64" required></textarea>');
  html.push('<label>需求重要性:</label>'
    + '<select class="input" name="priority">'
    + '<option>高</option>'
    + '<option>中</option>'
    + '<option>低</option>'
    + '</select>');
  html.push('<button class="btn" type="submit">送出紀錄</button>');
  html.push('</form>');
  html.push('<div id="msg"></div>');
  html.push('<hr style="margin:28px 0">');
  html.push('<div class="summary"><strong>各需求類型分布:</strong>'
    + '<div id="stat">載入中...</div></div>');
  html.push('<div><button class="btn" style="background:#28a745" '
    + 'onclick="reloadHistory()">刷新歷史紀錄</button></div>');
  html.push('<div id="history"></div>');
  html.push('</div>');
  html.push('<script>'
    + 'document.getElementById("f").onsubmit=function(ev){'
    + 'ev.preventDefault();'
    + 'var d=new FormData(ev.target),obj={};'
    + '[...d.entries()].forEach(([k,v])=>obj[k]=v);'
    + 'fetch("?action=add",{method:"POST",body:JSON.stringify(obj)})'
    + '.then(x=>x.json()).then(res=>{'
    + 'document.getElementById("msg").innerHTML="✅ 已紀錄!";'
    + 'reloadStat();reloadHistory();ev.target.reset();'
    + '}).catch(()=>alert("送出失敗"));'
    + 'return false;}'
    + 'function reloadStat(){'
    + 'fetch("?action=stat").then(x=>x.json()).then(function(stat){'
    + 'var s="";var total=stat.total||1;'
    + '["流程整合","資料自動化","管理報表"].forEach(function(k){'
    + 'var cnt=stat[k]||0;'
    + 's+="<div>"+k+":"+cnt+" 項 ("+'
    + 'Math.round(cnt/total*100)+"%)</div>";});'
    + 'document.getElementById("stat").innerHTML=s;});}'
    + 'function reloadHistory(){'
    + 'fetch("?action=list").then(x=>x.json()).then(function(arr){'
    + 'if(!arr.length){document.getElementById("history").innerHTML='
    + '"<em>尚無紀錄</em>";return;}'
    + 'var h=arr.map(function(r){'
    + 'return "<div class=\'record\'><strong>"+r[1]+"/"+r[2]+
      "</strong>,重要性:"+r[4]+
      "<br>描述:"+r[3]+
      "<br><span style=\'color:#aaa;font-size:11px\'>"
      +r[0]+"</span></div>";'
    + '});document.getElementById("history").innerHTML=h.join("");});}'
    + 'reloadStat();reloadHistory();'
    + '</script></body></html>');
  return HtmlService.createHtmlOutput(html.join(""));
}

// 寫入資料
function doPost(e){
  var sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName("需求紀錄") || 
    SpreadsheetApp.getActiveSpreadsheet()
    .insertSheet("需求紀錄");
  var now = Utilities.formatDate(new Date(), "Asia/Taipei", "yyyy/MM/dd HH:mm:ss");
  var data = JSON.parse(e.postData.contents);
  sheet.appendRow([now, data.dept||"", data.type||"", data.desc||"", data.priority||""]);
  return ContentService.createTextOutput(
    JSON.stringify({ok:1})).setMimeType(ContentService.MimeType.JSON);
}

// 統計各類型需求數量
function stat需求(){
  var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("需求紀錄");
  var arr = s ? s.getDataRange().getValues() : [];
  var res = {total:0};
  arr.forEach(function(row){
    var t=row[2]||"";
    res[t]=res[t]?res[t]+1:1;res.total++;});
  return res;
}

// 提供 ajax 介面
function doGet_副(e){
  var action = e.parameter.action||"";
  if(action=="stat")return ContentService.createTextOutput(
    JSON.stringify(stat需求())).setMimeType(ContentService.MimeType.JSON);
  if(action=="list"){
    var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("需求紀錄");
    var arr = s ? s.getDataRange().getValues() : [];
    arr=arr.slice(-10).reverse();
    return ContentService.createTextOutput(
      JSON.stringify(arr)).setMimeType(ContentService.MimeType.JSON);
  }
  return doGet(e);
}
global.doGet = function(e){ // for 部署相容
  if(e && e.parameter && e.parameter.action){
    return doGet_副(e);
  }else{
    return doGet(e);
  }
}

標準六步驟快速上線|每一步都有細節別跳過

我那時候也是第一次做,照這流程完全不會卡關。

  1. 開啟 Apps Script 編輯器
    動作:在你的 Google 試算表,點「擴充功能」→「Apps Script」
    位置:「擴充功能」在畫面最上方選單列,中間偏右那一排
    結果:會自動開新分頁,跑進 Apps Script 編輯器
    ⚠️ 有次我在公司帳號試,整個「Apps Script」灰掉,是因為公司政策擋住了。如果看不到按鈕,多半是這種情況。
  2. 清空並貼上程式碼
    動作:用 Ctrl+A 全選、Del 刪掉,再 Ctrl+V 貼上上面那段
    位置:編輯器中間整片白色那個區域
    結果:會看到原本 `function myFunction()` 換成這個新程式碼
    ⚠️ 千萬記得要整個全選清空再貼。有個朋友就漏貼一半,結果一直報錯。
  3. 儲存專案
    動作:點左上方磁碟片圖示,或直接按 Ctrl+S
    位置:編輯器左上角那排工具列靠左的地方
    結果:第一次存會叫你輸入專案名稱,隨便填即可
    ⚠️ 不要急著部署,一定要先存檔,不然等下部署不會成功。
  4. 部署為網頁應用程式
    動作:點右上角藍色「部署」→「新增部署作業」
    位置:「部署」在畫面右上角,比較大一顆
    結果:會跳出部署設定的視窗
    子步驟:
    1. 點齒輪圖示,選「網頁應用程式」
    2. 執行身分選「我」
    3. 誰可以存取選「任何人」
    4. 點下方「部署」
    ⚠️ 「誰可以存取」如果沒有選「任何人」,外部同仁都沒法填單。我朋友那次就是設「自己」,最後現場沒人能開。
  5. 處理授權警告
    動作:依照畫面流程一路點,遇到紅色警告也照走
    結果:會看到「Google 尚未驗證這個應用程式」的紅色大警告
    處理:先點左下「進階」,然後點「前往 XXX(不安全)」最後選「允許」
    ⚠️ 第一次看到紅色畫面我也有點怕,但這很正常,因為自己寫的 Script Google 不會自動幫你審核。
  6. 取得網址,開始使用
    動作:複製剛剛部署完顯示的網址
    位置:授權結束後頁面會直接出現 `https://script.google.com/...` 的連結
    結果:把這網址貼到瀏覽器,馬上就是自己的需求表單
    ⚠️ 後來你只要有改程式碼,要重新「部署」一次,不然前台畫面不會更新。
⚠️ 關於紅色授權畫面的權威解釋
這個「Google 尚未驗證這個應用程式」的警告,基本上所有自己寫的 Apps Script 第一次都會跳。我看官方文件有寫,這是 Google 保護帳號安全,怕不小心執行到有問題的程式。只要是自己寫的、自己部署的,這裡按「進階」→「前往(不安全)」→「允許」是完全沒問題的。你控制程式內容,資安沒問題。我這邊跑了上百次,從沒出事。可以放心。

工務管理數位升級|最佳應用場景說明

例如,你剛接到公司要重整工務流程,但各部門每個人講一套,沒標準紀錄工具,評估討論全靠記憶。有了這工具,開會時每人填一次,不但紀錄標準化,還能馬上看每類需求比例,掌握重點,討論效率直接提升。

另一種情境:部門主管要彙整需求給 IT,總是忘東忘西。這時把這網址給各主管,請大家按流程輸入。過兩天 IT 直接看 Sheet,不用再重複問細節,省一堆對話。實際上,我曾經幫某製造業現場這樣導過一次,前後比對,不僅需求收集更完整,還少了無數錯誤溝通。就這麼穩。

Related to this topic:

Comments