update,
This commit is contained in:
4
catmk2/task1/.clasp.json
Normal file
4
catmk2/task1/.clasp.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"scriptId": "1E3I99AvUTQ7ydwCVsuD5-OpbCJyW4LhVbo78xDQJuWWFLNGOLRzRkJ1b",
|
||||
"rootDir": "/workspace/carousell-comission-playlist/catmk2/task1"
|
||||
}
|
2
catmk2/task1/.claspignore
Normal file
2
catmk2/task1/.claspignore
Normal file
@@ -0,0 +1,2 @@
|
||||
tests
|
||||
**/node_modules/**
|
10
catmk2/task1/Code.js
Normal file
10
catmk2/task1/Code.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function onOpen() {
|
||||
const ui = SpreadsheetApp.getUi();
|
||||
ui.createMenu("Automator Menu " + VER)
|
||||
// .addItem("send 繳費通知 (未通知 -> 已通知)", "processPaymentNotice")
|
||||
.addItem("debug-Say Hello", "sayHelloworld")
|
||||
// .addItem("debug-helloWorldEmail", "helloWorldEmail")
|
||||
// .addItem("debug-helloWorldWriteCell", "helloWorldWriteCell")
|
||||
// .addItem("debug-processPaymentNotice", "processPaymentNotice")
|
||||
.addToUi();
|
||||
}
|
6
catmk2/task1/appsscript.json
Normal file
6
catmk2/task1/appsscript.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"timeZone": "Asia/Hong_Kong",
|
||||
"dependencies": {},
|
||||
"exceptionLogging": "STACKDRIVER",
|
||||
"runtimeVersion": "V8"
|
||||
}
|
30
catmk2/task1/config.js
Normal file
30
catmk2/task1/config.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const VER = "1.0.3";
|
||||
const SHEET_ID = "1yHIRyYetq6SC3BZtGNVDzCfIJvuwcROnmdqyk9Jmyss";
|
||||
|
||||
// 學員進度
|
||||
const SHEET_STUDENT_PROGRESS = "學員進度";
|
||||
|
||||
const COL_STUDENT_PROGRESS_CHINESE_NAME = "A"; //中文姓名
|
||||
const COL_STUDENT_PROGRESS_ENGLISH_NAME = "B"; // 英文姓名
|
||||
const COL_STUDENT_PROGRESS_COURSE_OFFERED = "C"; // 報讀課程
|
||||
const COL_STUDENT_PROGRESS_COURSE_CODE = "D"; // 課程班號
|
||||
const COL_STUDENT_PROGRESS_GENDER = "E"; // 性別
|
||||
const COL_STUDENT_PROGRESS_PHONE_NUMBER = "F"; // 手提電話
|
||||
const COL_STUDENT_PROGRESS_EMAIL_ADDRESS = "G"; // 電郵地址
|
||||
const COL_STUDENT_PROGRESS_ATTENDANCE_PROGRESS = "H"; // 上堂進度
|
||||
const COL_STUDENT_PROGRESS_PAYMENT_PROGRESS = "I"; // 繳費進度
|
||||
const COL_STUDENT_PROGRESS_PAYMENT_LINK = "K"; // 付款連結
|
||||
const COL_STUDENT_PROGRESS_NOTIFICATION_DATE = "J"; // 通知日期 (yyyy-mm-dd)
|
||||
// const COL_STUDENT_PROGRESS_PAYMENT_PROOF_PROVIDED = "M"; // 已提供付款證明
|
||||
const COL_STUDENT_PROGRESS_CERTIFICATE_REISSUE = "L"; // 證書補發
|
||||
const COL_STUDENT_PROGRESS_CERTIFICATE_FEE_RECEIVED = "M"; // 己收補證書費用
|
||||
const COL_STUDENT_PROGRESS_REMARKS = "O"; // 備註
|
||||
const COL_STUDENT_PROGRESS_RESULT = "Y"; // RESULT
|
||||
|
||||
const CONST_NOT_NOTIFIED = "未通知";
|
||||
const CONST_NOTIFIED_ALREADY = "已通知";
|
||||
const EMAIL_QUOTA_USED_UP="對不起,email 配額已用完"
|
||||
|
||||
const ROW_START = 2;
|
||||
|
||||
console.log("config initialized");
|
3301
catmk2/task1/package-lock.json
generated
Normal file
3301
catmk2/task1/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
catmk2/task1/package.json
Normal file
23
catmk2/task1/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "task1",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "Code.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"cP": "clasp push",
|
||||
"gitUpdate": "git add . && git commit -m\"update,\"",
|
||||
"watch:cP": "nodemon -L --delay 1 --exec \"npm run cP\"",
|
||||
"watch:format": "npx nodemon -L --exec \"npx prettier --write . \""
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"browser-sync": "^2.29.3",
|
||||
"nodemon": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"clasp": "^1.0.0"
|
||||
}
|
||||
}
|
1
catmk2/task1/slides_src/.gitignore
vendored
Normal file
1
catmk2/task1/slides_src/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.html
|
BIN
catmk2/task1/slides_src/assets/email-screenshot.png
(Stored with Git LFS)
Normal file
BIN
catmk2/task1/slides_src/assets/email-screenshot.png
(Stored with Git LFS)
Normal file
Binary file not shown.
1
catmk2/task1/slides_src/assets/github-mark.svg
Normal file
1
catmk2/task1/slides_src/assets/github-mark.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>
|
After Width: | Height: | Size: 963 B |
BIN
catmk2/task1/slides_src/assets/resend.png
(Stored with Git LFS)
Normal file
BIN
catmk2/task1/slides_src/assets/resend.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
catmk2/task1/slides_src/assets/run_script.png
(Stored with Git LFS)
Normal file
BIN
catmk2/task1/slides_src/assets/run_script.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
catmk2/task1/slides_src/assets/send_email_done.png
(Stored with Git LFS)
Normal file
BIN
catmk2/task1/slides_src/assets/send_email_done.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
catmk2/task1/slides_src/assets/wanted_row.png
(Stored with Git LFS)
Normal file
BIN
catmk2/task1/slides_src/assets/wanted_row.png
(Stored with Git LFS)
Normal file
Binary file not shown.
6
catmk2/task1/slides_src/build.sh
Normal file
6
catmk2/task1/slides_src/build.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
npx marp -w index.md
|
||||
npx marp --pdf --allow-local-files ./index.md
|
58
catmk2/task1/slides_src/index.md
Normal file
58
catmk2/task1/slides_src/index.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
marp: true
|
||||
title: Helloworld
|
||||
description: Hosting Marp slide deck on the web
|
||||
theme: uncover
|
||||
paginate: true
|
||||
_paginate: false
|
||||
header: '**google apps script send email**'
|
||||
footer: ' https://louiscklaw.github.io'
|
||||
---
|
||||
|
||||
<!-- headingDivider: 2 -->
|
||||
|
||||
# google apps script
|
||||
send email
|
||||
|
||||
## 目的: 通知報名者
|
||||
|
||||
1. 已獲取錄
|
||||
1. 付款
|
||||
|
||||
## 做法:
|
||||
- 頁面 '學員進度'
|
||||
- 欄 '通知日期' 中,該列 "變成" 觸發日期
|
||||
- 欄 '繳費進度' 自己轉為 "已通知"
|
||||
- 自動 SEND EMAIL 去 同列的 '電郵地址'
|
||||
|
||||
## requirement/需要資料:
|
||||
1. 係學員進度呢個頁面度
|
||||
1. 首先 "繳費進度" 要係未通知
|
||||
1. 跟住 "電郵地址" 要係一個有效嘅地址
|
||||
1. 加埋 "付款連結" 要係一條 link ()
|
||||
|
||||

|
||||
|
||||
## how to run/點行呢?
|
||||
1. click "Automator Menu"
|
||||
1. click "send 繳費通知 (未通知 -> 己通知)"
|
||||

|
||||
|
||||
## done/行完?
|
||||
|
||||
**send 左 email 的話:**
|
||||
1. 繳費進度 由 "未通知" -> "已通知"
|
||||
1. 通知日期 會填上 "日期"
|
||||

|
||||
|
||||
## email/電郵?
|
||||

|
||||
|
||||
## resend/s重發 email?
|
||||
1. 將繳費進度由 "己通知" 轉番去 "未通知",
|
||||
1. 然後再行個 script 一次 (slide 5)
|
||||

|
||||
|
||||
## QnA/問問題?
|
||||
|
||||
😃
|
BIN
catmk2/task1/slides_src/main.png
(Stored with Git LFS)
Normal file
BIN
catmk2/task1/slides_src/main.png
(Stored with Git LFS)
Normal file
Binary file not shown.
2887
catmk2/task1/slides_src/package-lock.json
generated
Normal file
2887
catmk2/task1/slides_src/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
catmk2/task1/slides_src/package.json
Normal file
18
catmk2/task1/slides_src/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "catmk2-presentation",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"gitUpdate": "git add . && git commit -m \"update catmk2-presentation,\" && git push",
|
||||
"build": "rm -rf *.html **/*.html && yarn marp -I . -o .",
|
||||
"watch": "npx nodemon -e \"*.md\" --exec yarn build"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@marp-team/marp-cli": "^2.0.4"
|
||||
}
|
||||
}
|
BIN
catmk2/task1/slides_src/slides.pdf
Normal file
BIN
catmk2/task1/slides_src/slides.pdf
Normal file
Binary file not shown.
84
catmk2/task1/template/notification_email.js
Normal file
84
catmk2/task1/template/notification_email.js
Normal file
@@ -0,0 +1,84 @@
|
||||
const email_title = (course_title) => `${course_title} 取錄 及 付款通知`;
|
||||
|
||||
const email_content = (
|
||||
chinese_name,
|
||||
course_name,
|
||||
course_code,
|
||||
payment_link,
|
||||
chinese_today_string
|
||||
) => {
|
||||
try {
|
||||
var output = {
|
||||
state: "init",
|
||||
debug: { chinese_name, course_name, course_code, chinese_today_string },
|
||||
error: {},
|
||||
};
|
||||
return `
|
||||
<div>
|
||||
${chinese_name ? chinese_name + " 您好," : "您好,"}<br />
|
||||
<br />
|
||||
多謝閣下報名參加 <br />
|
||||
<br />
|
||||
${course_name ? "課程: " + course_name : ""}<br />
|
||||
${course_code ? "班號: " + course_code : ""}<br />
|
||||
<br />
|
||||
很高興通知您,課程即將開辦,請閣下於盡快完成付款手續,以確認報名。<br />
|
||||
<br />
|
||||
<a href="${payment_link}" target="_blank">按此到 付款連結</a><br />
|
||||
<br />
|
||||
另煩請保留 <underline>付款截圖</underline> 或 <underline>證明</underline>,貼上附件後回覆本電郵。<br />
|
||||
<br />
|
||||
<br />
|
||||
如付款過程中遇到任何困難,煩請聯絡 9134 7967 或 <a href="">回覆</a>本電郵即可。<br />
|
||||
於課程開始 7 天前仍未付款者,本司有權將課程名額轉讓至候補名單<br />
|
||||
<br />
|
||||
最後,隨信附上二維碼付款指引教學以供參考。謝謝 😊 <br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
樂歷課程報名處<br />
|
||||
${chinese_today_string || ""}<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
</div>
|
||||
`.trim();
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log("notification_email.js errors");
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
const email_content1 = (chinese_name, course_name, course_code) => {
|
||||
return `
|
||||
<中文姓名> 你好,
|
||||
|
||||
多謝閣下報名參加
|
||||
|
||||
${course_name}
|
||||
${course_code}
|
||||
|
||||
很高興通知您,課程即將開辦,請閣下於盡快完成付款收續,以確認報名。
|
||||
|
||||
繳費方式 :
|
||||
請按下方連結下載轉數快/ FPS 二維碼,並使用各大銀行的手機現財App 内掃描二維碼會直接付款。
|
||||
|
||||
<付款連結>
|
||||
|
||||
請保留付款截圖或證明後,貼上附件後回覆本電郵。
|
||||
|
||||
|
||||
如付款有任何困難,請聯絡 9134 7967 或 回覆本電郵即可
|
||||
如課程前7天前仍未付款者,本司有權將課程名額轉讓至候補名單
|
||||
|
||||
最後,附上二維碼付款指引教學,以供參考。謝謝 😊
|
||||
|
||||
<附件 - 智豐收二維碼付款指引.pdf>
|
||||
|
||||
樂歷課程報名處
|
||||
<今日日期>
|
||||
|
||||
`.trim();
|
||||
};
|
12
catmk2/task1/template/package.json
Normal file
12
catmk2/task1/template/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "template",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
20
catmk2/task1/utils/appendResult.js
Normal file
20
catmk2/task1/utils/appendResult.js
Normal file
@@ -0,0 +1,20 @@
|
||||
function appendResult(row, comment_to_write) {
|
||||
var output = { state: "init", debug: { comment_to_write }, error: "" };
|
||||
try {
|
||||
var sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(
|
||||
SHEET_STUDENT_PROGRESS
|
||||
);
|
||||
|
||||
var result_cell = getCell(sheet, row, COL_STUDENT_PROGRESS_RESULT);
|
||||
var result_value = readCell(result_cell);
|
||||
|
||||
if (result_value.trim() == "") {
|
||||
writeCell(result_cell, comment_to_write);
|
||||
} else {
|
||||
writeCell(result_cell, [result_value, comment_to_write].join("\n"));
|
||||
}
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log(output);
|
||||
}
|
||||
}
|
12
catmk2/task1/utils/checkEmailQuotaAvailable.js
Normal file
12
catmk2/task1/utils/checkEmailQuotaAvailable.js
Normal file
@@ -0,0 +1,12 @@
|
||||
function checkEmailQuotaAvailable() {
|
||||
var output = { state: "init", debug: {}, error: {} };
|
||||
try {
|
||||
var emailQuotaRemaining = MailApp.getRemainingDailyQuota();
|
||||
|
||||
return emailQuotaRemaining > 0;
|
||||
} catch (error) {
|
||||
output = {...output , error}
|
||||
console.log('checkEmailQuotaAvailable error')
|
||||
console.log(output);
|
||||
}
|
||||
}
|
57
catmk2/task1/utils/checkLastRow.js
Normal file
57
catmk2/task1/utils/checkLastRow.js
Normal file
@@ -0,0 +1,57 @@
|
||||
function checkLastRow(sheet, current_row) {
|
||||
// return true if considered last row, false if not
|
||||
// check email column only
|
||||
output = {state:'init', debug:{sheet, current_row}, error:{}}
|
||||
try {
|
||||
var current_row_cell = getCell(
|
||||
sheet,
|
||||
current_row,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
var current_row_cell_1 = getCell(
|
||||
sheet,
|
||||
current_row + 1,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
|
||||
var current_row_cell_2 = getCell(
|
||||
sheet,
|
||||
current_row + 2,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
|
||||
var current_row_cell_3 = getCell(
|
||||
sheet,
|
||||
current_row + 3,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
|
||||
var current_row_cell_4 = getCell(
|
||||
sheet,
|
||||
current_row + 4,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
|
||||
var current_row_cell_5 = getCell(
|
||||
sheet,
|
||||
current_row + 5,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
|
||||
var check_is_empty = [
|
||||
isCellEmpty(current_row_cell),
|
||||
isCellEmpty(current_row_cell_1),
|
||||
isCellEmpty(current_row_cell_2),
|
||||
isCellEmpty(current_row_cell_3),
|
||||
isCellEmpty(current_row_cell_4),
|
||||
isCellEmpty(current_row_cell_5),
|
||||
];
|
||||
|
||||
return check_is_empty.indexOf(false) < 0;
|
||||
} catch (error) {
|
||||
output ={...output, error}
|
||||
console.log("checkLastRow: error");
|
||||
console.log(output)
|
||||
return false;
|
||||
}
|
||||
}
|
10
catmk2/task1/utils/checkNotNotifiedForPayment.js
Normal file
10
catmk2/task1/utils/checkNotNotifiedForPayment.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function checkNotNotifiedForPayment(cell_value) {
|
||||
var output = { state: "init", debug: {}, error: "" };
|
||||
try {
|
||||
return cell_value == CONST_NOT_NOTIFIED;
|
||||
} catch (error) {
|
||||
console.log('checkNotNotifiedForPayment error')
|
||||
output = { ...output, error };
|
||||
console.log(output);
|
||||
}
|
||||
}
|
27
catmk2/task1/utils/checkPaymentLinkAvailable.js
Normal file
27
catmk2/task1/utils/checkPaymentLinkAvailable.js
Normal file
@@ -0,0 +1,27 @@
|
||||
function checkPaymentLinkAvailable(current_row) {
|
||||
var output = { state: "init", debug: { current_row }, error: {} };
|
||||
try {
|
||||
var sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(
|
||||
SHEET_STUDENT_PROGRESS
|
||||
);
|
||||
|
||||
var payment_link_cell = getCell(
|
||||
sheet,
|
||||
current_row,
|
||||
COL_STUDENT_PROGRESS_PAYMENT_LINK
|
||||
);
|
||||
var payment_link = readCell(payment_link_cell);
|
||||
console.log({ payment_link });
|
||||
|
||||
if (payment_link.search(/^https?:\/\/.+/) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log('checkPaymentLinkAvailable error')
|
||||
console.log(output);
|
||||
return false;
|
||||
}
|
||||
}
|
10
catmk2/task1/utils/getCell.js
Normal file
10
catmk2/task1/utils/getCell.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function getCell(sheet, row, column) {
|
||||
output = {state:'init', debug:{}, error:{}}
|
||||
try {
|
||||
var cell = sheet.getRange(column + row);
|
||||
return cell;
|
||||
} catch (error) {
|
||||
output = {...output, error}
|
||||
console.log(output);
|
||||
}
|
||||
}
|
3
catmk2/task1/utils/getChineseDayString.js
Normal file
3
catmk2/task1/utils/getChineseDayString.js
Normal file
@@ -0,0 +1,3 @@
|
||||
function getChineseDayString() {
|
||||
return Utilities.formatDate(new Date(), "GMT+8", "yyyy 年 MM 月 dd 日");
|
||||
}
|
27
catmk2/task1/utils/getLastRow.js
Normal file
27
catmk2/task1/utils/getLastRow.js
Normal file
@@ -0,0 +1,27 @@
|
||||
function getLastRow(sheet) {
|
||||
var output = { state: "init", debug: {sheet}, error: "" };
|
||||
try {
|
||||
var last_row = -1;
|
||||
var row_scan = 99999;
|
||||
|
||||
for (let i = 1; i < row_scan; i++) {
|
||||
if (checkLastRow(sheet, i)) {
|
||||
// print last row number
|
||||
last_row = i - 1;
|
||||
output = { ...output, debug: { ...output.debug, last_row } };
|
||||
console.log("last row is " + last_row.toString());
|
||||
break;
|
||||
} else {
|
||||
// keep going
|
||||
}
|
||||
}
|
||||
if (last_row == -1) {
|
||||
throw new Error('cannot find the last row')
|
||||
}
|
||||
return last_row;
|
||||
} catch (error) {
|
||||
console.log('getLastRow error')
|
||||
output = { ...output, error };
|
||||
console.log(output);
|
||||
}
|
||||
}
|
14
catmk2/task1/utils/getSheetStudentProgress.js
Normal file
14
catmk2/task1/utils/getSheetStudentProgress.js
Normal file
@@ -0,0 +1,14 @@
|
||||
function getSheetStudentProgress() {
|
||||
output = {state:'init', debug:{}, error:{}}
|
||||
|
||||
try {
|
||||
var sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(
|
||||
SHEET_STUDENT_PROGRESS
|
||||
);
|
||||
return sheet;
|
||||
} catch (error) {
|
||||
output = {...output, error}
|
||||
console.log("getSheetStudentProgress error")
|
||||
console.log(output);
|
||||
}
|
||||
}
|
12
catmk2/task1/utils/isCellEmpty.js
Normal file
12
catmk2/task1/utils/isCellEmpty.js
Normal file
@@ -0,0 +1,12 @@
|
||||
function isCellEmpty(cell) {
|
||||
var output = { state: "init", debug: {}, error: {} };
|
||||
try {
|
||||
// console.log("isCellEmpty:" + cell.getValue());
|
||||
var temp = cell.getValue().toString().trim();
|
||||
return temp == "";
|
||||
} catch (error) {
|
||||
console.log("isCellEmpty error");
|
||||
output = { ...output, error };
|
||||
console.log(output);
|
||||
}
|
||||
}
|
51
catmk2/task1/utils/processPaymentNotice.js
Normal file
51
catmk2/task1/utils/processPaymentNotice.js
Normal file
@@ -0,0 +1,51 @@
|
||||
function processPaymentNotice() {
|
||||
var output = { state: "init", debug: {}, error: "" };
|
||||
try {
|
||||
var sheet = getSheetStudentProgress();
|
||||
var last_row = getLastRow(sheet);
|
||||
output = { ...output, debug: { ...output.debug, last_row } };
|
||||
|
||||
for (var i = ROW_START; i < last_row + 1; i++) {
|
||||
var email_cell = getCell(sheet, i, COL_STUDENT_PROGRESS_EMAIL_ADDRESS);
|
||||
var payment_progress_cell = getCell(
|
||||
sheet,
|
||||
i,
|
||||
COL_STUDENT_PROGRESS_PAYMENT_PROGRESS
|
||||
);
|
||||
var payment_progress = readCell(payment_progress_cell);
|
||||
|
||||
if (checkNotNotifiedForPayment(payment_progress)) {
|
||||
resetResult(i);
|
||||
appendResult(
|
||||
i,
|
||||
`not notified(${CONST_NOT_NOTIFIED}), proceed send payment notification email`
|
||||
);
|
||||
|
||||
var quota_available = checkEmailQuotaAvailable();
|
||||
var payment_link_available = checkPaymentLinkAvailable(i);
|
||||
if (quota_available && payment_link_available) {
|
||||
try {
|
||||
sendPaymentNoticeEmail(i);
|
||||
updateRowToNotificationSent(i);
|
||||
} catch (error) {
|
||||
Browser.msgBox("error during sending email");
|
||||
}
|
||||
} else {
|
||||
if (quota_available < 1) {
|
||||
Browser.msgBox(EMAIL_QUOTA_USED_UP);
|
||||
}
|
||||
if (!payment_link_available) {
|
||||
appendResult(i, `payment link not exist, skipping`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resetResult(i);
|
||||
appendResult(i, `not "${CONST_NOT_NOTIFIED}" skipping`);
|
||||
// var student_email = readCell(email_cell);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log(output);
|
||||
}
|
||||
}
|
10
catmk2/task1/utils/readCell.js
Normal file
10
catmk2/task1/utils/readCell.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function readCell(cell) {
|
||||
var output = { state: "init", debug: {}, error: {} };
|
||||
|
||||
try {
|
||||
return cell.getValue() || "";
|
||||
} catch (error) {
|
||||
output = {...output, err: error}
|
||||
console.log(error);
|
||||
}
|
||||
}
|
16
catmk2/task1/utils/resetResult.js
Normal file
16
catmk2/task1/utils/resetResult.js
Normal file
@@ -0,0 +1,16 @@
|
||||
function resetResult(row) {
|
||||
var output = { state: "init", debug: {}, error: "" };
|
||||
try {
|
||||
var sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(
|
||||
SHEET_STUDENT_PROGRESS
|
||||
);
|
||||
|
||||
var result_cell = getCell(sheet, row, COL_STUDENT_PROGRESS_RESULT);
|
||||
return writeCell(result_cell, null);
|
||||
} catch (error) {
|
||||
console.log("resetResult error");
|
||||
output = { ...output, error };
|
||||
console.log(output);
|
||||
console.log(error);
|
||||
}
|
||||
}
|
3
catmk2/task1/utils/sayHelloworld.js
Normal file
3
catmk2/task1/utils/sayHelloworld.js
Normal file
@@ -0,0 +1,3 @@
|
||||
function sayHelloworld() {
|
||||
console.log("say helloworld");
|
||||
}
|
11
catmk2/task1/utils/sendEmail.js
Normal file
11
catmk2/task1/utils/sendEmail.js
Normal file
@@ -0,0 +1,11 @@
|
||||
function sendEmail(options) {
|
||||
var output = { state: "init", debug: {}, error: {} };
|
||||
try {
|
||||
MailApp.sendEmail(options);
|
||||
output = { ...output, state: "done" };
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log("sendEmail error");
|
||||
console.log(output);
|
||||
}
|
||||
}
|
121
catmk2/task1/utils/sendPaymentNoticeEmail.js
Normal file
121
catmk2/task1/utils/sendPaymentNoticeEmail.js
Normal file
@@ -0,0 +1,121 @@
|
||||
function sendPaymentNoticeEmail(row) {
|
||||
var output = { state: "init", debug: {}, error: {} };
|
||||
var sheet = getSheetStudentProgress();
|
||||
|
||||
// var filename = "payment_guide.pdf";
|
||||
var fps_tutorial_pdf_file_id = "1iD4CL8X-Nr7vfmj3UI3OzrJaKl1Gbg8tGAi6T6EmEJ0";
|
||||
var fps_tutorial_pdf_file = DriveApp.getFileById(fps_tutorial_pdf_file_id);
|
||||
|
||||
// NOTE: student email?
|
||||
var student_email_address_cell = getCell(
|
||||
sheet,
|
||||
row,
|
||||
COL_STUDENT_PROGRESS_EMAIL_ADDRESS
|
||||
);
|
||||
var student_email_address = readCell(student_email_address_cell);
|
||||
|
||||
var student_chinese_name_cell = getCell(
|
||||
sheet,
|
||||
row,
|
||||
COL_STUDENT_PROGRESS_CHINESE_NAME
|
||||
);
|
||||
var student_chinese_name = readCell(student_chinese_name_cell);
|
||||
|
||||
// NOTE: courase_name
|
||||
var course_offered_cell = getCell(
|
||||
sheet,
|
||||
row,
|
||||
COL_STUDENT_PROGRESS_COURSE_OFFERED
|
||||
);
|
||||
var course_offered = readCell(course_offered_cell);
|
||||
if (course_offered == "") {
|
||||
output = {
|
||||
...output,
|
||||
debug: {
|
||||
...output.debug,
|
||||
remarks: {
|
||||
course_offered,
|
||||
comment: "found empty",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: course_code
|
||||
var course_code_cell = getCell(sheet, row, COL_STUDENT_PROGRESS_COURSE_CODE);
|
||||
var course_code = readCell(course_code_cell);
|
||||
if (course_code == "") {
|
||||
output = {
|
||||
...output,
|
||||
debug: {
|
||||
...output.debug,
|
||||
remarks: {
|
||||
course_code,
|
||||
comment: "found empty",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: payment_link
|
||||
var payment_link_cell = getCell(
|
||||
sheet,
|
||||
row,
|
||||
COL_STUDENT_PROGRESS_PAYMENT_LINK
|
||||
);
|
||||
var payment_link = readCell(payment_link_cell);
|
||||
if (payment_link == "") {
|
||||
output = {
|
||||
...output,
|
||||
debug: {
|
||||
...output.debug,
|
||||
remarks: {
|
||||
payment_link,
|
||||
comment: "found empty",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: courase_name
|
||||
// NOTE: courase_name
|
||||
|
||||
try {
|
||||
var subject = email_title(course_offered);
|
||||
// var body = email_content("中文名", "chinese 中文科", "CHI001");
|
||||
var htmlBody = email_content(
|
||||
student_chinese_name,
|
||||
course_offered,
|
||||
course_code,
|
||||
payment_link,
|
||||
getChineseDayString()
|
||||
);
|
||||
var recipient = student_email_address;
|
||||
if (recipient=='') throw new Error('email address not valid');
|
||||
|
||||
var sender = "testhelloworld04@gmail.com";
|
||||
|
||||
// https://developers.google.com/apps-script/reference/mail/mail-app
|
||||
var options = {
|
||||
bcc: sender,
|
||||
|
||||
replyTo: sender,
|
||||
to: recipient,
|
||||
subject: subject,
|
||||
// body: body,
|
||||
htmlBody: htmlBody,
|
||||
attachments: [fps_tutorial_pdf_file.getAs(MimeType.PDF)],
|
||||
};
|
||||
|
||||
sendEmail(options);
|
||||
updateNotificationDate(row)
|
||||
appendResult(row, "send email done");
|
||||
|
||||
output = { ...output, state: "send email done" };
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log("sendEmail error");
|
||||
console.log(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
15
catmk2/task1/utils/updateNotificationDate.js
Normal file
15
catmk2/task1/utils/updateNotificationDate.js
Normal file
@@ -0,0 +1,15 @@
|
||||
function updateNotificationDate(row) {
|
||||
output = {state:"init", debug:{}, error:{}}
|
||||
try {
|
||||
var student_progress_sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(
|
||||
SHEET_STUDENT_PROGRESS
|
||||
);
|
||||
var notification_date_cell = getCell(student_progress_sheet, row, COL_STUDENT_PROGRESS_NOTIFICATION_DATE)
|
||||
writeCell(notification_date_cell, getChineseDayString().replace(/ /g,''))
|
||||
|
||||
} catch (error) {
|
||||
output = {...output, error}
|
||||
console.log('updateNotificationDate error')
|
||||
console.log(output)
|
||||
}
|
||||
}
|
17
catmk2/task1/utils/updateRowToNotificationSent.js
Normal file
17
catmk2/task1/utils/updateRowToNotificationSent.js
Normal file
@@ -0,0 +1,17 @@
|
||||
function updateRowToNotificationSent(row) {
|
||||
var output = { state: "init", debug: { row }, error: {} };
|
||||
try {
|
||||
var sheet = getSheetStudentProgress();
|
||||
var payment_progress_cell = getCell(
|
||||
sheet,
|
||||
row,
|
||||
COL_STUDENT_PROGRESS_PAYMENT_PROGRESS
|
||||
);
|
||||
writeCell(payment_progress_cell, CONST_NOTIFIED_ALREADY);
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
output = { ...output, error };
|
||||
console.log(error);
|
||||
}
|
||||
}
|
11
catmk2/task1/utils/writeCell.js
Normal file
11
catmk2/task1/utils/writeCell.js
Normal file
@@ -0,0 +1,11 @@
|
||||
function writeCell(cell, content) {
|
||||
var output = { state: "init", debug: {}, error: "" };
|
||||
try {
|
||||
cell.setValue(content);
|
||||
} catch (error) {
|
||||
output = {...output, error}
|
||||
console.log("writeCell error");
|
||||
console.log(output);
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user