- 省時
- 減錯
短期顧問聘用:業務填一份表單,協議、金額、勞務報酬單自己接上
用一張追蹤表串起協議簽署、發票設定與勞報單回收,保留各地的簽署規則。
背景與使用技術(4 項)
請外部顧問來做一天,業務同事得自己套合約範本、把姓名與費率貼進文件、寄信追簽名,再用試算表手動記錄進度。案件一多就開始漏件,甚至同一份協議寄了兩次。改成由表單觸發的端到端流程:業務填表開案,三個地區各走各的簽署規則,所有案件落在同一張追蹤表上,並用識別碼(token)加狀態檢查擋掉重複觸發。
誰在用
發起短期顧問聘用的業務,以及負責報稅的財務人員
原本怎麼做
一次短期聘用看起來只是付一筆錢,後面卻掛著一條法律與財務的鏈:協議要先簽好,會議次數要照算式換成金額,最後還要收回有簽名的勞務報酬單,公司才報得了稅。協議寄出後沒有東西提醒追簽名;看不出案子停在哪一步、停了幾天;同一份協議被重複產出,會留下兩份互相矛盾的文件;三地報酬單格式與簽署方式各異,案件一多就容易套錯範本。
前後對比
量測:實測=有計時或有紀錄;估計=喜特先生推估;客戶自述=客戶回報;規格=設計上的固定條件;待補=尚未取得數字。
流程一眼看懂
協議寄出
靠人記得追簽名
手算金額
人工收勞務報酬單
業務填協議表單
產生協議與簽署連結
填會議次數,算出總額
預填發票表單
顧問填表,產出勞務報酬單
流程示意:依本案既有做法整理,非客戶實際畫面。
做了什麼
- 整條鏈拆成三個階段,由一張追蹤表串起,每個階段用表單當接觸點。
- 金額由系統照「實作費+會議單價×次數」算,業務只填次數。
- 狀態閘擋重複:每一步做完就記下來,同一件案子不會被處理兩次。
- 三地差異集中在一處:費率與範本放同一份設定,不散在各個流程裡。
程式碼與實作細節收在頁面下方,需要時再展開。
你的情況像這樣嗎?
- 你有一條「簽協議、算金額、收單據」的鏈,每一步靠人記得。
- 同一份文件偶爾被重複產出,事後才發現兩份對不上。
- 不同地區的文件規則不同,案件一多就怕套錯。
更多成果與運作條件
一份表單開案
業務只填寫一次,後續文件產生、寄送與金額計算全部自動完成
34 欄追蹤表
每件案子一列,狀態、表單回填資料與 PDF 檔案 ID 都在同一列
6 份表單對應 3 套規則
三地各一份協議表單、一份發票表單,地區費率與範本 ID 集中在同一份設定
以上為本案既有成果與運作條件;估計值依原始資料標示,其他專案需另行評估,並非通用成效保證。
用一列追蹤整個案件
追蹤表串起各階段的連結與狀態,識別碼(token)加狀態檢查協助擋住重複觸發。
畫面示意・範例資料,非客戶實際截圖。手機可左右滑動查看。
挑戰:原本遇到的困難
一次短期聘用看起來只是付一筆錢,後面卻掛著一條法律與財務的鏈:協議要先簽好,會議次數要照算式換成金額,最後還要收回有簽名的勞務報酬單(簡稱勞報單),公司才報得了稅。
- 每一步都靠人記得:協議寄出後沒有東西提醒追簽名
- 斷在看不見的地方:看不出案子停在哪一步、停了幾天
- 重複簽署補不回來:同一份協議被重複產出,留下兩份互相矛盾的文件
- 三地規則不同:報酬單格式與簽署方式各異,案件一多就容易套錯範本
所以流程要同時做到:每一步有明確的下一步、同一件案子不被處理兩次、三地差異集中在一處。
完整解決方案與設計取捨
把整條鏈拆成三個階段,由一張 Tracking 試算表串起來;每個階段以 Google 表單作為系統與顧問的接觸點。
- 開案與協議簽署:業務同事填寫該地區的協議表單,帶入顧問姓名、email、日期與費率。系統複製協議文件、產生預覽 PDF 與線上簽署連結寄給顧問;簽署後,簽署版 PDF 存入雲端硬碟,並寄給雙方留存。
- 發票設定:業務填入當天實際的會議次數,系統依「實作費 + 會議單價 × 次數」算出總額,並寄出已預填的發票表單連結。
- 勞報單回收:顧問填寫表單提供個資與證件資訊,系統複製勞務報酬單。其中一地寄出未簽版本,請顧問列印親簽、掃描上傳;另外兩地直接帶入數位簽名。
業務現在只填一份表單,顧問只會看到兩個連結。三地共六份表單(每區一份協議、一份發票),對應三套簽署規則。每個接觸點發出一組 token(隨機識別碼),再次進來時用狀態閘(檢查這一步是否已做過)判斷,擋住重複觸發。
技術與實作細節
展開完整實作說明
情境改寫:依這類案件的常見做法整理,細節為示意。
某個工作日,一位業務同事談成了一位顧問來公司做一天實作。接下來他要做的事是:打開 Word 協議範本,把顧問的姓名、email、日期、費率一格格打進去;存成 PDF 寄出;過幾天再寄一封信問對方簽了沒;最後回到共用試算表,手動記下「這件簽了、那件還沒」。同一筆資料要在 Word、PDF、信箱、試算表四個地方各打一次,任何一處少打一個字,後面的步驟就跟著錯。
一兩件案子時,他還顧得來。後來這條鏈接成一套流程:業務填一份表單開案,之後交給系統。以下說明它怎麼接、怎麼擋重複觸發,以及踩過的坑。
人工做,會壞在哪一步
案子一多,這條鏈會斷在三個地方。
第一是忘了追簽名。協議寄出後,沒有任何東西提醒誰該再寄一封信;簽回來也沒有東西提醒誰該算錢、發下一張表。
第二是套錯地區的範本。三地的勞務契約與報酬單格式不同,同時在跑的案子越多,拿錯範本的機率越高。
第三是同一份協議寄了兩次。Word 範本不會記得自己已經產出過合約,對一個已經簽過的人,它照樣會再產出一份。這一種最危險:漏掉一步事後還能補,簽了兩份內容矛盾的協議,補不回來。
怎麼接成一條鏈:三步,每步都寫明下一步
圖:三個階段由左到右串接,token 在每一步發出,狀態閘靠它判斷這一步是否已經做過。
第一步:業務開案,系統寄出協議
業務填寫該地區的協議表單,帶入顧問的姓名、email、日期與費率。系統收到表單後,複製一份協議文件(Google 文件),產生預覽 PDF 與線上簽署連結,寄給顧問。顧問點開連結線上簽署,簽署版 PDF 存入雲端硬碟,並寄給雙方留存。
開案由業務填,是因為只有業務知道案子存不存在、費率是否已談定。系統在顧問簽名前,先用這些資料做基本核對。
第二步:填會議次數,系統算金額
一日實作的錢分兩塊:固定的實作費,加上會議單價乘以當天實際開的會議次數。業務在系統頁面填入次數,系統算出總額,再寄出一份已預填好的發票表單連結給顧問。
示意:假資料,實作費 3000、會議單價 800、會議 4 次,總額為 6200
=3000 + 800 * 4第三步:回收勞務報酬單,依地區分流
顧問填寫表單,提供個資與證件資訊,系統複製一份勞務報酬單。這一步依地區分流:其中一地寄出未簽版本,請顧問列印、親簽、掃描後上傳;另外兩地直接帶入數位簽名,PDF 完成即可。最後系統通知雙方與營運窗口,案件結束。
同一件案子,怎麼擋住第二次觸發?
沒有後端資料庫,能用的只有 Apps Script(Google 的指令碼環境)與試算表。這裡的做法是 token 加狀態閘。token 是系統在某個動作完成時發出的一組隨機字串,存進追蹤表那一列;狀態閘則是下一次請求進來時的判斷:這個 token 是否已經用過、這份文件是否已經簽過。
流程的三個接觸點各有一個 token:consent(協議同意)、invoiceSetup(發票設定)、signatureReturn(簽名回收)。token 一旦發出就永不清除。清掉它,系統就忘了這一步做過,閘也就形同虛設。
下面是簽名回收那一關的判斷邏輯,示意用:
function acceptSignature_(row, token) {
if (row.signatureReturn !== token) return fail_('token 不符');
if (row.signed === true) return fail_('已簽署,拒絕重送');
row.signed = true;
return ok_(row);
}發票回收那一關另外疊了兩道檢查:先核對表單提交人的 email 是否與案件記錄的顧問 email 一致,再檢查 invoiceReturned 狀態旗標。任何一關沒過,就退回並送 Slack 通知,不硬把資料寫進去。被轉寄出去的連結、被重複點下去的按鈕,都會撞上閘門。這些情境目前只用程式路徑檢查過,還沒有用真實的重送資料跑完整批測試。
追蹤表:一案一列,34 欄
所有狀態都在一張 Tracking 試算表上,每件案子一列。34 欄包含主鍵、各表單回填的資料、各階段的簽署狀態,還有指向雲端硬碟上 PDF 的檔案 ID,另有幾欄公式做彙總。
圖:示意資料,只畫出 34 欄中的 7 欄。選取框停在協議 token,簽署閘讀取的就是這一格。
檔案 ID 指向的是實際用於交換的 PDF,文件本身仍是 Google 文件。文件是活的,隨時可能被改動;寄出去、被當作憑據的是 PDF。預覽版與正式簽署版各自留在雲端硬碟,對帳時對到的,才是當時寄出的那一份。彙總頁(Dashboard)是唯讀的,要改案件資料,只能改 Tracking 本身。
兩筆幾乎同時回填,會發生什麼?
每個 Web App 的 doPost 處理函式(Web App 是 Apps Script 發布成的網址,用來接收表單提交)一開始就取得 LockService.getScriptLock()。兩筆提交幾乎同時回填時,若不排隊,兩個寫入可能同時碰到追蹤表的同一列,後寫的會蓋掉先寫的。排隊慢一點,寫進去的內容才確定。
地區差異,改哪裡?
三地的差異包括費率、表單 ID、範本文件 ID,以及可以開案的業務名單,全部放在一個 REGIONS 常數裡。要調某一地的費率,或加第四地,改這個常數就好,不必到各處找判斷式。
通知只寄給送件的人,並固定 cc 一位維運窗口。其中一地另外有一組 initiators 白名單,記的是實際會送該地協議表單的業務,出事時知道該找誰。
踩過的坑
當時自己拼接 entry.X=Y 的預填網址,用的 X 是題目的 item.getId(),但表單預填要用的是 entry ID,兩組數字不同。網址看起來正常,點開卻完全不帶入資料,而且不會有任何錯誤。之後改用 form.createResponse().toPrefilledUrl(),讓官方 API 產生網址。
限制與還沒量到的事
錯誤回報是自己寫的一層薄包裝 tryRun,統一處理 try-catch 與錯誤通知。沒有沿用另外維護的共用函式庫,因為這個專案的接觸點與狀態流程,和那套函式庫假設的不同。
其中一地的勞報單要求列印親簽後掃描回傳,另外兩地接受數位簽名。修改地區規則前,先確認該地區的簽署方式,避免把未簽版本寄到不該寄的流程。
目前還沒量到的有三件:每件案子從開案到案件結束實際花的時間,尚未實測;重複觸發的整批重送測試,尚未實測,目前只有程式路徑的檢查;上線前人工作業花了多少時間,沒有留下記錄,無法拿來比較。