chore: migrate Python dependency management from pip to uv and update project tooling
This commit is contained in:
parent
24ccf66546
commit
932afb18d7
20 changed files with 2661 additions and 1320 deletions
21
.github/workflows/tests.yml
vendored
21
.github/workflows/tests.yml
vendored
|
|
@ -25,12 +25,11 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@v5
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: backend/requirements.txt
|
||||
enable-cache: true
|
||||
cache-dependency-glob: 'backend/uv.lock'
|
||||
|
||||
- name: Install system dependencies (WeasyPrint)
|
||||
run: |
|
||||
|
|
@ -43,9 +42,8 @@ jobs:
|
|||
shared-mime-info
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r backend/requirements.txt
|
||||
working-directory: backend
|
||||
run: uv sync --frozen
|
||||
|
||||
- name: Run tests with coverage
|
||||
working-directory: backend
|
||||
|
|
@ -53,15 +51,12 @@ jobs:
|
|||
DJANGO_SETTINGS_MODULE: crm.test_settings
|
||||
SECRET_KEY: test-secret-key-for-ci
|
||||
ADMIN_EMAIL: admin@test.com
|
||||
run: |
|
||||
pytest -m "not postgres_only" --tb=short -v
|
||||
run: uv run pytest -m "not postgres_only" --tb=short -v
|
||||
|
||||
- name: Generate coverage badge
|
||||
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
||||
working-directory: backend
|
||||
run: |
|
||||
pip install "genbadge[coverage]"
|
||||
genbadge coverage -i coverage.xml -o ../coverage-badge.svg
|
||||
run: uvx --from "genbadge[coverage]" genbadge coverage -i coverage.xml -o ../coverage-badge.svg
|
||||
|
||||
- name: Commit coverage badge
|
||||
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
||||
|
|
|
|||
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -27,6 +27,12 @@ venv/
|
|||
.venv/
|
||||
ENV/
|
||||
|
||||
# Python build artifacts
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
*.egg
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
|
@ -38,6 +44,10 @@ ENV/
|
|||
.pytest_cache/
|
||||
htmlcov/
|
||||
coverage.xml
|
||||
|
||||
# Linter / type checker caches
|
||||
.ruff_cache/
|
||||
.mypy_cache/
|
||||
coverage-badge.svg
|
||||
|
||||
# Documentation
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
onCreate:
|
||||
- sudo apt-get update -y
|
||||
- sudo apt install python-is-python3 xvfb libfontconfig wkhtmltopdf libpq-dev python3-dev python3-pip build-essential libssl-dev libffi-dev python3-venv redis-server redis-tools virtualenv zsh python3-virtualenv -y
|
||||
- sudo apt install python-is-python3 xvfb libfontconfig wkhtmltopdf libpq-dev python3-dev build-essential libssl-dev libffi-dev redis-server redis-tools zsh -y
|
||||
- |
|
||||
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
||||
|
|
@ -10,15 +10,14 @@ onCreate:
|
|||
sudo -u postgres psql postgres -c "ALTER USER postgres PASSWORD 'root'"
|
||||
sudo -u postgres psql postgres -c "CREATE DATABASE bottlecrm WITH OWNER = postgres"
|
||||
- |
|
||||
virtualenv -p python3 ../venv
|
||||
. ../venv/bin/activate
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
cp ENV.md .env
|
||||
pip install -U pip
|
||||
pip install -r requirements.txt
|
||||
python manage.py migrate
|
||||
uv sync --frozen
|
||||
uv run python manage.py migrate
|
||||
onStart:
|
||||
- |
|
||||
. ../venv/bin/activate
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
WS_DOMAIN=`cat /home/ubuntu/runcode/ws-url-domain.txt`
|
||||
printf "\nGO TO THIS URL TO VIEW PAGE \033[4;34m https://8000-${WS_DOMAIN}\033[0;30m\n\n"
|
||||
python manage.py runserver
|
||||
uv run python manage.py runserver
|
||||
|
|
|
|||
12
Dockerfile
12
Dockerfile
|
|
@ -17,11 +17,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
# Install Python dependencies (layer cached)
|
||||
COPY backend/requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
# Install uv (fast Python package manager).
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.11 /uv /usr/local/bin/uv
|
||||
|
||||
# Install Python dependencies into /app/.venv (layer cached on lockfile changes)
|
||||
COPY backend/pyproject.toml backend/uv.lock backend/.python-version ./
|
||||
RUN uv sync --frozen --no-install-project
|
||||
|
||||
# Copy backend source
|
||||
COPY backend/ .
|
||||
|
||||
# Put the venv's binaries on PATH so `python`, `gunicorn`, `celery` etc. resolve.
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
EXPOSE 8000
|
||||
|
|
|
|||
42
README.md
42
README.md
|
|
@ -67,31 +67,50 @@ BottleCRM is a full-featured Customer Relationship Management system designed fo
|
|||
|
||||
### Backend Setup
|
||||
|
||||
The backend uses [`uv`](https://docs.astral.sh/uv/) for Python dependency management — it reads `pyproject.toml`, installs from `uv.lock`, and creates the virtual environment for you. uv is much faster than pip and gives reproducible installs out of the box.
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/MicroPyramid/Django-CRM.git
|
||||
cd Django-CRM
|
||||
cd Django-CRM/backend
|
||||
|
||||
# Create and activate virtual environment
|
||||
cd backend
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
# Install uv (one time, system-wide)
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
# Or on macOS via Homebrew: brew install uv
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
# Install Python (matches the version in .python-version) and all deps into .venv/
|
||||
uv sync
|
||||
|
||||
# Set up environment variables (see env.md for details)
|
||||
cp .env.example .env
|
||||
# Edit .env with your database and other settings
|
||||
|
||||
# Run migrations
|
||||
python manage.py migrate
|
||||
uv run python manage.py migrate
|
||||
|
||||
# Create a superuser
|
||||
python manage.py createsuperuser
|
||||
uv run python manage.py createsuperuser
|
||||
|
||||
# Start the development server
|
||||
python manage.py runserver
|
||||
uv run python manage.py runserver
|
||||
```
|
||||
|
||||
`uv run <cmd>` resolves binaries from `.venv/bin/` automatically — no need to `source .venv/bin/activate`. If you prefer the activate-then-run flow, that still works:
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
python manage.py runserver # equivalent to `uv run python manage.py runserver`
|
||||
```
|
||||
|
||||
Common dev commands (from `backend/`):
|
||||
|
||||
```bash
|
||||
uv run pytest # run tests
|
||||
uv run python manage.py makemigrations # create migrations
|
||||
uv run celery -A crm worker --loglevel=INFO # background worker
|
||||
uv add <package> # add a dependency (updates pyproject.toml + uv.lock)
|
||||
uv add --group dev <package> # add a dev-only dependency
|
||||
uv lock --upgrade # refresh the lockfile
|
||||
```
|
||||
|
||||
### Frontend Setup
|
||||
|
|
@ -112,8 +131,7 @@ pnpm run dev
|
|||
```bash
|
||||
# In a new terminal
|
||||
cd backend
|
||||
source venv/bin/activate
|
||||
celery -A crm worker --loglevel=INFO
|
||||
uv run celery -A crm worker --loglevel=INFO
|
||||
```
|
||||
|
||||
### Access the Application
|
||||
|
|
|
|||
|
|
@ -100,8 +100,7 @@ Migrations automatically enable RLS on all protected tables:
|
|||
|
||||
```bash
|
||||
cd backend
|
||||
source venv/bin/activate
|
||||
python manage.py migrate
|
||||
uv run python manage.py migrate
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
1
backend/.python-version
Normal file
1
backend/.python-version
Normal file
|
|
@ -0,0 +1 @@
|
|||
3.12
|
||||
|
|
@ -35,30 +35,37 @@ The backend for BottleCRM, a multi-tenant CRM platform built with Django REST Fr
|
|||
|
||||
## Prerequisites
|
||||
|
||||
- **Python 3.8+**
|
||||
- **Python 3.10+** (uv installs a matching Python automatically if needed)
|
||||
- **PostgreSQL**
|
||||
- **Redis** (for Celery)
|
||||
- **virtualenv**
|
||||
- **[uv](https://docs.astral.sh/uv/)** — Python package & venv manager (replaces pip + virtualenv)
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Create and activate virtual environment
|
||||
### 1. Install uv
|
||||
|
||||
```bash
|
||||
# Linux / macOS
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Or via Homebrew
|
||||
brew install uv
|
||||
```
|
||||
|
||||
### 2. Install Python dependencies
|
||||
|
||||
`uv sync` reads `pyproject.toml` + `uv.lock`, picks the Python version from `.python-version`, and creates `.venv/` with everything installed.
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
uv sync
|
||||
```
|
||||
|
||||
### 2. Install dependencies
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
> Run any backend command with `uv run <cmd>` (e.g. `uv run python manage.py migrate`). uv resolves binaries from `.venv/bin/` automatically — no manual `source .venv/bin/activate` needed (though that still works if you prefer it).
|
||||
|
||||
### 3. Install PDF generation system dependencies
|
||||
|
||||
Invoice PDF generation uses WeasyPrint (already included in requirements.txt). However, WeasyPrint requires system libraries that must be installed separately:
|
||||
Invoice PDF generation uses WeasyPrint (a runtime dep). It requires system libraries that must be installed separately:
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
|
|
@ -129,16 +136,16 @@ ALTER USER postgres WITH PASSWORD 'root';
|
|||
\q
|
||||
|
||||
# Run migrations
|
||||
python manage.py migrate
|
||||
uv run python manage.py migrate
|
||||
|
||||
# Create superuser (optional)
|
||||
python manage.py createsuperuser
|
||||
uv run python manage.py createsuperuser
|
||||
```
|
||||
|
||||
### 6. Run the development server
|
||||
|
||||
```bash
|
||||
python manage.py runserver
|
||||
uv run python manage.py runserver
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:8000`
|
||||
|
|
@ -148,7 +155,7 @@ The API will be available at `http://localhost:8000`
|
|||
For background tasks (emails, notifications), run the Celery worker:
|
||||
|
||||
```bash
|
||||
celery -A crm worker --loglevel=INFO
|
||||
uv run celery -A crm worker --loglevel=INFO
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
|
@ -321,7 +328,9 @@ GET/POST /api/<module>/attachment/<pk>/ # Attachments
|
|||
```
|
||||
backend/
|
||||
├── manage.py
|
||||
├── requirements.txt
|
||||
├── pyproject.toml # Python deps + project metadata (uv-managed)
|
||||
├── uv.lock # Pinned, reproducible dependency tree
|
||||
├── .python-version # Python version pin (uv reads this on `uv sync`)
|
||||
├── crm/ # Django project settings
|
||||
│ ├── settings.py
|
||||
│ ├── urls.py
|
||||
|
|
@ -355,20 +364,36 @@ backend/
|
|||
|
||||
```bash
|
||||
# Format code
|
||||
black .
|
||||
uv run black .
|
||||
|
||||
# Sort imports
|
||||
isort .
|
||||
uv run isort .
|
||||
|
||||
# Run tests
|
||||
pytest
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
### Managing Dependencies
|
||||
|
||||
```bash
|
||||
# Add a runtime dependency (updates pyproject.toml + uv.lock)
|
||||
uv add <package>
|
||||
|
||||
# Add a dev-only dependency (e.g. test or lint tool)
|
||||
uv add --group dev <package>
|
||||
|
||||
# Remove a dependency
|
||||
uv remove <package>
|
||||
|
||||
# Refresh the lockfile
|
||||
uv lock --upgrade
|
||||
```
|
||||
|
||||
### Creating a New App
|
||||
|
||||
1. Create the app:
|
||||
```bash
|
||||
python manage.py startapp myapp
|
||||
uv run python manage.py startapp myapp
|
||||
```
|
||||
|
||||
2. Add to `INSTALLED_APPS` in `crm/settings.py`
|
||||
|
|
@ -390,8 +415,8 @@ pytest
|
|||
|
||||
5. Run migrations:
|
||||
```bash
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
uv run python manage.py makemigrations
|
||||
uv run python manage.py migrate
|
||||
```
|
||||
|
||||
## Environment Variables Reference
|
||||
|
|
@ -428,10 +453,10 @@ sudo -u postgres psql -l
|
|||
|
||||
```bash
|
||||
# Show migration status
|
||||
python manage.py showmigrations
|
||||
uv run python manage.py showmigrations
|
||||
|
||||
# Reset migrations (development only)
|
||||
python manage.py migrate --fake <app> zero
|
||||
uv run python manage.py migrate --fake <app> zero
|
||||
```
|
||||
|
||||
### Celery Not Processing Tasks
|
||||
|
|
@ -441,7 +466,7 @@ python manage.py migrate --fake <app> zero
|
|||
redis-cli ping
|
||||
|
||||
# Check Celery worker logs
|
||||
celery -A crm worker --loglevel=DEBUG
|
||||
uv run celery -A crm worker --loglevel=DEBUG
|
||||
```
|
||||
|
||||
## License
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class Account(AssignableMixin, BaseModel):
|
|||
),
|
||||
# Annual revenue must be non-negative
|
||||
models.CheckConstraint(
|
||||
check=Q(annual_revenue__gte=0) | Q(annual_revenue__isnull=True),
|
||||
condition=Q(annual_revenue__gte=0) | Q(annual_revenue__isnull=True),
|
||||
name="account_revenue_non_negative",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -162,12 +162,12 @@ class Lead(AssignableMixin, BaseModel):
|
|||
),
|
||||
# Probability must be 0-100
|
||||
models.CheckConstraint(
|
||||
check=Q(probability__gte=0) & Q(probability__lte=100),
|
||||
condition=Q(probability__gte=0) & Q(probability__lte=100),
|
||||
name="lead_probability_range",
|
||||
),
|
||||
# Opportunity amount must be non-negative
|
||||
models.CheckConstraint(
|
||||
check=Q(opportunity_amount__gte=0) | Q(opportunity_amount__isnull=True),
|
||||
condition=Q(opportunity_amount__gte=0) | Q(opportunity_amount__isnull=True),
|
||||
name="lead_amount_non_negative",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -128,12 +128,12 @@ class Opportunity(AssignableMixin, BaseModel):
|
|||
constraints = [
|
||||
# Probability must be 0-100
|
||||
models.CheckConstraint(
|
||||
check=Q(probability__gte=0) & Q(probability__lte=100),
|
||||
condition=Q(probability__gte=0) & Q(probability__lte=100),
|
||||
name="opportunity_probability_range",
|
||||
),
|
||||
# Amount must be non-negative
|
||||
models.CheckConstraint(
|
||||
check=Q(amount__gte=0) | Q(amount__isnull=True),
|
||||
condition=Q(amount__gte=0) | Q(amount__isnull=True),
|
||||
name="opportunity_amount_non_negative",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
118
backend/pyproject.toml
Normal file
118
backend/pyproject.toml
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "django-crm"
|
||||
version = "1.0.0"
|
||||
description = "Open-source multi-tenant CRM platform built on Django REST Framework with row-level security."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
license = { text = "MIT" }
|
||||
authors = [
|
||||
{ name = "MicroPyramid", email = "hello@micropyramid.com" },
|
||||
]
|
||||
keywords = [
|
||||
"django",
|
||||
"crm",
|
||||
"drf",
|
||||
"django-rest-framework",
|
||||
"multi-tenant",
|
||||
"saas",
|
||||
"sales",
|
||||
"leads",
|
||||
"contacts",
|
||||
"opportunity",
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Web Environment",
|
||||
"Framework :: Django",
|
||||
"Framework :: Django :: 6.0",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Office/Business",
|
||||
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"django>=6.0.5",
|
||||
"celery>=5.6.2",
|
||||
"python-dotenv>=1.2.1",
|
||||
"django-cors-headers>=4.9.0",
|
||||
"djangorestframework>=3.16.1",
|
||||
"djangorestframework-simplejwt>=5.5.1",
|
||||
"drf-spectacular>=0.29.0",
|
||||
"django-ses>=4.7.1",
|
||||
"psycopg2-binary>=2.9.11",
|
||||
"whitenoise>=6.11.0",
|
||||
"sentry-sdk>=2.53.0",
|
||||
"django-storages>=1.14.6",
|
||||
"django-crum>=0.7.9",
|
||||
"disposable-email-domains>=0.0.162",
|
||||
"redis>=7.2.0",
|
||||
"pytz>=2025.2",
|
||||
"requests>=2.32.5",
|
||||
"faker>=40.4.0",
|
||||
"python-dateutil>=2.9.0.post0",
|
||||
"google-auth>=2.48.0",
|
||||
# PDF generation (also needs system libs: cairo, pango, gdk-pixbuf, libffi, shared-mime-info)
|
||||
"weasyprint>=68.1",
|
||||
"cairocffi>=1.7.1",
|
||||
# Production WSGI server
|
||||
"gunicorn>=25.1.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/MicroPyramid/Django-CRM"
|
||||
Repository = "https://github.com/MicroPyramid/Django-CRM"
|
||||
Documentation = "https://github.com/MicroPyramid/Django-CRM#readme"
|
||||
Issues = "https://github.com/MicroPyramid/Django-CRM/issues"
|
||||
Changelog = "https://github.com/MicroPyramid/Django-CRM/releases"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=9.0.2",
|
||||
"pytest-django>=4.12.0",
|
||||
"pytest-cov>=7.0.0",
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = [
|
||||
"accounts",
|
||||
"cases",
|
||||
"common",
|
||||
"contacts",
|
||||
"crm",
|
||||
"invoices",
|
||||
"leads",
|
||||
"opportunity",
|
||||
"orders",
|
||||
"tasks",
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
include = [
|
||||
"accounts/",
|
||||
"cases/",
|
||||
"common/",
|
||||
"contacts/",
|
||||
"crm/",
|
||||
"invoices/",
|
||||
"leads/",
|
||||
"opportunity/",
|
||||
"orders/",
|
||||
"tasks/",
|
||||
"static/",
|
||||
"templates/",
|
||||
"manage.py",
|
||||
".env.example",
|
||||
"pytest.ini",
|
||||
"ruff.toml",
|
||||
"README.md",
|
||||
]
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
django==5.2.11
|
||||
celery==5.6.2
|
||||
python-dotenv==1.2.1
|
||||
django-cors-headers==4.9.0
|
||||
djangorestframework==3.16.1
|
||||
djangorestframework-simplejwt==5.5.1
|
||||
drf-spectacular==0.29.0
|
||||
django-ses==4.7.1
|
||||
psycopg2-binary==2.9.11
|
||||
whitenoise==6.11.0
|
||||
sentry-sdk==2.53.0
|
||||
django_storages==1.14.6
|
||||
|
||||
django-crum==0.7.9
|
||||
disposable-email-domains>=0.0.162
|
||||
redis==7.2.0
|
||||
pytz==2025.2
|
||||
requests==2.32.5
|
||||
faker==40.4.0
|
||||
python-dateutil==2.9.0.post0
|
||||
google-auth==2.48.0
|
||||
|
||||
# PDF Generation
|
||||
weasyprint==68.1
|
||||
cairocffi==1.7.1
|
||||
|
||||
# Production server
|
||||
gunicorn==25.1.0
|
||||
|
||||
# Testing
|
||||
pytest==9.0.2
|
||||
pytest-django==4.12.0
|
||||
pytest-cov==7.0.0
|
||||
|
|
@ -6,16 +6,15 @@ Management command to generate realistic test data for development and testing.
|
|||
|
||||
```bash
|
||||
cd backend
|
||||
source venv/bin/activate
|
||||
|
||||
# Basic usage (creates 1 org with default counts)
|
||||
python manage.py seed_data --email admin@example.com
|
||||
uv run python manage.py seed_data --email admin@example.com
|
||||
```
|
||||
|
||||
## Full Options
|
||||
|
||||
```bash
|
||||
python manage.py seed_data \
|
||||
uv run python manage.py seed_data \
|
||||
--email admin@example.com \ # Required: Admin user email
|
||||
--orgs 2 \ # Number of orgs (default: 1)
|
||||
--users-per-org 5 \ # Users per org (default: 3)
|
||||
|
|
@ -37,16 +36,16 @@ python manage.py seed_data \
|
|||
|
||||
```bash
|
||||
# Create 2 organizations with lots of data
|
||||
python manage.py seed_data --email admin@example.com --orgs 2 --leads 100 --accounts 50
|
||||
uv run python manage.py seed_data --email admin@example.com --orgs 2 --leads 100 --accounts 50
|
||||
|
||||
# Reproducible seeding (same data every time)
|
||||
python manage.py seed_data --email admin@example.com --seed 42
|
||||
uv run python manage.py seed_data --email admin@example.com --seed 42
|
||||
|
||||
# Clear all CRM data and reseed
|
||||
python manage.py seed_data --email admin@example.com --clear --no-input
|
||||
uv run python manage.py seed_data --email admin@example.com --clear --no-input
|
||||
|
||||
# Minimal data for quick testing
|
||||
python manage.py seed_data --email admin@example.com --leads 5 --accounts 3 --contacts 5 --opportunities 3 --cases 2 --tasks 5
|
||||
uv run python manage.py seed_data --email admin@example.com --leads 5 --accounts 3 --contacts 5 --opportunities 3 --cases 2 --tasks 5
|
||||
```
|
||||
|
||||
## Features
|
||||
|
|
@ -81,7 +80,7 @@ This allows you to reseed CRM data without losing user accounts.
|
|||
## Sample Output
|
||||
|
||||
```
|
||||
$ python manage.py seed_data --email admin@test.com --orgs 2 --seed 42
|
||||
$ uv run python manage.py seed_data --email admin@test.com --orgs 2 --seed 42
|
||||
|
||||
Seeding CRM database...
|
||||
Using seed: 42
|
||||
|
|
@ -130,8 +129,4 @@ Total time: 1.22 seconds
|
|||
|
||||
## Dependencies
|
||||
|
||||
The script requires the `faker` package (already in requirements.txt):
|
||||
|
||||
```bash
|
||||
pip install faker
|
||||
```
|
||||
The script requires the `faker` package, which is already declared in `pyproject.toml` and installed by `uv sync`. No extra step is needed.
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
import os
|
||||
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), "README.rst")) as readme:
|
||||
README = readme.read()
|
||||
|
||||
# allow setup.py to be run from any path
|
||||
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
|
||||
PROJECT_NAME = "django_crm"
|
||||
|
||||
data_files = []
|
||||
for dirpath, dirnames, filenames in os.walk(PROJECT_NAME):
|
||||
for i, dirname in enumerate(dirnames):
|
||||
if dirname.startswith("."):
|
||||
del dirnames[i]
|
||||
if "__init__.py" in filenames:
|
||||
continue
|
||||
elif filenames:
|
||||
for f in filenames:
|
||||
data_files.append(os.path.join(dirpath[len(PROJECT_NAME) + 1 :], f))
|
||||
|
||||
setup(
|
||||
name="django-crm",
|
||||
version="0.7.0",
|
||||
packages=find_packages(exclude=["tests", "tests.*"]),
|
||||
include_package_data=True,
|
||||
description="An opensourse CRM developed on django framework",
|
||||
long_description=README,
|
||||
url="https://github.com/MicroPyramid/Django-CRM.git",
|
||||
author="Micropyramid",
|
||||
author_email="hello@micropyramid.com",
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
"Framework :: Django",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.2",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
],
|
||||
install_requires=[],
|
||||
)
|
||||
1490
backend/uv.lock
Normal file
1490
backend/uv.lock
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -14,45 +14,46 @@
|
|||
"lint": "prettier --check . && eslint ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^2.0.3",
|
||||
"@eslint/compat": "^2.1.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@internationalized/date": "^3.12.0",
|
||||
"@lucide/svelte": "^0.577.0",
|
||||
"@internationalized/date": "^3.12.1",
|
||||
"@lucide/svelte": "^1.14.0",
|
||||
"@sveltejs/adapter-node": "^5.5.4",
|
||||
"@sveltejs/kit": "^2.55.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"@sveltejs/kit": "^2.59.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@types/node": "^25.5.0",
|
||||
"bits-ui": "^2.16.3",
|
||||
"eslint": "^10.0.3",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"@types/node": "^25.6.2",
|
||||
"bits-ui": "^2.18.1",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-svelte": "^3.15.2",
|
||||
"globals": "^17.4.0",
|
||||
"eslint-plugin-svelte": "^3.17.1",
|
||||
"globals": "^17.6.0",
|
||||
"mode-watcher": "^1.1.0",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier-plugin-svelte": "^3.5.1",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"svelte": "^5.54.0",
|
||||
"svelte-check": "^4.4.5",
|
||||
"svelte-sonner": "^1.1.0",
|
||||
"tailwindcss": "^4.2.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.3.1"
|
||||
"prettier-plugin-tailwindcss": "^0.8.0",
|
||||
"svelte": "^5.55.5",
|
||||
"svelte-check": "^4.4.8",
|
||||
"svelte-sonner": "^1.1.1",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "^6.0.3",
|
||||
"vite": "^8.0.11"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
"esbuild",
|
||||
"@sentry/cli"
|
||||
],
|
||||
"overrides": {
|
||||
"svelte-eslint-parser>eslint-scope": "^9.1.0"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/sveltekit": "^10.44.0",
|
||||
"axios": "^1.13.6",
|
||||
"@sentry/sveltekit": "^10.52.0",
|
||||
"axios": "^1.16.0",
|
||||
"clsx": "^2.1.1",
|
||||
"libphonenumber-js": "^1.12.40",
|
||||
"libphonenumber-js": "^1.13.0",
|
||||
"svelte-dnd-action": "^0.9.69",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tailwind-variants": "^3.2.2",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
5
frontend/pnpm-workspace.yaml
Normal file
5
frontend/pnpm-workspace.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
allowBuilds:
|
||||
'@sentry/cli': true
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
- '@sentry/cli'
|
||||
|
|
@ -79,6 +79,7 @@
|
|||
───────────────────────────────────────────────────────────────────────── */
|
||||
--color-primary-default: #ea580c;
|
||||
--color-primary-hover: #c2410c;
|
||||
--color-primary-dark: #c2410c;
|
||||
--color-primary-active: #9a3412;
|
||||
--color-primary-light: #fff7ed;
|
||||
|
||||
|
|
@ -98,6 +99,7 @@
|
|||
|
||||
/* Success */
|
||||
--color-success-default: #28a745;
|
||||
--color-success-dark: #1e7e34;
|
||||
--color-success-light: #e8f5e9;
|
||||
|
||||
/* Info */
|
||||
|
|
@ -141,6 +143,7 @@
|
|||
BORDER COLORS
|
||||
───────────────────────────────────────────────────────────────────────── */
|
||||
--border-default: #e0e0e0;
|
||||
--border-subtle: #eeeeee;
|
||||
--border-strong: #bdbdbd;
|
||||
--border-focus: #ea580c;
|
||||
--border-error: #dc3545;
|
||||
|
|
@ -191,9 +194,13 @@
|
|||
PRIORITY LEVELS
|
||||
───────────────────────────────────────────────────────────────────────── */
|
||||
--priority-urgent: #dc2626;
|
||||
--priority-urgent-bg: #fee2e2;
|
||||
--priority-high: #f97316;
|
||||
--priority-high-bg: #ffedd5;
|
||||
--priority-medium: #fbbf24;
|
||||
--priority-medium-bg: #fef3c7;
|
||||
--priority-low: #22c55e;
|
||||
--priority-low-bg: #dcfce7;
|
||||
--priority-none: #9ca3af;
|
||||
|
||||
/* ─────────────────────────────────────────────────────────────────────────
|
||||
|
|
@ -344,6 +351,7 @@
|
|||
───────────────────────────────────────────────────────────────────────── */
|
||||
--sidebar-width: 260px;
|
||||
--sidebar-width-collapsed: 72px;
|
||||
--sidebar-width-icon: 3rem;
|
||||
--drawer-width: 520px;
|
||||
--header-height: 60px;
|
||||
--content-padding: 28px;
|
||||
|
|
@ -461,6 +469,7 @@
|
|||
/* Primary color scale - Dark mode */
|
||||
--color-primary-default: #fb923c;
|
||||
--color-primary-hover: #fdba74;
|
||||
--color-primary-dark: #f97316;
|
||||
--color-primary-active: #f97316;
|
||||
--color-primary-light: #431407;
|
||||
|
||||
|
|
@ -481,6 +490,7 @@
|
|||
|
||||
/* Border Colors - Dark mode */
|
||||
--border-default: #3d3d3d;
|
||||
--border-subtle: #2a2a2a;
|
||||
--border-strong: #525252;
|
||||
--border-focus: #fb923c;
|
||||
--border-error: #f87171;
|
||||
|
|
@ -517,6 +527,7 @@
|
|||
--color-warning-dark: #fcd34d;
|
||||
--color-warning-light: rgba(251, 191, 36, 0.15);
|
||||
--color-success-default: #34d399;
|
||||
--color-success-dark: #10b981;
|
||||
--color-success-light: rgba(52, 211, 153, 0.15);
|
||||
--color-info-default: #38bdf8;
|
||||
--color-info-light: rgba(56, 189, 248, 0.15);
|
||||
|
|
|
|||
Loading…
Reference in a new issue