fix: resolve setup and Docker issues preventing project from running
Use shared_task instead of standalone Celery apps so celery -A crm worker discovers all tasks. Add safe defaults for all required env vars in settings.py so missing .env no longer crashes Django. Create idempotent management command to bootstrap a superuser in Docker. Populate .env.example with working dev defaults. Fixes #490, #493, #508, #388, #383, #382, #381, #441, #519 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1f6b797909
commit
cbcab8636a
13 changed files with 94 additions and 72 deletions
|
|
@ -28,6 +28,7 @@ CELERY_RESULT_BACKEND=redis://redis:6379/0
|
||||||
# Email (console backend in dev — emails print to stdout)
|
# Email (console backend in dev — emails print to stdout)
|
||||||
DEFAULT_FROM_EMAIL=noreply@localhost
|
DEFAULT_FROM_EMAIL=noreply@localhost
|
||||||
ADMIN_EMAIL=admin@localhost
|
ADMIN_EMAIL=admin@localhost
|
||||||
|
ADMIN_PASSWORD=admin
|
||||||
|
|
||||||
# CORS
|
# CORS
|
||||||
CORS_ALLOW_ALL=True
|
CORS_ALLOW_ALL=True
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,41 @@
|
||||||
# Environment variables
|
# Environment variables
|
||||||
|
# Copy this file to .env and adjust as needed: cp .env.example .env
|
||||||
|
|
||||||
SECRET_KEY=""
|
SECRET_KEY="django-insecure-dev-key-please-change-in-production"
|
||||||
ENV_TYPE="dev"
|
ENV_TYPE="dev"
|
||||||
DOMAIN_NAME=""
|
DEBUG=True
|
||||||
|
DOMAIN_NAME="http://localhost:8000"
|
||||||
|
SWAGGER_ROOT_URL="http://localhost:8000"
|
||||||
|
|
||||||
# AWS
|
# AWS (only needed for production / S3 storage)
|
||||||
AWS_BUCKET_NAME=""
|
AWS_BUCKET_NAME=""
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID=""
|
AWS_ACCESS_KEY_ID=""
|
||||||
AWS_SECRET_ACCESS_KEY=""
|
AWS_SECRET_ACCESS_KEY=""
|
||||||
AWS_SES_REGION_NAME=""
|
AWS_SES_REGION_NAME=""
|
||||||
AWS_SES_REGION_ENDPOINT=""
|
AWS_SES_REGION_ENDPOINT=""
|
||||||
|
|
||||||
|
|
||||||
# DB
|
# DB
|
||||||
DBNAME=""
|
DBNAME="crm_db"
|
||||||
DBUSER=""
|
DBUSER="postgres"
|
||||||
DBPASSWORD=""
|
DBPASSWORD="postgres"
|
||||||
DBHOST=""
|
DBHOST="localhost"
|
||||||
DBPORT=""
|
DBPORT="5432"
|
||||||
|
|
||||||
# Sentry
|
# Sentry (optional)
|
||||||
SENTRY_DSN=""
|
SENTRY_DSN=""
|
||||||
|
|
||||||
# Celery
|
# Celery
|
||||||
CELERY_BROKER_URL="redis://localhost:6379/0"
|
CELERY_BROKER_URL="redis://localhost:6379/0"
|
||||||
CELERY_RESULT_BACKEND="redis://localhost:6379/0"
|
CELERY_RESULT_BACKEND="redis://localhost:6379/0"
|
||||||
|
|
||||||
# Swagger
|
# Google OAuth (optional — leave blank to disable)
|
||||||
SWAGGER_ROOT_URL=""
|
|
||||||
|
|
||||||
# Google OAuth
|
|
||||||
GOOGLE_CLIENT_ID=""
|
GOOGLE_CLIENT_ID=""
|
||||||
GOOGLE_CLIENT_SECRET=""
|
GOOGLE_CLIENT_SECRET=""
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
DEFAULT_FROM_EMAIL=""
|
DEFAULT_FROM_EMAIL="noreply@localhost"
|
||||||
ADMIN_EMAIL=""
|
ADMIN_EMAIL="admin@localhost"
|
||||||
|
|
||||||
ALLOWED_HOSTS=yourdomain.com
|
ALLOWED_HOSTS=localhost,127.0.0.1
|
||||||
CORS_ALLOWED_ORIGINS=https://yourdomain.com
|
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
|
||||||
CSRF_TRUSTED_ORIGINS=https://yourdomain.com
|
CSRF_TRUSTED_ORIGINS=http://localhost:5173
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
|
|
@ -8,10 +8,8 @@ from accounts.models import Account, AccountEmail, AccountEmailLog
|
||||||
from common.models import Profile
|
from common.models import Profile
|
||||||
from common.tasks import set_rls_context
|
from common.tasks import set_rls_context
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
@app.task
|
|
||||||
def send_email(email_obj_id, org_id):
|
def send_email(email_obj_id, org_id):
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
email_obj = AccountEmail.objects.filter(id=email_obj_id).first()
|
email_obj = AccountEmail.objects.filter(id=email_obj_id).first()
|
||||||
|
|
@ -58,7 +56,7 @@ def send_email(email_obj_id, org_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email_to_assigned_user(recipients, account_id, org_id):
|
def send_email_to_assigned_user(recipients, account_id, org_id):
|
||||||
"""Send Mail To Users When they are assigned to an account"""
|
"""Send Mail To Users When they are assigned to an account"""
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
|
@ -7,10 +7,8 @@ from cases.models import Case
|
||||||
from common.models import Profile
|
from common.models import Profile
|
||||||
from common.tasks import set_rls_context
|
from common.tasks import set_rls_context
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
@app.task
|
|
||||||
def send_email_to_assigned_user(recipients, case_id, org_id):
|
def send_email_to_assigned_user(recipients, case_id, org_id):
|
||||||
"""Send Mail To Users When they are assigned to a case"""
|
"""Send Mail To Users When they are assigned to a case"""
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
|
|
|
||||||
25
backend/common/management/commands/create_default_admin.py
Normal file
25
backend/common/management/commands/create_default_admin.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Create a default superuser if none exists (for Docker bootstrap)"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
if User.objects.filter(is_superuser=True).exists():
|
||||||
|
self.stdout.write(self.style.SUCCESS("Superuser already exists — skipping."))
|
||||||
|
return
|
||||||
|
|
||||||
|
email = os.environ.get("ADMIN_EMAIL", "admin@localhost")
|
||||||
|
password = os.environ.get("ADMIN_PASSWORD", "admin")
|
||||||
|
|
||||||
|
User.objects.create_superuser(
|
||||||
|
username=email,
|
||||||
|
email=email,
|
||||||
|
password=password,
|
||||||
|
)
|
||||||
|
self.stdout.write(self.style.SUCCESS(f"Created default superuser: {email}"))
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
|
|
@ -13,8 +13,6 @@ from django.utils.http import urlsafe_base64_encode
|
||||||
from common.models import Comment, Profile, Teams, User
|
from common.models import Comment, Profile, Teams, User
|
||||||
from common.token_generator import account_activation_token
|
from common.token_generator import account_activation_token
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
|
||||||
def set_rls_context(org_id):
|
def set_rls_context(org_id):
|
||||||
"""
|
"""
|
||||||
|
|
@ -33,7 +31,7 @@ def set_rls_context(org_id):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email_to_new_user(user_id):
|
def send_email_to_new_user(user_id):
|
||||||
"""Send Mail To Users When their account is created"""
|
"""Send Mail To Users When their account is created"""
|
||||||
user_obj = User.objects.filter(id=user_id).first()
|
user_obj = User.objects.filter(id=user_id).first()
|
||||||
|
|
@ -75,7 +73,7 @@ def send_email_to_new_user(user_id):
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email_user_mentions(
|
def send_email_user_mentions(
|
||||||
comment_id,
|
comment_id,
|
||||||
called_from,
|
called_from,
|
||||||
|
|
@ -145,7 +143,7 @@ def send_email_user_mentions(
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email_user_status(
|
def send_email_user_status(
|
||||||
user_id,
|
user_id,
|
||||||
status_changed_user="",
|
status_changed_user="",
|
||||||
|
|
@ -185,7 +183,7 @@ def send_email_user_status(
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email_user_delete(
|
def send_email_user_delete(
|
||||||
user_email,
|
user_email,
|
||||||
deleted_by="",
|
deleted_by="",
|
||||||
|
|
@ -211,7 +209,7 @@ def send_email_user_delete(
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def resend_activation_link_to_user(
|
def resend_activation_link_to_user(
|
||||||
user_email="",
|
user_email="",
|
||||||
):
|
):
|
||||||
|
|
@ -260,7 +258,7 @@ def resend_activation_link_to_user(
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def remove_users(removed_users_list, team_id, org_id=None):
|
def remove_users(removed_users_list, team_id, org_id=None):
|
||||||
# Set RLS context for org-scoped queries
|
# Set RLS context for org-scoped queries
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
|
|
@ -311,7 +309,7 @@ def remove_users(removed_users_list, team_id, org_id=None):
|
||||||
invoice.assigned_to.remove(user)
|
invoice.assigned_to.remove(user)
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def update_team_users(team_id, org_id=None):
|
def update_team_users(team_id, org_id=None):
|
||||||
"""this function updates assigned_to field on all models when a team is updated"""
|
"""this function updates assigned_to field on all models when a team is updated"""
|
||||||
# Set RLS context for org-scoped queries
|
# Set RLS context for org-scoped queries
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
|
@ -7,10 +7,8 @@ from common.models import Profile
|
||||||
from common.tasks import set_rls_context
|
from common.tasks import set_rls_context
|
||||||
from contacts.models import Contact
|
from contacts.models import Contact
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
@app.task
|
|
||||||
def send_email_to_assigned_user(recipients, contact_id, org_id):
|
def send_email_to_assigned_user(recipients, contact_id, org_id):
|
||||||
"""Send Mail To Users When they are assigned to a contact"""
|
"""Send Mail To Users When they are assigned to a contact"""
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ app.config_from_object("django.conf:settings", namespace="CELERY")
|
||||||
|
|
||||||
# Load task modules from all registered Django app configs.
|
# Load task modules from all registered Django app configs.
|
||||||
app.autodiscover_tasks()
|
app.autodiscover_tasks()
|
||||||
|
app.autodiscover_tasks(related_name="celery_tasks") # tasks app uses celery_tasks.py
|
||||||
|
|
||||||
# Celery Beat Schedule for recurring tasks
|
# Celery Beat Schedule for recurring tasks
|
||||||
app.conf.beat_schedule = {
|
app.conf.beat_schedule = {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = os.environ["SECRET_KEY"]
|
SECRET_KEY = os.environ.get("SECRET_KEY", "django-insecure-dev-key-please-change-in-production")
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = os.environ.get("DEBUG", "False").lower() == "true"
|
DEBUG = os.environ.get("DEBUG", "False").lower() == "true"
|
||||||
|
|
@ -86,11 +86,11 @@ WSGI_APPLICATION = "crm.wsgi.application"
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
"default": {
|
"default": {
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
"ENGINE": "django.db.backends.postgresql",
|
||||||
"NAME": os.environ["DBNAME"],
|
"NAME": os.environ.get("DBNAME", "crm_db"),
|
||||||
"USER": os.environ["DBUSER"],
|
"USER": os.environ.get("DBUSER", "postgres"),
|
||||||
"PASSWORD": os.environ["DBPASSWORD"],
|
"PASSWORD": os.environ.get("DBPASSWORD", "postgres"),
|
||||||
"HOST": os.environ["DBHOST"],
|
"HOST": os.environ.get("DBHOST", "localhost"),
|
||||||
"PORT": os.environ["DBPORT"],
|
"PORT": os.environ.get("DBPORT", "5432"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,20 +131,20 @@ STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
|
||||||
STATIC_URL = "/static/"
|
STATIC_URL = "/static/"
|
||||||
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
|
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
|
||||||
|
|
||||||
ENV_TYPE = os.environ["ENV_TYPE"]
|
ENV_TYPE = os.environ.get("ENV_TYPE", "dev")
|
||||||
if ENV_TYPE == "dev":
|
if ENV_TYPE == "dev":
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
|
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
|
||||||
MEDIA_URL = "/media/"
|
MEDIA_URL = "/media/"
|
||||||
elif ENV_TYPE == "prod":
|
elif ENV_TYPE == "prod":
|
||||||
from .server_settings import *
|
from .server_settings import *
|
||||||
|
|
||||||
DEFAULT_FROM_EMAIL = os.environ["DEFAULT_FROM_EMAIL"]
|
DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL", "noreply@localhost")
|
||||||
ADMIN_EMAIL = os.environ["ADMIN_EMAIL"]
|
ADMIN_EMAIL = os.environ.get("ADMIN_EMAIL", "admin@localhost")
|
||||||
|
|
||||||
|
|
||||||
# celery Tasks
|
# celery Tasks
|
||||||
CELERY_BROKER_URL = os.environ["CELERY_BROKER_URL"]
|
CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL", "redis://localhost:6379/0")
|
||||||
CELERY_RESULT_BACKEND = os.environ["CELERY_RESULT_BACKEND"]
|
CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", "redis://localhost:6379/0")
|
||||||
|
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
|
|
@ -306,7 +306,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
||||||
# STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
# STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
||||||
|
|
||||||
DOMAIN_NAME = os.getenv("DOMAIN_NAME")
|
DOMAIN_NAME = os.environ.get("DOMAIN_NAME", "http://localhost:8000")
|
||||||
|
|
||||||
|
|
||||||
SIMPLE_JWT = {
|
SIMPLE_JWT = {
|
||||||
|
|
@ -330,8 +330,8 @@ SIMPLE_JWT = {
|
||||||
JWT_ALGO = "HS256"
|
JWT_ALGO = "HS256"
|
||||||
|
|
||||||
|
|
||||||
DOMAIN_NAME = os.environ["DOMAIN_NAME"]
|
DOMAIN_NAME = os.environ.get("DOMAIN_NAME", "http://localhost:8000")
|
||||||
SWAGGER_ROOT_URL = os.environ["SWAGGER_ROOT_URL"]
|
SWAGGER_ROOT_URL = os.environ.get("SWAGGER_ROOT_URL", "http://localhost:8000")
|
||||||
|
|
||||||
# Google OAuth Configuration
|
# Google OAuth Configuration
|
||||||
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", "")
|
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", "")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMessage, EmailMultiAlternatives
|
from django.core.mail import EmailMessage, EmailMultiAlternatives
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
@ -11,15 +11,13 @@ from common.models import Org, Profile
|
||||||
from common.tasks import set_rls_context
|
from common.tasks import set_rls_context
|
||||||
from leads.models import Lead
|
from leads.models import Lead
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
|
||||||
def get_rendered_html(template_name, context={}):
|
def get_rendered_html(template_name, context={}):
|
||||||
html_content = render_to_string(template_name, context)
|
html_content = render_to_string(template_name, context)
|
||||||
return html_content
|
return html_content
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email(
|
def send_email(
|
||||||
subject,
|
subject,
|
||||||
html_content,
|
html_content,
|
||||||
|
|
@ -45,7 +43,7 @@ def send_email(
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_lead_assigned_emails(lead_id, new_assigned_to_list, site_address, org_id):
|
def send_lead_assigned_emails(lead_id, new_assigned_to_list, site_address, org_id):
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
lead_instance = Lead.objects.filter(
|
lead_instance = Lead.objects.filter(
|
||||||
|
|
@ -76,7 +74,7 @@ def send_lead_assigned_emails(lead_id, new_assigned_to_list, site_address, org_i
|
||||||
send_email.delay(**mail_kwargs)
|
send_email.delay(**mail_kwargs)
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def send_email_to_assigned_user(recipients, lead_id, org_id, source=""):
|
def send_email_to_assigned_user(recipients, lead_id, org_id, source=""):
|
||||||
"""Send Mail To Users When they are assigned to a lead"""
|
"""Send Mail To Users When they are assigned to a lead"""
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
|
|
@ -102,7 +100,7 @@ def send_email_to_assigned_user(recipients, lead_id, org_id, source=""):
|
||||||
msg.send()
|
msg.send()
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@shared_task
|
||||||
def create_lead_from_file(validated_rows, invalid_rows, user_id, source, company_id):
|
def create_lead_from_file(validated_rows, invalid_rows, user_id, source, company_id):
|
||||||
"""Parameters : validated_rows, invalid_rows, user_id.
|
"""Parameters : validated_rows, invalid_rows, user_id.
|
||||||
This function is used to create leads from a given file.
|
This function is used to create leads from a given file.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
|
@ -7,10 +7,8 @@ from common.models import Profile
|
||||||
from common.tasks import set_rls_context
|
from common.tasks import set_rls_context
|
||||||
from opportunity.models import Opportunity
|
from opportunity.models import Opportunity
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
@app.task
|
|
||||||
def send_email_to_assigned_user(recipients, opportunity_id, org_id):
|
def send_email_to_assigned_user(recipients, opportunity_id, org_id):
|
||||||
"""Send Mail To Users When they are assigned to an opportunity"""
|
"""Send Mail To Users When they are assigned to an opportunity"""
|
||||||
set_rls_context(org_id)
|
set_rls_context(org_id)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from celery import Celery
|
from celery import shared_task
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from django.shortcuts import reverse
|
from django.shortcuts import reverse
|
||||||
|
|
@ -10,10 +10,8 @@ from common.tasks import set_rls_context
|
||||||
from contacts.models import Contact
|
from contacts.models import Contact
|
||||||
from tasks.models import Task
|
from tasks.models import Task
|
||||||
|
|
||||||
app = Celery("redis://")
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
@app.task
|
|
||||||
def send_email(
|
def send_email(
|
||||||
task_id, recipients, org_id, domain="demo.django-crm.io", protocol="http"
|
task_id, recipients, org_id, domain="demo.django-crm.io", protocol="http"
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,20 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "Waiting for PostgreSQL..."
|
echo "Waiting for PostgreSQL..."
|
||||||
|
retries=0
|
||||||
|
max_retries=30
|
||||||
while ! python -c "
|
while ! python -c "
|
||||||
import socket, os
|
import socket, os
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
s.connect((os.environ['DBHOST'], int(os.environ['DBPORT'])))
|
s.connect((os.environ['DBHOST'], int(os.environ['DBPORT'])))
|
||||||
s.close()
|
s.close()
|
||||||
" 2>/dev/null; do
|
" 2>/dev/null; do
|
||||||
|
retries=$((retries + 1))
|
||||||
|
if [ "$retries" -ge "$max_retries" ]; then
|
||||||
|
echo "ERROR: Could not connect to PostgreSQL after $max_retries attempts."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " PostgreSQL not ready yet (attempt $retries/$max_retries)..."
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
echo "PostgreSQL is ready."
|
echo "PostgreSQL is ready."
|
||||||
|
|
@ -15,6 +23,9 @@ echo "PostgreSQL is ready."
|
||||||
echo "Running migrations..."
|
echo "Running migrations..."
|
||||||
python manage.py migrate --noinput
|
python manage.py migrate --noinput
|
||||||
|
|
||||||
|
echo "Creating default admin user (if needed)..."
|
||||||
|
python manage.py create_default_admin
|
||||||
|
|
||||||
echo "Collecting static files..."
|
echo "Collecting static files..."
|
||||||
python manage.py collectstatic --noinput
|
python manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue