File size: 18,330 Bytes
257ea87
 
 
 
 
 
 
 
 
 
fc8eee0
257ea87
fc8eee0
257ea87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337287d
 
 
 
257ea87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
from fastapi import FastAPI, HTTPException, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from datetime import datetime, timedelta
from typing import Optional, List
import sqlite3
import csv
import io
from ai_handler import MetaAIHandler
from database import Database

app = FastAPI(title="Ejide Pharmacy API")

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Initialize
db = Database()
ai_handler = MetaAIHandler()

class ChatMessage(BaseModel):
    phone_number: str
    message: str
    is_admin: bool
    timestamp: str

@app.on_event("startup")
async def startup():
    db.initialize()
    print("βœ… Database initialized with medication tracking")

@app.get("/")
def root():
    return {"message": "Ejide Pharmacy API is running"}

@app.post("/chat")
async def chat(msg: ChatMessage):
    """Main chat endpoint - handles all incoming messages"""
    
    # Log conversation
    db.log_conversation(msg.phone_number, msg.message, msg.is_admin)
    
    message_lower = msg.message.lower().strip()
    
    # Admin commands
    if msg.is_admin:
        # Inventory management
        if message_lower.startswith(("add drug", "update drug", "add inventory")):
            return handle_admin_inventory(msg.message, msg.phone_number)
        
        # Analytics commands
        elif message_lower in ["analytics", "show analytics", "predictive insights", "insights"]:
            return generate_analytics_report()
        
        # Inventory analysis
        elif message_lower in ["inventory report", "show inventory", "stock report", "inventory analysis"]:
            return generate_inventory_report()
        
        # Weekly report
        elif message_lower in ["weekly report", "week report", "weekly summary"]:
            return generate_weekly_report()
        
        # Help command
        elif message_lower == "help":
            return {"reply": get_admin_help()}
    
    # Check for cart/checkout commands
    if message_lower.startswith(("checkout", "check out")):
        return handle_checkout(msg.phone_number, msg.message)
    
    # Get context
    customer_history = db.get_customer_history(msg.phone_number)
    inventory = db.get_inventory()
    cart = db.get_cart(msg.phone_number)
    
    # Generate AI response
    ai_response = ai_handler.generate_response(
        message=msg.message,
        customer_history=customer_history,
        inventory=inventory,
        cart=cart,
        is_admin=msg.is_admin
    )
    
    # Check if customer wants to add to cart
    cart_action = parse_cart_action(msg.message, inventory)
    if cart_action:
        db.add_to_cart(msg.phone_number, cart_action['drug_name'], cart_action['quantity'])
        cart = db.get_cart(msg.phone_number)
        cart_summary = format_cart_summary(cart)
        ai_response += f"\n\n{cart_summary}"
    
    return {"reply": ai_response}

def parse_cart_action(message: str, inventory: List[dict]) -> Optional[dict]:
    """Parse if customer wants to add items to cart"""
    message_lower = message.lower()
    
    # Patterns: "add 2 paracetamol", "3 ibuprofen", "I want 5 chloroquine"
    words = message_lower.split()
    
    for i, word in enumerate(words):
        if word.isdigit() and i + 1 < len(words):
            quantity = int(word)
            potential_drug = words[i + 1]
            
            for item in inventory:
                if potential_drug in item['drug_name'].lower():
                    return {
                        'drug_name': item['drug_name'],
                        'quantity': quantity
                    }
    
    return None

def format_cart_summary(cart: List[dict]) -> str:
    """Format cart items with total"""
    if not cart:
        return "πŸ›’ Your cart is empty."
    
    summary = "πŸ›’ *YOUR CART:*\n"
    total = 0
    
    for item in cart:
        item_total = item['quantity'] * item['price']
        total += item_total
        summary += f"β€’ {item['drug_name'].title()} x{item['quantity']} = ₦{item_total:,.2f}\n"
    
    summary += f"\nπŸ’° *TOTAL: ₦{total:,.2f}*\n"
    summary += "\nReady to checkout? Reply 'checkout'"
    
    return summary

def handle_checkout(phone_number: str, message: str) -> dict:
    """Handle customer checkout"""
    cart = db.get_cart(phone_number)
    
    if not cart:
        return {"reply": "Your cart is empty. Add items first!\n\nExample: 'I want 2 paracetamol'"}
    
    # Calculate total
    total = sum(item['quantity'] * item['price'] for item in cart)
    
    # Generate order summary
    order_id = f"EJD{datetime.now().strftime('%Y%m%d%H%M%S')}"
    
    receipt = "🧾 *ORDER SUMMARY*\n"
    receipt += f"Order ID: {order_id}\n"
    receipt += f"Date: {datetime.now().strftime('%B %d, %Y %I:%M %p')}\n"
    receipt += "="*35 + "\n\n"
    
    receipt += "πŸ“¦ *ITEMS:*\n"
    for item in cart:
        item_total = item['quantity'] * item['price']
        receipt += f"β€’ {item['drug_name'].title()}\n"
        receipt += f"  Qty: {item['quantity']} x ₦{item['price']:,.2f} = ₦{item_total:,.2f}\n"
        
        # Add dosage info if available
        if item.get('dosage_days') and item['dosage_days'] > 0:
            receipt += f"  πŸ“… Treatment: {item['dosage_days']} days ({item.get('dosage_frequency', 'as prescribed')})\n"
        receipt += "\n"
    
    receipt += "="*35 + "\n"
    receipt += f"πŸ’° *TOTAL: ₦{total:,.2f}*\n\n"
    
    receipt += "πŸ’³ *PAYMENT DETAILS:*\n"
    receipt += get_account_details() + "\n\n"
    
    receipt += "πŸ“ *NEXT STEPS:*\n"
    receipt += "1. Transfer amount to account above\n"
    receipt += "2. Send screenshot of payment\n"
    receipt += "3. We'll confirm and prepare order\n"
    receipt += "4. Visit pharmacy or request delivery\n\n"
    
    # Add medication reminder notice
    has_medication = any(item.get('dosage_days', 0) > 0 for item in cart)
    if has_medication:
        receipt += "πŸ’Š *MEDICATION REMINDERS:*\n"
        receipt += "You'll receive daily reminders to take your medication and health checkups after treatment. Stay healthy! 😊\n\n"
    
    receipt += "⏰ Order valid for 24 hours\n"
    receipt += "πŸ“ž Reply 'help' for assistance\n\n"
    receipt += "Thank you for choosing Ejide Pharmacy! πŸ₯"
    
    # Record purchases
    for item in cart:
        db.record_purchase(
            phone_number, 
            item['drug_name'], 
            item['quantity'], 
            item['price'] * item['quantity']
        )
    
    # Clear cart
    db.clear_cart(phone_number)
    
    return {"reply": receipt}

def get_account_details() -> str:
    """Get pharmacy account details"""
    return """Bank: GTBank
Account Name: Ejide Pharmacy Ltd
Account Number: 0123456789

OR

Bank: Access Bank  
Account Name: Ejide Pharmacy
Account Number: 9876543210"""

def handle_admin_inventory(message: str, phone_number: str) -> dict:
    """Handle admin inventory commands"""
    try:
        parts = message.lower().split()
        
        if len(parts) >= 5:
            drug_name = parts[2]
            quantity = int(parts[3])
            price = float(parts[4])
            category = " ".join(parts[5:]) if len(parts) > 5 else "general"
            
            db.update_inventory(drug_name, quantity, price, category)
            
            return {
                "reply": f"βœ… *Inventory Updated!*\n\n"
                        f"Drug: {drug_name.title()}\n"
                        f"Qty: {quantity}\n"
                        f"Price: ₦{price:,.2f}\n"
                        f"Category: {category.title()}"
            }
        else:
            return {
                "reply": "❌ Invalid format.\n\n"
                        "*Use:* add drug [name] [qty] [price] [category]\n"
                        "*Example:* add drug paracetamol 100 500 fever"
            }
    except Exception as e:
        return {"reply": f"❌ Error: {str(e)}"}

def generate_analytics_report() -> dict:
    """Generate predictive analytics report"""
    analytics = db.get_predictive_analytics()
    
    report = "πŸ“Š *PREDICTIVE ANALYTICS & INSIGHTS*\n"
    report += f"πŸ“… Generated: {datetime.now().strftime('%B %d, %Y %I:%M %p')}\n"
    report += "="*40 + "\n\n"
    
    # Revenue Trends
    report += "πŸ’° *REVENUE TRENDS:*\n"
    rev = analytics['revenue_trend']
    report += f"This Week: ₦{rev['this_week']:,.2f}\n"
    report += f"Last Week: ₦{rev['last_week']:,.2f}\n"
    growth = rev.get('growth_percent', 0)
    emoji = "πŸ“ˆ" if growth > 0 else "πŸ“‰" if growth < 0 else "➑️"
    report += f"Growth: {growth:+.1f}% {emoji}\n\n"
    
    # Top Selling Drugs
    report += "πŸ”₯ *TOP SELLING (Last 30 Days):*\n"
    for i, drug in enumerate(analytics['top_drugs_30days'][:3], 1):
        report += f"{i}. {drug['drug_name'].title()}: {drug['total_qty']} units ({drug['purchase_count']} orders)\n"
    report += "\n"
    
    # Stock-Out Risk
    if analytics['stockout_risk']:
        report += "⚠️ *STOCK-OUT RISK ALERT:*\n"
        for item in analytics['stockout_risk'][:3]:
            report += f"β€’ {item['drug_name'].title()}: {item['current_stock']} left "
            report += f"({item.get('days_until_stockout', 'N/A')} days until out)\n"
        report += "πŸ’‘ *Action:* Restock these items soon!\n\n"
    
    # Customer Retention
    report += "πŸ‘₯ *CUSTOMER METRICS:*\n"
    ret = analytics['retention_metrics']
    report += f"Total Customers: {ret['total_customers']}\n"
    report += f"Returning: {ret['returning_customers']}\n"
    report += f"Retention Rate: {ret['retention_rate']}%\n\n"
    
    # Medication Adherence
    report += "πŸ’Š *MEDICATION ADHERENCE:*\n"
    adh = analytics['adherence_metrics']
    report += f"Active Treatments: {adh['total_prescriptions']}\n"
    report += f"Completed: {adh['completed_treatments']}\n"
    report += f"Adherence Rate: {adh['adherence_rate']}%\n\n"
    
    # Peak Hours
    if analytics['peak_hours']:
        report += "⏰ *BUSIEST HOURS:*\n"
        for peak in analytics['peak_hours']:
            hour = peak['hour']
            period = "AM" if hour < 12 else "PM"
            display_hour = hour if hour <= 12 else hour - 12
            if display_hour == 0:
                display_hour = 12
            report += f"β€’ {display_hour} {period}: {peak['message_count']} messages\n"
        report += "\n"
    
    report += "πŸ’‘ *AI RECOMMENDATIONS:*\n"
    
    # Generate smart recommendations
    if analytics['stockout_risk']:
        report += "β€’ Urgent: Restock low inventory items\n"
    
    if rev.get('growth_percent', 0) < 0:
        report += "β€’ Consider promotional campaigns\n"
    
    if ret['retention_rate'] < 50:
        report += "β€’ Improve customer retention programs\n"
    
    if adh['adherence_rate'] < 70:
        report += "β€’ Enhance medication reminder system\n"
    
    report += "\nπŸ“ˆ Powered by Meta AI Analytics"
    
    return {"reply": report}

def generate_inventory_report() -> dict:
    """Generate comprehensive inventory analysis"""
    analysis = db.get_inventory_analysis()
    
    report = "πŸ“¦ *INVENTORY ANALYSIS*\n"
    report += "="*35 + "\n\n"
    
    # Overview
    overview = analysis['overview']
    report += f"πŸ“Š *OVERVIEW:*\n"
    report += f"Total Items: {overview['total_items']}\n"
    report += f"Total Value: ₦{overview['total_value']:,.2f}\n"
    report += f"Avg Stock: {int(overview['avg_stock_level'])} units\n\n"
    
    # Low Stock
    if analysis['low_stock']:
        report += f"⚠️ *LOW STOCK ({len(analysis['low_stock'])} items):*\n"
        for item in analysis['low_stock'][:5]:
            report += f"β€’ {item['drug_name'].title()}: {item['quantity']} left (₦{item['price']})\n"
        report += "\n"
    
    # High Value Items
    report += "πŸ’Ž *TOP VALUE ITEMS:*\n"
    for item in analysis['high_value_items'][:3]:
        report += f"β€’ {item['drug_name'].title()}: ₦{item['total_value']:,.2f}\n"
    report += "\n"
    
    # By Category
    report += "πŸ“ *BY CATEGORY:*\n"
    for cat in analysis['by_category'][:5]:
        report += f"β€’ {cat['category'].title()}: {cat['item_count']} items (₦{cat['category_value']:,.2f})\n"
    
    return {"reply": report}

def generate_weekly_report() -> dict:
    """Generate weekly summary report"""
    stats = db.get_weekly_stats()
    
    report = "πŸ“Š *WEEKLY SUMMARY REPORT*\n"
    report += f"πŸ“… {datetime.now().strftime('%B %d, %Y')}\n"
    report += "="*35 + "\n\n"
    
    report += f"πŸ’° *SALES:*\n"
    report += f"Total Revenue: ₦{stats['total_revenue']:,.2f}\n"
    report += f"Orders: {stats['total_purchases']}\n"
    report += f"Customers: {stats['unique_customers']}\n"
    report += f"Top Drug: {stats['top_drug']}\n\n"
    
    report += f"πŸ“¨ *ENGAGEMENT:*\n"
    report += f"Messages: {stats['total_messages']}\n\n"
    
    # Get low stock items
    inventory = db.get_inventory()
    low_stock = [i for i in inventory if i['quantity'] < 20]
    
    if low_stock:
        report += f"⚠️ *LOW STOCK:* {len(low_stock)} items\n"
        for item in low_stock[:3]:
            report += f"  β€’ {item['drug_name'].title()}: {item['quantity']}\n"
    
    return {"reply": report}

def get_admin_help() -> str:
    """Admin help message"""
    return """πŸ”§ *ADMIN COMMANDS:*

πŸ“¦ *Inventory:*
β€’ add drug [name] [qty] [price] [category]
β€’ inventory report / inventory analysis
β€’ Upload CSV via WhatsApp

πŸ“Š *Analytics:*
β€’ analytics / predictive insights
β€’ weekly report / weekly summary

πŸ’‘ *Examples:*
β€’ "analytics" - Get AI-powered insights
β€’ "inventory report" - Full stock analysis
β€’ "weekly report" - Week summary
β€’ "add drug paracetamol 100 500 fever"

πŸ“€ *CSV Upload:*
Send CSV file with columns:
drug_name,quantity,price,category,description,dosage_days,dosage_frequency"""

@app.post("/upload-inventory")
async def upload_inventory_csv(file: UploadFile = File(...)):
    """Upload inventory via CSV"""
    try:
        contents = await file.read()
        decoded = contents.decode('utf-8')
        csv_reader = csv.DictReader(io.StringIO(decoded))
        
        added_count = 0
        errors = []
        
        for row in csv_reader:
            try:
                drug_name = row['drug_name'].strip().lower()
                quantity = int(row['quantity'])
                price = float(row['price'])
                category = row.get('category', 'general').strip()
                description = row.get('description', '').strip()
                dosage_days = int(row.get('dosage_days', 0))
                dosage_frequency = row.get('dosage_frequency', 'as prescribed').strip()
                
                db.update_inventory(drug_name, quantity, price, category, description, dosage_days, dosage_frequency)
                added_count += 1
                
            except Exception as e:
                errors.append(f"Row {added_count + 1}: {str(e)}")
        
        response = f"βœ… *CSV Upload Complete!*\n\n"
        response += f"βœ“ Added/Updated: {added_count} items\n"
        
        if errors:
            response += f"\n⚠️ Errors ({len(errors)}):\n"
            for error in errors[:5]:
                response += f"β€’ {error}\n"
        
        return {"reply": response}
        
    except Exception as e:
        return {"reply": f"❌ CSV Upload Failed: {str(e)}"}

@app.get("/medication-reminders")
async def get_medication_reminders():
    """Get medication reminders for automated system"""
    reminders_list = db.get_medication_reminders()
    
    reminders = []
    for reminder in reminders_list:
        phone = reminder['phone_number']
        drug = reminder['drug_name']
        reminder_type = reminder['reminder_type']
        dosage = reminder.get('dosage_frequency', 'as prescribed')
        
        if reminder_type == 'daily':
            message = (
                f"πŸ’Š *MEDICATION REMINDER*\n\n"
                f"Time to take your {drug.title()}!\n"
                f"Dosage: {dosage}\n\n"
                f"βœ… Reply 'took it' to confirm\n"
                f"❌ Reply 'missed' if you missed a dose\n\n"
                f"Stay consistent for best results! πŸ’ͺ"
            )
        elif reminder_type == 'completion':
            message = (
                f"πŸŽ‰ *TREATMENT MILESTONE*\n\n"
                f"You've completed your {drug.title()} treatment course!\n\n"
                f"How are you feeling?\n"
                f"β€’ Much better 😊\n"
                f"β€’ Some improvement πŸ€”\n"
                f"β€’ No change 😟\n\n"
                f"Your feedback helps us serve you better!"
            )
        else:  # checkup
            message = (
                f"πŸ₯ *HEALTH CHECK-IN*\n\n"
                f"It's been 3 days since you completed {drug.title()}.\n\n"
                f"Quick checkup:\n"
                f"β€’ Are your symptoms gone?\n"
                f"β€’ Any side effects?\n"
                f"β€’ Need any other medication?\n\n"
                f"We're here to help! 😊"
            )
        
        reminders.append({
            "phone_number": phone,
            "message": message,
            "purchase_id": reminder['purchase_id'],
            "reminder_type": reminder_type
        })
        
        # Mark reminder as sent
        db.mark_reminder_sent(reminder['purchase_id'])
        
        # Mark as completed if checkup
        if reminder_type == 'checkup':
            db.mark_treatment_completed(reminder['purchase_id'])
    
    return {"reminders": reminders}

@app.get("/generate-weekly-report")
async def api_generate_weekly_report():
    """API endpoint for weekly report generation"""
    result = generate_weekly_report()
    return {"report": result["reply"]}

@app.get("/health")
async def health_check():
    return {
        "status": "healthy", 
        "service": "Ejide Pharmacy API",
        "features": [
            "24/7 WhatsApp engagement",
            "AI-powered inventory",
            "Medication reminders",
            "Smart shopping cart",
            "Predictive analytics",
            "On-demand admin reports"
        ]
    }