diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index c4cf650..93e6085 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index b06800a..2e8ff7d 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index ddeb8a3..9c3b770 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 656f462..61d387a 100644 --- a/core/admin.py +++ b/core/admin.py @@ -112,7 +112,7 @@ class AppSettingAdmin(admin.ModelAdmin): (None, {'fields': ('app_name', 'logo', 'slogan')}), (_('Contact Information'), {'fields': ('contact_phone', 'contact_email', 'contact_address')}), (_('Legal'), {'fields': ('registration_number', 'tax_number', 'terms_of_service', 'privacy_policy')}), - (_('Subscription Status'), {'fields': ('subscription_enabled',)}), + (_('Subscription Status'), {'fields': ('subscription_enabled', 'thawani_enabled')}), (_('Shipper Subscription Fees'), {'fields': ('shipper_monthly_fee', 'shipper_annual_fee')}), (_('Truck Owner Subscription Fees'), {'fields': ('truck_owner_monthly_fee', 'truck_owner_annual_fee')}), ) diff --git a/core/migrations/0021_appsetting_thawani_enabled.py b/core/migrations/0021_appsetting_thawani_enabled.py new file mode 100644 index 0000000..75592b2 --- /dev/null +++ b/core/migrations/0021_appsetting_thawani_enabled.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-01-24 07:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0020_transaction_payment_status_transaction_session_id'), + ] + + operations = [ + migrations.AddField( + model_name='appsetting', + name='thawani_enabled', + field=models.BooleanField(default=True, verbose_name='Enable Thawani Payment'), + ), + ] diff --git a/core/migrations/__pycache__/0021_appsetting_thawani_enabled.cpython-311.pyc b/core/migrations/__pycache__/0021_appsetting_thawani_enabled.cpython-311.pyc new file mode 100644 index 0000000..91a4da2 Binary files /dev/null and b/core/migrations/__pycache__/0021_appsetting_thawani_enabled.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 1ca61f8..3384816 100644 --- a/core/models.py +++ b/core/models.py @@ -261,6 +261,7 @@ class AppSetting(models.Model): terms_of_service = models.TextField(_('Terms of Service'), blank=True) privacy_policy = models.TextField(_('Privacy Policy'), blank=True) subscription_enabled = models.BooleanField(_('Enable Subscription Fee'), default=False) + thawani_enabled = models.BooleanField(_("Enable Thawani Payment"), default=True) # Shipper Fees shipper_monthly_fee = models.DecimalField(_('Shipper Monthly Fee'), max_digits=10, decimal_places=2, default=0.00) diff --git a/core/templates/core/place_bid.html b/core/templates/core/place_bid.html index bb96997..738f3e6 100644 --- a/core/templates/core/place_bid.html +++ b/core/templates/core/place_bid.html @@ -46,35 +46,52 @@ {% trans "Owner" %}: {{ truck.owner.username }} | {% trans "Plate" %}: {{ truck.plate_no }} -
- - {{ form.required_truck_type_link }} - {{ form.required_truck_type_link.errors }} -
+ {% if form.errors %} +
+
{% trans "Please correct the following errors:" %}
+ +
+ {% endif %} +
{% csrf_token %}
{% trans "Shipment Details" %}
+
+ + {{ form.required_truck_type_link }} + {% if form.required_truck_type_link.errors %}
{{ form.required_truck_type_link.errors.0 }}
{% endif %} +
+
{{ form.description }} - {{ form.description.errors }} + {% if form.description.errors %}
{{ form.description.errors.0 }}
{% endif %}
{{ form.weight }} - {{ form.weight.errors }} + {% if form.weight.errors %}
{{ form.weight.errors.0 }}
{% endif %}
{{ form.delivery_date }} - {{ form.delivery_date.errors }} + {% if form.delivery_date.errors %}
{{ form.delivery_date.errors.0 }}
{% endif %}
@@ -85,22 +102,22 @@
{{ form.origin_country }} - {{ form.origin_country.errors }} + {% if form.origin_country.errors %}
{{ form.origin_country.errors.0 }}
{% endif %}
{{ form.origin_city }} - {{ form.origin_city.errors }} + {% if form.origin_city.errors %}
{{ form.origin_city.errors.0 }}
{% endif %}
{{ form.destination_country }} - {{ form.destination_country.errors }} + {% if form.destination_country.errors %}
{{ form.destination_country.errors.0 }}
{% endif %}
{{ form.destination_city }} - {{ form.destination_city.errors }} + {% if form.destination_city.errors %}
{{ form.destination_city.errors.0 }}
{% endif %}
@@ -114,13 +131,13 @@ $ {{ form.amount }} - {{ form.amount.errors }} + {% if form.amount.errors %}
{{ form.amount.errors.0 }}
{% endif %}
{{ form.comments }} - {{ form.comments.errors }} + {% if form.comments.errors %}
{{ form.comments.errors.0 }}
{% endif %}
@@ -170,11 +187,16 @@ document.addEventListener('DOMContentLoaded', function() { if (originCountry && originCity) { originCountry.addEventListener('change', () => updateCities(originCountry, originCity)); - updateCities(originCountry, originCity); + // Only run on load if there's no pre-existing selection (to avoid clearing initial filtered values) + if (!originCity.value || originCity.value === "") { + updateCities(originCountry, originCity); + } } if (destCountry && destCity) { destCountry.addEventListener('change', () => updateCities(destCountry, destCity)); - updateCities(destCountry, destCity); + if (!destCity.value || destCity.value === "") { + updateCities(destCountry, destCity); + } } }); diff --git a/core/templates/core/post_shipment.html b/core/templates/core/post_shipment.html index a0b0848..b3138b7 100644 --- a/core/templates/core/post_shipment.html +++ b/core/templates/core/post_shipment.html @@ -30,30 +30,46 @@

{% trans "Post a New Shipment" %}

{% trans "Enter shipment details to receive bids or send as an offer." %}

- + {% if form.errors %} +
+
{% trans "Please correct the following errors:" %}
+
    + {% for field in form %} + {% for error in field.errors %} +
  • {{ field.label }}: {{ error }}
  • + {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
  • {{ error }}
  • + {% endfor %} +
+
+ {% endif %} + + {% csrf_token %}
{{ form.description }} - {% if form.description.errors %}
{{ form.description.errors }}
{% endif %} + {% if form.description.errors %}
{{ form.description.errors.0 }}
{% endif %}
{{ form.weight }} - {% if form.weight.errors %}
{{ form.weight.errors }}
{% endif %} + {% if form.weight.errors %}
{{ form.weight.errors.0 }}
{% endif %}
{{ form.required_truck_type_link }} - {% if form.required_truck_type_link.errors %}
{{ form.required_truck_type_link.errors }}
{% endif %} + {% if form.required_truck_type_link.errors %}
{{ form.required_truck_type_link.errors.0 }}
{% endif %}
{{ form.delivery_date }} - {% if form.delivery_date.errors %}
{{ form.delivery_date.errors }}
{% endif %} + {% if form.delivery_date.errors %}
{{ form.delivery_date.errors.0 }}
{% endif %}
@@ -66,18 +82,22 @@
{{ form.origin_country }} + {% if form.origin_country.errors %}
{{ form.origin_country.errors.0 }}
{% endif %} {{ form.origin_city }} + {% if form.origin_city.errors %}
{{ form.origin_city.errors.0 }}
{% endif %}
{{ form.destination_country }} + {% if form.destination_country.errors %}
{{ form.destination_country.errors.0 }}
{% endif %} {{ form.destination_city }} + {% if form.destination_city.errors %}
{{ form.destination_city.errors.0 }}
{% endif %}
@@ -128,13 +148,17 @@ document.addEventListener('DOMContentLoaded', function() { if (originCountry && originCity) { originCountry.addEventListener('change', () => updateCities(originCountry, originCity)); - updateCities(originCountry, originCity); + if (!originCity.value || originCity.value === "") { + updateCities(originCountry, originCity); + } } if (destCountry && destCity) { destCountry.addEventListener('change', () => updateCities(destCountry, destCity)); - updateCities(destCountry, destCity); + if (!destCity.value || destCity.value === "") { + updateCities(destCountry, destCity); + } } }); -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/subscription_expired.html b/core/templates/core/subscription_expired.html index 4ae3541..634574c 100644 --- a/core/templates/core/subscription_expired.html +++ b/core/templates/core/subscription_expired.html @@ -42,9 +42,16 @@
+ {% if app_settings.thawani_enabled %} + {% else %} +
+ + {% trans "Online payment is currently disabled. Please contact support for renewal." %} +
+ {% endif %}
@@ -95,4 +102,4 @@ } }); -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/core/views.py b/core/views.py index c33254e..788ccd6 100644 --- a/core/views.py +++ b/core/views.py @@ -22,6 +22,9 @@ from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse from django.contrib.sites.shortcuts import get_current_site import json +import logging + +logger = logging.getLogger(__name__) def home(request): """Render the landing screen for MASAR CARGO.""" @@ -36,7 +39,7 @@ def home(request): def register(request): app_settings = AppSetting.objects.first() - subscription_enabled = app_settings.subscription_enabled if app_settings else False + subscription_enabled = (app_settings.subscription_enabled and app_settings.thawani_enabled) if app_settings else False # Simplified fees dictionary for JS # Ensuring keys are exactly as they appear in Profile.ROLE_CHOICES @@ -325,6 +328,7 @@ def post_shipment(request): messages.success(request, _("Shipment posted successfully! It is now open for bids or you can browse trucks to send it as an offer.")) return redirect('dashboard') else: + logger.error(f"Post Shipment Form Errors: {form.errors}") messages.error(request, _("Please correct the errors in the form.")) else: form = ShipmentForm() @@ -382,6 +386,7 @@ def place_bid(request, truck_id): messages.success(request, _("Offer sent successfully!")) return redirect('dashboard') else: + logger.error(f"Place Bid Form Errors: {form.errors}") messages.error(request, _("Error sending offer. Please check the form.")) else: form = ShipperOfferForm() @@ -498,6 +503,9 @@ def renew_subscription(request): def thawani_checkout(request, plan): profile = request.user.profile app_settings = AppSetting.objects.first() + if app_settings and not app_settings.thawani_enabled: + messages.error(request, _("Online payment is currently disabled. Please contact support.")) + return redirect("dashboard") amount = 0 if profile.role == 'SHIPPER':