small fixes

This commit is contained in:
ismail 2025-09-24 12:09:11 +03:00
parent 2727588f58
commit 417475ad54
3 changed files with 126 additions and 116 deletions

View File

@ -7,16 +7,16 @@ from django_ledger.models import EstimateModel, BillModel, AccountModel, LedgerM
class Command(BaseCommand):
def handle(self, *args, **kwargs):
Permission.objects.get_or_create(
name="Can view crm",
codename="can_view_crm",
content_type=ContentType.objects.get_for_model(Lead),
)
Permission.objects.get_or_create(
name="Can reassign lead",
codename="can_reassign_lead",
content_type=ContentType.objects.get_for_model(Lead),
)
# Permission.objects.get_or_create(
# name="Can view crm",
# codename="can_view_crm",
# content_type=ContentType.objects.get_for_model(Lead),
# )
# Permission.objects.get_or_create(
# name="Can reassign lead",
# codename="can_reassign_lead",
# content_type=ContentType.objects.get_for_model(Lead),
# )
Permission.objects.get_or_create(
name="Can view sales",
codename="can_view_sales",

View File

@ -2134,6 +2134,10 @@ class Lead(models.Model):
slug = RandomCharField(length=8, unique=True)
class Meta:
permissions = [
("can_view_crm", _("Can view CRM")),
("can_reassign_lead", _("Can reassign lead")),
]
verbose_name = _("Lead")
verbose_name_plural = _("Leads")
indexes = [

View File

@ -10259,31 +10259,52 @@ def submit_plan(request, dealer_slug):
# @login_required
def payment_callback(request, dealer_slug):
from django.db import transaction
payment_id = request.GET.get("id")
payment_status = request.GET.get("status")
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(
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()
if not history:
logger.error(f"No PaymentHistory found for transaction_id: {payment_id}")
return render(
request, "payment_failed.html", {"message": "Invalid transaction"}
with transaction.atomic():
history = (
models.PaymentHistory.objects
.select_for_update()
.filter(transaction_id=payment_id)
.first()
)
if history.status == "paid":
logger.info("Payment already processed. Redirecting to home.")
return redirect("home")
if not history:
logger.error(f"No PaymentHistory found for transaction_id: {payment_id}")
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":
logger.info(
f"Payment successful for transaction ID {payment_id}. Creating order..."
)
logger.info(f"Payment successful for transaction ID {payment_id}. Creating order...")
# Get metadata from PaymentHistory (passed during handle_payment)
metadata = history.user_data
if isinstance(metadata, str):
try:
@ -10291,116 +10312,101 @@ def payment_callback(request, dealer_slug):
except json.JSONDecodeError:
logger.error(f"Failed to decode metadata JSON: {metadata}")
metadata = {}
plan_pricing_id = metadata.get("plan_pricing_id")
dealer_slug_from_meta = metadata.get("dealer_slug")
if not plan_pricing_id or dealer_slug_from_meta != dealer_slug:
logger.error("Invalid metadata in payment callback")
history.status = "failed"
history.save()
return render(
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}.")
history.save(update_fields=["status"])
return render(request, "payment_failed.html", {"message": "Invalid payment data"})
try:
# Complete the order (this may generate invoice, etc.)
order.complete_order()
history.status = "paid"
history.order = order # Link payment to order
history.save()
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
pp = get_object_or_404(PlanPricing, pk=plan_pricing_id)
with transaction.atomic():
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()
logger.info(f"Order {order.id} completed. Rendering success page.")
logger.info(f"Order {order.id} completed successfully.")
return render(
request, "payment_success.html", {"order": order, "invoice": invoice}
)
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.save()
return render(
request, "payment_failed.html", {"message": "Plan activation error"}
)
history.save(update_fields=["status"])
return render(request, "payment_failed.html", {"message": "Payment processing error"})
finally:
# Activate dealer & staff if needed
if dealer := getattr(order.user, "dealer", None):
if not dealer.user.is_active:
dealer.user.is_active = True
dealer.user.save()
for staff in dealer.get_staff():
if not staff.user.is_active:
staff.activate_account()
try:
if dealer := getattr(order.user, "dealer", None):
if not dealer.user.is_active:
dealer.user.is_active = True
dealer.user.save()
for staff in dealer.get_staff():
if not staff.user.is_active:
staff.activate_account()
except Exception as ex:
logger.warning(f"Failed to activate dealer/staff: {ex}")
elif payment_status == "failed":
logger.warning(
f"Payment failed for transaction ID {payment_id}. Message: {message}"
)
logger.warning(f"Payment failed for transaction ID {payment_id}. Message: {message}")
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": "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
# @permission_required("inventory.change_dealer", raise_exception=True)
@ -11555,16 +11561,16 @@ def upload_cars(request, dealer_slug, pk=None):
try:
if item:
# data = [x.strip() for x in item.item_model.name.split("||")]
make = models.CarMake.objects.get(pk=item.addition_info.get("make"))
model = models.CarModel.objects.get(pk=item.addition_info.get("model"))
trim = models.CarTrim.objects.get(pk=item.addition_info.get("trim"))
serie = models.CarSerie.objects.get(pk=item.addition_info.get("serie"))
year = item.addition_info.get("year")
make = models.CarMake.objects.get(pk=item.additional_info.get("make"))
model = models.CarModel.objects.get(pk=item.additional_info.get("model"))
trim = models.CarTrim.objects.get(pk=item.additional_info.get("trim"))
serie = models.CarSerie.objects.get(pk=item.additional_info.get("serie"))
year = item.additional_info.get("year")
exterior = models.ExteriorColors.objects.get(
pk=item.addition_info.get("exterior")
pk=item.additional_info.get("exterior")
)
interior = models.InteriorColors.objects.get(
pk=item.addition_info.get("interior")
pk=item.additional_info.get("interior")
)
receiving_date = timezone.now()
vendor_model = item.bill_model.vendor