small fixes
This commit is contained in:
parent
2727588f58
commit
417475ad54
@ -7,16 +7,16 @@ from django_ledger.models import EstimateModel, BillModel, AccountModel, LedgerM
|
|||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **kwargs):
|
def handle(self, *args, **kwargs):
|
||||||
Permission.objects.get_or_create(
|
# Permission.objects.get_or_create(
|
||||||
name="Can view crm",
|
# name="Can view crm",
|
||||||
codename="can_view_crm",
|
# codename="can_view_crm",
|
||||||
content_type=ContentType.objects.get_for_model(Lead),
|
# content_type=ContentType.objects.get_for_model(Lead),
|
||||||
)
|
# )
|
||||||
Permission.objects.get_or_create(
|
# Permission.objects.get_or_create(
|
||||||
name="Can reassign lead",
|
# name="Can reassign lead",
|
||||||
codename="can_reassign_lead",
|
# codename="can_reassign_lead",
|
||||||
content_type=ContentType.objects.get_for_model(Lead),
|
# content_type=ContentType.objects.get_for_model(Lead),
|
||||||
)
|
# )
|
||||||
Permission.objects.get_or_create(
|
Permission.objects.get_or_create(
|
||||||
name="Can view sales",
|
name="Can view sales",
|
||||||
codename="can_view_sales",
|
codename="can_view_sales",
|
||||||
|
|||||||
@ -2134,6 +2134,10 @@ class Lead(models.Model):
|
|||||||
slug = RandomCharField(length=8, unique=True)
|
slug = RandomCharField(length=8, unique=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
permissions = [
|
||||||
|
("can_view_crm", _("Can view CRM")),
|
||||||
|
("can_reassign_lead", _("Can reassign lead")),
|
||||||
|
]
|
||||||
verbose_name = _("Lead")
|
verbose_name = _("Lead")
|
||||||
verbose_name_plural = _("Leads")
|
verbose_name_plural = _("Leads")
|
||||||
indexes = [
|
indexes = [
|
||||||
|
|||||||
@ -10259,31 +10259,52 @@ def submit_plan(request, dealer_slug):
|
|||||||
|
|
||||||
# @login_required
|
# @login_required
|
||||||
def payment_callback(request, dealer_slug):
|
def payment_callback(request, dealer_slug):
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
payment_id = request.GET.get("id")
|
payment_id = request.GET.get("id")
|
||||||
payment_status = request.GET.get("status")
|
payment_status = request.GET.get("status")
|
||||||
message = request.GET.get("message", "")
|
message = request.GET.get("message", "")
|
||||||
|
|
||||||
|
if not payment_id:
|
||||||
|
logger.error("Missing payment ID in callback")
|
||||||
|
return render(request, "payment_failed.html", {"message": "Invalid request"})
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Received payment callback for dealer_slug: {dealer_slug}, payment_id: {payment_id}, status: {payment_status}"
|
f"Received payment callback for dealer_slug: {dealer_slug}, payment_id: {payment_id}, status: {payment_status}"
|
||||||
)
|
)
|
||||||
|
|
||||||
history = models.PaymentHistory.objects.filter(transaction_id=payment_id).first()
|
with transaction.atomic():
|
||||||
if not history:
|
history = (
|
||||||
logger.error(f"No PaymentHistory found for transaction_id: {payment_id}")
|
models.PaymentHistory.objects
|
||||||
return render(
|
.select_for_update()
|
||||||
request, "payment_failed.html", {"message": "Invalid transaction"}
|
.filter(transaction_id=payment_id)
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
|
|
||||||
if history.status == "paid":
|
if not history:
|
||||||
logger.info("Payment already processed. Redirecting to home.")
|
logger.error(f"No PaymentHistory found for transaction_id: {payment_id}")
|
||||||
return redirect("home")
|
return render(
|
||||||
|
request, "payment_failed.html", {"message": "Invalid transaction"}
|
||||||
|
)
|
||||||
|
|
||||||
|
if history.status == "paid":
|
||||||
|
logger.info("Payment already processed. Redirecting to home.")
|
||||||
|
return redirect("home")
|
||||||
|
|
||||||
|
if history.status == "processing":
|
||||||
|
logger.warning(f"Payment {payment_id} is already being processed. Skipping.")
|
||||||
|
return redirect("home")
|
||||||
|
|
||||||
|
if history.status == "failed" and payment_status != "paid":
|
||||||
|
logger.warning(f"Payment {payment_id} already failed. Ignoring.")
|
||||||
|
return render(request, "payment_failed.html", {"message": message or "Payment failed"})
|
||||||
|
|
||||||
|
history.status = "processing"
|
||||||
|
history.save(update_fields=["status"])
|
||||||
|
|
||||||
if payment_status == "paid":
|
if payment_status == "paid":
|
||||||
logger.info(
|
logger.info(f"Payment successful for transaction ID {payment_id}. Creating order...")
|
||||||
f"Payment successful for transaction ID {payment_id}. Creating order..."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get metadata from PaymentHistory (passed during handle_payment)
|
|
||||||
metadata = history.user_data
|
metadata = history.user_data
|
||||||
if isinstance(metadata, str):
|
if isinstance(metadata, str):
|
||||||
try:
|
try:
|
||||||
@ -10291,116 +10312,101 @@ def payment_callback(request, dealer_slug):
|
|||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
logger.error(f"Failed to decode metadata JSON: {metadata}")
|
logger.error(f"Failed to decode metadata JSON: {metadata}")
|
||||||
metadata = {}
|
metadata = {}
|
||||||
|
|
||||||
plan_pricing_id = metadata.get("plan_pricing_id")
|
plan_pricing_id = metadata.get("plan_pricing_id")
|
||||||
dealer_slug_from_meta = metadata.get("dealer_slug")
|
dealer_slug_from_meta = metadata.get("dealer_slug")
|
||||||
|
|
||||||
if not plan_pricing_id or dealer_slug_from_meta != dealer_slug:
|
if not plan_pricing_id or dealer_slug_from_meta != dealer_slug:
|
||||||
logger.error("Invalid metadata in payment callback")
|
logger.error("Invalid metadata in payment callback")
|
||||||
history.status = "failed"
|
history.status = "failed"
|
||||||
history.save()
|
history.save(update_fields=["status"])
|
||||||
return render(
|
return render(request, "payment_failed.html", {"message": "Invalid payment data"})
|
||||||
request, "payment_failed.html", {"message": "Invalid payment data"}
|
|
||||||
)
|
|
||||||
|
|
||||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
|
||||||
pp = get_object_or_404(PlanPricing, pk=plan_pricing_id)
|
|
||||||
|
|
||||||
# ✅ CREATE ORDER HERE
|
|
||||||
try:
|
|
||||||
order = Order.objects.create(
|
|
||||||
user=dealer.user,
|
|
||||||
plan=pp.plan,
|
|
||||||
pricing=pp.pricing,
|
|
||||||
amount=pp.price,
|
|
||||||
currency="SAR", # Fixed typo: was "SA"
|
|
||||||
tax=15,
|
|
||||||
status=Order.STATUS.NEW, # Use constant if available
|
|
||||||
)
|
|
||||||
logger.info(f"Order {order.id} created for user {dealer.user}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception(f"Failed to create order: {e}")
|
|
||||||
history.status = "failed"
|
|
||||||
history.save()
|
|
||||||
return render(
|
|
||||||
request, "payment_failed.html", {"message": "Order creation failed"}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create or get BillingInfo
|
|
||||||
billing_info, created = BillingInfo.objects.get_or_create(
|
|
||||||
user=dealer.user,
|
|
||||||
defaults={
|
|
||||||
"tax_number": dealer.vrn,
|
|
||||||
"name": dealer.arabic_name,
|
|
||||||
"street": dealer.address,
|
|
||||||
"zipcode": dealer.entity.zip_code or " ",
|
|
||||||
"city": dealer.entity.city or " ",
|
|
||||||
"country": dealer.entity.country or " ",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if created:
|
|
||||||
logger.info(f"Created new billing info for user {dealer.user}.")
|
|
||||||
else:
|
|
||||||
logger.debug(f"Billing info already exists for user {dealer.user}.")
|
|
||||||
|
|
||||||
# Create or update UserPlan
|
|
||||||
if not hasattr(order.user, "userplan"):
|
|
||||||
UserPlan.objects.create(
|
|
||||||
user=order.user,
|
|
||||||
plan=order.plan,
|
|
||||||
# expire=datetime.now().date() + timedelta(days=order.get_plan_pricing().pricing.period)
|
|
||||||
)
|
|
||||||
logger.info(
|
|
||||||
f"Created new UserPlan for user {order.user} with plan {order.plan}."
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Optional: upgrade existing plan
|
|
||||||
# user_plan = order.user.userplan
|
|
||||||
# user_plan.plan = order.plan
|
|
||||||
# user_plan.save()
|
|
||||||
logger.info(f"UserPlan already exists for user {order.user}.")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Complete the order (this may generate invoice, etc.)
|
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||||
order.complete_order()
|
pp = get_object_or_404(PlanPricing, pk=plan_pricing_id)
|
||||||
history.status = "paid"
|
|
||||||
history.order = order # Link payment to order
|
with transaction.atomic():
|
||||||
history.save()
|
history.refresh_from_db()
|
||||||
|
if history.status == "paid":
|
||||||
|
logger.info("Payment was already completed by another request. Skipping.")
|
||||||
|
return redirect("home")
|
||||||
|
|
||||||
|
order = Order.objects.create(
|
||||||
|
user=dealer.user,
|
||||||
|
plan=pp.plan,
|
||||||
|
pricing=pp.pricing,
|
||||||
|
amount=pp.price,
|
||||||
|
currency="SAR",
|
||||||
|
tax=15,
|
||||||
|
status=Order.STATUS.NEW,
|
||||||
|
)
|
||||||
|
logger.info(f"Order {order.id} created for user {dealer.user}")
|
||||||
|
|
||||||
|
billing_info, created = BillingInfo.objects.get_or_create(
|
||||||
|
user=dealer.user,
|
||||||
|
defaults={
|
||||||
|
"tax_number": dealer.vrn,
|
||||||
|
"name": dealer.arabic_name,
|
||||||
|
"street": dealer.address,
|
||||||
|
"zipcode": dealer.entity.zip_code or " ",
|
||||||
|
"city": dealer.entity.city or " ",
|
||||||
|
"country": dealer.entity.country or " ",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create UserPlan if missing
|
||||||
|
if not hasattr(order.user, "userplan"):
|
||||||
|
UserPlan.objects.create(
|
||||||
|
user=order.user,
|
||||||
|
plan=order.plan,
|
||||||
|
)
|
||||||
|
logger.info(f"Created new UserPlan for user {order.user} with plan {order.plan}.")
|
||||||
|
else:
|
||||||
|
logger.info(f"UserPlan already exists for user {order.user}.")
|
||||||
|
|
||||||
|
order.complete_order()
|
||||||
|
|
||||||
|
history.status = "paid"
|
||||||
|
history.order = order
|
||||||
|
history.save(update_fields=["status", "order"])
|
||||||
|
|
||||||
invoice = order.get_invoices().first()
|
invoice = order.get_invoices().first()
|
||||||
|
logger.info(f"Order {order.id} completed successfully.")
|
||||||
logger.info(f"Order {order.id} completed. Rendering success page.")
|
|
||||||
return render(
|
return render(
|
||||||
request, "payment_success.html", {"order": order, "invoice": invoice}
|
request, "payment_success.html", {"order": order, "invoice": invoice}
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Error completing order {order.id}: {e}")
|
logger.exception(f"Error processing paid payment {payment_id}: {e}")
|
||||||
|
# Mark as failed
|
||||||
history.status = "failed"
|
history.status = "failed"
|
||||||
history.save()
|
history.save(update_fields=["status"])
|
||||||
return render(
|
return render(request, "payment_failed.html", {"message": "Payment processing error"})
|
||||||
request, "payment_failed.html", {"message": "Plan activation error"}
|
|
||||||
)
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Activate dealer & staff if needed
|
try:
|
||||||
if dealer := getattr(order.user, "dealer", None):
|
if dealer := getattr(order.user, "dealer", None):
|
||||||
if not dealer.user.is_active:
|
if not dealer.user.is_active:
|
||||||
dealer.user.is_active = True
|
dealer.user.is_active = True
|
||||||
dealer.user.save()
|
dealer.user.save()
|
||||||
for staff in dealer.get_staff():
|
for staff in dealer.get_staff():
|
||||||
if not staff.user.is_active:
|
if not staff.user.is_active:
|
||||||
staff.activate_account()
|
staff.activate_account()
|
||||||
|
except Exception as ex:
|
||||||
|
logger.warning(f"Failed to activate dealer/staff: {ex}")
|
||||||
|
|
||||||
elif payment_status == "failed":
|
elif payment_status == "failed":
|
||||||
logger.warning(
|
logger.warning(f"Payment failed for transaction ID {payment_id}. Message: {message}")
|
||||||
f"Payment failed for transaction ID {payment_id}. Message: {message}"
|
|
||||||
)
|
|
||||||
history.status = "failed"
|
history.status = "failed"
|
||||||
history.save()
|
history.save(update_fields=["status"])
|
||||||
return render(request, "payment_failed.html", {"message": message})
|
return render(request, "payment_failed.html", {"message": message})
|
||||||
|
|
||||||
return render(request, "payment_failed.html", {"message": "Unknown payment status"})
|
else:
|
||||||
|
logger.warning(f"Unknown payment status: {payment_status}")
|
||||||
|
history.status = "failed"
|
||||||
|
history.save(update_fields=["status"])
|
||||||
|
return render(request, "payment_failed.html", {"message": "Unknown payment status"})
|
||||||
|
|
||||||
# @login_required
|
# @login_required
|
||||||
# @permission_required("inventory.change_dealer", raise_exception=True)
|
# @permission_required("inventory.change_dealer", raise_exception=True)
|
||||||
@ -11555,16 +11561,16 @@ def upload_cars(request, dealer_slug, pk=None):
|
|||||||
try:
|
try:
|
||||||
if item:
|
if item:
|
||||||
# data = [x.strip() for x in item.item_model.name.split("||")]
|
# data = [x.strip() for x in item.item_model.name.split("||")]
|
||||||
make = models.CarMake.objects.get(pk=item.addition_info.get("make"))
|
make = models.CarMake.objects.get(pk=item.additional_info.get("make"))
|
||||||
model = models.CarModel.objects.get(pk=item.addition_info.get("model"))
|
model = models.CarModel.objects.get(pk=item.additional_info.get("model"))
|
||||||
trim = models.CarTrim.objects.get(pk=item.addition_info.get("trim"))
|
trim = models.CarTrim.objects.get(pk=item.additional_info.get("trim"))
|
||||||
serie = models.CarSerie.objects.get(pk=item.addition_info.get("serie"))
|
serie = models.CarSerie.objects.get(pk=item.additional_info.get("serie"))
|
||||||
year = item.addition_info.get("year")
|
year = item.additional_info.get("year")
|
||||||
exterior = models.ExteriorColors.objects.get(
|
exterior = models.ExteriorColors.objects.get(
|
||||||
pk=item.addition_info.get("exterior")
|
pk=item.additional_info.get("exterior")
|
||||||
)
|
)
|
||||||
interior = models.InteriorColors.objects.get(
|
interior = models.InteriorColors.objects.get(
|
||||||
pk=item.addition_info.get("interior")
|
pk=item.additional_info.get("interior")
|
||||||
)
|
)
|
||||||
receiving_date = timezone.now()
|
receiving_date = timezone.now()
|
||||||
vendor_model = item.bill_model.vendor
|
vendor_model = item.bill_model.vendor
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user