first commit

This commit is contained in:
2025-10-14 16:50:42 +05:30
commit fcc1fc7b0b
6 changed files with 579 additions and 0 deletions

533
Project/microservice.py Normal file
View File

@ -0,0 +1,533 @@
from flask import Flask, request, jsonify, Response
import requests
import os
from flask_cors import CORS
# Initialize Flask app
app = Flask(__name__)
# Enhanced CORS configuration
CORS(app,
resources={r"/*": {"origins": "*"}},
supports_credentials=True,
allow_headers=["Content-Type", "Authorization", "Access-Control-Allow-Credentials"],
methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"]
)
# Configuration - point to your main backend
MAIN_BACKEND_URL = "http://127.0.0.1:5000" # Change this to your main backend URL
# Add OPTIONS handler for preflight requests
@app.before_request
def handle_preflight():
if request.method == "OPTIONS":
response = Response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
return response
# Routes
@app.route('/login', methods=['POST'])
def login():
"""Handle machine login"""
try:
data = request.json
print(f"Login request received: {data}")
# Forward the login request to the main backend
response = requests.post(f"{MAIN_BACKEND_URL}/login", json=data)
print(f"Login response status: {response.status_code}")
# Pass through the response
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Login error: {e}")
return jsonify({"error": "Login service unavailable"}), 500
@app.route('/uploads/<path:filename>', methods=['GET'])
def get_image(filename):
"""Forward image requests to the main backend"""
try:
response = requests.get(f"{MAIN_BACKEND_URL}/uploads/{filename}", stream=True)
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'image/jpeg')
)
except Exception as e:
print(f"Image fetch error: {e}")
return jsonify({"error": "Image not found"}), 404
@app.route('/machine-slots/<machine_id>', methods=['GET'])
def get_machine_slots(machine_id):
"""Get slots for a specific machine"""
try:
print(f"Fetching slots for machine: {machine_id}")
# Simply forward the request to the main backend
response = requests.get(f"{MAIN_BACKEND_URL}/machine-slots/{machine_id}")
print(f"Slots response status: {response.status_code}")
# Pass through the response
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Machine slots error: {e}")
return jsonify({"error": "Could not fetch machine slots"}), 500
@app.route('/machine-slots/update-inventory', methods=['POST'])
def update_inventory():
"""Forward inventory update request to main backend"""
try:
print("=== Inventory Update Request ===")
data = request.json
if not data:
return jsonify({"error": "No data received"}), 400
machine_id = data.get('machineId')
updates = data.get('inventoryUpdates', [])
print(f"Machine ID: {machine_id}")
print(f"Inventory updates: {len(updates)}")
response = requests.post(
f"{MAIN_BACKEND_URL}/machine-slots/update-inventory",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Inventory update response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Inventory update error: {e}")
return jsonify({"error": "Could not update inventory"}), 500
@app.route('/vending-state/<machine_id>', methods=['GET'])
def get_vending_state(machine_id):
"""Get the vending state for a machine"""
try:
# Forward the request to the main backend
response = requests.get(f"{MAIN_BACKEND_URL}/machines/{machine_id}")
# Pass through the response
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Vending state error: {e}")
return jsonify({"error": "Could not fetch vending state"}), 500
@app.route('/create-payu-order', methods=['POST', 'OPTIONS'])
def create_payu_order():
"""Create PayU payment order - forward to main backend"""
try:
print("=== PayU Order Creation Request ===")
data = request.json
print(f"Request data: {data}")
if not data:
print("No data received in request")
return jsonify({"error": "No data received"}), 400
# Forward to main backend
print(f"Forwarding to: {MAIN_BACKEND_URL}/create-payu-order")
response = requests.post(
f"{MAIN_BACKEND_URL}/create-payu-order",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Main backend response status: {response.status_code}")
print(f"Main backend response: {response.text}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except requests.exceptions.ConnectionError as e:
print(f"Connection error to main backend: {e}")
return jsonify({"error": "Payment service unavailable"}), 503
except Exception as e:
print(f"PayU order creation error: {e}")
return jsonify({"error": "Could not create payment order"}), 500
@app.route('/vending-state/<machine_id>', methods=['PUT'])
def update_vending_state(machine_id):
"""Update the vending state for a machine"""
try:
# Forward the request to the main backend
headers = {k: v for k, v in request.headers.items() if k not in ['Host', 'Content-Length']}
response = requests.put(
f"{MAIN_BACKEND_URL}/machines/{machine_id}/vending-state",
json=request.json,
headers=headers
)
# Pass through the response
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Update vending state error: {e}")
return jsonify({"error": "Could not update vending state"}), 500
# NEW: Serial Communication Routes
@app.route('/machine/connect', methods=['POST'])
def connect_machine():
"""Forward machine connection request to main backend"""
try:
print("=== Machine Connection Request ===")
data = request.json or {}
print(f"Connection data: {data}")
response = requests.post(
f"{MAIN_BACKEND_URL}/machine/connect",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Connection response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Machine connection error: {e}")
return jsonify({"error": "Could not connect to machine"}), 500
@app.route('/machine/status', methods=['GET'])
def get_machine_status():
"""Forward machine status request to main backend"""
try:
print("=== Machine Status Request ===")
response = requests.get(f"{MAIN_BACKEND_URL}/machine/status")
print(f"Status response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Machine status error: {e}")
return jsonify({"error": "Could not get machine status"}), 500
@app.route('/machine/dispense', methods=['POST'])
def dispense_product():
"""Forward single product dispensing to main backend"""
try:
print("=== Single Product Dispensing Request ===")
data = request.json
if not data:
return jsonify({"error": "No data received"}), 400
print(f"Dispense data: {data}")
response = requests.post(
f"{MAIN_BACKEND_URL}/machine/dispense",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Dispense response: {response.status_code}")
print(f"Dispense result: {response.text}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Product dispensing error: {e}")
return jsonify({"error": "Could not dispense product"}), 500
@app.route('/machine/dispense-multiple', methods=['POST'])
def dispense_multiple_products():
"""Forward multiple product dispensing to main backend"""
try:
print("=== Multiple Product Dispensing Request ===")
data = request.json
if not data:
return jsonify({"error": "No data received"}), 400
machine_id = data.get('machineId')
items = data.get('items', [])
print(f"Machine ID: {machine_id}")
print(f"Items to dispense: {len(items)}")
for item in items:
print(f" - Slot {item.get('slotId')}: {item.get('quantity')}x {item.get('productName')}")
response = requests.post(
f"{MAIN_BACKEND_URL}/machine/dispense-multiple",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Multiple dispense response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Multiple product dispensing error: {e}")
return jsonify({"error": "Could not dispense multiple products"}), 500
@app.route('/machine/reset', methods=['POST'])
def reset_machine():
"""Forward machine reset request to main backend"""
try:
print("=== Machine Reset Request ===")
response = requests.post(f"{MAIN_BACKEND_URL}/machine/reset")
print(f"Reset response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Machine reset error: {e}")
return jsonify({"error": "Could not reset machine"}), 500
@app.route('/machine/disconnect', methods=['POST'])
def disconnect_machine():
"""Forward machine disconnect request to main backend"""
try:
print("=== Machine Disconnect Request ===")
response = requests.post(f"{MAIN_BACKEND_URL}/machine/disconnect")
print(f"Disconnect response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Machine disconnect error: {e}")
return jsonify({"error": "Could not disconnect machine"}), 500
@app.route('/payment-confirmed', methods=['POST'])
def payment_confirmed():
"""Forward payment confirmation to main backend for dispensing"""
try:
print("=== Payment Confirmation Request ===")
data = request.json
if not data:
return jsonify({"error": "No data received"}), 400
machine_id = data.get('machineId')
cart_items = data.get('cartItems', [])
print(f"Payment confirmed for machine: {machine_id}")
print(f"Cart items: {len(cart_items)}")
response = requests.post(
f"{MAIN_BACKEND_URL}/payment-confirmed",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Payment confirmation response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Payment confirmation error: {e}")
return jsonify({"error": "Could not process payment confirmation"}), 500
@app.route('/transactions/bulk-create', methods=['POST'])
def bulk_create_transactions():
"""Forward bulk transaction creation to main backend"""
try:
print("=== Bulk Transaction Creation Request ===")
data = request.json
if not data:
return jsonify({"error": "No data received"}), 400
transactions = data.get('transactions', [])
print(f"Creating {len(transactions)} transactions")
for trans in transactions:
print(f" - {trans.get('product_name')} x {trans.get('quantity')} = ₹{trans.get('amount')}")
response = requests.post(
f"{MAIN_BACKEND_URL}/transactions/bulk-create",
json=data,
headers={'Content-Type': 'application/json'}
)
print(f"Bulk transaction response: {response.status_code}")
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
print(f"Bulk transaction creation error: {e}")
return jsonify({"error": "Could not create transactions"}), 500
# LEGACY: Keep existing dispense-products route for backward compatibility
@app.route('/dispense-products', methods=['POST'])
def dispense_products():
"""Legacy route - redirect to new dispensing system"""
print("=== Legacy Dispense Products Request ===")
print("Redirecting to new dispensing system...")
# Get dispensing instructions from the request
data = request.json
if not data:
print("No JSON data received")
return jsonify({"error": "No data received"}), 400
machine_id = data.get('machineId')
dispensing_instructions = data.get('dispensingInstructions', [])
if not machine_id or not dispensing_instructions:
print("Missing machine ID or dispensing instructions")
return jsonify({"error": "Missing machine ID or dispensing instructions"}), 400
# Convert to new format and forward to new dispensing endpoint
try:
new_format = {
'machineId': machine_id,
'items': [
{
'slotId': instruction.get('slotId'),
'quantity': instruction.get('quantity', 1),
'productName': instruction.get('productName', 'Unknown')
}
for instruction in dispensing_instructions
]
}
return dispense_multiple_products_internal(new_format)
except Exception as e:
print(f"Legacy conversion error: {e}")
return jsonify({"error": "Could not process legacy request"}), 500
def dispense_multiple_products_internal(data):
"""Internal function to handle dispensing without duplicate logging"""
try:
response = requests.post(
f"{MAIN_BACKEND_URL}/machine/dispense-multiple",
json=data,
headers={'Content-Type': 'application/json'}
)
return Response(
response.content,
status=response.status_code,
content_type=response.headers.get('Content-Type', 'application/json')
)
except Exception as e:
return jsonify({"error": "Could not dispense products"}), 500
@app.route('/payment-success', methods=['POST', 'GET'])
def payment_success():
data = request.form.to_dict() or request.args.to_dict()
print("✅ Payment Success:", data)
return jsonify({
"success": True,
"message": "Payment successful",
"data": data
}), 200
@app.route('/payment-failure', methods=['POST', 'GET'])
def payment_failure():
data = request.form.to_dict() or request.args.to_dict()
print("❌ Payment Failure:", data)
return jsonify({
"success": False,
"message": "Payment failed",
"data": data
}), 200
# Add a test route to verify the server is running
@app.route('/', methods=['GET'])
def test_route():
return jsonify({"status": "Flask server is running"}), 200
# Add error handlers
@app.errorhandler(404)
def not_found(error):
return jsonify({"error": "Endpoint not found"}), 404
@app.errorhandler(500)
def internal_error(error):
return jsonify({"error": "Internal server error"}), 500
if __name__ == '__main__':
# Print startup message
print("Starting Flask server on port 5001...")
print("Available routes:")
print(" - /")
print(" - /login [POST]")
print(" - /uploads/<filename> [GET]")
print(" - /machine-slots/<machine_id> [GET]")
print(" - /vending-state/<machine_id> [GET/PUT]")
print(" - /create-payu-order [POST]")
print(" - /dispense-products [POST] (legacy)")
print(" - /machine/connect [POST]")
print(" - /machine/status [GET]")
print(" - /machine/dispense [POST]")
print(" - /machine/dispense-multiple [POST]")
print(" - /machine/reset [POST]")
print(" - /machine/disconnect [POST]")
print(" - /payment-confirmed [POST]")
print(f"Main backend URL: {MAIN_BACKEND_URL}")
# Run the server
app.run(host='0.0.0.0', debug=True, port=5001)