Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.git
.gitignore
.venv
venv
__pycache__
*.pyc
*.pyo
.pytest_cache
.mypy_cache
.dmypy.json
.ruff_cache
.coverage
htmlcov

node_modules
frontend/node_modules
frontend/dist
frontend/.vite

chroma_db
backend/chroma_db
*.log

docs
evals
.claude
.github
*.md
!README.md

.env
.env.*
!.env.example
.DS_Store
1 change: 1 addition & 0 deletions Dockerfile.backend
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ COPY --from=builder /build/packages /usr/local/lib/python3.12/site-packages
COPY backend/ .
EXPOSE 8000
ENV PYTHONPATH=/app
ENV PATH="/usr/local/lib/python3.12/site-packages/bin:${PATH}"
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,13 @@ cd procureai

```bash
cp backend/.env.example backend/.env # then fill in your API keys
python backend/data/seed.py # seed MongoDB with sample data
```

Sample data (suppliers, bids) is seeded automatically into MongoDB on first startup.
To re-seed manually:

```bash
cd backend && PYTHONPATH=. python data/seed.py
```

Start the backend server:
Expand Down
4 changes: 2 additions & 2 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ SENTRY_ENVIRONMENT=development
APP_VERSION=procureai@dev

# LangSmith
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=your_langsmith_api_key_here
LANGCHAIN_TRACING_V2=false
LANGCHAIN_API_KEY=
LANGCHAIN_PROJECT=procureai
28 changes: 18 additions & 10 deletions backend/data/seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,24 +223,32 @@
]


async def seed_database():
load_dotenv()
mongodb_url = os.getenv("MONGODB_URI", "mongodb://localhost:27017")
client = AsyncIOMotorClient(mongodb_url)
db = client.procureai
async def seed_if_empty(db) -> bool:
if await db.suppliers.count_documents({}, limit=1):
return False

# Insert suppliers
supplier_ids = {}
for i, supplier in enumerate(mock_suppliers):
result = await db.suppliers.insert_one(supplier.dict(by_alias=True))
result = await db.suppliers.insert_one(supplier.model_dump(by_alias=True))
supplier_ids[str(i + 1)] = str(result.inserted_id)

# Update bids with actual supplier_ids
for bid in mock_bids:
bid.supplier_id = supplier_ids[bid.supplier_id]
await db.bids.insert_one(bid.dict(by_alias=True))
await db.bids.insert_one(bid.model_dump(by_alias=True))

return True


async def seed_database():
load_dotenv()
mongodb_url = os.getenv("MONGODB_URI", "mongodb://localhost:27017")
client = AsyncIOMotorClient(mongodb_url)
db = client.procureai

print("Seed data inserted successfully!")
if await seed_if_empty(db):
print("Seed data inserted successfully!")
else:
print("Suppliers collection is not empty, skipping seed.")


if __name__ == "__main__":
Expand Down
44 changes: 27 additions & 17 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ async def lifespan(app: FastAPI):
await db.audit_logs.create_index([("user_id", 1), ("timestamp", -1)])
# await db.audit_logs.create_index("timestamp", expireAfterSeconds=90*24*60*60)

from data.seed import seed_if_empty

await seed_if_empty(db)

if is_vectorstore_empty():
pdf_dir = Path(settings.CHROMA_PATH).parent / "data" / "pdfs"
if pdf_dir.exists():
Expand All @@ -65,23 +69,29 @@ async def lifespan(app: FastAPI):
except Exception as exc:
log.error("pdf_ingest_failed", file=pdf_path.name, error=str(exc))
# --- Superuser seed ---
from crud.user import create_user, get_user_by_email
from schemas.user import UserCreate

existing = await get_user_by_email(db, settings.FIRST_SUPERUSER_EMAIL)
if not existing:
superuser_in = UserCreate(
email=settings.FIRST_SUPERUSER_EMAIL,
password=settings.FIRST_SUPERUSER_PASSWORD,
full_name="Admin",
)
user_doc = await create_user(db, superuser_in)
if user_doc:
await db.users.update_one(
{"email": settings.FIRST_SUPERUSER_EMAIL},
{"$set": {"is_superuser": True, "role": "admin"}},
)
log.info("superuser_created", email=settings.FIRST_SUPERUSER_EMAIL)
from datetime import datetime, timezone

from auth.security import get_password_hash
from bson import ObjectId

upsert_result = await db.users.update_one(
{"email": settings.FIRST_SUPERUSER_EMAIL},
{
"$setOnInsert": {
"_id": str(ObjectId()),
"email": settings.FIRST_SUPERUSER_EMAIL,
"hashed_password": get_password_hash(settings.FIRST_SUPERUSER_PASSWORD),
"full_name": "Admin",
"is_active": True,
"is_superuser": True,
"role": "admin",
"created_at": datetime.now(timezone.utc),
}
},
upsert=True,
)
if upsert_result.upserted_id:
log.info("superuser_created", email=settings.FIRST_SUPERUSER_EMAIL)
else:
log.info("superuser_exists", email=settings.FIRST_SUPERUSER_EMAIL)
yield
Expand Down
6 changes: 2 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.9"

services:
backend:
build:
Expand All @@ -9,9 +7,9 @@ services:
INSTALL_RERANK: ${INSTALL_RERANK:-false}
ports:
- "8000:8000"
env_file:
- backend/.env
environment:
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
OPENAI_API_KEY: ${OPENAI_API_KEY}
MONGODB_URI: mongodb://mongo:27017
CHROMA_PATH: /app/chroma_db
ALLOWED_ORIGINS: http://localhost:3000,http://frontend
Expand Down
Loading