adding whats config
This commit is contained in:
parent
0bccc28caf
commit
1e836a1d9d
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -34,9 +34,24 @@ class ParcelAdmin(admin.ModelAdmin):
|
|||||||
@admin.register(PlatformProfile)
|
@admin.register(PlatformProfile)
|
||||||
class PlatformProfileAdmin(admin.ModelAdmin):
|
class PlatformProfileAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name', 'phone_number', 'registration_number')
|
list_display = ('name', 'phone_number', 'registration_number')
|
||||||
|
fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'fields': ('name', 'logo', 'slogan')
|
||||||
|
}),
|
||||||
|
('Contact Information', {
|
||||||
|
'fields': ('address', 'phone_number', 'registration_number', 'vat_number')
|
||||||
|
}),
|
||||||
|
('Legal', {
|
||||||
|
'fields': ('privacy_policy', 'terms_conditions')
|
||||||
|
}),
|
||||||
|
('WhatsApp Configuration', {
|
||||||
|
'fields': ('whatsapp_access_token', 'whatsapp_business_phone_number_id'),
|
||||||
|
'description': 'Enter your Meta WhatsApp Business API credentials here. These will override the system defaults.'
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
def has_add_permission(self, request):
|
def has_add_permission(self, request):
|
||||||
# Allow adding only if no instance exists
|
# Allow adding only if no instance exists
|
||||||
if self.model.objects.exists():
|
if self.model.objects.exists():
|
||||||
return False
|
return False
|
||||||
return super().has_add_permission(request)
|
return super().has_add_permission(request)
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-01-25 12:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0009_profile_address_profile_profile_picture_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platformprofile',
|
||||||
|
name='whatsapp_access_token',
|
||||||
|
field=models.TextField(blank=True, help_text='Permanent or temporary access token from Meta Business.', verbose_name='WhatsApp Access Token'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platformprofile',
|
||||||
|
name='whatsapp_business_phone_number_id',
|
||||||
|
field=models.CharField(blank=True, help_text='The Phone Number ID from WhatsApp API setup.', max_length=100, verbose_name='WhatsApp Phone Number ID'),
|
||||||
|
),
|
||||||
|
]
|
||||||
Binary file not shown.
@ -159,6 +159,10 @@ class PlatformProfile(models.Model):
|
|||||||
vat_number = models.CharField(_('VAT Number'), max_length=100, blank=True)
|
vat_number = models.CharField(_('VAT Number'), max_length=100, blank=True)
|
||||||
privacy_policy = models.TextField(_('Privacy Policy'), blank=True)
|
privacy_policy = models.TextField(_('Privacy Policy'), blank=True)
|
||||||
terms_conditions = models.TextField(_('Terms and Conditions'), blank=True)
|
terms_conditions = models.TextField(_('Terms and Conditions'), blank=True)
|
||||||
|
|
||||||
|
# WhatsApp Configuration
|
||||||
|
whatsapp_access_token = models.TextField(_('WhatsApp Access Token'), blank=True, help_text=_("Permanent or temporary access token from Meta Business."))
|
||||||
|
whatsapp_business_phone_number_id = models.CharField(_('WhatsApp Phone Number ID'), max_length=100, blank=True, help_text=_("The Phone Number ID from WhatsApp API setup."))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -180,4 +184,4 @@ class OTPVerification(models.Model):
|
|||||||
|
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
# OTP valid for 10 minutes
|
# OTP valid for 10 minutes
|
||||||
return self.created_at >= timezone.now() - timezone.timedelta(minutes=10)
|
return self.created_at >= timezone.now() - timezone.timedelta(minutes=10)
|
||||||
@ -1,29 +1,54 @@
|
|||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from .models import PlatformProfile
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def get_whatsapp_credentials():
|
||||||
|
"""
|
||||||
|
Retrieves WhatsApp credentials from PlatformProfile (preferred) or settings.
|
||||||
|
Returns tuple: (api_key, phone_id)
|
||||||
|
"""
|
||||||
|
# Default to settings
|
||||||
|
api_key = settings.WHATSAPP_API_KEY
|
||||||
|
phone_id = settings.WHATSAPP_PHONE_ID
|
||||||
|
|
||||||
|
# Try to fetch from PlatformProfile
|
||||||
|
try:
|
||||||
|
profile = PlatformProfile.objects.first()
|
||||||
|
if profile:
|
||||||
|
if profile.whatsapp_access_token:
|
||||||
|
api_key = profile.whatsapp_access_token
|
||||||
|
if profile.whatsapp_business_phone_number_id:
|
||||||
|
phone_id = profile.whatsapp_business_phone_number_id
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to fetch PlatformProfile for WhatsApp config: {e}")
|
||||||
|
|
||||||
|
return api_key, phone_id
|
||||||
|
|
||||||
def send_whatsapp_message(phone_number, message):
|
def send_whatsapp_message(phone_number, message):
|
||||||
"""
|
"""
|
||||||
Sends a WhatsApp message using the configured gateway.
|
Sends a WhatsApp message using the configured gateway.
|
||||||
This implementation assumes Meta WhatsApp Business API (Graph API).
|
This implementation assumes Meta WhatsApp Business API (Graph API).
|
||||||
"""
|
"""
|
||||||
if not settings.WHATSAPP_ENABLED:
|
if not settings.WHATSAPP_ENABLED:
|
||||||
logger.info("WhatsApp notifications are disabled.")
|
logger.info("WhatsApp notifications are disabled by settings.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not settings.WHATSAPP_API_KEY or not settings.WHATSAPP_PHONE_ID:
|
api_key, phone_id = get_whatsapp_credentials()
|
||||||
logger.warning("WhatsApp API configuration is missing.")
|
|
||||||
|
if not api_key or not phone_id:
|
||||||
|
logger.warning("WhatsApp API configuration is missing (checked PlatformProfile and settings).")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Normalize phone number (ensure it has country code and no +)
|
# Normalize phone number (ensure it has country code and no +)
|
||||||
clean_phone = "".join(filter(str.isdigit, str(phone_number)))
|
clean_phone = "".join(filter(str.isdigit, str(phone_number)))
|
||||||
|
|
||||||
url = f"https://graph.facebook.com/v17.0/{settings.WHATSAPP_PHONE_ID}/messages"
|
url = f"https://graph.facebook.com/v17.0/{phone_id}/messages"
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {settings.WHATSAPP_API_KEY}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +83,9 @@ Tracking Number: {parcel.tracking_number}
|
|||||||
Status: {parcel.get_status_display()}
|
Status: {parcel.get_status_display()}
|
||||||
|
|
||||||
Please proceed to payment to make it visible to drivers."""
|
Please proceed to payment to make it visible to drivers."""
|
||||||
return send_whatsapp_message(parcel.shipper.profile.phone_number, message)
|
if hasattr(parcel.shipper, 'profile') and parcel.shipper.profile.phone_number:
|
||||||
|
return send_whatsapp_message(parcel.shipper.profile.phone_number, message)
|
||||||
|
return False
|
||||||
|
|
||||||
def notify_payment_received(parcel):
|
def notify_payment_received(parcel):
|
||||||
"""Notifies the shipper and receiver about successful payment."""
|
"""Notifies the shipper and receiver about successful payment."""
|
||||||
@ -66,7 +93,9 @@ def notify_payment_received(parcel):
|
|||||||
shipper_name = parcel.shipper.get_full_name() or parcel.shipper.username
|
shipper_name = parcel.shipper.get_full_name() or parcel.shipper.username
|
||||||
shipper_msg = f"""Payment successful for shipment {parcel.tracking_number}.
|
shipper_msg = f"""Payment successful for shipment {parcel.tracking_number}.
|
||||||
Your shipment is now visible to available drivers."""
|
Your shipment is now visible to available drivers."""
|
||||||
send_whatsapp_message(parcel.shipper.profile.phone_number, shipper_msg)
|
|
||||||
|
if hasattr(parcel.shipper, 'profile') and parcel.shipper.profile.phone_number:
|
||||||
|
send_whatsapp_message(parcel.shipper.profile.phone_number, shipper_msg)
|
||||||
|
|
||||||
# Notify Receiver
|
# Notify Receiver
|
||||||
receiver_msg = f"""Hello {parcel.receiver_name},
|
receiver_msg = f"""Hello {parcel.receiver_name},
|
||||||
@ -81,12 +110,16 @@ def notify_driver_assigned(parcel):
|
|||||||
driver_name = parcel.carrier.get_full_name() or parcel.carrier.username
|
driver_name = parcel.carrier.get_full_name() or parcel.carrier.username
|
||||||
msg = f"""Shipment {parcel.tracking_number} has been picked up by {driver_name}.
|
msg = f"""Shipment {parcel.tracking_number} has been picked up by {driver_name}.
|
||||||
Status: {parcel.get_status_display()}"""
|
Status: {parcel.get_status_display()}"""
|
||||||
send_whatsapp_message(parcel.shipper.profile.phone_number, msg)
|
|
||||||
|
if hasattr(parcel.shipper, 'profile') and parcel.shipper.profile.phone_number:
|
||||||
|
send_whatsapp_message(parcel.shipper.profile.phone_number, msg)
|
||||||
send_whatsapp_message(parcel.receiver_phone, msg)
|
send_whatsapp_message(parcel.receiver_phone, msg)
|
||||||
|
|
||||||
def notify_status_change(parcel):
|
def notify_status_change(parcel):
|
||||||
"""Notifies parties about general status updates (In Transit, Delivered)."""
|
"""Notifies parties about general status updates (In Transit, Delivered)."""
|
||||||
msg = f"""Update for shipment {parcel.tracking_number}:
|
msg = f"""Update for shipment {parcel.tracking_number}:
|
||||||
New Status: {parcel.get_status_display()}"""
|
New Status: {parcel.get_status_display()}"""
|
||||||
send_whatsapp_message(parcel.shipper.profile.phone_number, msg)
|
|
||||||
send_whatsapp_message(parcel.receiver_phone, msg)
|
if hasattr(parcel.shipper, 'profile') and parcel.shipper.profile.phone_number:
|
||||||
|
send_whatsapp_message(parcel.shipper.profile.phone_number, msg)
|
||||||
|
send_whatsapp_message(parcel.receiver_phone, msg)
|
||||||
BIN
media/profile_pics/white_mocha.jfif
Normal file
BIN
media/profile_pics/white_mocha.jfif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
Loading…
x
Reference in New Issue
Block a user