# Ecoloop Backend Ecoloop is a Django + DRF backend for recycling businesses and factories to manage pickups, pricing, invoices/payouts, and a bidding marketplace for scrap lots. It supports multi-organization setups, JWT auth, and a Tailwind-powered UI layer. ## Quick Start - Requirements: Python 3.11, Postgres, Node (for Tailwind in dev) - Environment: copy `.env` and set `SECRET_KEY`, `DEBUG`, `DB_*`, `ALLOWED_HOSTS` - Run (Docker): `docker-compose up --build` (web on http://localhost:8024) - Run (local): - `python manage.py migrate` - `python manage.py runserver` - Optional demo: `python manage.py seed_ecoloop` - API docs: Swagger UI at `/api/schema/swagger-ui/` ## Project Scopes (Summary) - Core operations: customers, sites, service agreements, materials, units; pickup lifecycle (request → schedule/assign → collect → weigh ticket → complete). - Pricing & finance: org/customer price lists (buy/sell), invoice generation from weigh tickets, payments, and payouts for buy-priced materials. - Bidding marketplace: factories post scrap listings (open/invite-only), recyclers bid with min-increment/reserve; award creates a pickup order. - Users & portal: roles (owner, manager, driver, customer, auditor); JWT auth; customer/driver-facing endpoints for assignments and status. - Compliance & docs: upload/attach documents (proofs, photos, certificates); audit logs for key state changes. - Reporting: benefit leaderboards and volume/revenue summaries (period filters). - Multi-org & locale: organization scoping, currency codes (THB/USD), units (kg/lb); env-driven config. ## Key Commands - `python manage.py migrate` — apply DB migrations - `python manage.py seed_ecoloop` — seed demo org, users, materials, pickup, weigh ticket, invoice, listing/bid - `python manage.py ecoloop_auto_close_award` — auto-close/award expired listings ## Multisite (Local Testing) - Purpose: Serve multiple sites on one codebase using Django Sites. - Config: - Enabled in `ecoloop/settings.py` via `django.contrib.sites` and `SITE_ID`. - `.env` includes defaults for local hosts: `ALLOWED_HOSTS=localhost,127.0.0.1,.lvh.me` - `.env` CSRF for Docker port: `CSRF_TRUSTED_ORIGINS=http://localhost:8024,http://*.lvh.me:8024` - Run: - `python manage.py migrate` (applies Sites tables) - In Admin → Sites, add domains like `alpha.lvh.me` and `beta.lvh.me`. - Visit `http://alpha.lvh.me:8024` and `http://beta.lvh.me:8024`. - Attach site-specific content in apps (e.g., CMS) by filtering on `get_current_site(request)` or adding a `ForeignKey` to `Site`. ## Structure - `ecoloop/` settings and URLs; `api/` public endpoints; `recycle_core/` domain models/APIs - Assets: `templates/`, `static/`, `media/`; Entrypoints: `manage.py`, `docker-compose.yml`, `Dockerfile` ## System Features & Use Cases ### Core Features - Materials: Master data with categories, units, and images; org‑scoped. - Customers & Sites: Accounts with multiple pickup locations and contacts. - Pickups: Lifecycle from request → schedule/assign → collect → weigh → invoice. - Weigh Tickets: Gross/tare/net with per‑material lines; optional finalize; audit trail. - Pricing: Org/customer price lists with buy/sell directions per material/unit. - Billing: Invoices from weigh tickets, payments tracking, and customer payouts from buy prices. - Marketplace: Scrap listings (open/invite‑only), bids, reserve/min‑increment, awarding creates a pickup. - Documents: File uploads attached to any record (leads, tickets, invoices, etc.). - Audit Logs: Structured entries for key actions (assignment, status change, award, invoice generation). - Leaderboard: User‑to‑user benefit scoring and rankings. ### Operational Flows - Request Intake: Public “Pickup Request” creates a Lead and optional attached Documents. - Scheduling: Manager assigns a driver and sets pickup status/schedule. - Collection: Driver updates statuses (`en_route`, `collecting`, `at_facility`). - Weighing: Create `WeighTicket` and `WeighLine`s per material; optional finalize. - Invoicing: Generate invoice from tickets; sell lines to customer, buy‑price payouts to customer. - Completion: Mark pickup completed; reconcile statuses and financials. ### Marketplace - Listings: Title/description, auction type (open/sealed), reserve, min increment, time window. - Visibility: Public or invite‑only via `ScrapListingInvite`. - Bidding: Validates status/time window, invite list, min increment, bidder org/role. - Awarding: Manual via API/action or auto (`ecoloop_auto_close_award`); accepts top qualifying bid, rejects others, creates a `PickupOrder`. ### Pricing & Finance - Price Lists: Org‑level with currency; customer can reference a list. - Sell vs Buy: Sell determines invoice lines; Buy determines `Payout` to customer. - Invoice Lifecycle: Draft/Issued/Paid/Void; due date; payments tracked. - Regeneration: Rebuild draft invoice lines if ticket lines/prices change (before issuing). ### Compliance & Carbon - Documents: Attach proofs, photos, and certificates to any object via generic relation. - Audit Trail: `AuditLog` records important actions and metadata. - Emission Factors: Per material/unit kgCO2e, configurable per org with effective dates. ### Users & Access - Roles: Owner/Manager/Driver/Customer/Auditor via `UserProfile` per organization. - Auth: JWT via Djoser (`/auth/`), optional social auth (Google/LINE/Facebook). - Multisite: Django Sites; map domains to orgs via `OrganizationSite`. ### API & Admin - REST API: DRF viewsets for core/billing/marketplace under `/api/`, filterable, with custom actions: - `pickups/{id}/assign`, `pickups/{id}/set_status` - `weigh-tickets/{id}/generate_invoice` - `scrap-listings/{id}/open`, `scrap-listings/{id}/close`, `scrap-awards/award-listing/` - Matching & Leaderboard: - `profiles/match/`, `opportunities/recommend/` - `leaderboard/` (public), `leaderboard/me/` (auth) - Admin UI: `/webadmin/…` routes for orgs, billing, recycle core, CMS, settings. - API Docs: Swagger at `/api/schema/swagger-ui/`. ### Typical Use Cases - Factory Pickup - Staff submits Pickup Request (lead + photos). - Manager creates `PickupOrder`, assigns driver, schedules. - Driver collects and records `WeighTicket` with material lines. - Invoicing generates sell lines; system issues payout when buy prices exist. - Finance records `Payment`; pickup moves to invoiced/completed. - Marketplace Sale - Factory posts `ScrapListing` with estimated quantities and a bidding window. - Invites recyclers or opens publicly; bidders place `ScrapBid`s. - On close/expiry, award highest valid bid (reserve honored); `PickupOrder` auto‑created. - Proceed with weighing and invoicing as standard. - Price Review & Adjustments - Update `PriceListItem` sell/buy rates by material/unit. - Regenerate draft invoices when ticket lines change before issuing. - Compliance & Reporting - Upload certificates/photos as `Document`s linked to tickets/invoices. - Review `AuditLog` for status changes and financial actions. - Use leaderboard and summaries for engagement and impact reporting. ## API Quick Links - Docs: `/api/schema/swagger-ui/` (interactive), `/api/schema/redoc/` - Auth (Djoser + JWT): - `POST /auth/jwt/create/` (get token) - `POST /auth/users/` (register), `GET /auth/users/me/` - Public API: - Profiles: `GET/POST /api/profiles/`, `GET /api/profiles/match/` - Opportunities: `GET/POST /api/opportunities/`, `GET /api/opportunities/recommend/` - Leaderboard: `GET /api/leaderboard/`, `GET /api/leaderboard/me/` - Core domain: - Orgs: `/api/organizations/` - Materials: `/api/material-categories/`, `/api/materials/` - Pricing: `/api/price-lists/`, `/api/price-list-items/` - Customers: `/api/customers/`, `/api/customer-sites/`, `/api/service-agreements/` - Pickups: `/api/pickups/` (actions: `POST /api/pickups/{id}/assign/`, `POST /api/pickups/{id}/set_status/`) - Weighing: `/api/weigh-tickets/` (action: `POST /api/weigh-tickets/{id}/generate_invoice/`), `/api/weigh-lines/` - Documents & Audit: `/api/documents/`, `/api/audit-logs/` - Billing: - Invoices: `/api/invoices/`, lines: `/api/invoice-lines/` - Payments: `/api/payments/`, Payouts: `/api/payouts/` - Marketplace: - Listings: `/api/scrap-listings/` (actions: `POST /api/scrap-listings/{id}/open/`, `POST /api/scrap-listings/{id}/close/`) - Items: `/api/scrap-listing-items/` - Bids: `/api/scrap-bids/` (action: `POST /api/scrap-bids/{id}/retract/`) - Award: `POST /api/scrap-awards/award-listing/` - Invites: `/api/scrap-listing-invites/` ## Verification Checklists ### Auth & Setup - Configure `.env` and run DB: `docker-compose up --build` or `python manage.py migrate && runserver`. - Optional: seed demo data: `python manage.py seed_ecoloop` (creates users `manager/manager123`, `driver/driver123`, `buyer/buyer123`). - Obtain JWT: `POST /auth/jwt/create/` with seeded credentials, use `Authorization: Bearer ` for protected endpoints. ### Pickup Lifecycle - Create customer/site/material (if not seeded): `POST /api/customers/`, `/api/customer-sites/`, `/api/materials/`. - Create pickup: `POST /api/pickups/` with `organization`, `customer`, `site`. - Assign driver: `POST /api/pickups/{id}/assign/ {"driver_id": }`; confirm status `scheduled`. - Update statuses: `POST /api/pickups/{id}/set_status/` → `en_route` → `collecting` → `at_facility`. - Add weigh ticket: `POST /api/weigh-tickets/` + lines via `/api/weigh-lines/`. - Generate invoice: `POST /api/weigh-tickets/{id}/generate_invoice/`; verify invoice under `/api/invoices/` and any payout under `/api/payouts/`. - Complete pickup: `POST /api/pickups/{id}/set_status/ {"status": "completed"}`. ### Marketplace Flow - Create listing: `POST /api/scrap-listings/` (status defaults to `draft`). - Open listing: `POST /api/scrap-listings/{id}/open/`; optionally add invites via `/api/scrap-listing-invites/`. - Place bid: `POST /api/scrap-bids/` with `listing`, `bidder_org`, `price_total` (ensure role and invite if private). - Close or auto-close: `POST /api/scrap-listings/{id}/close/` or run `python manage.py ecoloop_auto_close_award`. - Award: `POST /api/scrap-awards/award-listing/ {"listing_id": }`; verify pickup created and proceed with weighing/invoicing. ### Billing & Pricing - Ensure price list with sell/buy items exists: `/api/price-lists/`, `/api/price-list-items/`. - After invoice generation, create payment: `POST /api/payments/ {"invoice": , "amount": ...}`. - Regenerate draft invoice when needed: use business flow that keeps status `draft`, then rebuild lines (see service `regenerate_invoice_for_pickup`). ### Documents & Audit - Submit public pickup request (UI) to create `Lead` and auto‑attach uploaded files as `Document`s. - Or directly upload: `POST /api/documents/` with file and content object. - Review audit entries: `GET /api/audit-logs/` after actions like assign, set_status, generate_invoice, award.