Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions CHECKLIST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Unit Test Checklist

## 1. **General Structure**
### 1.1 Test Case Pattern
- **Test Case Format**:
- **Test Case Title**: Tên test case, mô tả ngắn gọn về mục tiêu của test.
- **Preconditions**: Các điều kiện cần thiết trước khi chạy test (data, trạng thái hệ thống,...).
- **Test Steps**: Các bước thực hiện test chi tiết.
- **Expected Result**: Kết quả mong đợi sau khi thực hiện test case.

### 1.2 Categories of Test Cases
- **Positive Test Cases**: Kiểm tra các tình huống hệ thống hoạt động đúng với dữ liệu hợp lệ.
- **Negative Test Cases**: Kiểm tra các tình huống khi hệ thống gặp lỗi hoặc dữ liệu không hợp lệ.
- **Edge Cases**: Kiểm tra các trường hợp biên, dữ liệu cực trị hoặc các tình huống bất thường.
- **Exception Handling**: Kiểm tra các tình huống xảy ra lỗi, exception được xử lý đúng.
- **Performance**: Kiểm tra hiệu suất, tốc độ xử lý của hệ thống trong các tình huống khối lượng lớn.

---

## 2. **Test Case Details**

### ✅ **Test Case 1: process_orders(user_id)**
- **Preconditions**:
- Có ít nhất một đơn hàng hợp lệ trong hệ thống.
- **Test Steps**:
- Gọi `process_orders(user_id)`.
- **Expected Result**:
- Trả về `true` nếu tất cả các đơn hàng được xử lý thành công.

---

### ✅ **Test Case 2: process_order(order, user_id)**
#### **2.1 Khi order type là 'A'**
- **Preconditions**:
- `order.type = 'A'` và đơn hàng có amount hợp lệ.
- **Test Steps**:
- Gọi `process_order(order, user_id)`.
- **Expected Result**:
- Nếu CSV tạo thành công, cập nhật `order.status = 'exported'`.

#### **2.2 Khi order type là 'B'**
- **Preconditions**:
- `order.type = 'B'` và API trả về kết quả hợp lệ.
- **Test Steps**:
- Gọi `process_order(order, user_id)`.
- **Expected Result**:
- Cập nhật trạng thái của `order` dựa trên dữ liệu trả về từ API (processed, pending, error).

#### **2.3 Khi order type không xác định**
- **Preconditions**:
- `order.type` không thuộc loại `A`, `B`, `C`.
- **Test Steps**:
- Gọi `process_order(order, user_id)`.
- **Expected Result**:
- Cập nhật trạng thái `order.status = 'unknown_type'`.

---

### ✅ **Test Case 3: update_priority(order)**
- **Preconditions**:
- `order.amount` có giá trị khác nhau (lớn hơn và nhỏ hơn 200).
- **Test Steps**:
- Gọi `update_priority(order)`.
- **Expected Result**:
- Nếu `order.amount > 200`, cập nhật `order.priority = 'high'`.
- Nếu `order.amount <= 200`, cập nhật `order.priority = 'low'`.

---

### ✅ **Test Case 4: save_order(order)**
- **Preconditions**:
- Đơn hàng có trạng thái hợp lệ và chưa lưu vào cơ sở dữ liệu.
- **Test Steps**:
- Gọi `save_order(order)`.
- **Expected Result**:
- Đơn hàng được lưu mà không có lỗi, trạng thái không thay đổi thành `'db_error'`.

#### **4.1 Trường hợp Database exception**
- **Preconditions**:
- Gây ra exception trong quá trình lưu trữ (`DatabaseException`).
- **Test Steps**:
- Gọi `save_order(order)`.
- **Expected Result**:
- Đơn hàng sẽ có `status = 'db_error'`.

---

### ✅ **Test Case 5: csv_generate(order, user_id)**
- **Preconditions**:
- `order.type = 'A'`, `csv_generate` được gọi với các tham số hợp lệ.
- **Test Steps**:
- Gọi `csv_generate(order, user_id)`.
- **Expected Result**:
- Tạo file CSV với các dữ liệu của `order`, bao gồm các trường như ID, Type, Amount, Flag, Status, Priority.

#### **5.1 Trường hợp đơn hàng có giá trị cao**
- **Preconditions**:
- `order.amount > 150`.
- **Test Steps**:
- Gọi `csv_generate(order, user_id)`.
- **Expected Result**:
- CSV bao gồm dòng `['', '', '', '', 'Note', 'High value order']`.

---
6 changes: 6 additions & 0 deletions app/models/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Order < ApplicationRecord
enum status: { new_order: 0, exported: 1, export_failed: 2, processed: 3, pending: 4, error: 5, api_error: 6, api_failure: 7, completed: 8, in_progress: 9, unknown_type: 10, db_error: 11 }
enum priority: { low: 0, high: 1 }

self.inheritance_column = :sti_type
end
90 changes: 90 additions & 0 deletions app/services/order_processing_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
class APIException < StandardError; end

class DatabaseException < StandardError; end

class OrderProcessingService
def initialize(api_client)
@api_client = api_client
end

def process_orders(user_id)
orders = Order.where(user_id: user_id)
return false if orders.empty?

orders.each do |order|
process_order(order, user_id)
update_priority(order)
save_order(order)
end
true
rescue StandardError
false
end

private

def process_order(order, user_id)
case order.type
when "A"
process_type_a(order, user_id)
when "B"
process_type_b(order)
when "C"
process_type_c(order)
else
order.update(status: :unknown_type)
end
end

def process_type_a(order, user_id)
begin
csv_generate(order, user_id)
order.update(status: :exported)
rescue StandardError
order.update(status: :export_failed)
end
end

def process_type_b(order)
begin
response = @api_client.call_api(order.id)
if response.status == "success"
if response.data >= 50 && order.amount < 100
order.update(status: :processed)
elsif response.data < 50 || order.flag
order.update(status: :pending)
else
order.update(status: :error)
end
else
order.update(status: :api_error)
end
rescue APIException
order.update(status: :api_failure)
end
end

def process_type_c(order)
order.update(status: order.flag ? :completed : :in_progress)
end

def csv_generate(order, user_id)
csv_file_path = "orders_type_A_#{user_id}_#{Time.now.to_i}.csv"

CSV.open(csv_file_path, "w") do |csv|
csv << ["ID", "Type", "Amount", "Flag", "Status", "Priority"]
csv << [order.id, order.type, order.amount, order.flag, order.status, order.priority]
csv << ["", "", "", "", "Note", "High value order"] if order.amount > 150
end
end

def update_priority(order)
order.update(priority: order.amount > 200 ? :high : :low)
end

def save_order(order)
order.save!
rescue DatabaseException
order.update(status: :db_error)
end
end
14 changes: 14 additions & 0 deletions db/migrate/20250403135748_create_orders.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateOrders < ActiveRecord::Migration[7.0]
def change
create_table :orders do |t|
t.references :user, foreign_key: true, null: false
t.string :type, null: false
t.integer :amount, null: false
t.boolean :flag, default: false
t.integer :status, default: 0, null: false
t.integer :priority, default: 0, null: false

t.timestamps
end
end
end
15 changes: 14 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions spec/factories/orders.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FactoryBot.define do
factory :order do
user_id { 123 }
type { 'A' }
amount { 100 }
flag { false }
status { :new_order }
priority { :low }
end
end
Loading