Repository navigation
Database and Storage
bearnannan edited this page Sep 6, 2026
·
1 revision
เอกสารนี้ระบุโครงสร้างฐานข้อมูล Supabase PostgreSQL กลไกความปลอดภัย Row-Level Security (RLS) การจัดการธุรกรรมแบบอะตอมมิก (Atomic Concurrency) และการจัดเก็บไฟล์บน Cloudflare R2
erDiagram
ITEMS ||--o{ TRANSACTIONS : "records in"
ITEMS ||--o{ KIT_ITEMS : "composed in"
KITS ||--|{ KIT_ITEMS : "contains"
ITEMS ||--o{ BORROW_RECORDS : "tracks serial"
TRANSACTIONS ||--o| APPROVALS : "requires"
ITEMS {
uuid id PK
varchar sku UK
varchar barcode
varchar name
text description
varchar category
varchar unit
integer quantity
integer min_stock
varchar location
numeric unit_price
text image_url
timestamptz updated_at
}
TRANSACTIONS {
uuid id PK
varchar reference_no UK
uuid item_id FK
varchar type "IN | OUT | ADJUST"
integer quantity
integer balance_after
varchar job_site
uuid created_by
varchar status "PENDING | APPROVED | COMPLETED | REJECTED"
timestamptz created_at
}
KITS {
uuid id PK
varchar code UK
varchar name
varchar site_type
boolean is_active
}
KIT_ITEMS {
uuid id PK
uuid kit_id FK
uuid item_id FK
integer default_quantity
}
BORROW_RECORDS {
uuid id PK
uuid item_id FK
varchar serial_no
varchar borrower_name
varchar borrower_dept
timestamptz borrowed_at
timestamptz expected_return
varchar status "BORROWED | RETURNED | OVERDUE"
text condition_image_url
}
ทุกตารางในฐานข้อมูลเปิดใช้งาน RLS อย่างเคร่งครัด (ALTER TABLE <table_name> ENABLE ROW LEVEL SECURITY;):
-
ตาราง
items:- ทุกคนที่ผ่านการยืนยันตัวตน (
authenticated) สามารถอ่าน (SELECT) ได้ - เฉพาะ Role
adminและstaffเท่านั้นที่สามารถเพิ่ม แก้ไข หรือลบ (INSERT,UPDATE,DELETE)
- ทุกคนที่ผ่านการยืนยันตัวตน (
-
ตาราง
transactions:- ผู้ใช้งานทั่วไปสามารถดูประวัติคำขอของตนเองได้
-
adminและmanagerสามารถดูรายการทั้งหมดในองค์กรได้
-
ตาราง
approvals:- ผู้อนุมัติ (
managerหรือadmin) เท่านั้นที่มีสิทธิ์UPDATEสถานะการอนุมัติ
- ผู้อนุมัติ (
เพื่อป้องกันปัญหาการเบิกสินค้าพร้อมกันจนสต็อกติดลบ การตัดสต็อกทั้งหมดดำเนินการผ่าน Stored Procedure ใน Supabase:
CREATE OR REPLACE FUNCTION process_stock_out(
p_item_id UUID,
p_quantity INT,
p_job_site TEXT,
p_user_id UUID
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_current_stock INT;
v_new_stock INT;
v_tx_id UUID;
BEGIN
-- 1. ล็อกแถวข้อมูลเพื่อป้องกันธุรกรรมอื่นแทรก (Row-level locking)
SELECT quantity INTO v_current_stock
FROM items
WHERE id = p_item_id
FOR UPDATE;
-- 2. ตรวจสอบสต็อกคงเหลือ
IF v_current_stock < p_quantity THEN
RAISE EXCEPTION 'สต็อกไม่เพียงพอ: คงเหลือ %, ต้องการ %', v_current_stock, p_quantity;
END IF;
-- 3. คำนวณยอดคงเหลือใหม่
v_new_stock := v_current_stock - p_quantity;
-- 4. บันทึกยอดสต็อกใหม่
UPDATE items
SET quantity = v_new_stock, updated_at = NOW()
WHERE id = p_item_id;
-- 5. บันทึก Transaction
INSERT INTO transactions (item_id, type, quantity, balance_after, job_site, created_by)
VALUES (p_item_id, 'OUT', p_quantity, v_new_stock, p_job_site, p_user_id)
RETURNING id INTO v_tx_id;
RETURN jsonb_build_object('success', true, 'transaction_id', v_tx_id, 'remaining_stock', v_new_stock);
END;
$$;Important
สังเกตการใช้ SECURITY DEFINER คู่กับ SET search_path = public เสมอ เพื่อป้องกันช่องโหว่ Search Path Hijacking ตามมาตรฐาน PostgreSQL Security Best Practices
ระบบใช้ Cloudflare R2 สำหรับการจัดเก็บรูปภาพพัสดุและภาพหลักฐาน โดยใช้โปรโตคอล AWS S3 Compatible API:
-
items/{sku}/{hash}.jpg— ภาพถ่ายประจำตัวสินค้า/พัสดุ -
evidence/{year}/{month}/{tx_id}.jpg— ภาพถ่ายสภาพเครื่องมือขณะส่งมอบหรือรับคืน -
receipts/{tx_id}.pdf— ใบเบิกจ่ายหรือสลิปพัสดุฉบับดิจิทัล
ต้องตั้งค่า CORS บน Cloudflare Dashboard เพื่อให้ Frontend อัปโหลดไฟล์ได้โดยตรง:
[
{
"AllowedOrigins": [
"https://stockflowth.online",
"https://eemeemmeex.github.io",
"http://localhost:5173"
],
"AllowedMethods": ["GET", "PUT", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]- Architecture — การเชื่อมต่อของเลเยอร์ต่างๆ
- Security — สิทธิ์และการควบคุมผู้ใช้งาน
Stock-Flow Enterprise OS • พัฒนาขึ้นสำหรับ บริษัท ฟอร์ท คอร์ปอเรชั่น จำกัด (มหาชน) • Current System Version:
v1.4.76