From 240e89475ab101ef1bee7a11f44bb80418972d26 Mon Sep 17 00:00:00 2001
From: Sirapob Lapanakokiat <65160126@go.buu.ac.th>
Date: Wed, 19 Mar 2025 20:39:21 +0700
Subject: [PATCH] Update File

---
 app.js               |   2 +
 database/db.js       |  60 ++++--
 routes/auth.js       |  10 +-
 routes/products.js   | 223 ++++++++++++++++++++--
 routes/stock.js      |  94 ++++++++++
 views/categories.ejs |   4 +-
 views/products.ejs   | 434 ++++++++++++++++++++++++++++++++++---------
 7 files changed, 698 insertions(+), 129 deletions(-)
 create mode 100644 routes/stock.js

diff --git a/app.js b/app.js
index a10f765..8e21428 100644
--- a/app.js
+++ b/app.js
@@ -33,6 +33,7 @@ const authMiddleware = (req, res, next) => {
 const authRoutes = require('./routes/auth');
 const productRoutes = require('./routes/products');
 const categoriesRouter = require('./routes/categories');
+const stockRoutes = require('./routes/stock');
 
 
 app.use('/auth', authRoutes);
@@ -49,6 +50,7 @@ app.get('/', (req, res) => {
 
 app.use('/products', authMiddleware, productRoutes);
 app.use('/categories', authMiddleware, categoriesRouter);
+app.use('/stock', stockRoutes);
 
 app.listen(3000, () => {
     console.log('Server running on port 3000');
diff --git a/database/db.js b/database/db.js
index e084d68..90cf4a6 100644
--- a/database/db.js
+++ b/database/db.js
@@ -2,10 +2,10 @@ const mysql = require('mysql2');
 const path = require('path');
 
 const db = mysql.createConnection({
-    host: 'localhost' || "10.104.22.31",
-    port: 3306,
+    host: 'localhost',
+    port: '3306',
     user: 'root',         
-    password: '' || "MAXrkt06755",         
+    password: '',         
     database: 'Project'
 });
 
@@ -17,7 +17,7 @@ db.connect((err) => {
     console.log('Connected to MySQL database');
 });
 
-// Create tables
+
 db.query(`CREATE TABLE IF NOT EXISTS users (
     id INT PRIMARY KEY AUTO_INCREMENT,
     username VARCHAR(255) UNIQUE,
@@ -33,19 +33,47 @@ db.query(`CREATE TABLE IF NOT EXISTS categories (
     if (err) console.error('Error creating categories table:', err);
 });
 
-db.query(`CREATE TABLE IF NOT EXISTS products (
-    id INT PRIMARY KEY AUTO_INCREMENT,
-    name VARCHAR(255),
-    price DECIMAL(10,2),
-    category_id INT,
-    user_id INT,
-    FOREIGN KEY (category_id) REFERENCES categories(id),
-    FOREIGN KEY (user_id) REFERENCES users(id)
-)`, (err) => {
-    if (err) console.error('Error creating products table:', err);
-});
 
+db.query(`DROP TABLE IF EXISTS stock_movements`, (err) => {
+    if (err) console.error('Error dropping stock_movements table:', err);
+    
+    
+    db.query(`DROP TABLE IF EXISTS products`, (err) => {
+        if (err) console.error('Error dropping products table:', err);
+        
+       
+        db.query(`CREATE TABLE IF NOT EXISTS products (
+            id INT PRIMARY KEY AUTO_INCREMENT,
+            name VARCHAR(255),
+            price DECIMAL(10,2),
+            stock_quantity INT DEFAULT 0,
+            minimum_stock INT DEFAULT 0,
+            location VARCHAR(255),
+            last_restock_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+            category_id INT,
+            user_id INT,
+            FOREIGN KEY (category_id) REFERENCES categories(id),
+            FOREIGN KEY (user_id) REFERENCES users(id)
+        )`, (err) => {
+            if (err) console.error('Error creating products table:', err);
+            
+                
+            db.query(`CREATE TABLE IF NOT EXISTS stock_movements (
+                id INT PRIMARY KEY AUTO_INCREMENT,
+                product_id INT,
+                quantity INT,
+                type ENUM('in', 'out'),
+                date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+                user_id INT,
+                description TEXT,
+                FOREIGN KEY (product_id) REFERENCES products(id),
+                FOREIGN KEY (user_id) REFERENCES users(id)
+            )`, (err) => {
+                if (err) console.error('Error creating stock_movements table:', err);
+            });
+        });
+    });
+});
 
 const promiseDb = db.promise();
-
 module.exports = promiseDb;
\ No newline at end of file
diff --git a/routes/auth.js b/routes/auth.js
index d6da6db..ba407c3 100644
--- a/routes/auth.js
+++ b/routes/auth.js
@@ -11,7 +11,7 @@ router.get('/register', (req, res) => {
 router.post('/register', async (req, res) => {
     try {
         const { username, password } = req.body;
-        // Check if username exists
+     
         const [existingUsers] = await db.query(
             'SELECT * FROM users WHERE username = ?', 
             [username]
@@ -35,12 +35,12 @@ router.post('/register', async (req, res) => {
     }
 });
 
-// Login page route
+
 router.get('/login', (req, res) => {
     res.render('login');
 });
 
-// Login post route
+
 router.post('/login', async (req, res) => {
     try {
         const { username, password } = req.body;
@@ -58,7 +58,7 @@ router.post('/login', async (req, res) => {
         const match = await bcrypt.compare(password, user.password);
         
         if (match) {
-            // Create session
+           
             req.session.userId = user.id;
             req.session.username = user.username;
             res.redirect('/products');
@@ -71,7 +71,7 @@ router.post('/login', async (req, res) => {
     }
 });
 
-// Logout route
+
 router.get('/logout', (req, res) => {
     req.session.destroy((err) => {
         if (err) {
diff --git a/routes/products.js b/routes/products.js
index b8550d4..a11fa05 100644
--- a/routes/products.js
+++ b/routes/products.js
@@ -15,26 +15,44 @@ const isAuthenticated = (req, res, next) => {
 router.get('/', isAuthenticated, async (req, res) => {
     try {
         const { search } = req.query;
+        
+        // Build query with search condition
         let sql = `
-            SELECT p.*, c.name as category_name, u.username as created_by
-            FROM products p 
+            SELECT p.*, c.name as category_name 
+            FROM products p
             LEFT JOIN categories c ON p.category_id = c.id
-            LEFT JOIN users u ON p.user_id = u.id
         `;
         
         let params = [];
         if (search) {
-            sql += ` WHERE p.name LIKE ?`;
-            params.push(`%${search}%`);
+            sql += ` WHERE p.name LIKE ? OR p.location LIKE ?`;
+            params = [`%${search}%`, `%${search}%`];
         }
         
+        // Execute query
         const [products] = await db.query(sql, params);
         const [categories] = await db.query('SELECT * FROM categories');
+
+        // Add helper function to be available in template
+        const getStockStatus = (current, minimum) => {
+            current = parseInt(current) || 0;
+            minimum = parseInt(minimum) || 0;
+            
+            if (current <= 0) {
+                return { text: 'หมด', class: 'status-out' };
+            }
+            if (current <= minimum) {
+                return { text: 'ต่ำ', class: 'status-low' };
+            }
+            return { text: 'ปกติ', class: 'status-normal' };
+        };
         
+        // Pass search value back to template
         res.render('products', { 
             products, 
             categories,
-            userId: req.session.userId 
+            searchQuery: search || '',
+            getStockStatus // Pass the function to the template
         });
     } catch (err) {
         console.error(err);
@@ -45,10 +63,34 @@ router.get('/', isAuthenticated, async (req, res) => {
 // Add product
 router.post('/', isAuthenticated, async (req, res) => {
     try {
-        const { name, price, category_id } = req.body;
+        const { 
+            name, 
+            price, 
+            stock_quantity, 
+            minimum_stock, 
+            location, 
+            category_id 
+        } = req.body;
+
         await db.query(
-            'INSERT INTO products (name, price, category_id, user_id) VALUES (?, ?, ?, ?)',
-            [name, price, category_id, req.session.userId]
+            `INSERT INTO products (
+                name, 
+                price, 
+                stock_quantity, 
+                minimum_stock, 
+                location, 
+                category_id, 
+                user_id
+            ) VALUES (?, ?, ?, ?, ?, ?, ?)`,
+            [
+                name, 
+                price, 
+                stock_quantity || 0, 
+                minimum_stock || 0, 
+                location || '', 
+                category_id,
+                req.session.userId
+            ]
         );
         res.redirect('/products');
     } catch (err) {
@@ -57,18 +99,83 @@ router.post('/', isAuthenticated, async (req, res) => {
     }
 });
 
+// Get edit form
+router.get('/edit/:id', isAuthenticated, async (req, res) => {
+    try {
+        const [products] = await db.query(
+            'SELECT * FROM products WHERE id = ?', 
+            [req.params.id]
+        );
+        const [categories] = await db.query('SELECT * FROM categories');
+
+        if (products.length === 0) {
+            return res.status(404).send('Product not found');
+        }
+
+        res.render('edit-product', { 
+            product: products[0],
+            categories: categories 
+        });
+    } catch (err) {
+        console.error(err);
+        res.status(500).json({ error: 'Database error' });
+    }
+});
+
+// Get product by ID
+router.get('/:id', isAuthenticated, async (req, res) => {
+    try {
+        const [products] = await db.query(
+            'SELECT * FROM products WHERE id = ?', 
+            [req.params.id]
+        );
+        
+        if (products.length === 0) {
+            return res.status(404).json({ error: 'Product not found' });
+        }
+        
+        res.json(products[0]);
+    } catch (err) {
+        console.error(err);
+        res.status(500).json({ error: 'Database error' });
+    }
+});
+
 // Update product
 router.put('/:id', isAuthenticated, async (req, res) => {
     try {
-        const { name, price, category_id } = req.body;
-        await db.query(
-            'UPDATE products SET name = ?, price = ?, category_id = ? WHERE id = ?',
-            [name, price, category_id, req.params.id]
-        );
+        const { 
+            name, 
+            price, 
+            stock_quantity, 
+            minimum_stock, 
+            location, 
+            category_id 
+        } = req.body;
+
+        await db.query(`
+            UPDATE products 
+            SET name = ?, 
+                price = ?, 
+                stock_quantity = ?,
+                minimum_stock = ?,
+                location = ?,
+                category_id = ?
+            WHERE id = ?
+        `, [
+            name, 
+            price, 
+            stock_quantity, 
+            minimum_stock, 
+            location, 
+            category_id, 
+            req.params.id
+        ]);
+
         res.json({ message: 'Product updated successfully' });
     } catch (err) {
         console.error(err);
-        res.status(400).json({ error: 'Error updating product' });
+        res.status(500).json({ error: 'Database error' });
     }
 });
 
@@ -83,4 +190,90 @@ router.delete('/:id', isAuthenticated, async (req, res) => {
     }
 });
 
+// เพิ่มสต็อก
+router.post('/stock/add', isAuthenticated, async (req, res) => {
+    try {
+        const { product_id, quantity, description } = req.body;
+        
+        await db.query('START TRANSACTION');
+        
+        // บันทึกการเพิ่มสต็อก
+        await db.query(
+            'INSERT INTO stock_movements (product_id, quantity, type, user_id, description) VALUES (?, ?, "in", ?, ?)',
+            [product_id, quantity, req.session.userId, description]
+        );
+        
+        // อัพเดตจำนวนสต็อก
+        await db.query(
+            'UPDATE products SET stock_quantity = stock_quantity + ? WHERE id = ?',
+            [quantity, product_id]
+        );
+        
+        await db.query('COMMIT');
+        res.json({ message: 'Stock added successfully' });
+    } catch (err) {
+        await db.query('ROLLBACK');
+        console.error(err);
+        res.status(400).json({ error: 'Error adding stock' });
+    }
+});
+
+// ตัดสต็อก
+router.post('/stock/remove', isAuthenticated, async (req, res) => {
+    try {
+        const { product_id, quantity, description } = req.body;
+        
+        await db.query('START TRANSACTION');
+        
+        // ตรวจสอบจำนวนสต็อก
+        const [product] = await db.query(
+            'SELECT stock_quantity FROM products WHERE id = ?',
+            [product_id]
+        );
+        
+        if (product[0].stock_quantity < quantity) {
+            await db.query('ROLLBACK');
+            return res.status(400).json({ error: 'Insufficient stock' });
+        }
+        
+        // บันทึกการตัดสต็อก
+        await db.query(
+            'INSERT INTO stock_movements (product_id, quantity, type, user_id, description) VALUES (?, ?, "out", ?, ?)',
+            [product_id, quantity, req.session.userId, description]
+        );
+        
+        // อัพเดตจำนวนสต็อก
+        await db.query(
+            'UPDATE products SET stock_quantity = stock_quantity - ? WHERE id = ?',
+            [quantity, product_id]
+        );
+        
+        await db.query('COMMIT');
+        res.json({ message: 'Stock removed successfully' });
+    } catch (err) {
+        await db.query('ROLLBACK');
+        console.error(err);
+        res.status(400).json({ error: 'Error removing stock' });
+    }
+});
+
+// ดูประวัติการเคลื่อนไหวของสต็อก
+router.get('/stock/history/:productId', isAuthenticated, async (req, res) => {
+    try {
+        const [movements] = await db.query(`
+            SELECT sm.*, u.username, p.name as product_name
+            FROM stock_movements sm
+            JOIN users u ON sm.user_id = u.id
+            JOIN products p ON sm.product_id = p.id
+            WHERE sm.product_id = ?
+            ORDER BY sm.date DESC
+        `, [req.params.productId]);
+        
+        res.json(movements);
+    } catch (err) {
+        console.error(err);
+        res.status(500).json({ error: 'Error fetching stock history' });
+    }
+});
+
 module.exports = router;
\ No newline at end of file
diff --git a/routes/stock.js b/routes/stock.js
new file mode 100644
index 0000000..fe00590
--- /dev/null
+++ b/routes/stock.js
@@ -0,0 +1,94 @@
+const express = require('express');
+const router = express.Router();
+const db = require('../database/db');
+
+// เพิ่มสต็อก (รับสินค้าเข้า)
+router.post('/add', async (req, res) => {
+    try {
+        const { product_id, quantity, description } = req.body;
+        
+        await db.query('START TRANSACTION');
+
+        // บันทึกการเคลื่อนไหว
+        await db.query(
+            'INSERT INTO stock_movements (product_id, quantity, type, user_id, description) VALUES (?, ?, "in", ?, ?)',
+            [product_id, quantity, req.session.userId, description]
+        );
+
+        // อัพเดตจำนวนสต็อก
+        await db.query(
+            'UPDATE products SET stock_quantity = stock_quantity + ?, last_restock_date = CURRENT_TIMESTAMP WHERE id = ?',
+            [quantity, product_id]
+        );
+
+        await db.query('COMMIT');
+        res.json({ success: true });
+    } catch (err) {
+        await db.query('ROLLBACK');
+        console.error(err);
+        res.status(500).json({ error: 'Database error' });
+    }
+});
+
+// ตัดสต็อก (เบิกสินค้าออก)
+router.post('/remove', async (req, res) => {
+    try {
+        const { product_id, quantity, description } = req.body;
+
+        await db.query('START TRANSACTION');
+
+        // ตรวจสอบสต็อกคงเหลือ
+        const [product] = await db.query(
+            'SELECT stock_quantity FROM products WHERE id = ?',
+            [product_id]
+        );
+
+        if (product[0].stock_quantity < quantity) {
+            await db.query('ROLLBACK');
+            return res.status(400).json({ error: 'สินค้าในสต็อกไม่เพียงพอ' });
+        }
+
+        // บันทึกการเคลื่อนไหว
+        await db.query(
+            'INSERT INTO stock_movements (product_id, quantity, type, user_id, description) VALUES (?, ?, "out", ?, ?)',
+            [product_id, quantity, req.session.userId, description]
+        );
+
+        // อัพเดตจำนวนสต็อก
+        await db.query(
+            'UPDATE products SET stock_quantity = stock_quantity - ? WHERE id = ?',
+            [quantity, product_id]
+        );
+
+        await db.query('COMMIT');
+        res.json({ success: true });
+    } catch (err) {
+        await db.query('ROLLBACK');
+        console.error(err);
+        res.status(500).json({ error: 'Database error' });
+    }
+});
+
+// ดูประวัติการเคลื่อนไหวของสินค้า
+router.get('/history/:productId', async (req, res) => {
+    try {
+        const [movements] = await db.query(`
+            SELECT 
+                sm.*,
+                p.name as product_name,
+                u.username as user_name
+            FROM stock_movements sm
+            JOIN products p ON sm.product_id = p.id
+            JOIN users u ON sm.user_id = u.id
+            WHERE sm.product_id = ?
+            ORDER BY sm.date DESC
+        `, [req.params.productId]);
+
+        res.json(movements);
+    } catch (err) {
+        console.error(err);
+        res.status(500).json({ error: 'Database error' });
+    }
+});
+
+module.exports = router;
\ No newline at end of file
diff --git a/views/categories.ejs b/views/categories.ejs
index 97b0d56..7dad304 100644
--- a/views/categories.ejs
+++ b/views/categories.ejs
@@ -33,8 +33,8 @@
                     <tr>
                         <td><%= category.name %></td>
                         <td>
-                            <button onclick="editCategory(<%= category.id %>)" class="edit-btn">แก้ไข</button>
-                            <button onclick="deleteCategory(<%= category.id %>)" class="delete-btn">ลบ</button>
+                            <button onclick="editCategory('<%= category.id %>')" class="edit-btn">แก้ไข</button>
+                            <button onclick="deleteCategory('<%= category.id %>')" class="delete-btn">ลบ</button>
                         </td>
                     </tr>
                 <% }); %>
diff --git a/views/products.ejs b/views/products.ejs
index d54cc1d..fd50d82 100644
--- a/views/products.ejs
+++ b/views/products.ejs
@@ -3,133 +3,349 @@
 <head>
     <title>จัดการสินค้า</title>
     <link rel="stylesheet" href="/css/style.css">
+    <script>
+        // Define getStockStatus function first
+        function getStockStatus(current, minimum) {
+            current = parseInt(current) || 0;
+            minimum = parseInt(minimum) || 0;
+            
+            if (current <= 0) {
+                return { text: 'หมด', class: 'status-out' };
+            }
+            if (current <= minimum) {
+                return { text: 'ต่ำ', class: 'status-low' };
+            }
+            return { text: 'ปกติ', class: 'status-normal' };
+        }
+    </script>
 </head>
 <body>
     <div class="container">
+        <!-- ส่วนหัว -->
         <div class="header">
-            <h1>จัดการสินค้า</h1>
+            <h1>จัดการสต็อกสินค้า</h1>
             <nav>
-                <a href="/categories" class="nav-link">จัดการหมวดหมู่</a>
+                <a href="/categories">จัดการหมวดหมู่</a>
                 <a href="/auth/logout" class="logout-btn">ออกจากระบบ</a>
             </nav>
         </div>
 
        
-        <form action="/products" method="GET" class="search-form">
-            <input type="text" name="search" placeholder="ค้นหาสินค้า">
-            <button type="submit">ค้นหา</button>
-        </form>
+        <!-- แก้ไขส่วนค้นหา -->
+        <div class="search-section">
+            <form action="/products" method="GET" class="search-form">
+                <input 
+                    type="text" 
+                    name="search"   
+                    placeholder="ค้นหาสินค้า" 
+                    value="<%= searchQuery %>"
+                >
+                <button type="submit">ค้นหา</button>
+                <% if (searchQuery) { %>
+                    <a href="/products" class="clear-search">ล้างการค้นหา</a>
+                <% } %>
+            </form>
+        </div>
 
-    
-        <form action="/products" method="POST" class="product-form">
-            <input type="text" name="name" placeholder="ชื่อสินค้า" required>
-            <input type="number" name="price" placeholder="ราคา" required>
-            <select name="category_id" required>
-                <option value="">เลือกหมวดหมู่</option>
-                <% categories.forEach(category => { %>
-                    <option value="<%= category.id %>"><%= category.name %></option>
-                <% }); %>
-            </select>
-            <button type="submit">เพิ่มสินค้า</button>
-        </form>
-
-        <table>
-            <thead>
-                <tr>
-                    <th>ชื่อสินค้า</th>
-                    <th>ราคา</th>
-                    <th>หมวดหมู่</th>
-                    <th>ผู้สร้าง</th>
-                    <th>จัดการ</th>
-                </tr>
-            </thead>
-            <tbody>
-                <% products.forEach(product => { %>
+        <!-- เพิ่มสินค้า -->
+        <div class="add-product-section">
+            <form action="/products" method="POST">
+                <div class="form-row">
+                    <input type="text" name="name" placeholder="ชื่อสินค้า" required>
+                    <input type="number" name="price" placeholder="ราคา" required>
+                </div>
+                <div class="form-row">
+                    <input type="number" name="stock_quantity" placeholder="จำนวนในสต็อก" required>
+                    <input type="number" name="minimum_stock" placeholder="จำนวนขั้นต่ำ" required>
+                </div>
+                <div class="form-row">
+                    <input type="text" name="location" placeholder="ตำแหน่งจัดเก็บ">
+                    <select name="category_id" required>
+                        <option value="">เลือกหมวดหมู่</option>
+                        <% categories.forEach(category => { %>
+                            <option value="<%= category.id %>"><%= category.name %></option>
+                        <% }); %>
+                    </select>
+                </div>
+                <button type="submit">เพิ่มสินค้า</button>
+            </form>
+        </div>
+
+        
+        <div class="product-list">
+            <table>
+                <thead>
                     <tr>
-                        <td><%= product.name %></td>
-                        <td><%= product.price %></td>
-                        <td><%= product.category_name %></td>
-                        <td><%= product.created_by  %></td>
-                        <td>
-                            <% if (product.user_id === userId) { %>
-                                <button onclick="editProduct(<%= JSON.stringify(product) %>)" class="edit-btn">แก้ไข</button>
-                                <button onclick="deleteProduct(<%= product.id %>)" class="delete-btn">ลบ</button>
-                            <% } %>
-                        </td>
+                        <th>ชื่อสินค้า</th>
+                        <th>ราคา</th>
+                        <th>จำนวน</th>
+                        <th>ขั้นต่ำ</th>
+                        <th>ตำแหน่ง</th>
+                        <th>หมวดหมู่</th>
+                        <th>สถานะ</th>
+                        <th>จัดการ</th>
                     </tr>
-                <% }); %>
-            </tbody>
-        </table>
+                </thead>
+                <tbody>
+                    <% if (products && products.length > 0) { %>
+                        <% products.forEach(product => { %>
+                            <tr>
+                                <td><%= product.name %></td>
+                                <td><%= product.price %></td>
+                                <td><%= product.stock_quantity %></td>
+                                <td><%= product.minimum_stock %></td>
+                                <td><%= product.location || '-' %></td>
+                                <td><%= product.category_name %></td>
+                                <td>
+                                    <% const status = getStockStatus(product.stock_quantity, product.minimum_stock); %>
+                                    <span class="status <%= status.class %>"><%= status.text %></span>
+                                </td>
+                                <td>
+                                    <button onclick="editProduct('<%= product.id %>')">แก้ไข</button>
+                                    <button onclick="deleteProduct('<%= product.id %>')">ลบ</button>
+                                    <button onclick="showStockModal('<%= product.id %>', 'in')">เพิ่มสต็อก</button>
+                                    <button onclick="showStockModal('<%= product.id %>', 'out')">เบิกสต็อก</button>
+                                    <button onclick="showHistory('<%= product.id %>')">ประวัติ</button>
+                                </td>
+                            </tr>
+                        <% }); %>
+                    <% } else { %>
+                        <tr>
+                            <td colspan="8" class="empty-message">ไม่พบข้อมูลสินค้า</td>
+                        </tr>
+                    <% } %>
+                </tbody>
+            </table>
+        </div>
     </div>
 
-   
+    
     <div id="editModal" class="modal">
         <div class="modal-content">
             <h2>แก้ไขสินค้า</h2>
             <form id="editForm">
-                <input type="text" id="editName" placeholder="ชื่อสินค้า" required>
-                <input type="number" id="editPrice" placeholder="ราคา" required>
-                <select id="editCategory" required>
-                    <% categories.forEach(category => { %>
-                        <option value="<%= category.id %>"><%= category.name %></option>
-                    <% }); %>
-                </select>
-                <button type="submit">บันทึก</button>
-                <button type="button" onclick="closeModal()">ยกเลิก</button>
+                <div class="form-row">
+                    <input type="text" id="editName" placeholder="ชื่อสินค้า" required>
+                    <input type="number" id="editPrice" placeholder="ราคา" required>
+                </div>
+                <div class="form-row">
+                    <input type="number" id="editStockQuantity" placeholder="จำนวนในสต็อก" required>
+                    <input type="number" id="editMinimumStock" placeholder="จำนวนขั้นต่ำ" required>
+                </div>
+                <div class="form-row">
+                    <input type="text" id="editLocation" placeholder="ตำแหน่งจัดเก็บ">
+                    <select id="editCategory" required>
+                        <option value="">เลือกหมวดหมู่</option>
+                        <% categories.forEach(category => { %>
+                            <option value="<%= category.id %>"><%= category.name %></option>
+                        <% }); %>
+                    </select>
+                </div>
+                <div class="form-actions">
+                    <button type="submit">บันทึก</button>
+                    <button type="button" onclick="closeEditModal()">ยกเลิก</button>
+                </div>
             </form>
         </div>
     </div>
-    
+
+   
+    <div id="stockModal" class="modal">
+        <div class="modal-content">
+            <h2 id="modalTitle"></h2>
+            <form id="stockForm">
+                <input type="number" id="stockQuantity" placeholder="จำนวน" required>
+                <textarea id="stockDescription" placeholder="รายละเอียด"></textarea>
+                <div class="form-actions">
+                    <button type="submit">บันทึก</button>
+                    <button type="button" onclick="closeModal()">ยกเลิก</button>
+                </div>
+            </form>
+        </div>
+    </div>
+
+   
+    <div id="historyModal" class="modal">
+        <div class="modal-content">
+            <h2>ประวัติการเคลื่อนไหว</h2>
+            <table id="historyTable">
+                <thead>
+                    <tr>
+                        <th>วันที่</th>
+                        <th>ประเภท</th>
+                        <th>จำนวน</th>
+                        <th>ผู้ดำเนินการ</th>
+                        <th>รายละเอียด</th>
+                    </tr>
+                </thead>
+                <tbody></tbody>
+            </table>
+            <button onclick="closeHistoryModal()">ปิด</button>
+        </div>
+    </div>
+
     <script>
-        const modal = document.getElementById('editModal');
+        // ฟังก์ชันจัดการสินค้า
+        const editModal = document.getElementById('editModal');
         let currentProductId = null;
 
-        async function deleteProduct(id) {
-            if (confirm('ต้องการลบสินค้านี้?')) {
-                const response = await fetch(`/products/${id}`, {
-                    method: 'DELETE'
+        function editProduct(id) {
+            currentProductId = id;
+            fetch(`/products/${id}`)
+                .then(response => response.json())
+                .then(product => {
+                    document.getElementById('editName').value = product.name;
+                    document.getElementById('editPrice').value = product.price;
+                    document.getElementById('editStockQuantity').value = product.stock_quantity;
+                    document.getElementById('editMinimumStock').value = product.minimum_stock;
+                    document.getElementById('editLocation').value = product.location || '';
+                    document.getElementById('editCategory').value = product.category_id;
+                    editModal.style.display = 'block';
                 });
-                if (response.ok) {
-                    location.reload();
-                }
-            }
-        }
-
-        function editProduct(product) {
-            currentProductId = product.id;
-            document.getElementById('editName').value = product.name;
-            document.getElementById('editPrice').value = product.price;
-            document.getElementById('editCategory').value = product.category_id;
-            modal.style.display = 'block';
         }
 
-        function closeModal() {
-            modal.style.display = 'none';
+        function closeEditModal() {
+            editModal.style.display = 'none';
         }
 
-        document.getElementById('editForm').onsubmit = async (e) => {
+        document.getElementById('editForm').onsubmit = function(e) {
             e.preventDefault();
             const data = {
                 name: document.getElementById('editName').value,
                 price: document.getElementById('editPrice').value,
+                stock_quantity: document.getElementById('editStockQuantity').value,
+                minimum_stock: document.getElementById('editMinimumStock').value,
+                location: document.getElementById('editLocation').value,
                 category_id: document.getElementById('editCategory').value
             };
-            
-            const response = await fetch(`/products/${currentProductId}`, {
+
+            fetch(`/products/${currentProductId}`, {
                 method: 'PUT',
                 headers: {
                     'Content-Type': 'application/json'
                 },
                 body: JSON.stringify(data)
+            }).then(() => {
+                closeEditModal();
+                window.location.reload();
             });
+        };
 
-            if (response.ok) {
-                location.reload();
+        function deleteProduct(id) {
+            if (confirm('ต้องการลบสินค้านี้?')) {
+                fetch(`/products/${id}`, { method: 'DELETE' })
+                    .then(() => window.location.reload());
+            }
+        }
+
+        let currentType;
+
+        function showStockModal(productId, type) {
+            currentProductId = productId;
+            currentType = type;
+            document.getElementById('modalTitle').textContent = type === 'in' ? 'เพิ่มสต็อก' : 'เบิกสต็อก';
+            document.getElementById('stockModal').style.display = 'block';
+        }
+
+        function closeModal() {
+            document.getElementById('stockModal').style.display = 'none';
+            document.getElementById('stockForm').reset();
+        }
+
+        document.getElementById('stockForm').onsubmit = async function(e) {
+            e.preventDefault();
+            const data = {
+                product_id: currentProductId,
+                quantity: document.getElementById('stockQuantity').value,
+                description: document.getElementById('stockDescription').value
+            };
+
+            const url = currentType === 'in' ? '/stock/add' : '/stock/remove';
+            
+            try {
+                const response = await fetch(url, {
+                    method: 'POST',
+                    headers: { 'Content-Type': 'application/json' },
+                    body: JSON.stringify(data)
+                });
+
+                if (response.ok) {
+                    closeModal();
+                    location.reload();
+                } else {
+                    const error = await response.json();
+                    alert(error.error);
+                }
+            } catch (err) {
+                console.error(err);
+                alert('เกิดข้อผิดพลาด');
             }
         };
+
+        async function showHistory(productId) {
+            try {
+                const response = await fetch(`/stock/history/${productId}`);
+                const movements = await response.json();
+                
+                const tbody = document.querySelector('#historyTable tbody');
+                tbody.innerHTML = movements.map(m => `
+                    <tr>
+                        <td>${new Date(m.date).toLocaleString()}</td>
+                        <td>${m.type === 'in' ? 'รับเข้า' : 'เบิกออก'}</td>
+                        <td>${m.quantity}</td>
+                        <td>${m.user_name}</td>
+                        <td>${m.description || '-'}</td>
+                    </tr>
+                `).join('');
+                
+                document.getElementById('historyModal').style.display = 'block';
+            } catch (err) {
+                console.error(err);
+                alert('เกิดข้อผิดพลาด');
+            }
+        }
+
+        function closeHistoryModal() {
+            document.getElementById('historyModal').style.display = 'none';
+        }
     </script>
 
     <style>
+        .container { padding: 20px; }
+        
+        .form-row {
+            display: flex;
+            gap: 10px;
+            margin-bottom: 10px;
+        }
+
+        .status {
+            padding: 5px 10px;
+            border-radius: 4px;
+            font-weight: bold;
+        }
+
+        .status-out { 
+            background: #dc3545; 
+            color: white; 
+        }
+        
+        .status-low { 
+            background: #ffc107; 
+            color: black; 
+        }
+        
+        .status-normal { 
+            background: #28a745; 
+            color: white; 
+        }
+
+        button {
+            padding: 5px 10px;
+            border-radius: 4px;
+            cursor: pointer;
+        }
+
         .modal {
             display: none;
             position: fixed;
@@ -138,38 +354,74 @@
             width: 100%;
             height: 100%;
             background-color: rgba(0,0,0,0.5);
+            z-index: 1000;
         }
 
         .modal-content {
             background-color: white;
             margin: 15% auto;
             padding: 20px;
+            width: 80%;
+            max-width: 600px;
             border-radius: 5px;
-            width: 50%;
-            max-width: 500px;
+            position: relative;
         }
 
-        .nav-link {
-            color: #007bff;
-            text-decoration: none;
-            margin-right: 15px;
+        .form-actions {
+            display: flex;
+            gap: 10px;
+            justify-content: flex-end;
+            margin-top: 20px;
+        }
+
+        .form-actions button {
+            padding: 8px 16px;
         }
 
-        .edit-btn {
-            background-color: #ffc107;
-            color: black;
+        .form-actions button[type="submit"] {
+            background-color: #28a745;
+            color: white;
+            border: none;
         }
 
-        .delete-btn {
+        .form-actions button[type="button"] {
             background-color: #dc3545;
             color: white;
+            border: none;
+        }
+
+        .search-section {
+            margin-bottom: 20px;
+        }
+
+        .search-form {
+            display: flex;
+            gap: 10px;
+            align-items: center;
         }
 
-        .product-form select {
+        .search-form input {
             padding: 8px;
             border: 1px solid #ddd;
             border-radius: 4px;
-            margin-right: 10px;
+            width: 300px;
+        }
+
+        .search-form button {
+            padding: 8px 16px;
+            background: #007bff;
+            color: white;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+        }
+
+        .clear-search {
+            padding: 8px 16px;
+            background: #6c757d;
+            color: white;
+            text-decoration: none;
+            border-radius: 4px;
         }
     </style>
 </body>
-- 
GitLab