File size: 14,994 Bytes
419099f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Seed Generic Medicine Catalog

This script populates the generic_catalog table with medicine data.
Can be extended to load data from:
- Jan Aushadhi Product List (PMBI)
- CDSCO Generic Medicine List
- Custom CSV files

Usage:
    python -m scripts.seed_generic_catalog
    
Or within Docker:
    docker exec -it ggw-backend python -m scripts.seed_generic_catalog
"""
import asyncio
import csv
import logging
from pathlib import Path
from typing import List, Dict, Any
from uuid import uuid4

# Setup Django-style imports
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Sample Jan Aushadhi medicines data
# In production, load from official PMBI CSV
SAMPLE_JAN_AUSHADHI_DATA = [
    # Format: (product_name, salt, strength, form, release_type, mrp, manufacturer)
    ("Paracetamol IP 500mg", "Paracetamol", "500mg", "tablet", None, 6.80, "PMBI"),
    ("Paracetamol IP 650mg", "Paracetamol", "650mg", "tablet", None, 8.50, "PMBI"),
    ("Metformin Hydrochloride IP 500mg", "Metformin", "500mg", "tablet", None, 12.50, "PMBI"),
    ("Metformin Hydrochloride IP 500mg SR", "Metformin", "500mg", "tablet", "SR", 15.00, "PMBI"),
    ("Metformin Hydrochloride IP 850mg", "Metformin", "850mg", "tablet", None, 18.00, "PMBI"),
    ("Metformin Hydrochloride IP 1000mg SR", "Metformin", "1000mg", "tablet", "SR", 22.00, "PMBI"),
    ("Atorvastatin IP 10mg", "Atorvastatin", "10mg", "tablet", None, 25.00, "PMBI"),
    ("Atorvastatin IP 20mg", "Atorvastatin", "20mg", "tablet", None, 35.00, "PMBI"),
    ("Atorvastatin IP 40mg", "Atorvastatin", "40mg", "tablet", None, 48.00, "PMBI"),
    ("Amlodipine IP 5mg", "Amlodipine", "5mg", "tablet", None, 8.00, "PMBI"),
    ("Amlodipine IP 10mg", "Amlodipine", "10mg", "tablet", None, 12.00, "PMBI"),
    ("Losartan Potassium IP 25mg", "Losartan", "25mg", "tablet", None, 15.00, "PMBI"),
    ("Losartan Potassium IP 50mg", "Losartan", "50mg", "tablet", None, 22.00, "PMBI"),
    ("Losartan Potassium IP 100mg", "Losartan", "100mg", "tablet", None, 35.00, "PMBI"),
    ("Telmisartan IP 20mg", "Telmisartan", "20mg", "tablet", None, 18.00, "PMBI"),
    ("Telmisartan IP 40mg", "Telmisartan", "40mg", "tablet", None, 25.00, "PMBI"),
    ("Telmisartan IP 80mg", "Telmisartan", "80mg", "tablet", None, 38.00, "PMBI"),
    ("Omeprazole IP 20mg", "Omeprazole", "20mg", "capsule", None, 12.00, "PMBI"),
    ("Pantoprazole IP 40mg", "Pantoprazole", "40mg", "tablet", None, 18.00, "PMBI"),
    ("Rabeprazole IP 20mg", "Rabeprazole", "20mg", "tablet", None, 22.00, "PMBI"),
    ("Cetirizine IP 10mg", "Cetirizine", "10mg", "tablet", None, 5.00, "PMBI"),
    ("Levocetirizine IP 5mg", "Levocetirizine", "5mg", "tablet", None, 8.00, "PMBI"),
    ("Azithromycin IP 250mg", "Azithromycin", "250mg", "tablet", None, 45.00, "PMBI"),
    ("Azithromycin IP 500mg", "Azithromycin", "500mg", "tablet", None, 65.00, "PMBI"),
    ("Amoxicillin IP 250mg", "Amoxicillin", "250mg", "capsule", None, 15.00, "PMBI"),
    ("Amoxicillin IP 500mg", "Amoxicillin", "500mg", "capsule", None, 25.00, "PMBI"),
    ("Ciprofloxacin IP 250mg", "Ciprofloxacin", "250mg", "tablet", None, 18.00, "PMBI"),
    ("Ciprofloxacin IP 500mg", "Ciprofloxacin", "500mg", "tablet", None, 28.00, "PMBI"),
    ("Ibuprofen IP 200mg", "Ibuprofen", "200mg", "tablet", None, 8.00, "PMBI"),
    ("Ibuprofen IP 400mg", "Ibuprofen", "400mg", "tablet", None, 12.00, "PMBI"),
    ("Diclofenac Sodium IP 50mg", "Diclofenac", "50mg", "tablet", None, 10.00, "PMBI"),
    ("Aspirin IP 75mg", "Aspirin", "75mg", "tablet", None, 5.00, "PMBI"),
    ("Aspirin IP 150mg", "Aspirin", "150mg", "tablet", None, 8.00, "PMBI"),
    ("Clopidogrel IP 75mg", "Clopidogrel", "75mg", "tablet", None, 18.00, "PMBI"),
    ("Rosuvastatin IP 5mg", "Rosuvastatin", "5mg", "tablet", None, 22.00, "PMBI"),
    ("Rosuvastatin IP 10mg", "Rosuvastatin", "10mg", "tablet", None, 32.00, "PMBI"),
    ("Rosuvastatin IP 20mg", "Rosuvastatin", "20mg", "tablet", None, 45.00, "PMBI"),
    ("Glimepiride IP 1mg", "Glimepiride", "1mg", "tablet", None, 15.00, "PMBI"),
    ("Glimepiride IP 2mg", "Glimepiride", "2mg", "tablet", None, 22.00, "PMBI"),
    ("Gliclazide IP 40mg", "Gliclazide", "40mg", "tablet", None, 18.00, "PMBI"),
    ("Gliclazide IP 80mg", "Gliclazide", "80mg", "tablet", None, 28.00, "PMBI"),
    ("Sitagliptin IP 50mg", "Sitagliptin", "50mg", "tablet", None, 85.00, "PMBI"),
    ("Sitagliptin IP 100mg", "Sitagliptin", "100mg", "tablet", None, 120.00, "PMBI"),
    ("Vildagliptin IP 50mg", "Vildagliptin", "50mg", "tablet", None, 75.00, "PMBI"),
    ("Empagliflozin IP 10mg", "Empagliflozin", "10mg", "tablet", None, 95.00, "PMBI"),
    ("Empagliflozin IP 25mg", "Empagliflozin", "25mg", "tablet", None, 130.00, "PMBI"),
    ("Dapagliflozin IP 5mg", "Dapagliflozin", "5mg", "tablet", None, 88.00, "PMBI"),
    ("Dapagliflozin IP 10mg", "Dapagliflozin", "10mg", "tablet", None, 115.00, "PMBI"),
    ("Linagliptin IP 5mg", "Linagliptin", "5mg", "tablet", None, 145.00, "PMBI"),
    ("Ramipril IP 2.5mg", "Ramipril", "2.5mg", "tablet", None, 12.00, "PMBI"),
    ("Ramipril IP 5mg", "Ramipril", "5mg", "tablet", None, 18.00, "PMBI"),
    ("Enalapril IP 2.5mg", "Enalapril", "2.5mg", "tablet", None, 10.00, "PMBI"),
    ("Enalapril IP 5mg", "Enalapril", "5mg", "tablet", None, 15.00, "PMBI"),
    ("Bisoprolol IP 2.5mg", "Bisoprolol", "2.5mg", "tablet", None, 12.00, "PMBI"),
    ("Bisoprolol IP 5mg", "Bisoprolol", "5mg", "tablet", None, 18.00, "PMBI"),
    ("Metoprolol Succinate IP 25mg XL", "Metoprolol", "25mg", "tablet", "XL", 22.00, "PMBI"),
    ("Metoprolol Succinate IP 50mg XL", "Metoprolol", "50mg", "tablet", "XL", 32.00, "PMBI"),
    ("Nebivolol IP 2.5mg", "Nebivolol", "2.5mg", "tablet", None, 25.00, "PMBI"),
    ("Nebivolol IP 5mg", "Nebivolol", "5mg", "tablet", None, 38.00, "PMBI"),
    ("Hydrochlorothiazide IP 12.5mg", "Hydrochlorothiazide", "12.5mg", "tablet", None, 8.00, "PMBI"),
    ("Hydrochlorothiazide IP 25mg", "Hydrochlorothiazide", "25mg", "tablet", None, 12.00, "PMBI"),
    ("Furosemide IP 40mg", "Furosemide", "40mg", "tablet", None, 10.00, "PMBI"),
    ("Spironolactone IP 25mg", "Spironolactone", "25mg", "tablet", None, 18.00, "PMBI"),
    ("Spironolactone IP 50mg", "Spironolactone", "50mg", "tablet", None, 28.00, "PMBI"),
    ("Montelukast IP 10mg", "Montelukast", "10mg", "tablet", None, 35.00, "PMBI"),
    ("Salbutamol IP 2mg", "Salbutamol", "2mg", "tablet", None, 8.00, "PMBI"),
    ("Salbutamol IP 4mg", "Salbutamol", "4mg", "tablet", None, 12.00, "PMBI"),
    ("Levothyroxine Sodium IP 25mcg", "Levothyroxine", "25mcg", "tablet", None, 15.00, "PMBI"),
    ("Levothyroxine Sodium IP 50mcg", "Levothyroxine", "50mcg", "tablet", None, 18.00, "PMBI"),
    ("Levothyroxine Sodium IP 100mcg", "Levothyroxine", "100mcg", "tablet", None, 22.00, "PMBI"),
    ("Calcium Carbonate IP 500mg + Vitamin D3 250IU", "Calcium+Vitamin D3", "500mg+250IU", "tablet", None, 12.00, "PMBI"),
    ("Folic Acid IP 5mg", "Folic Acid", "5mg", "tablet", None, 8.00, "PMBI"),
    ("Ferrous Sulfate IP 200mg", "Ferrous Sulfate", "200mg", "tablet", None, 10.00, "PMBI"),
    ("Vitamin B Complex", "Vitamin B Complex", "", "tablet", None, 15.00, "PMBI"),
    ("Multivitamin Tablets", "Multivitamin", "", "tablet", None, 18.00, "PMBI"),
]

# Common generic alternatives (non-Jan-Aushadhi)
GENERIC_ALTERNATIVES = [
    ("Metformin 500mg Tab", "Metformin", "500mg", "tablet", None, 25.00, "Generic Pharma"),
    ("Metformin 500mg SR Tab", "Metformin", "500mg", "tablet", "SR", 35.00, "Generic Pharma"),
    ("Metformin 850mg Tab", "Metformin", "850mg", "tablet", None, 38.00, "Generic Pharma"),
    ("Atorvastatin 10mg Tab", "Atorvastatin", "10mg", "tablet", None, 55.00, "Generic Pharma"),
    ("Atorvastatin 20mg Tab", "Atorvastatin", "20mg", "tablet", None, 85.00, "Generic Pharma"),
    ("Amlodipine 5mg Tab", "Amlodipine", "5mg", "tablet", None, 22.00, "Generic Pharma"),
    ("Losartan 50mg Tab", "Losartan", "50mg", "tablet", None, 48.00, "Generic Pharma"),
    ("Telmisartan 40mg Tab", "Telmisartan", "40mg", "tablet", None, 55.00, "Generic Pharma"),
    ("Pantoprazole 40mg Tab", "Pantoprazole", "40mg", "tablet", None, 38.00, "Generic Pharma"),
    ("Cetirizine 10mg Tab", "Cetirizine", "10mg", "tablet", None, 12.00, "Generic Pharma"),
    ("Azithromycin 500mg Tab", "Azithromycin", "500mg", "tablet", None, 125.00, "Generic Pharma"),
    ("Paracetamol 500mg Tab", "Paracetamol", "500mg", "tablet", None, 15.00, "Generic Pharma"),
    ("Paracetamol 650mg Tab", "Paracetamol", "650mg", "tablet", None, 22.00, "Generic Pharma"),
]


async def seed_database(database_url: str):
    """Seed the generic_catalog table with medicine data."""
    
    # Create async engine
    engine = create_async_engine(database_url, echo=False)
    async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
    
    async with async_session() as session:
        # Check if table exists and has data
        try:
            result = await session.execute(text("SELECT COUNT(*) FROM generic_catalog"))
            count = result.scalar()
            if count > 0:
                logger.info(f"generic_catalog already has {count} entries. Skipping seed.")
                logger.info("To re-seed, truncate the table first: TRUNCATE generic_catalog;")
                return
        except Exception as e:
            logger.error(f"Table check failed: {e}")
            logger.info("Make sure to run database migrations first!")
            return
        
        # Insert Jan Aushadhi data
        logger.info("Seeding Jan Aushadhi medicines...")
        for item in SAMPLE_JAN_AUSHADHI_DATA:
            product_name, salt, strength, form, release_type, mrp, manufacturer = item
            await session.execute(
                text("""
                    INSERT INTO generic_catalog 
                    (id, product_name, salt, strength, form, release_type, mrp, manufacturer, source, is_jan_aushadhi, created_at)
                    VALUES (:id, :product_name, :salt, :strength, :form, :release_type, :mrp, :manufacturer, :source, :is_jan_aushadhi, NOW())
                """),
                {
                    "id": str(uuid4()),
                    "product_name": product_name,
                    "salt": salt,
                    "strength": strength,
                    "form": form,
                    "release_type": release_type,
                    "mrp": mrp,
                    "manufacturer": manufacturer,
                    "source": "PMBI Jan Aushadhi",
                    "is_jan_aushadhi": True
                }
            )
        
        # Insert generic alternatives
        logger.info("Seeding generic alternatives...")
        for item in GENERIC_ALTERNATIVES:
            product_name, salt, strength, form, release_type, mrp, manufacturer = item
            await session.execute(
                text("""
                    INSERT INTO generic_catalog 
                    (id, product_name, salt, strength, form, release_type, mrp, manufacturer, source, is_jan_aushadhi, created_at)
                    VALUES (:id, :product_name, :salt, :strength, :form, :release_type, :mrp, :manufacturer, :source, :is_jan_aushadhi, NOW())
                """),
                {
                    "id": str(uuid4()),
                    "product_name": product_name,
                    "salt": salt,
                    "strength": strength,
                    "form": form,
                    "release_type": release_type,
                    "mrp": mrp,
                    "manufacturer": manufacturer,
                    "source": "Generic",
                    "is_jan_aushadhi": False
                }
            )
        
        await session.commit()
        
        # Verify
        result = await session.execute(text("SELECT COUNT(*) FROM generic_catalog"))
        count = result.scalar()
        logger.info(f"Successfully seeded {count} medicines to generic_catalog!")


async def seed_from_csv(database_url: str, csv_path: str):
    """
    Seed from a CSV file.
    
    Expected CSV columns:
    product_name, salt, strength, form, release_type, mrp, manufacturer, source, is_jan_aushadhi
    """
    csv_file = Path(csv_path)
    if not csv_file.exists():
        logger.error(f"CSV file not found: {csv_path}")
        return
    
    engine = create_async_engine(database_url, echo=False)
    async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
    
    async with async_session() as session:
        with open(csv_file, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            count = 0
            
            for row in reader:
                try:
                    await session.execute(
                        text("""
                            INSERT INTO generic_catalog 
                            (id, product_name, salt, strength, form, release_type, mrp, manufacturer, source, is_jan_aushadhi, created_at)
                            VALUES (:id, :product_name, :salt, :strength, :form, :release_type, :mrp, :manufacturer, :source, :is_jan_aushadhi, NOW())
                            ON CONFLICT DO NOTHING
                        """),
                        {
                            "id": str(uuid4()),
                            "product_name": row.get('product_name', ''),
                            "salt": row.get('salt', ''),
                            "strength": row.get('strength', ''),
                            "form": row.get('form', 'tablet'),
                            "release_type": row.get('release_type') or None,
                            "mrp": float(row.get('mrp', 0)) if row.get('mrp') else None,
                            "manufacturer": row.get('manufacturer', ''),
                            "source": row.get('source', 'CSV Import'),
                            "is_jan_aushadhi": row.get('is_jan_aushadhi', '').lower() in ('true', '1', 'yes')
                        }
                    )
                    count += 1
                except Exception as e:
                    logger.error(f"Error inserting row: {row}, error: {e}")
            
            await session.commit()
            logger.info(f"Imported {count} medicines from CSV")


if __name__ == "__main__":
    import os
    
    # Get database URL from environment or use default
    database_url = os.getenv(
        "DATABASE_URL",
        "postgresql+asyncpg://ggw:ggwpassword@localhost:5432/ggwdb"
    )
    
    # Check for CSV argument
    if len(sys.argv) > 1:
        csv_path = sys.argv[1]
        logger.info(f"Seeding from CSV: {csv_path}")
        asyncio.run(seed_from_csv(database_url, csv_path))
    else:
        logger.info("Seeding with sample data...")
        asyncio.run(seed_database(database_url))