Prerequisites
- โปรเจคตั้งต้นคือโปรเจคนี้
- กำหนดให้ส่งลิ้งค์คำตอบคือ github repository ที่เก็บโค้ดของคุณ
https://github.com/<your github name>/assessment
- MUST use go module
- MUST use PostgreSQL
- NEED to create table named
expenses
when start the application if not exist - MUST use go module
go mod init github.com/<your github name>/assessment
- MUST use go 1.18 or above
- api port MUST get from environment variable name
PORT
(should be able to config for api start from port:2565
) - database url MUST get from environment variable name
DATABASE_URL
Business Requirements
- Expense tracking system
- ให้สร้างระบบ REST API เพื่อจัดเก็บประวัติการใช้จ่าย (expense) ของลูกค้าธนาคาร ซึ่งความสามารถระบบมีดังนี้
- ระบบสามารถจัดเก็บข้อมูล เรื่อง(title), ยอดค่าใช้จ่าย(amount), บันทึกย่อ(note) และ หมวดหมู่(tags)
- ระบบสามารถเพิ่มประวัติการใช้จ่ายใหม่ได้
- ระบบสามารถปรับเปลี่ยน/แก้ไข ข้อมูลของการใช้จ่ายได้
- ระบบสามารถดึงข้อมูลการใช้จ่ายทั้งหมดออกมาแสดงได้
- ระบบสามารถดึงข้อมูลการใช้จ่ายทีละรายการได้
User Stories
Story: EXP01
* As a user, I want to add a new expense So that I can track my expenses
* ในฐานะผู้ใช้ ฉันต้องการเพิ่มประวัติการใช้จ่ายใหม่ เพื่อที่จะติดตามประวัติการใช้จ่ายของฉัน
Technical Details: EXP01
- POST /expenses
- Request Body
{
"title": "strawberry smoothie",
"amount": 79,
"note": "night market promotion discount 10 bath",
"tags": ["food", "beverage"]
}
- Response Body
{
"id": "1",
"title": "strawberry smoothie",
"amount": 79,
"note": "night market promotion discount 10 bath",
"tags": ["food", "beverage"]
}
Story: EXP02
* As a user, I want to see my expense by using expense ID So that I can check my expense information
* ในฐานะผู้ใช้ ฉันต้องการดูข้อมูลประวัติการใช้จ่ายของฉันโดยใช้รหัสประวัติการใช้จ่าย เพื่อที่จะตรวจสอบข้อมูลประวัติการใช้จ่ายของฉัน
Technical Details: EXP02
- GET /expenses/:id
- :id = 1
- Response Body
{
"id": "1",
"title": "strawberry smoothie",
"amount": 79,
"note": "night market promotion discount 10 bath",
"tags": ["food", "beverage"]
}
Story: EXP03
* As a user, I want to update my expense So that I can correct my expense information
* ในฐานะผู้ใช้ ฉันต้องการปรับปรุงข้อมูลประวัติการใช้จ่ายของฉัน เพื่อที่จะแก้ไขข้อมูลประวัติการใช้จ่ายของฉัน
Technical Details: EXP03
- PUT /expenses/:id
- :id = 1
- Request Body
{
"title": "apple smoothie",
"amount": 89,
"note": "no discount",
"tags": ["beverage"]
}
- Response Body
{
"id": "1",
"title": "apple smoothie",
"amount": 89,
"note": "no discount",
"tags": ["beverage"]
}
Story: EXP04
* As a user, I want to see all my expenses So that I can check my expense information
* ในฐานะผู้ใช้ ฉันต้องการดูข้อมูลประวัติการใช้จ่ายทั้งหมดของฉัน เพื่อที่จะตรวจสอบข้อมูลประวัติการใช้จ่ายของฉัน
Technical Details: EXP04
- GET /expenses
- Response Body
[
{
"id": "1",
"title": "apple smoothie",
"amount": 89,
"note": "no discount",
"tags": ["beverage"]
},
{
"id": "2",
"title": "iPhone 14 Pro Max 1TB",
"amount": 66900,
"note": "birthday gift from my love",
"tags": ["gadget"]
}
]
Technical Requirements
-
ใช้ภาษา Go สำหรับการพัฒนา
-
ใช้ PostgreSQL สำหรับเก็บข้อมูล
-
ใช้ go module สำหรับการจัดการ package
-
ใช้ go 1.18 ขึ้นไป
-
":2565" ใช้เป็น port ของ api server
-
ชื่อโปรเจคของคุณต้องเป็น assessment
-
ระบบต้องออกแบบตามมาตรฐาน REST API
- POST /expenses
- GET /expenses/:id
- PUT /expenses/:id
- GET /expenses
Hints
- ทำทีละ story โดยเริ่มจาก story แรกแล้วทำเรียงตามลำดับ
os.Getenv("PORT")
ใช้เพื่อรับค่า port จาก environment variableos.Getenv("DATABASE_URL")
ใช้เพื่อรับค่า database url จาก environment variable- เวลารัน
DATABASE_URL=postgres://... PORT=:2565 go run server.go
pq.Array(&tags)
is used to convert []string to postgres array- script to create table
CREATE TABLE IF NOT EXISTS expenses (
id SERIAL PRIMARY KEY,
title TEXT,
amount FLOAT,
note TEXT,
tags TEXT[]
);
- example data
{
"title": "buy a new phone",
"amount": 39000,
"note": "buy a new phone",
"tags": ["gadget", "shopping"]
}
- example response
{
"id": 1,
"title": "buy a new phone",
"amount": 39000,
"note": "buy a new phone",
"tags": ["gadget", "shopping"]
}
Acceptance Guidelines
- Postman collection สำหรับทดสอบ API ทั้งหมดรันผ่าน
- หลังจาก import postman collection แล้ว อย่าลืมสร้าง postman environment สำหรับเก็บค่าตัวแปรเวลารัน Postman
- กรณี success ต้อง response status code ให้เหมาะสม เช่น
- 201 StatusCreated
- 200 StatusOK
- กรณี error ต่างๆ ให้ระบบ response status code ตามความเหมาะสม เช่น
- 400 StatusBadRequst
- 500 StatusInternalServerError
- API server ควรจะรองรับ Graceful shutdown
- โปรเจคควรรองรับการ build ด้วย docker โดยใช้ multi-stage build เพื่อสะดวกต่อการ deploy
- มีการเขียน unit test, integration test
- สำหรับ integration test สามารถเทคนิค docker-compose testing sandbox ที่เรียนในรายวิชา devops สำหรับรัน postgres ได้เพื่อการทดสอบ
- ซอร์สโค้ดควรจัดรูปแบบด้วย gofmt
- ใช้ความรู้ทุกอย่างที่เรียนมาพร้อมด้วยสิ่งที่ศึกษาเพิ่มเติมเอง
- แต่ละ story ควรใช้ branch ของตัวเองแล้ว merge กลับไปที่ main ด้วย 3-way merge
Setup guildline
Setup infrastructure
- Devlopment
- Create environment variable by using
.env
file that contain the data which show below
- Create environment variable by using
DOMAIN=kkgo_dev.com
DB_DATABASE=expense_db
DB_USER=admin_dev
DB_PASSWORD=4b2d5c67c29ad39dcb60a2ddcf6b0465
DB_PORT=5432
- Start service
docker compose -f docker-compose.dev.yaml -p kkgo-ets-dev up -d
- Down service (optional)
docker compose -f docker-compose.dev.yaml -p kkgo-ets-dev down
- Production
- Create environment variable by using
.env
file that contain the data which show below
- Create environment variable by using
DOMAIN=kkgo_prod.com
IMAGE_NAME=kkgo
VERSION=1.0.0
PORT=2565
DB_DATABASE=expense_db
DB_USER=admin_prod
DB_PASSWORD=a2c3daf674e752878546ce30778171ef
DB_PORT=5432
DB_URL=postgresql://$DB_USER:$DB_PASSWORD@database.$DOMAIN:$DB_PORT/$DB_DATABASE?sslmode=disable
Start service
- Devlopment
- Run the script to start the service
PORT=:2565 DATABASE_URL=postgresql://admin_dev:4b2d5c67c29ad39dcb60a2ddcf6b0465@0.0.0.0:5432/expense_db?sslmode=disable go run app/server.go
- Production
- Start service
docker compose -f docker-compose.yaml -p kkgo-ets-prod up --build -d
- Down service (optional)
docker compose -f docker-compose.yaml -p kkgo-ets-prod down
Testing
- Unit test
- Run unit test
go test -v -tags unit ./...
-
Integration test
- Create environment variable by using
.env
file that contain the data which show below
- Create environment variable by using
DOMAIN=kkgo_test.com
IMAGE_NAME=kkgo
VERSION=1.0.0
PORT=2565
DB_DATABASE=expense_db
DB_USER=admin_test
DB_PASSWORD=418fec5f0f023b7a3f5766e8202f8e1c
DB_PORT=5432
DB_URL=postgresql://$DB_USER:$DB_PASSWORD@database.$DOMAIN:$DB_PORT/$DB_DATABASE?sslmode=disable
-
Run integration test
-
Start service with docker (optional)
docker compose -f docker-compose.test.yaml -p kkgo-ets-test up --build --abort-on-container-exit --exit-code-from expense_tracking
- Down service with docker (optional)
docker compose -f docker-compose.test.yaml -p kkgo-ets-test down