├── README.md
├── code.js
├── resources
├── checkin-controller.png
├── email.png
├── entry-point.png
├── form.png
├── gscript.png
├── info-sheet.png
├── mail-template.png
├── run-code.png
├── workflow.jpg
└── workflow2.jpg
└── template.html
/README.md:
--------------------------------------------------------------------------------
1 | # Attendance system using QR code
2 | Hệ thống điểm danh người tham gia sự kiện qua QR gửi trong thư mời.
3 |
4 | Cập nhật lần cuối 23/09/2023.
5 |
6 | ## Giới thiệu
7 | Với việc triển khai các bước dưới đây, bạn có thể:
8 | - Tạo email thư mời/vé tham gia sự kiện/chiến dịch,... trong đó kèm mã QR.
9 | - Khi người dùng đến tham gia, bạn có thể sử dụng thiết bị (của bạn), quét QR trên ticket/thư mời của người dùng, để
10 | - Biết được người tham gia đó có hợp lệ (nhận được thư mời từ ban tổ chức hoặc đã mua vé) hay không.
11 | - Kiểm soát được danh sách người đã đến tham dự sự kiện theo **thời gian thực**.
12 |
13 | ## Luồng hoạt động
14 |
15 |
16 | - Về cơ bản, ảnh trên đã mô tả các thành phần và chức năng riêng của chúng trong hệ thống của mình, trông thì có vẻ phức tạp nhưng thực ra đơn giản thôi.
17 | - Một số trick được áp dụng khi dùng từng công cụ mà kết hợp chúng lại nó thực hiện được công việc mình đang cần:
18 | - `Google script`: thường mọi người dùng Google Sheets chỉ để làm bảng tính, thay thế Excel thôi, nhưng thực tế thì nó còn có khả năng tự động hóa các công việc rất mạnh nữa. Trong trường hợp này mình sẽ viết code để gửi mail tới cho danh sách người tham gia.
19 | - `Google Forms`: Forms thì ai cũng biết, nhưng mình tìm hiểu được thêm việc có thể submit form tự động bằng link kèm params. Tức là QR code của mỗi người thực tế sẽ là một link trỏ đến link điền form với param là login code của người đó, vậy khi mình scan lúc điểm danh (thực chất là truy cập link đó), thì kết quả sẽ được lưu lại là 1 phản hồi cho form đó. Đây cũng là chìa khóa của công cụ này.
20 | - `image-charts API`: API để gen ra QR được cá nhân hóa theo từng người. API này mở, không giới hạn lượt dùng, không limit thời gian sử dụng (bạn không lo bị khóa link sau một thời gian).
21 |
22 | ## Cách thực hiện
23 | - Đầu tiên bạn truy cập [sheet này](https://docs.google.com/spreadsheets/d/134WF55HkPuSOizzZRZ8eW9xXsTUWFQwtFiXPMBiw1tI/edit?usp=sharing). Chọn `File` > `Make a copy` cho tiện hoặc bạn cứ đọc để hiểu nguyên lý hoạt động chứ sheet này mình vừa làm vừa nháp, hơi xấu nên khó nhìn.
24 |
25 |
26 |
27 |
28 | - Có một số cột mình cần giải thích:
29 | - `Email`: email của từng người tham gia, tất nhiên vì bảo mật của sự kiện nên mình đã xóa đi.
30 | - `Login code`: như đã giải thích bên trên, cái này là mã đăng nhập của mỗi người, bạn tự tạo theo format nào bạn thích, miễn không trùng nhau là được. Bạn có thể dùng MSSV, CCCD nếu thích.
31 | - `Link form`: link đến form điểm danh. Các ô trong cột đấy đều có giá trị như nhau, mình kéo xuống để cho tiện thôi.
32 | - `Form entry point`: nó là entry point của ô câu trả lời khi bạn điền form. Cái này hơi technical 1 xíu, tí giải thích bên dưới. Tương tự cột link form, các ô trong cột này đều có giá trị như nhau, mình kéo xuống để cho tiện thôi.
33 | - `Generated QR link`: mình dùng API từ [image-charts.com](image-charts.com) để tạo từ **_link form_** + **_entry point_** + **_login code_**, để tạo ra một link QR cho từng người. Bạn chỉ cần copy y hệt là được.
34 |
35 |
36 | - Tiếp theo, mình đi viết [script](https://viblo.asia/p/google-apps-script-co-gi-hay-ho-07LKX2xElV4) cho sheet này. Bạn có thể nhấn vào phần `Extensions` > `App Script`. Mình đã viết sẵn script trong đó, bao gồm 2 file.
37 | - `template.html`: Đây là template mail động như bình thường thôi, mình dùng MJML để viết rồi dịch sang HTML, bạn hoàn toàn có thể sử dụng các công cụ khác. Mail có kèm hình ảnh và thông tin sự kiện của mình, tên người tham gia và QR. Vì mình muốn customize phần tên và QR code cho từng người nên những phần đó mình sẽ để dưới dạng biến truyền vào.
38 |
39 | - `mã.gs`: đây là phần script của mình. Có 3 function chính:
40 | - _getData()_: lấy thông tin người tham dự (tên, email, QR) từ sheet.
41 | - _getEmailHtml()_: lấy template mail mình đã chuẩn bị ở file `template.html`.
42 | - _sendMail()_: lấy thông tin, template mail để gửi đến email của từng người dùng.
43 |
44 | - 2 file mình đều đã để trong repo github này, bạn có thể vào đọc trước xem.
45 |
46 |
47 | - Tiếp theo mình đi tạo Form checkin:
48 | - `Giao diện Form`: đơn giản thôi, chỉ cần 1 câu hỏi duy nhất.
49 |
50 |
51 |
52 | - `Lấy địa chỉ entry point`: đầu tiên mình bật F12, rồi thử gửi 1 câu trả lời mẫu, rồi vào tab `Network`, tìm `formResponse` rồi xem phần `Payload` là ra, copy lại vào Sheet bên trên là được.
53 |
54 |
55 |
56 | - Phần form check-in này mọi người nhớ chỉ cấp quyền điền form cho địa chỉ email của Ban tổ chức máy dùng để scan khi người ta đi vào sự kiện. Chứ ai cũng scan & điền form được thì họ tự điểm danh cho nhau rồi.
57 |
58 | - Customize sheet phản hồi để kiểm soát người tham gia theo thời gian thực (kiểu như là đến thì nó hiện chữ có mặt và nền màu xanh). Cái này múa vài dòng lệnh sheet cơ làm được rồi, nên mình cũng không nói dài nữa & chỉ để [mẫu](https://docs.google.com/spreadsheets/d/1WR0jBY9Mn63x19XxeQhmGXuzvN-sr1pXHGQPQASSbfc/edit?usp=sharing) thôi nhé.
59 |
60 |
61 |
62 | - Xong rồi thì quay lại sheet thông tin rồi chạy phần script đã chuẩn bị để tự động gửi mail đến người tham gia thôi. ⚠️ **PLEASE NOTE**: hãy kiểm tra thật kỹ thông tin, test code cẩn thận trước khi run code, nếu không thì email với thông tin và QR sai được gửi tới người dùng thì không thể cứu vãn được đâu
63 |
64 |
65 |
66 | ## Các link liên quan
67 | - [Mẫu sheet thông tin người tham gia](https://docs.google.com/spreadsheets/d/134WF55HkPuSOizzZRZ8eW9xXsTUWFQwtFiXPMBiw1tI/edit?usp=sharing)
68 | - [Mẫu sheet checkin](https://docs.google.com/spreadsheets/d/1WR0jBY9Mn63x19XxeQhmGXuzvN-sr1pXHGQPQASSbfc/edit?usp=drive_link)
69 | - [Gscript sử dụng](code.js)
70 | - [Template mail động](template.html)
71 | - [MJML để viết mail động](https://mjml.io/)
72 | - [Extension Simple Mass Downloader](https://chrome.google.com/webstore/detail/simple-mass-downloader/abdkkegmcbiomijcbdaodaflgehfffed)
73 | - [Image Chart API](https://documentation.image-charts.com/qr-codes/)
74 |
75 | ## Phần bổ sung
76 | - Đây là phần nghiên cứu mình hoàn toàn tự mày mò dựa trên sự kiện mình tham gia ở năm ngoái, không tham khảo ở bất cứ nguồn nào. Vì vậy, mình hi vọng nếu các bạn thấy bài viết này có ích & sử dụng ý tưởng này có thể dẫn link tới repo này của mình để nhiều người biết hơn nhé.
77 | - Nếu gặp những vấn đề khi triển khai, bạn có thể liên lạc với mình qua [facebook](https://www.facebook.com/huythai855/) hoặc [email](mailto:nguyenhuythai15@gmail.com), mình sẽ cố gắng giải đáp.
78 | - Nếu bạn thấy bài hướng dẫn có ích, hãy để lại cho mình 1 star ⭐ nhé, cảm ơn bạn rất nhiều!
79 |
--------------------------------------------------------------------------------
/code.js:
--------------------------------------------------------------------------------
1 | function getData(i) {
2 | var sheet = SpreadsheetApp.getActive().getSheetByName("sheet1");
3 | var data = sheet.getRange(2, 1, 121, 25).getValues();
4 | var stocks = [];
5 | var stock = {};
6 | stock.name = data[i][3];
7 | stock.link = "" + data[i][18] + "";
8 | stocks.push(stock);
9 | return stocks;
10 | }
11 |
12 |
13 | function getEmailHtml(stockData) {
14 | var htmlTemplate = HtmlService.createTemplateFromFile("template.html");
15 | htmlTemplate.stockData = stockData;
16 | var htmlBody = htmlTemplate.evaluate().getContent();
17 | return htmlBody;
18 | }
19 |
20 |
21 | function sendEmail() {
22 | var sheet = SpreadsheetApp.getActiveSheet();
23 | var startRow = 2;
24 | var numRows = 120;
25 | var dataRange = sheet.getRange(startRow, 1, numRows, 25)
26 | var data = dataRange.getValues();
27 |
28 | var count = 0;
29 |
30 | for (i in data) {
31 | var row = data[i];
32 | var emailAddress = row[10];
33 |
34 | var stockData = getData(i);
35 | var htmlBody = getEmailHtml(stockData);
36 |
37 | // MailApp.sendEmail({
38 | // to: emailAddress,
39 | // subject: "[SGUET] Chúc mừng bạn đã nhận được tấm vé tham gia BIGGAME 2022!!!",
40 | // htmlBody: htmlBody
41 | // });
42 |
43 |
44 | ++count;
45 | Logger.log(count);
46 | Logger.log(stockData[0].name);
47 | Logger.log(stockData[0].link);
48 | Logger.log("Gửi email thành công đến" + JSON.stringify(emailAddress));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/resources/checkin-controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/checkin-controller.png
--------------------------------------------------------------------------------
/resources/email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/email.png
--------------------------------------------------------------------------------
/resources/entry-point.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/entry-point.png
--------------------------------------------------------------------------------
/resources/form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/form.png
--------------------------------------------------------------------------------
/resources/gscript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/gscript.png
--------------------------------------------------------------------------------
/resources/info-sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/info-sheet.png
--------------------------------------------------------------------------------
/resources/mail-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/mail-template.png
--------------------------------------------------------------------------------
/resources/run-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/run-code.png
--------------------------------------------------------------------------------
/resources/workflow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/workflow.jpg
--------------------------------------------------------------------------------
/resources/workflow2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huythai855/Attendance-system-using-QR-code/fb67d17a0ea074b9e6ab1d83b7c78878ceffc69c/resources/workflow2.jpg
--------------------------------------------------------------------------------
/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Lời đầu tiên, SGUET xin cảm ơn bạn đã quan tâm và dành thời gian đăng ký tham gia BIGGAME 2022. Sau quá trình lọc đơn đăng ký tham gia rất kỹ lưỡng, SGUET xin được chúc mừng bạn đã trở thành chủ nhân của chiếc vé may mắn tham dự sự kiện đặc biệt này.
245 |
BIGGAME 2022 là sự kiện dành cho các tân sinh viên K67 trường Đại học Công nghệ. Sự kiện sẽ kéo dài trong vòng 1 tuần, người tham gia sẽ được tham gia lần lượt những hoạt động hấp dẫn như bonding, chơi game online, giải đáp thắc mắc, tâm sự chuyện đại học,.. đây đều là các trải nghiệm thú vị được diễn ra dưới sự hướng dẫn của các supporter và Ban tổ chức. Điểm nhấn của Tuần Biggame này sẽ là 2 sự kiện: talkshow “A Step Forward” và hội chính “Biggame: The Ancient Code”.
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | for (var i = 0; i < stockData.length+3; i++) { ?>
255 | Timeline của sự kiện: } ?>
256 |
257 |
258 |
🔹Các hoạt động bonding, làm quen, giao lưu onl/offline của các team sẽ diễn ra từ chiều nay.
259 |
🔹Các minigame sẽ được tổ chức trên group facebook Big Game 2022
Hãy nhanh tay lưu lại chiếc vé này để có thể tham gia check-in vào các sự kiện nhé. Việc cần làm của bạn ngay bây giờ chuẩn bị cho mình một tâm hồn đẹp để giao lưu cùng các diễn giả trong ngày Talkshow và hòa mình vào cổ ngữ Rune độc đáo trong ngày Hội chính. Đặc biệt, người tham gia sẽ có một phần quà đặc biệt, vì vậy hãy nhanh chóng follow SGUET để có thể cập nhật thông tin nhanh và chính xác nhất.