iT邦幫忙

2024 iThome 鐵人賽

DAY 4
1
Modern Web

我阿嬤都會的 kintone 客製化開發系列 第 4

Day 04 | 小試身手之「自動編碼」篇

  • 分享至 

  • xImage
  •  

這篇文章中,我們來嘗試開發一個 自動編碼 的客製化功能。

什麼是自動編碼

在 kintone 應用程式中,每筆資料都會有一個紀錄編號,這個紀錄編號會從 1 一直往上疊加,是系統自動生成且無法修改的。一般企業在使用時,會希望只要每次新增一筆紀錄,該紀錄都會自動產生一個編號,例如:

  • 前綴加日期加編號:ET-240805-001
  • 日期加編號:240805001
  • 前綴加編號:RS001

之後只要再新增一筆紀錄,該紀錄的編碼就會變成 ET-240805-002,諸如此類的編排方式,再基於這個方式新增一些條件,例如每天的編號需要重新計算等等,像這類型的功能我們會稱作自動編碼,日文是「自動採番」。

實際開發

我們來實際開發一個 YYYYMMDD流水號 的功能,期望是新增一筆資料的時候會自動編碼,因此事件我們使用 app.record.create.submitmobile.app.record.create.submit

然後為了方便,我們把到時候要編碼的欄位 ID 以及 APP ID 都拉到最外面,因此就會變成以下:

const APP_ID = "75"
const idField = "編碼id" // 自動編碼的欄位

kintone.events.on(["app.record.create.submit", "mobile.app.record.create.submit"], async (event) => {
  // ...
})

取得今天的最後一筆紀錄

透過 API 取得所有資料,並使用 query 篩選出今天的最後一筆資料

/**
 * 取得今天該應用程式的最後一筆記錄
 * @returns {Promise<Object|null>} 當天的最後一筆記錄,如果沒有則為 null
 */
const getTodayLastRecord = async () => {
  try {
    // 當天的開始及結束時間
    const now = new Date();
    const midnight = new Date(now.setHours(0, 0, 0, 0)).toISOString();
    const tomorrowMidnight = new Date(now.setHours(24, 0, 0, 0)).toISOString();

    // 搜尋用 query (今天 0 點到 24 點,的最後一筆資料)
    const creatTime = "建立時間";
    const query = `
      ${creatTime} >= "${midnight}" 
      and ${creatTime} < "${tomorrowMidnight}" 
      order by ${creatTime} 
      desc limit 1
    `;

    const response = await kintone.api(
      kintone.api.url("/k/v1/records", true),
      "GET",
      {
        app: APP_ID,
        query: query,
      }
    );

    // 沒有當日資料就回傳 null
    return response.records[0] || null;
  } catch (e) {
    console.error("Error fetching records:", e);
  }
};

拿到今天的 YYYYMMDD 日期

  • 如果今天沒有編碼過的資料,就必須要產生 YYYYMMDD001
  • 如果已經有資料,把 YYYYMMDD001 + 1 就可以。
/**
 * 取得 YYYYMMDD 格式的今天日期
 * @returns {string} YYYYMMDD 格式的今天日期
 */
const getTodayFormatTime = () => {
  const today = new Date();
  const year = today.getFullYear().toString();
  const month = (today.getMonth() + 1).toString().padStart(2, '0');
  const day = today.getDate().toString().padStart(2, '0');
  const yyyymmdd = `${year}${month}${day}`;

  return yyyymmdd;
};

判斷是否建立過

/**
 * 判斷今天有沒有建立過,並增加自動編碼的編號
 * @param {Object | null} record 當天的最後一筆記錄
 * @returns {string} 新的自動編碼值
 */
const incrementAutoId = (record) => {
  if (record === null) {
    const today = getTodayFormatTime();
    return `${today}001`;
  }

  const autoId = record[idField].value;
  const newAutoId = Number(autoId) + 1;

  return newAutoId;
};

事件寫回 events.on

kintone.events.on(["app.record.create.submit", "mobile.app.record.create.submit"], async (event) => {
  const lastRecord = await getTodayLastRecord();
  const autoid = incrementAutoId(lastRecord);

  // 取得當前記錄並更新
  const { record } = event;
  record[idField].value = autoid;
  return event;
});

完整程式碼

/**
 * 範例程式碼會產生 20240519001 格式的編碼並寫回當前的 idField 欄位
 * 若已有 20240519001 則回寫 20240519002
 */

const APP_ID = "75";
const idField = "編碼id";

/**
 * 取得今天該應用程式的最後一筆記錄
 * @returns {Promise<Object|null>} 當天的最後一筆記錄,如果沒有則為 null
 */
const getTodayLastRecord = async () => {
  try {
    // 當天的開始及結束時間
    const now = new Date();
    const midnight = new Date(now.setHours(0, 0, 0, 0)).toISOString();
    const tomorrowMidnight = new Date(now.setHours(24, 0, 0, 0)).toISOString();

    // 搜尋用 query (今天 0 點到 24 點,的最後一筆資料)
    const creatTime = "建立時間";
    const query = `
      ${creatTime} >= "${midnight}" 
      and ${creatTime} < "${tomorrowMidnight}" 
      order by ${creatTime} 
      desc limit 1
    `;

    const response = await kintone.api(
      kintone.api.url("/k/v1/records", true),
      "GET",
      {
        app: APP_ID,
        query: query,
      }
    );

    // 沒有當日資料就回傳 null
    return response.records[0] || null;
  } catch (e) {
    console.error("Error fetching records:", e);
  }
};

/**
 * 取得 YYYYMMDD 格式的今天日期
 * @returns {string} YYYYMMDD 格式的今天日期
 */
const getTodayFormatTime = () => {
  const today = new Date();
  const year = today.getFullYear().toString();
  const month = (today.getMonth() + 1).toString().padStart(2, '0');
  const day = today.getDate().toString().padStart(2, '0');
  const yyyymmdd = `${year}${month}${day}`;

  return yyyymmdd;
};

/**
 * 判斷今天有沒有建立過,並增加自動編碼的編號
 * @param {Object | null} record 當天的最後一筆記錄
 * @returns {string} 新的自動編碼值
 */
const incrementAutoId = (record) => {
  if (record === null) {
    const today = getTodayFormatTime();
    return `${today}001`;
  }

  const autoId = record[idField].value;
  const newAutoId = Number(autoId) + 1;

  return newAutoId;
};

kintone.events.on(["app.record.create.submit", "mobile.app.record.create.submit"], async (event) => {
  const lastRecord = await getTodayLastRecord();
  const autoid = incrementAutoId(lastRecord);

  // 取得當前記錄並更新
  const { record } = event;
  record[idField].value = autoid;
  return event;
});

這樣就大功告成了!記得要把寫好的 js 檔案上傳到 kintone 的後台才能正確使用!這份自動編碼的程式只適合在當天沒有紀錄的時候使用,因為會一直去抓之前的紀錄,我們沒有針對這部分去處理,所以需要注意。


上一篇
Day 03 | 發送 request 至 kintone 時的身份驗證
下一篇
Day 05 | kintone 開發環境建置
系列文
我阿嬤都會的 kintone 客製化開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言