adding subscription fee

This commit is contained in:
Flatlogic Bot 2026-01-24 03:30:04 +00:00
parent 081f578fb5
commit 9726a81f0c
11 changed files with 111 additions and 6 deletions

View File

@ -25,8 +25,8 @@ class TruckTypeAdmin(admin.ModelAdmin):
@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'role', 'country_code', 'phone_number')
list_filter = ('role',)
list_display = ('user', 'role', 'country_code', 'phone_number', 'subscription_plan', 'is_subscription_active')
list_filter = ('role', 'subscription_plan', 'is_subscription_active')
search_fields = ('user__username', 'phone_number')
@admin.register(Truck)
@ -90,7 +90,13 @@ class WhatsAppConfigAdmin(admin.ModelAdmin):
@admin.register(AppSetting)
class AppSettingAdmin(admin.ModelAdmin):
list_display = ('app_name', 'contact_phone', 'contact_email')
list_display = ('app_name', 'contact_phone', 'contact_email', 'subscription_enabled')
fieldsets = (
(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'), {'fields': ('subscription_enabled', 'monthly_fee', 'annual_fee')}),
)
def has_add_permission(self, request):
# Only allow one configuration record
@ -109,4 +115,4 @@ class HomeSectionAdmin(admin.ModelAdmin):
list_display = ('title', 'section_type', 'order', 'is_active')
list_editable = ('order', 'is_active')
list_filter = ('section_type', 'is_active', 'background_color')
search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar', 'content', 'content_ar')
search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar', 'content', 'content_ar')

View File

@ -1,5 +1,5 @@
from django import forms
from .models import Truck, Shipment, Bid, Profile, Country, OTPCode, City, TruckType
from .models import Truck, Shipment, Bid, Profile, Country, OTPCode, City, TruckType, AppSetting
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
@ -10,6 +10,8 @@ class UserRegistrationForm(UserCreationForm):
role = forms.ChoiceField(choices=[choice for choice in Profile.ROLE_CHOICES if choice[0] != 'ADMIN'], widget=forms.Select(attrs={'class': 'form-select'}))
country_code = forms.ChoiceField(choices=[], widget=forms.Select(attrs={'class': 'form-select'}))
phone_number = forms.CharField(max_length=20, required=True, widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '123456789'}))
subscription_plan = forms.ChoiceField(choices=[('MONTHLY', _('Monthly')), ('ANNUAL', _('Annual'))], required=False, widget=forms.Select(attrs={'class': 'form-select'}), label=_('Subscription Plan'))
accept_terms = forms.BooleanField(required=True, widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}), label=_('I have read and agree to the Terms and Conditions and Privacy Policy'))
class Meta(UserCreationForm.Meta):
model = User
@ -29,6 +31,16 @@ class UserRegistrationForm(UserCreationForm):
self.fields['country_code'].choices = [('966', 'Saudi Arabia (+966)')]
self.fields['country_code'].initial = '966'
app_settings = AppSetting.objects.first()
if app_settings and app_settings.subscription_enabled:
self.fields['subscription_plan'].choices = [
('MONTHLY', _('Monthly (%(fee)s)') % {'fee': app_settings.monthly_fee}),
('ANNUAL', _('Annual (%(fee)s)') % {'fee': app_settings.annual_fee}),
]
self.fields['subscription_plan'].required = True
else:
self.fields['subscription_plan'].required = False
for field in self.fields.values():
if not isinstance(field.widget, (forms.CheckboxInput, forms.Select)):
field.widget.attrs.update({'class': 'form-control'})

View File

@ -0,0 +1,43 @@
# Generated by Django 5.2.7 on 2026-01-24 03:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0016_homesection'),
]
operations = [
migrations.AddField(
model_name='appsetting',
name='annual_fee',
field=models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='Annual Fee'),
),
migrations.AddField(
model_name='appsetting',
name='monthly_fee',
field=models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='Monthly Fee'),
),
migrations.AddField(
model_name='appsetting',
name='subscription_enabled',
field=models.BooleanField(default=False, verbose_name='Enable Subscription Fee'),
),
migrations.AddField(
model_name='profile',
name='is_subscription_active',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profile',
name='subscription_expiry',
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name='profile',
name='subscription_plan',
field=models.CharField(choices=[('MONTHLY', 'Monthly'), ('ANNUAL', 'Annual'), ('NONE', 'None')], default='NONE', max_length=20),
),
]

View File

@ -53,6 +53,14 @@ class Profile(models.Model):
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='SHIPPER')
SUBSCRIPTION_CHOICES = (
('MONTHLY', _('Monthly')),
('ANNUAL', _('Annual')),
('NONE', _('None')),
)
subscription_plan = models.CharField(max_length=20, choices=SUBSCRIPTION_CHOICES, default='NONE')
subscription_expiry = models.DateField(null=True, blank=True)
is_subscription_active = models.BooleanField(default=False)
country_code = models.CharField(max_length=5, blank=True, default="966")
phone_number = models.CharField(max_length=20, unique=True, null=True) # Changed to unique and nullable for migration safety
@ -240,6 +248,9 @@ class AppSetting(models.Model):
contact_address = models.TextField(_('Contact Address'), blank=True)
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)
monthly_fee = models.DecimalField(_('Monthly Fee'), max_digits=10, decimal_places=2, default=0.00)
annual_fee = models.DecimalField(_('Annual Fee'), max_digits=10, decimal_places=2, default=0.00)
class Meta:
verbose_name = _('App Setting')

View File

@ -47,6 +47,33 @@
</div>
{% elif field.name == 'phone_number' %}
{# Handled above #}
{% elif field.name == 'subscription_plan' %}
{% if subscription_enabled %}
<div class="mb-3">
<label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
{% if field.errors %}
{% for error in field.errors %}
<div class="text-danger small">{{ error }}</div>
{% endfor %}
{% endif %}
</div>
{% endif %}
{% elif field.name == 'accept_terms' %}
<div class="mb-3 form-check">
{{ field }}
<label class="form-check-label small" for="{{ field.id_for_label }}">
{% trans "I have read and agree to the" %}
<a href="{% url 'terms_of_service' %}" target="_blank">{% trans "Terms of Service" %}</a>
{% trans "and" %}
<a href="{% url 'privacy_policy' %}" target="_blank">{% trans "Privacy Policy" %}</a>
</label>
{% if field.errors %}
{% for error in field.errors %}
<div class="text-danger small">{{ error }}</div>
{% endfor %}
{% endif %}
</div>
{% else %}
<div class="mb-3">
<label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>

View File

@ -23,6 +23,8 @@ def home(request):
return render(request, "core/index.html", context)
def register(request):
app_settings = AppSetting.objects.first()
subscription_enabled = app_settings.subscription_enabled if app_settings else False
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
if form.is_valid():
@ -34,6 +36,7 @@ def register(request):
'role': form.cleaned_data['role'],
'phone_number': form.cleaned_data['phone_number'],
'country_code': form.cleaned_data['country_code'],
'subscription_plan': form.cleaned_data.get('subscription_plan', 'NONE'),
}
request.session['registration_data'] = registration_data
@ -50,7 +53,7 @@ def register(request):
messages.error(request, _("Please correct the errors below."))
else:
form = UserRegistrationForm()
return render(request, 'registration/register.html', {'form': form})
return render(request, 'registration/register.html', {'form': form, 'subscription_enabled': subscription_enabled})
def verify_otp_registration(request):
registration_data = request.session.get('registration_data')
@ -78,6 +81,9 @@ def verify_otp_registration(request):
profile.role = registration_data['role']
profile.phone_number = registration_data['phone_number']
profile.country_code = registration_data['country_code']
profile.subscription_plan = registration_data.get('subscription_plan', 'NONE')
if profile.subscription_plan != 'NONE':
profile.is_subscription_active = True
profile.save()
login(request, user)