From f1fcbddfebd75757f7815fd16009d1aceb33f723 Mon Sep 17 00:00:00 2001 From: rhanarmt Date: Tue, 21 Apr 2026 00:05:51 +0700 Subject: [PATCH] backend fitur produk dan transaki --- lib/services/ml_service.dart | 19 ++++-- ml_model/setup_database.sql | 121 +++++++++++++++++++++++++++++++++++ test_backend.py | 93 +++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 ml_model/setup_database.sql create mode 100644 test_backend.py diff --git a/lib/services/ml_service.dart b/lib/services/ml_service.dart index 9ff3760..95c26fc 100644 --- a/lib/services/ml_service.dart +++ b/lib/services/ml_service.dart @@ -237,15 +237,26 @@ class MLService { } else if (response.statusCode == 409) { final result = jsonDecode(response.body); return result; - } else { + } else if (response.statusCode == 400) { + final result = jsonDecode(response.body); return { 'status': 'error', - 'message': 'Server error: ${response.statusCode}', + 'message': result['message'] ?? 'Bad request' + }; + } else { + print('Create product error - Status: ${response.statusCode}'); + print('Response body: ${response.body}'); + return { + 'status': 'error', + 'message': 'Server error: ${response.statusCode}' }; } } catch (e) { - print('Create product error: $e'); - return {'status': 'error', 'message': 'Connection error: $e'}; + print('Create product exception: $e'); + return { + 'status': 'error', + 'message': 'Connection error: $e' + }; } } diff --git a/ml_model/setup_database.sql b/ml_model/setup_database.sql new file mode 100644 index 0000000..63ca3d3 --- /dev/null +++ b/ml_model/setup_database.sql @@ -0,0 +1,121 @@ +-- Create Database and Tables for Prediksi Stok Bahan Kue +-- Run this in MySQL to setup the database + +-- Create Database +CREATE DATABASE IF NOT EXISTS prediksi_stok_db; +USE prediksi_stok_db; + +-- Create Products Table +CREATE TABLE IF NOT EXISTS products ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL UNIQUE, + category VARCHAR(100) NOT NULL, + price INT NOT NULL, + current_stock INT NOT NULL DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Create Transactions Table +CREATE TABLE IF NOT EXISTS transactions ( + id INT AUTO_INCREMENT PRIMARY KEY, + product_name VARCHAR(255) NOT NULL, + category VARCHAR(100) NOT NULL, + quantity INT NOT NULL, + unit_price INT NOT NULL, + total_price INT NOT NULL, + transaction_date DATE NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Create Predictions Table +CREATE TABLE IF NOT EXISTS predictions ( + id INT AUTO_INCREMENT PRIMARY KEY, + product_name VARCHAR(255) NOT NULL, + category VARCHAR(100) NOT NULL, + unit_price INT NOT NULL, + prediction_date DATE NOT NULL, + predicted_quantity INT NOT NULL, + raw_value FLOAT, + estimated_total_price INT, + accuracy_r2 FLOAT, + error_mae FLOAT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Create Recipes Table +CREATE TABLE IF NOT EXISTS recipes ( + id INT AUTO_INCREMENT PRIMARY KEY, + recipe_name VARCHAR(255) NOT NULL, + description TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Create Recipe Ingredients Table +CREATE TABLE IF NOT EXISTS recipe_ingredients ( + id INT AUTO_INCREMENT PRIMARY KEY, + recipe_id INT NOT NULL, + product_name VARCHAR(255) NOT NULL, + quantity_needed FLOAT NOT NULL, + unit VARCHAR(50) NOT NULL, + FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Insert Initial Products (8 items) +INSERT INTO products (name, category, price, current_stock) VALUES +('Tepung Terigu 1kg', 'Tepung', 15000, 50), +('Telur 1kg', 'Telur', 25000, 30), +('Gula Pasir 1kg', 'Gula', 12000, 40), +('Susu Bubuk', 'Susu', 20000, 20), +('Cokelat Bubuk 250gr', 'Cokelat', 18000, 15), +('Mentega 500gr', 'Mentega', 22000, 25), +('Keju Parut 250gr', 'Keju', 28000, 10), +('Baking Powder', 'Bahan Tambahan', 8000, 35); + +-- Insert Sample Recipes +INSERT INTO recipes (recipe_name, description) VALUES +('Donat', 'Resep donat lezat'), +('Roti Putih', 'Resep roti putih'), +('Kue Brownies', 'Resep brownies cokelat'), +('Kue Tart', 'Resep kue tart'); + +-- Insert Recipe Ingredients +-- Donat +INSERT INTO recipe_ingredients (recipe_id, product_name, quantity_needed, unit) VALUES +(1, 'Tepung Terigu 1kg', 0.5, 'kg'), +(1, 'Telur 1kg', 2, 'butir'), +(1, 'Gula Pasir 1kg', 0.1, 'kg'), +(1, 'Mentega 500gr', 0.05, 'kg'), +(1, 'Baking Powder', 0.005, 'kg'); + +-- Roti Putih +INSERT INTO recipe_ingredients (recipe_id, product_name, quantity_needed, unit) VALUES +(2, 'Tepung Terigu 1kg', 0.8, 'kg'), +(2, 'Telur 1kg', 3, 'butir'), +(2, 'Gula Pasir 1kg', 0.08, 'kg'), +(2, 'Mentega 500gr', 0.08, 'kg'), +(2, 'Susu Bubuk', 0.05, 'kg'), +(2, 'Baking Powder', 0.008, 'kg'); + +-- Kue Brownies +INSERT INTO recipe_ingredients (recipe_id, product_name, quantity_needed, unit) VALUES +(3, 'Tepung Terigu 1kg', 0.3, 'kg'), +(3, 'Cokelat Bubuk 250gr', 0.1, 'kg'), +(3, 'Telur 1kg', 4, 'butir'), +(3, 'Gula Pasir 1kg', 0.2, 'kg'), +(3, 'Mentega 500gr', 0.15, 'kg'), +(3, 'Baking Powder', 0.005, 'kg'); + +-- Kue Tart +INSERT INTO recipe_ingredients (recipe_id, product_name, quantity_needed, unit) VALUES +(4, 'Tepung Terigu 1kg', 0.4, 'kg'), +(4, 'Telur 1kg', 5, 'butir'), +(4, 'Gula Pasir 1kg', 0.15, 'kg'), +(4, 'Mentega 500gr', 0.2, 'kg'), +(4, 'Keju Parut 250gr', 0.1, 'kg'), +(4, 'Susu Bubuk', 0.08, 'kg'); + +-- Verify tables created +SELECT 'Tables created successfully!' as status; +SELECT COUNT(*) as total_products FROM products; +SELECT COUNT(*) as total_recipes FROM recipes; diff --git a/test_backend.py b/test_backend.py new file mode 100644 index 0000000..86a513b --- /dev/null +++ b/test_backend.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +""" +Simple backend connectivity test +Run: python test_backend.py +""" + +import requests +import json +from datetime import datetime + +# Change this to your backend URL +BACKEND_URL = "http://192.168.1.2:5000" + +def test_health(): + """Test if backend is running""" + try: + print("\n[TEST 1] Health Check") + print(f"URL: {BACKEND_URL}/health") + response = requests.get(f"{BACKEND_URL}/health", timeout=5) + print(f"Status: {response.status_code}") + print(f"Response: {response.json()}") + return response.status_code == 200 + except Exception as e: + print(f"❌ Error: {e}") + return False + +def test_get_products(): + """Test get products endpoint""" + try: + print("\n[TEST 2] Get Products") + print(f"URL: {BACKEND_URL}/products") + response = requests.get(f"{BACKEND_URL}/products", timeout=5) + print(f"Status: {response.status_code}") + data = response.json() + print(f"Total products: {data.get('total', 0)}") + if data.get('products'): + print(f"First product: {data['products'][0]}") + return response.status_code == 200 + except Exception as e: + print(f"❌ Error: {e}") + return False + +def test_create_product(): + """Test create product endpoint""" + try: + print("\n[TEST 3] Create Product") + print(f"URL: {BACKEND_URL}/products") + + payload = { + "name": f"Test Produk {datetime.now().strftime('%H%M%S')}", + "category": "Test", + "price": 10000, + "current_stock": 5 + } + print(f"Payload: {json.dumps(payload, indent=2)}") + + response = requests.post( + f"{BACKEND_URL}/products", + json=payload, + headers={"Content-Type": "application/json"}, + timeout=5 + ) + print(f"Status: {response.status_code}") + print(f"Response: {response.json()}") + return response.status_code in [201, 409] + except Exception as e: + print(f"❌ Error: {e}") + return False + +if __name__ == "__main__": + print("="*80) + print(f"Backend Connectivity Test - {BACKEND_URL}") + print("="*80) + + tests = [ + ("Health Check", test_health()), + ("Get Products", test_get_products()), + ("Create Product", test_create_product()), + ] + + print("\n" + "="*80) + print("SUMMARY:") + for test_name, result in tests: + status = "✅ PASS" if result else "❌ FAIL" + print(f" {status}: {test_name}") + + print("="*80) + + all_passed = all(result for _, result in tests) + if all_passed: + print("\n✅ Backend is working correctly!") + else: + print("\n❌ Some tests failed. Check your backend connection.")