update
This commit is contained in:
parent
27a71b658a
commit
d912313a27
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -9,6 +9,7 @@ from simple_history.admin import SimpleHistoryAdmin
|
||||
from .models import (
|
||||
Service,
|
||||
Package,
|
||||
PackageService,
|
||||
Payer,
|
||||
Invoice,
|
||||
InvoiceLineItem,
|
||||
@ -45,6 +46,16 @@ class ServiceAdmin(admin.ModelAdmin):
|
||||
)
|
||||
|
||||
|
||||
class PackageServiceInline(admin.TabularInline):
|
||||
"""Inline admin for Package Services."""
|
||||
|
||||
model = PackageService
|
||||
extra = 1
|
||||
readonly_fields = ['id']
|
||||
fields = ['service', 'sessions']
|
||||
autocomplete_fields = ['service']
|
||||
|
||||
|
||||
@admin.register(Package)
|
||||
class PackageAdmin(admin.ModelAdmin):
|
||||
"""Admin interface for Package model."""
|
||||
@ -52,15 +63,15 @@ class PackageAdmin(admin.ModelAdmin):
|
||||
list_display = ['name_en', 'total_sessions', 'price', 'validity_days', 'is_active', 'tenant']
|
||||
list_filter = ['is_active', 'tenant']
|
||||
search_fields = ['name_en', 'name_ar']
|
||||
readonly_fields = ['id', 'created_at', 'updated_at']
|
||||
filter_horizontal = ['services']
|
||||
readonly_fields = ['id', 'total_sessions', 'created_at', 'updated_at']
|
||||
inlines = [PackageServiceInline]
|
||||
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('name_en', 'name_ar', 'tenant', 'is_active')
|
||||
}),
|
||||
(_('Package Details'), {
|
||||
'fields': ('services', 'total_sessions', 'price', 'validity_days')
|
||||
'fields': ('total_sessions', 'price', 'validity_days')
|
||||
}),
|
||||
(_('Description'), {
|
||||
'fields': ('description',),
|
||||
|
||||
@ -10,7 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Layout, Fieldset, Row, Column, Submit, HTML
|
||||
|
||||
from .models import Invoice, InvoiceLineItem, Payment, Service, Package, PackagePurchase, Payer
|
||||
from .models import Invoice, InvoiceLineItem, Payment, Service, Package, PackageService, PackagePurchase, Payer
|
||||
|
||||
|
||||
class InvoiceForm(forms.ModelForm):
|
||||
@ -284,14 +284,11 @@ class PackageForm(forms.ModelForm):
|
||||
model = Package
|
||||
fields = [
|
||||
'name_en', 'name_ar',
|
||||
'services', 'total_sessions', 'price',
|
||||
'validity_days', 'description', 'is_active',
|
||||
'price', 'validity_days', 'description', 'is_active',
|
||||
]
|
||||
widgets = {
|
||||
'name_en': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'name_ar': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'services': forms.CheckboxSelectMultiple(),
|
||||
'total_sessions': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}),
|
||||
'price': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01', 'min': '0'}),
|
||||
'validity_days': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}),
|
||||
'description': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}),
|
||||
@ -306,32 +303,45 @@ class PackageForm(forms.ModelForm):
|
||||
if field_name == 'is_active':
|
||||
if 'class' not in field.widget.attrs:
|
||||
field.widget.attrs['class'] = 'form-check-input'
|
||||
elif field_name != 'services': # services uses CheckboxSelectMultiple
|
||||
else:
|
||||
if 'class' not in field.widget.attrs:
|
||||
field.widget.attrs['class'] = 'form-control'
|
||||
|
||||
|
||||
class PackageServiceForm(forms.ModelForm):
|
||||
"""
|
||||
Form for package service items (service + session count).
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = PackageService
|
||||
fields = ['service', 'sessions']
|
||||
widgets = {
|
||||
'service': forms.Select(attrs={'class': 'form-control select2', 'data-placeholder': 'Select service'}),
|
||||
'sessions': forms.NumberInput(attrs={'class': 'form-control', 'min': '1', 'value': '1'}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Filter to show only active services
|
||||
self.fields['service'].queryset = Service.objects.filter(is_active=True)
|
||||
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_method = 'post'
|
||||
self.helper.layout = Layout(
|
||||
Fieldset(
|
||||
_('Package Information'),
|
||||
Row(
|
||||
Column('name_en', css_class='form-group col-md-6 mb-0'),
|
||||
Column('name_ar', css_class='form-group col-md-6 mb-0'),
|
||||
css_class='form-row'
|
||||
),
|
||||
'services',
|
||||
Row(
|
||||
Column('total_sessions', css_class='form-group col-md-4 mb-0'),
|
||||
Column('price', css_class='form-group col-md-4 mb-0'),
|
||||
Column('validity_days', css_class='form-group col-md-4 mb-0'),
|
||||
css_class='form-row'
|
||||
),
|
||||
'description',
|
||||
'is_active',
|
||||
),
|
||||
Submit('submit', _('Save Package'), css_class='btn btn-primary')
|
||||
)
|
||||
# Add CSS classes
|
||||
for field_name, field in self.fields.items():
|
||||
if 'class' not in field.widget.attrs:
|
||||
field.widget.attrs['class'] = 'form-control'
|
||||
|
||||
|
||||
# Inline formset for package services
|
||||
PackageServiceFormSet = inlineformset_factory(
|
||||
Package,
|
||||
PackageService,
|
||||
form=PackageServiceForm,
|
||||
extra=0, # Start with 1 empty form
|
||||
can_delete=True,
|
||||
min_num=1,
|
||||
validate_min=True,
|
||||
)
|
||||
|
||||
|
||||
class PackagePurchaseForm(forms.ModelForm):
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
# Generated by Django 5.2.3 on 2025-11-02 12:07
|
||||
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def migrate_package_services(apps, schema_editor):
|
||||
"""
|
||||
Migrate existing package-service relationships to the new through model.
|
||||
"""
|
||||
Package = apps.get_model('finance', 'Package')
|
||||
PackageService = apps.get_model('finance', 'PackageService')
|
||||
|
||||
# For each package, create PackageService entries for existing services
|
||||
for package in Package.objects.all():
|
||||
# Get existing services through the old M2M relationship
|
||||
for service in package.services.all():
|
||||
# Create a PackageService with default 1 session
|
||||
PackageService.objects.create(
|
||||
package=package,
|
||||
service=service,
|
||||
sessions=1
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('finance', '0004_csid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# Step 1: Alter total_sessions field
|
||||
migrations.AlterField(
|
||||
model_name='package',
|
||||
name='total_sessions',
|
||||
field=models.PositiveIntegerField(default=0, help_text='Auto-calculated from service sessions', verbose_name='Total Sessions'),
|
||||
),
|
||||
|
||||
# Step 2: Create the PackageService model
|
||||
migrations.CreateModel(
|
||||
name='PackageService',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('sessions', models.PositiveIntegerField(default=1, help_text='Number of sessions for this service in the package', verbose_name='Number of Sessions')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='finance.package', verbose_name='Package')),
|
||||
('service', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='finance.service', verbose_name='Service')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Package Service',
|
||||
'verbose_name_plural': 'Package Services',
|
||||
'ordering': ['package', 'service'],
|
||||
'unique_together': {('package', 'service')},
|
||||
},
|
||||
),
|
||||
|
||||
# Step 3: Migrate existing data
|
||||
migrations.RunPython(migrate_package_services, reverse_code=migrations.RunPython.noop),
|
||||
|
||||
# Step 4: Remove the old M2M field
|
||||
migrations.RemoveField(
|
||||
model_name='package',
|
||||
name='services',
|
||||
),
|
||||
|
||||
# Step 5: Add the new M2M field with through
|
||||
migrations.AddField(
|
||||
model_name='package',
|
||||
name='services',
|
||||
field=models.ManyToManyField(related_name='packages', through='finance.PackageService', to='finance.service', verbose_name='Services'),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
@ -89,11 +89,14 @@ class Package(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
|
||||
)
|
||||
services = models.ManyToManyField(
|
||||
Service,
|
||||
through='PackageService',
|
||||
related_name='packages',
|
||||
verbose_name=_("Services")
|
||||
)
|
||||
total_sessions = models.PositiveIntegerField(
|
||||
verbose_name=_("Total Sessions")
|
||||
default=0,
|
||||
verbose_name=_("Total Sessions"),
|
||||
help_text=_("Auto-calculated from service sessions")
|
||||
)
|
||||
price = models.DecimalField(
|
||||
max_digits=10,
|
||||
@ -122,6 +125,51 @@ class Package(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name_en} ({self.total_sessions} sessions)"
|
||||
|
||||
def calculate_total_sessions(self):
|
||||
"""Calculate total sessions from all package services."""
|
||||
return sum(ps.sessions for ps in self.packageservice_set.all())
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""Override save to auto-calculate total sessions."""
|
||||
super().save(*args, **kwargs)
|
||||
# Update total_sessions after save (when through relationships exist)
|
||||
if self.pk:
|
||||
self.total_sessions = self.calculate_total_sessions()
|
||||
if self.total_sessions != self._state.fields_cache.get('total_sessions', 0):
|
||||
Package.objects.filter(pk=self.pk).update(total_sessions=self.total_sessions)
|
||||
|
||||
|
||||
class PackageService(UUIDPrimaryKeyMixin):
|
||||
"""
|
||||
Intermediate model linking packages to services with session counts.
|
||||
Allows specifying how many sessions of each service are included in a package.
|
||||
"""
|
||||
|
||||
package = models.ForeignKey(
|
||||
Package,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_("Package")
|
||||
)
|
||||
service = models.ForeignKey(
|
||||
Service,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_("Service")
|
||||
)
|
||||
sessions = models.PositiveIntegerField(
|
||||
default=1,
|
||||
verbose_name=_("Number of Sessions"),
|
||||
help_text=_("Number of sessions for this service in the package")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Package Service")
|
||||
verbose_name_plural = _("Package Services")
|
||||
unique_together = [['package', 'service']]
|
||||
ordering = ['package', 'service']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.package.name_en} - {self.service.name_en} ({self.sessions} sessions)"
|
||||
|
||||
|
||||
class Payer(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
|
||||
|
||||
@ -25,15 +25,30 @@
|
||||
.form-check-input {
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
.select2-container--default .select2-selection--single {
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.375rem;
|
||||
min-height: 38px;
|
||||
}
|
||||
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||
.select2-container--default.select2-container--focus .select2-selection--single {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
.service-row {
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
.service-row:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.btn-remove-service {
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
@ -55,7 +70,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
<form method="post" id="packageForm">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
@ -69,42 +84,47 @@
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Name (English)" %} <span class="text-danger">*</span></label>
|
||||
{{ form.name_en }}
|
||||
{% if form.name_en.errors %}
|
||||
<div class="text-danger small">{{ form.name_en.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Name (Arabic)" %}</label>
|
||||
{{ form.name_ar }}
|
||||
{% if form.name_ar.errors %}
|
||||
<div class="text-danger small">{{ form.name_ar.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Total Sessions" %} <span class="text-danger">*</span></label>
|
||||
{{ form.total_sessions }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Price" %} <span class="text-danger">*</span></label>
|
||||
{{ form.price }}
|
||||
{% if form.price.errors %}
|
||||
<div class="text-danger small">{{ form.price.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Validity (days)" %} <span class="text-danger">*</span></label>
|
||||
{{ form.validity_days }}
|
||||
{% if form.validity_days.errors %}
|
||||
<div class="text-danger small">{{ form.validity_days.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Services Included" %} <span class="text-danger">*</span></label>
|
||||
{{ form.services }}
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">{% trans "Description" %}</label>
|
||||
{{ form.description }}
|
||||
{% if form.description.errors %}
|
||||
<div class="text-danger small">{{ form.description.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-check">
|
||||
{{ form.is_active }}
|
||||
@ -115,6 +135,56 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-success text-white d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0"><i class="fas fa-list me-2"></i>{% trans "Services Included" %}</h5>
|
||||
<div>
|
||||
<span class="me-2">{% trans "Total Sessions:" %}</span>
|
||||
<span class="fw-bold fs-16px" id="totalSessionsDisplay">0</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ service_formset.management_form }}
|
||||
|
||||
<div id="serviceRows">
|
||||
{% for service_form in service_formset %}
|
||||
<div class="service-row" data-form-index="{{ forloop.counter0 }}">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-7">
|
||||
<label class="form-label small">{% trans "Service" %} <span class="text-danger">*</span></label>
|
||||
{{ service_form.service }}
|
||||
{% if service_form.service.errors %}
|
||||
<div class="text-danger small">{{ service_form.service.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small">{% trans "Sessions" %} <span class="text-danger">*</span></label>
|
||||
{{ service_form.sessions }}
|
||||
{% if service_form.sessions.errors %}
|
||||
<div class="text-danger small">{{ service_form.sessions.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-2 text-end">
|
||||
<label class="form-label small d-block"> </label>
|
||||
{% if not service_form.instance.pk or service_formset.can_delete %}
|
||||
<button type="button" class="btn btn-danger btn-sm btn-remove-service">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
{{ service_form.id }}
|
||||
<div style="display: none;">{{ service_form.DELETE }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-outline-success btn-sm mt-2" id="addServiceBtn">
|
||||
<i class="fas fa-plus me-1"></i>{% trans "Add Service" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
@ -136,8 +206,8 @@
|
||||
<p class="small">{% trans "Create service packages for bundled pricing." %}</p>
|
||||
<ul class="small">
|
||||
<li>{% trans "Set package name and price" %}</li>
|
||||
<li>{% trans "Define number of sessions" %}</li>
|
||||
<li>{% trans "Select included services" %}</li>
|
||||
<li>{% trans "Add services and specify sessions for each" %}</li>
|
||||
<li>{% trans "Total sessions are calculated automatically" %}</li>
|
||||
<li>{% trans "Set validity period" %}</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -146,16 +216,124 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Empty form template for cloning -->
|
||||
<script type="text/template" id="emptyFormTemplate">
|
||||
<div class="service-row" data-form-index="__prefix__">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-7">
|
||||
<label class="form-label small">{% trans "Service" %} <span class="text-danger">*</span></label>
|
||||
{{ service_formset.empty_form.service }}
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small">{% trans "Sessions" %} <span class="text-danger">*</span></label>
|
||||
{{ service_formset.empty_form.sessions }}
|
||||
</div>
|
||||
<div class="col-md-2 text-end">
|
||||
<label class="form-label small d-block"> </label>
|
||||
<button type="button" class="btn btn-danger btn-sm btn-remove-service">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
{{ service_formset.empty_form.id }}
|
||||
<div style="display: none;">{{ service_formset.empty_form.DELETE }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#id_services').select2({
|
||||
placeholder: '{% trans "Select Services" %}',
|
||||
allowClear: true
|
||||
$(document).ready(function() {
|
||||
let formIndex = {{ service_formset.total_form_count }};
|
||||
|
||||
// Initialize Select2 for existing service dropdowns
|
||||
initializeSelect2();
|
||||
|
||||
// Calculate total sessions on page load
|
||||
calculateTotalSessions();
|
||||
|
||||
// Add new service row
|
||||
$('#addServiceBtn').click(function() {
|
||||
// Get the template HTML and replace __prefix__
|
||||
let templateHtml = $('#emptyFormTemplate').html();
|
||||
templateHtml = templateHtml.replace(/__prefix__/g, formIndex);
|
||||
|
||||
// Create new row from the modified HTML
|
||||
const newRow = $(templateHtml);
|
||||
|
||||
// Append to service rows
|
||||
$('#serviceRows').append(newRow);
|
||||
|
||||
// Update form count
|
||||
const totalForms = $('#id_packageservice_set-TOTAL_FORMS');
|
||||
totalForms.val(parseInt(totalForms.val()) + 1);
|
||||
|
||||
// Initialize Select2 for the new dropdown
|
||||
newRow.find('select[name$="-service"]').select2({
|
||||
placeholder: '{% trans "Select Service" %}',
|
||||
allowClear: true,
|
||||
width: '100%'
|
||||
});
|
||||
|
||||
formIndex++;
|
||||
|
||||
// Recalculate total sessions
|
||||
calculateTotalSessions();
|
||||
});
|
||||
|
||||
// Remove service row
|
||||
$(document).on('click', '.btn-remove-service', function() {
|
||||
const row = $(this).closest('.service-row');
|
||||
const deleteCheckbox = row.find('input[name$="-DELETE"]');
|
||||
|
||||
if (deleteCheckbox.length > 0) {
|
||||
// Mark for deletion if it's an existing record
|
||||
deleteCheckbox.prop('checked', true);
|
||||
row.hide();
|
||||
} else {
|
||||
// Remove from DOM if it's a new record
|
||||
row.remove();
|
||||
}
|
||||
|
||||
// Recalculate total sessions
|
||||
calculateTotalSessions();
|
||||
});
|
||||
|
||||
// Recalculate total sessions when session count changes
|
||||
$(document).on('input change', 'input[name$="-sessions"]', function() {
|
||||
calculateTotalSessions();
|
||||
});
|
||||
|
||||
function initializeSelect2() {
|
||||
$('select[name$="-service"]').each(function() {
|
||||
if (!$(this).hasClass('select2-hidden-accessible')) {
|
||||
$(this).select2({
|
||||
placeholder: '{% trans "Select Service" %}',
|
||||
allowClear: true,
|
||||
width: '100%'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function calculateTotalSessions() {
|
||||
let total = 0;
|
||||
|
||||
$('.service-row:visible').each(function() {
|
||||
const deleteCheckbox = $(this).find('input[name$="-DELETE"]');
|
||||
const isMarkedForDeletion = deleteCheckbox.length > 0 && deleteCheckbox.is(':checked');
|
||||
|
||||
if (!isMarkedForDeletion) {
|
||||
const sessionsInput = $(this).find('input[name$="-sessions"]');
|
||||
const sessions = parseInt(sessionsInput.val()) || 0;
|
||||
total += sessions;
|
||||
}
|
||||
});
|
||||
|
||||
$('#totalSessionsDisplay').text(total);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@ -731,17 +731,52 @@ class PackageCreateView(LoginRequiredMixin, RolePermissionMixin, AuditLogMixin,
|
||||
success_url = reverse_lazy('finance:package_list')
|
||||
allowed_roles = [User.Role.ADMIN, User.Role.FINANCE]
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Set tenant."""
|
||||
form.instance.tenant = self.request.user.tenant
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add form title."""
|
||||
"""Add form title and service formset."""
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['form_title'] = 'Create New Package'
|
||||
context['submit_text'] = 'Create Package'
|
||||
|
||||
# Add package service formset
|
||||
if self.request.POST:
|
||||
context['service_formset'] = PackageServiceFormSet(
|
||||
self.request.POST,
|
||||
instance=self.object
|
||||
)
|
||||
else:
|
||||
context['service_formset'] = PackageServiceFormSet(
|
||||
instance=self.object
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Set tenant and save formset."""
|
||||
form.instance.tenant = self.request.user.tenant
|
||||
|
||||
# Save package first
|
||||
self.object = form.save()
|
||||
|
||||
# Get and validate formset
|
||||
formset = PackageServiceFormSet(
|
||||
self.request.POST,
|
||||
instance=self.object
|
||||
)
|
||||
|
||||
if formset.is_valid():
|
||||
# Save package services
|
||||
formset.save()
|
||||
|
||||
# Update total sessions
|
||||
self.object.total_sessions = self.object.calculate_total_sessions()
|
||||
self.object.save()
|
||||
|
||||
messages.success(self.request, self.success_message)
|
||||
return redirect(self.get_success_url())
|
||||
else:
|
||||
# If formset is invalid, delete the package and show errors
|
||||
self.object.delete()
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
||||
class PackageUpdateView(LoginRequiredMixin, RolePermissionMixin, TenantFilterMixin,
|
||||
@ -761,11 +796,48 @@ class PackageUpdateView(LoginRequiredMixin, RolePermissionMixin, TenantFilterMix
|
||||
allowed_roles = [User.Role.ADMIN, User.Role.FINANCE]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add form title."""
|
||||
"""Add form title and service formset."""
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['form_title'] = f'Update Package: {self.object.name_en}'
|
||||
context['submit_text'] = 'Update Package'
|
||||
|
||||
# Add package service formset
|
||||
if self.request.POST:
|
||||
context['service_formset'] = PackageServiceFormSet(
|
||||
self.request.POST,
|
||||
instance=self.object
|
||||
)
|
||||
else:
|
||||
context['service_formset'] = PackageServiceFormSet(
|
||||
instance=self.object
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Save package and formset."""
|
||||
# Save package
|
||||
self.object = form.save()
|
||||
|
||||
# Get and validate formset
|
||||
formset = PackageServiceFormSet(
|
||||
self.request.POST,
|
||||
instance=self.object
|
||||
)
|
||||
|
||||
if formset.is_valid():
|
||||
# Save package services
|
||||
formset.save()
|
||||
|
||||
# Update total sessions
|
||||
self.object.total_sessions = self.object.calculate_total_sessions()
|
||||
self.object.save()
|
||||
|
||||
messages.success(self.request, self.success_message)
|
||||
return redirect(self.get_success_url())
|
||||
else:
|
||||
# If formset is invalid, show errors
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
||||
class PayerListView(LoginRequiredMixin, TenantFilterMixin, PaginationMixin, ListView):
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n static %}
|
||||
{% load i18n static hr_tags %}
|
||||
|
||||
{% block title %}{% trans "Schedule Grid" %} - {{ block.super }}{% endblock %}
|
||||
|
||||
|
||||
0
hr/templatetags/__init__.py
Normal file
0
hr/templatetags/__init__.py
Normal file
BIN
hr/templatetags/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
hr/templatetags/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
hr/templatetags/__pycache__/hr_tags.cpython-312.pyc
Normal file
BIN
hr/templatetags/__pycache__/hr_tags.cpython-312.pyc
Normal file
Binary file not shown.
14
hr/templatetags/hr_tags.py
Normal file
14
hr/templatetags/hr_tags.py
Normal file
@ -0,0 +1,14 @@
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def get_item(dictionary, key):
|
||||
"""
|
||||
Template filter to get an item from a dictionary using a variable key.
|
||||
Usage: {{ mydict|get_item:key_variable }}
|
||||
"""
|
||||
if dictionary is None:
|
||||
return None
|
||||
return dictionary.get(key)
|
||||
494
logs/django.log
494
logs/django.log
@ -72455,3 +72455,497 @@ INFO 2025-11-02 14:30:00,006 tasks 16180 8648941888 Radiology results sync compl
|
||||
INFO 2025-11-02 14:30:00,012 tasks 16180 8648941888 Lab results sync started
|
||||
INFO 2025-11-02 14:30:00,012 tasks 16180 8648941888 Lab results sync completed: {'status': 'success', 'new_results': 0, 'updated_results': 0, 'errors': 0, 'timestamp': '2025-11-02 11:30:00.012252+00:00'}
|
||||
ERROR 2025-11-02 14:34:02,219 tasks 16180 8648941888 Appointment 8f028c27-4142-489c-91a8-417fa19038bf not found
|
||||
ERROR 2025-11-02 14:47:58,725 tasks 16172 8648941888 Appointment a754db19-dbcb-40e9-a03e-742e2c13ea83 not found
|
||||
ERROR 2025-11-02 14:47:58,725 tasks 16181 8648941888 Appointment 7d208dcb-490f-4f66-97e0-807f7a4cc9d4 not found
|
||||
ERROR 2025-11-02 14:47:58,725 tasks 16180 8648941888 Appointment 4e16bbd2-83d1-46e7-a439-b2f3d06fc35a not found
|
||||
ERROR 2025-11-02 14:47:58,725 tasks 16173 8648941888 Appointment 80157786-4d02-4e2a-960f-8ff0acdb443b not found
|
||||
INFO 2025-11-02 14:47:59,225 basehttp 18386 6198079488 "GET / HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 14:47:59,298 basehttp 18386 6214905856 "GET /en/ HTTP/1.1" 200 56415
|
||||
ERROR 2025-11-02 14:51:13,535 tasks 16172 8648941888 Appointment 1ba52899-1a8e-4bce-93bd-d1d643bb7b69 not found
|
||||
ERROR 2025-11-02 14:51:13,535 tasks 16180 8648941888 Appointment 84999784-a5ac-4385-82c0-6beee6a870fe not found
|
||||
ERROR 2025-11-02 14:52:08,315 tasks 16180 8648941888 Appointment 77bb0820-19c1-473f-a574-3cb8845eb3f9 not found
|
||||
INFO 2025-11-02 14:52:49,872 basehttp 18386 6198079488 "GET /en/hr/schedules/ HTTP/1.1" 200 101408
|
||||
ERROR 2025-11-02 14:52:59,587 log 18386 6198079488 Internal Server Error: /en/hr/schedules/grid/
|
||||
Traceback (most recent call last):
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
|
||||
response = get_response(request)
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response
|
||||
response = response.render()
|
||||
^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render
|
||||
self.content = self.rendered_content
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content
|
||||
template = self.resolve_template(self.template_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template
|
||||
return select_template(template, using=self.using)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template
|
||||
return engine.get_template(template_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template
|
||||
return Template(self.engine.get_template(template_name), self)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template
|
||||
template, origin = self.find_template(template_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template
|
||||
template = loader.get_template(name, skip=skip)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template
|
||||
template = super().get_template(template_name, skip)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template
|
||||
return Template(
|
||||
^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__
|
||||
self.nodelist = self.compile_nodelist()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist
|
||||
nodelist = parser.parse()
|
||||
^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends
|
||||
nodelist = parser.parse()
|
||||
^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block
|
||||
nodelist = parser.parse(("endblock",))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if
|
||||
nodelist = parser.parse(("elif", "else", "endif"))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for
|
||||
nodelist_loop = parser.parse(
|
||||
^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for
|
||||
nodelist_loop = parser.parse(
|
||||
^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if
|
||||
nodelist = parser.parse(("elif", "else", "endif"))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 1531, in do_with
|
||||
extra_context = token_kwargs(remaining_bits, parser, support_legacy=True)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 1127, in token_kwargs
|
||||
kwargs[key] = parser.compile_filter(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter
|
||||
return FilterExpression(token, self)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__
|
||||
filter_func = parser.find_filter(filter_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter
|
||||
raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)
|
||||
django.template.exceptions.TemplateSyntaxError: Invalid filter: 'get_item'
|
||||
ERROR 2025-11-02 14:52:59,689 basehttp 18386 6198079488 "GET /en/hr/schedules/grid/ HTTP/1.1" 500 333280
|
||||
ERROR 2025-11-02 14:56:54,423 tasks 16180 8648941888 Appointment 84999784-a5ac-4385-82c0-6beee6a870fe not found
|
||||
ERROR 2025-11-02 14:56:54,423 tasks 16172 8648941888 Appointment 1ba52899-1a8e-4bce-93bd-d1d643bb7b69 not found
|
||||
ERROR 2025-11-02 14:57:39,019 log 18386 6198079488 Internal Server Error: /en/hr/schedules/grid/
|
||||
Traceback (most recent call last):
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
|
||||
response = get_response(request)
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response
|
||||
response = response.render()
|
||||
^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render
|
||||
self.content = self.rendered_content
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content
|
||||
template = self.resolve_template(self.template_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template
|
||||
return select_template(template, using=self.using)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template
|
||||
return engine.get_template(template_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template
|
||||
return Template(self.engine.get_template(template_name), self)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template
|
||||
template, origin = self.find_template(template_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template
|
||||
template = loader.get_template(name, skip=skip)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template
|
||||
template = super().get_template(template_name, skip)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template
|
||||
return Template(
|
||||
^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__
|
||||
self.nodelist = self.compile_nodelist()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist
|
||||
nodelist = parser.parse()
|
||||
^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends
|
||||
nodelist = parser.parse()
|
||||
^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block
|
||||
nodelist = parser.parse(("endblock",))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if
|
||||
nodelist = parser.parse(("elif", "else", "endif"))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for
|
||||
nodelist_loop = parser.parse(
|
||||
^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for
|
||||
nodelist_loop = parser.parse(
|
||||
^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if
|
||||
nodelist = parser.parse(("elif", "else", "endif"))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse
|
||||
raise self.error(token, e)
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse
|
||||
compiled_result = compile_func(self, token)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 1531, in do_with
|
||||
extra_context = token_kwargs(remaining_bits, parser, support_legacy=True)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 1127, in token_kwargs
|
||||
kwargs[key] = parser.compile_filter(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter
|
||||
return FilterExpression(token, self)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__
|
||||
filter_func = parser.find_filter(filter_name)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/Users/marwanalwali/AgdarCentre/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter
|
||||
raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)
|
||||
django.template.exceptions.TemplateSyntaxError: Invalid filter: 'get_item'
|
||||
ERROR 2025-11-02 14:57:39,104 basehttp 18386 6198079488 "GET /en/hr/schedules/grid/ HTTP/1.1" 500 333401
|
||||
INFO 2025-11-02 14:57:44,128 autoreload 58250 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 14:57:45,995 basehttp 58250 6137393152 "GET /en/hr/schedules/grid/ HTTP/1.1" 200 161820
|
||||
INFO 2025-11-02 14:57:55,893 basehttp 58250 6137393152 "GET /en/hr/schedules/cf7163b9-672c-44f1-b48f-b39d8a24b6dc/ HTTP/1.1" 200 34704
|
||||
INFO 2025-11-02 14:58:01,898 basehttp 58250 6137393152 "GET /en/hr/schedules/cf7163b9-672c-44f1-b48f-b39d8a24b6dc/update/ HTTP/1.1" 200 36723
|
||||
INFO 2025-11-02 14:58:12,857 basehttp 58250 6137393152 "GET /en/hr/schedules/grid/ HTTP/1.1" 200 161818
|
||||
INFO 2025-11-02 14:58:14,328 basehttp 58250 6137393152 "GET /en/hr/schedules/create/ HTTP/1.1" 200 36648
|
||||
INFO 2025-11-02 14:58:30,834 basehttp 58250 6137393152 "GET / HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 14:58:30,916 basehttp 58250 6154219520 "GET /en/ HTTP/1.1" 200 56415
|
||||
INFO 2025-11-02 14:58:42,299 basehttp 58250 6154219520 "GET /en/finance/packages/ HTTP/1.1" 200 40594
|
||||
INFO 2025-11-02 14:58:45,783 basehttp 58250 6154219520 "GET /en/finance/packages/fb821bd4-d545-4c4c-9fbf-8f3597489cf4/update/ HTTP/1.1" 200 44132
|
||||
ERROR 2025-11-02 14:58:54,055 tasks 16181 8648941888 Appointment 310d15a7-8bf3-4742-9d66-ea672cb4ff53 not found
|
||||
ERROR 2025-11-02 14:58:54,055 tasks 16180 8648941888 Appointment 35bc0ce1-174a-41ad-bc93-fb7d92e34947 not found
|
||||
ERROR 2025-11-02 14:58:54,055 tasks 16172 8648941888 Appointment bf8645b9-dc70-43b2-a756-a1cbc04a2bae not found
|
||||
WARNING 2025-11-02 14:58:56,664 basehttp 58250 6137393152 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 14:58:56,689 basehttp 58250 6137393152 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 2154602
|
||||
WARNING 2025-11-02 14:58:56,711 log 58250 6154219520 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 14:58:56,711 basehttp 58250 6154219520 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 14:59:18,356 log 58250 6154219520 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 14:59:18,356 basehttp 58250 6154219520 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 14:59:18,417 log 58250 6154219520 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 14:59:18,417 basehttp 58250 6154219520 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
INFO 2025-11-02 14:59:20,557 basehttp 58250 6154219520 "GET /en/finance/packages/create/ HTTP/1.1" 200 43961
|
||||
WARNING 2025-11-02 14:59:20,629 log 58250 6154219520 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 14:59:20,629 basehttp 58250 6154219520 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 14:59:20,650 basehttp 58250 6154219520 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:00:00,002 tasks 16180 8648941888 Radiology results sync started
|
||||
INFO 2025-11-02 15:00:00,003 tasks 16180 8648941888 Radiology results sync completed: {'status': 'success', 'new_studies': 0, 'new_reports': 0, 'errors': 0, 'timestamp': '2025-11-02 12:00:00.003104+00:00'}
|
||||
INFO 2025-11-02 15:00:00,007 tasks 16172 8648941888 Lab results sync started
|
||||
INFO 2025-11-02 15:00:00,007 tasks 16172 8648941888 Lab results sync completed: {'status': 'success', 'new_results': 0, 'updated_results': 0, 'errors': 0, 'timestamp': '2025-11-02 12:00:00.007361+00:00'}
|
||||
ERROR 2025-11-02 15:00:00,009 tasks 16180 8648941888 Appointment 7d8e8281-f28e-47b2-bae6-04647dd5204d not found
|
||||
ERROR 2025-11-02 15:01:03,106 tasks 16172 8648941888 Appointment f3cf1889-ed7b-4416-8f02-ea8113a8b650 not found
|
||||
ERROR 2025-11-02 15:01:03,106 tasks 16180 8648941888 Appointment 6f4fe326-9e43-4b30-bae0-619526511ee5 not found
|
||||
INFO 2025-11-02 15:01:49,025 autoreload 58250 8648941888 /Users/marwanalwali/AgdarCentre/finance/forms.py changed, reloading.
|
||||
INFO 2025-11-02 15:01:49,407 autoreload 60273 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:02:00,876 basehttp 60273 6161133568 "GET /en/finance/packages/create/ HTTP/1.1" 200 41737
|
||||
WARNING 2025-11-02 15:02:00,958 log 60273 6161133568 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:02:00,958 basehttp 60273 6161133568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:02:00,987 basehttp 60273 6161133568 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 15:02:03,838 tasks 16180 8648941888 Appointment e494458f-a5fd-481b-97a3-c14466b6f1a1 not found
|
||||
ERROR 2025-11-02 15:02:04,122 tasks 16180 8648941888 Appointment e494458f-a5fd-481b-97a3-c14466b6f1a1 not found
|
||||
ERROR 2025-11-02 15:03:35,012 tasks 16181 8648941888 Appointment 0ff795b3-68a3-44e3-ad35-9b50b6e098a8 not found
|
||||
ERROR 2025-11-02 15:03:35,012 tasks 16172 8648941888 Appointment 642dc474-cd97-4dc0-8924-b2b832eeaea1 not found
|
||||
ERROR 2025-11-02 15:03:35,012 tasks 16180 8648941888 Appointment 251d4c8d-ad19-44b7-a10b-3b3ff3951257 not found
|
||||
ERROR 2025-11-02 15:04:52,071 tasks 16172 8648941888 Appointment 6f4fe326-9e43-4b30-bae0-619526511ee5 not found
|
||||
ERROR 2025-11-02 15:04:52,071 tasks 16180 8648941888 Appointment f3cf1889-ed7b-4416-8f02-ea8113a8b650 not found
|
||||
ERROR 2025-11-02 15:06:13,808 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:06:13,812 tasks 16172 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:06:13,818 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:06:13,927 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:06:13,935 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:07:00,671 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
INFO 2025-11-02 15:07:10,323 autoreload 60273 8648941888 /Users/marwanalwali/AgdarCentre/finance/models.py changed, reloading.
|
||||
INFO 2025-11-02 15:07:10,686 autoreload 63004 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:07:49,337 autoreload 63004 8648941888 /Users/marwanalwali/AgdarCentre/finance/admin.py changed, reloading.
|
||||
INFO 2025-11-02 15:07:49,687 autoreload 63420 8648941888 Watching for file changes with StatReloader
|
||||
ERROR 2025-11-02 15:08:01,336 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:08:58,551 tasks 16172 8648941888 Appointment 1ba52899-1a8e-4bce-93bd-d1d643bb7b69 not found
|
||||
ERROR 2025-11-02 15:08:58,551 tasks 16180 8648941888 Appointment 84999784-a5ac-4385-82c0-6beee6a870fe not found
|
||||
INFO 2025-11-02 15:09:25,294 autoreload 63420 8648941888 /Users/marwanalwali/AgdarCentre/finance/forms.py changed, reloading.
|
||||
INFO 2025-11-02 15:09:25,624 autoreload 64288 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:09:41,782 autoreload 64288 8648941888 /Users/marwanalwali/AgdarCentre/finance/forms.py changed, reloading.
|
||||
INFO 2025-11-02 15:09:42,069 autoreload 64395 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:10:12,304 autoreload 64395 8648941888 /Users/marwanalwali/AgdarCentre/finance/views.py changed, reloading.
|
||||
INFO 2025-11-02 15:10:12,618 autoreload 64676 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:11:58,836 autoreload 65634 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:12:01,831 basehttp 65634 6189592576 "GET /en/finance/packages/create/ HTTP/1.1" 200 57459
|
||||
WARNING 2025-11-02 15:12:01,933 log 65634 6189592576 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:12:01,933 basehttp 65634 6189592576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:12:01,934 basehttp 65634 6206418944 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:13:10,989 basehttp 65634 13170143232 "GET /en/finance/packages/create/ HTTP/1.1" 200 57538
|
||||
WARNING 2025-11-02 15:13:11,064 log 65634 13170143232 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:13:11,064 basehttp 65634 13170143232 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:13:11,090 basehttp 65634 13170143232 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:13:59,288 autoreload 65634 8648941888 /Users/marwanalwali/AgdarCentre/finance/forms.py changed, reloading.
|
||||
INFO 2025-11-02 15:13:59,607 autoreload 66715 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:14:03,144 basehttp 66715 6163656704 "GET /en/finance/packages/create/ HTTP/1.1" 200 57540
|
||||
WARNING 2025-11-02 15:14:03,247 basehttp 66715 13304360960 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:14:03,303 log 66715 6163656704 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:14:03,303 basehttp 66715 6163656704 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16670
|
||||
INFO 2025-11-02 15:14:04,873 basehttp 66715 6163656704 "GET /en/finance/packages/create/ HTTP/1.1" 200 57538
|
||||
WARNING 2025-11-02 15:14:04,948 log 66715 6163656704 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:14:04,948 basehttp 66715 6163656704 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:14:04,961 basehttp 66715 6163656704 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:14:13,430 autoreload 66860 8648941888 Watching for file changes with StatReloader
|
||||
INFO 2025-11-02 15:14:15,779 basehttp 66860 6197473280 "GET /en/finance/packages/create/ HTTP/1.1" 200 57540
|
||||
WARNING 2025-11-02 15:14:15,892 basehttp 66860 6214299648 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:14:15,898 log 66860 6197473280 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:14:15,898 basehttp 66860 6197473280 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16670
|
||||
ERROR 2025-11-02 15:17:58,789 tasks 16180 8648941888 Appointment b00eedde-1f8d-4556-bef4-07369f144d4e not found
|
||||
ERROR 2025-11-02 15:17:58,789 tasks 16181 8648941888 Appointment a0aed854-c98c-4d7a-b0d3-981bd7efb97f not found
|
||||
ERROR 2025-11-02 15:17:58,790 tasks 16173 8648941888 Appointment 7221c9b8-2318-4410-8548-141cae6b9132 not found
|
||||
ERROR 2025-11-02 15:17:58,791 tasks 16172 8648941888 Appointment d51ff4c0-8550-419f-bc72-c743e6c7098d not found
|
||||
ERROR 2025-11-02 15:17:58,792 tasks 16182 8648941888 Appointment d1318b1d-29af-448b-a49d-4747e962b336 not found
|
||||
ERROR 2025-11-02 15:18:44,536 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:21:11,927 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:21:12,182 tasks 16180 8648941888 Appointment d3a1ced0-c9ad-46e7-8c9c-28d5a9e39178 not found
|
||||
ERROR 2025-11-02 15:21:40,631 tasks 16180 8648941888 Appointment 4b81a2bd-b651-4c74-96ca-f624d7506c25 not found
|
||||
ERROR 2025-11-02 15:22:08,369 tasks 16173 8648941888 Appointment 70b4da76-44f5-42a8-92c2-a8915a849a3a not found
|
||||
ERROR 2025-11-02 15:22:08,369 tasks 16172 8648941888 Appointment 800db3b9-d5ac-452d-8bb4-c046e1b066d7 not found
|
||||
ERROR 2025-11-02 15:22:08,369 tasks 16181 8648941888 Appointment 0a8e9bd3-9c80-4e96-a583-3159f209047d not found
|
||||
ERROR 2025-11-02 15:22:08,369 tasks 16182 8648941888 Appointment ec4c2b50-b176-4fb2-b6cb-77b1271cae77 not found
|
||||
ERROR 2025-11-02 15:22:08,369 tasks 16180 8648941888 Appointment 8b124918-494c-44bb-967a-7a96e1cc2642 not found
|
||||
ERROR 2025-11-02 15:24:51,817 tasks 16180 8648941888 Appointment 7d8e8281-f28e-47b2-bae6-04647dd5204d not found
|
||||
ERROR 2025-11-02 15:28:53,975 tasks 16172 8648941888 Appointment b0c1c980-442f-4adc-ac76-2cd181929efd not found
|
||||
ERROR 2025-11-02 15:28:53,975 tasks 16180 8648941888 Appointment 07419aca-aaed-4f2f-9af3-680578504323 not found
|
||||
ERROR 2025-11-02 15:29:59,924 tasks 16172 8648941888 Appointment 01e64bc4-bb55-4589-ade8-2d684af8679f not found
|
||||
ERROR 2025-11-02 15:29:59,924 tasks 16180 8648941888 Appointment 7046f839-aede-4d5e-86f6-716893505439 not found
|
||||
INFO 2025-11-02 15:30:00,010 tasks 16180 8648941888 Radiology results sync started
|
||||
INFO 2025-11-02 15:30:00,010 tasks 16180 8648941888 Radiology results sync completed: {'status': 'success', 'new_studies': 0, 'new_reports': 0, 'errors': 0, 'timestamp': '2025-11-02 12:30:00.010630+00:00'}
|
||||
INFO 2025-11-02 15:30:00,017 tasks 16180 8648941888 Lab results sync started
|
||||
INFO 2025-11-02 15:30:00,017 tasks 16180 8648941888 Lab results sync completed: {'status': 'success', 'new_results': 0, 'updated_results': 0, 'errors': 0, 'timestamp': '2025-11-02 12:30:00.017207+00:00'}
|
||||
ERROR 2025-11-02 15:31:03,023 tasks 16181 8648941888 Appointment 642dc474-cd97-4dc0-8924-b2b832eeaea1 not found
|
||||
ERROR 2025-11-02 15:31:03,024 tasks 16180 8648941888 Appointment 0ff795b3-68a3-44e3-ad35-9b50b6e098a8 not found
|
||||
ERROR 2025-11-02 15:31:03,023 tasks 16172 8648941888 Appointment 251d4c8d-ad19-44b7-a10b-3b3ff3951257 not found
|
||||
ERROR 2025-11-02 15:32:03,753 tasks 16180 8648941888 Appointment 8f028c27-4142-489c-91a8-417fa19038bf not found
|
||||
ERROR 2025-11-02 15:32:04,031 tasks 16180 8648941888 Appointment 8f028c27-4142-489c-91a8-417fa19038bf not found
|
||||
ERROR 2025-11-02 15:34:51,981 tasks 16180 8648941888 Appointment 251d4c8d-ad19-44b7-a10b-3b3ff3951257 not found
|
||||
ERROR 2025-11-02 15:34:51,981 tasks 16172 8648941888 Appointment 0ff795b3-68a3-44e3-ad35-9b50b6e098a8 not found
|
||||
ERROR 2025-11-02 15:34:51,981 tasks 16181 8648941888 Appointment 642dc474-cd97-4dc0-8924-b2b832eeaea1 not found
|
||||
INFO 2025-11-02 15:36:10,655 basehttp 66860 6197473280 "GET /en/finance/packages/create/ HTTP/1.1" 200 57540
|
||||
WARNING 2025-11-02 15:36:10,740 basehttp 66860 6214299648 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:36:10,741 log 66860 6197473280 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:36:10,741 basehttp 66860 6197473280 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
INFO 2025-11-02 15:36:15,168 basehttp 66860 6197473280 "GET /en/finance/packages/create/ HTTP/1.1" 200 57538
|
||||
WARNING 2025-11-02 15:36:15,247 log 66860 6197473280 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:36:15,248 basehttp 66860 6197473280 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:36:15,267 basehttp 66860 6197473280 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:36:42,110 basehttp 66860 6214299648 "GET /en/finance/packages/create/ HTTP/1.1" 200 57982
|
||||
WARNING 2025-11-02 15:36:42,182 log 66860 6214299648 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:36:42,183 basehttp 66860 6214299648 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:36:42,220 basehttp 66860 6214299648 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:37:25,764 autoreload 66860 8648941888 /Users/marwanalwali/AgdarCentre/finance/forms.py changed, reloading.
|
||||
INFO 2025-11-02 15:37:26,230 autoreload 77901 8648941888 Watching for file changes with StatReloader
|
||||
WARNING 2025-11-02 15:37:26,923 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:37:27,014 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:37:27,014 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:37:27,074 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:37:27,075 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
INFO 2025-11-02 15:37:28,916 basehttp 77901 12901707776 "GET /en/finance/packages/create/ HTTP/1.1" 200 52910
|
||||
WARNING 2025-11-02 15:37:28,986 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:37:28,986 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:37:29,020 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 15:40:24,595 tasks 16180 8648941888 Appointment f3cf1889-ed7b-4416-8f02-ea8113a8b650 not found
|
||||
ERROR 2025-11-02 15:40:24,594 tasks 16172 8648941888 Appointment 6f4fe326-9e43-4b30-bae0-619526511ee5 not found
|
||||
INFO 2025-11-02 15:40:34,026 basehttp 77901 6157529088 "GET /en/finance/packages/create/ HTTP/1.1" 200 52555
|
||||
WARNING 2025-11-02 15:40:34,116 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:40:34,116 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:40:34,124 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:42:11,603 basehttp 77901 6157529088 "GET /en/finance/packages/create/ HTTP/1.1" 200 52557
|
||||
WARNING 2025-11-02 15:42:11,706 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:42:11,711 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:42:11,712 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16669
|
||||
INFO 2025-11-02 15:43:59,095 basehttp 77901 6157529088 "GET /en/finance/packages/create/ HTTP/1.1" 200 52429
|
||||
WARNING 2025-11-02 15:43:59,171 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:43:59,171 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:43:59,187 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:44:19,576 basehttp 77901 12901707776 "GET /en/finance/packages/create/ HTTP/1.1" 200 52434
|
||||
WARNING 2025-11-02 15:44:19,649 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:44:19,649 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:44:19,692 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:44:20,778 basehttp 77901 6157529088 "GET /en/finance/packages/create/ HTTP/1.1" 200 52434
|
||||
WARNING 2025-11-02 15:44:20,850 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:44:20,850 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:44:20,876 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:44:33,112 basehttp 77901 12901707776 "GET /en/finance/packages/create/ HTTP/1.1" 200 52437
|
||||
WARNING 2025-11-02 15:44:33,189 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:44:33,190 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:44:33,227 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:44:43,111 basehttp 77901 6157529088 "GET /en/finance/packages/create/ HTTP/1.1" 200 52437
|
||||
WARNING 2025-11-02 15:44:43,188 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:44:43,188 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:44:43,209 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:47:37,234 basehttp 77901 6157529088 "POST /en/finance/packages/create/ HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 15:47:37,304 basehttp 77901 6157529088 "GET /en/finance/packages/ HTTP/1.1" 200 42734
|
||||
WARNING 2025-11-02 15:47:37,388 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:47:37,388 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:47:37,400 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:47:47,853 basehttp 77901 12901707776 "GET /en/finance/packages/7b83fae1-71b3-4360-b10f-54955d640db1/update/ HTTP/1.1" 200 62819
|
||||
WARNING 2025-11-02 15:47:47,926 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:47:47,926 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:47:47,955 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:47:52,703 basehttp 77901 6157529088 "GET /en/finance/packages/ HTTP/1.1" 200 42414
|
||||
WARNING 2025-11-02 15:47:52,780 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:47:52,781 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:47:52,791 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:47:55,809 basehttp 77901 12901707776 "GET /en/ HTTP/1.1" 200 56418
|
||||
WARNING 2025-11-02 15:47:55,882 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:47:55,882 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:47:55,909 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 15:47:58,764 tasks 16180 8648941888 Appointment 77bb0820-19c1-473f-a574-3cb8845eb3f9 not found
|
||||
INFO 2025-11-02 15:48:21,205 basehttp 77901 6157529088 "GET /en/finance/reports/ HTTP/1.1" 200 45947
|
||||
WARNING 2025-11-02 15:48:21,286 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:48:21,287 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:48:21,330 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:49:26,985 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
WARNING 2025-11-02 15:49:27,092 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:49:27,092 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16669
|
||||
WARNING 2025-11-02 15:49:27,194 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:49:27,194 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16669
|
||||
INFO 2025-11-02 15:51:26,953 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 57783
|
||||
WARNING 2025-11-02 15:51:27,027 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:51:27,027 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:51:27,073 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 15:51:40,611 tasks 16180 8648941888 Appointment a754db19-dbcb-40e9-a03e-742e2c13ea83 not found
|
||||
ERROR 2025-11-02 15:51:40,611 tasks 16181 8648941888 Appointment 80157786-4d02-4e2a-960f-8ff0acdb443b not found
|
||||
ERROR 2025-11-02 15:51:40,612 tasks 16172 8648941888 Appointment 4e16bbd2-83d1-46e7-a439-b2f3d06fc35a not found
|
||||
ERROR 2025-11-02 15:51:40,612 tasks 16173 8648941888 Appointment 7d208dcb-490f-4f66-97e0-807f7a4cc9d4 not found
|
||||
ERROR 2025-11-02 15:52:08,345 tasks 16180 8648941888 Appointment 35bc0ce1-174a-41ad-bc93-fb7d92e34947 not found
|
||||
ERROR 2025-11-02 15:52:08,345 tasks 16172 8648941888 Appointment bf8645b9-dc70-43b2-a756-a1cbc04a2bae not found
|
||||
ERROR 2025-11-02 15:52:08,345 tasks 16181 8648941888 Appointment 310d15a7-8bf3-4742-9d66-ea672cb4ff53 not found
|
||||
INFO 2025-11-02 15:52:48,840 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 56671
|
||||
WARNING 2025-11-02 15:52:48,912 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:52:48,912 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:52:48,963 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:53:51,042 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 56804
|
||||
WARNING 2025-11-02 15:53:51,120 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:53:51,121 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:53:51,161 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:54:13,667 basehttp 77901 12901707776 "GET /en/ HTTP/1.1" 200 56793
|
||||
WARNING 2025-11-02 15:54:13,741 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:54:13,741 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:54:13,790 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 15:54:51,782 tasks 16180 8648941888 Appointment 01e64bc4-bb55-4589-ade8-2d684af8679f not found
|
||||
ERROR 2025-11-02 15:54:51,782 tasks 16172 8648941888 Appointment 7046f839-aede-4d5e-86f6-716893505439 not found
|
||||
INFO 2025-11-02 15:55:58,320 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 57146
|
||||
WARNING 2025-11-02 15:55:58,395 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:55:58,395 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:55:58,443 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:56:23,634 basehttp 77901 12901707776 "GET /en/ HTTP/1.1" 200 57137
|
||||
WARNING 2025-11-02 15:56:23,709 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:56:23,709 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:56:23,750 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 15:58:01,008 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 56508
|
||||
WARNING 2025-11-02 15:58:01,081 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 15:58:01,082 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 15:58:01,133 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 15:58:53,924 tasks 16180 8648941888 Appointment e494458f-a5fd-481b-97a3-c14466b6f1a1 not found
|
||||
INFO 2025-11-02 16:00:00,006 tasks 16180 8648941888 Radiology results sync started
|
||||
INFO 2025-11-02 16:00:00,007 tasks 16180 8648941888 Radiology results sync completed: {'status': 'success', 'new_studies': 0, 'new_reports': 0, 'errors': 0, 'timestamp': '2025-11-02 13:00:00.007287+00:00'}
|
||||
INFO 2025-11-02 16:00:00,013 tasks 16180 8648941888 Lab results sync started
|
||||
INFO 2025-11-02 16:00:00,013 tasks 16180 8648941888 Lab results sync completed: {'status': 'success', 'new_results': 0, 'updated_results': 0, 'errors': 0, 'timestamp': '2025-11-02 13:00:00.013790+00:00'}
|
||||
INFO 2025-11-02 16:00:00,201 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 51718
|
||||
WARNING 2025-11-02 16:00:00,272 log 77901 6157529088 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 16:00:00,272 basehttp 77901 6157529088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 16:00:00,327 basehttp 77901 6157529088 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
INFO 2025-11-02 16:00:35,311 basehttp 77901 12901707776 "GET /en/ HTTP/1.1" 200 47869
|
||||
WARNING 2025-11-02 16:00:35,384 log 77901 12901707776 Not Found: /.well-known/appspecific/com.chrome.devtools.json
|
||||
WARNING 2025-11-02 16:00:35,385 basehttp 77901 12901707776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 16668
|
||||
WARNING 2025-11-02 16:00:35,429 basehttp 77901 12901707776 "GET /static/plugins/toastr/toastr.js.map HTTP/1.1" 404 2011
|
||||
ERROR 2025-11-02 16:02:03,710 tasks 16172 8648941888 Appointment 1ba52899-1a8e-4bce-93bd-d1d643bb7b69 not found
|
||||
ERROR 2025-11-02 16:02:03,710 tasks 16180 8648941888 Appointment 84999784-a5ac-4385-82c0-6beee6a870fe not found
|
||||
ERROR 2025-11-02 16:02:03,983 tasks 16180 8648941888 Appointment 84999784-a5ac-4385-82c0-6beee6a870fe not found
|
||||
ERROR 2025-11-02 16:02:03,983 tasks 16172 8648941888 Appointment 1ba52899-1a8e-4bce-93bd-d1d643bb7b69 not found
|
||||
INFO 2025-11-02 16:02:12,288 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 47781
|
||||
INFO 2025-11-02 16:02:22,838 basehttp 77901 6157529088 "GET /en/switch_language/?language=ar HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 16:02:22,917 basehttp 77901 6157529088 "GET / HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 16:02:22,996 basehttp 77901 12901707776 "GET /ar/ HTTP/1.1" 200 49014
|
||||
INFO 2025-11-02 16:02:23,008 basehttp 77901 6157529088 "GET /static/css/rtl-fixes.css HTTP/1.1" 200 1420
|
||||
INFO 2025-11-02 16:02:23,010 basehttp 77901 12901707776 "GET /static/css/default/app-rtl.min.css HTTP/1.1" 200 1020811
|
||||
INFO 2025-11-02 16:02:33,341 basehttp 77901 12901707776 "GET /ar/switch_language/?language=en HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 16:02:33,401 basehttp 77901 12901707776 "GET / HTTP/1.1" 302 0
|
||||
INFO 2025-11-02 16:02:33,495 basehttp 77901 6157529088 "GET /en/ HTTP/1.1" 200 47778
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- User Menu - Only visible when authenticated -->
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="navbar-item navbar-user dropdown">
|
||||
|
||||
@ -41,194 +41,194 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-panel-divider"></div>
|
||||
|
||||
<!-- BEGIN theme-switch -->
|
||||
<div class="row mt-10px align-items-center">
|
||||
<div class="col-8 control-label text-body fw-bold">Header Fixed</div>
|
||||
<div class="col-4 d-flex">
|
||||
<div class="form-check form-switch ms-auto mb-0">
|
||||
<input type="checkbox" class="form-check-input" name="app-header-fixed" id="appHeaderFixed" value="1" checked />
|
||||
<label class="form-check-label" for="appHeaderFixed"> </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-10px align-items-center">
|
||||
<div class="col-8 control-label text-body fw-bold">Header Inverse</div>
|
||||
<div class="col-4 d-flex">
|
||||
<div class="form-check form-switch ms-auto mb-0">
|
||||
<input type="checkbox" class="form-check-input" name="app-header-inverse" id="appHeaderInverse" value="1" />
|
||||
<label class="form-check-label" for="appHeaderInverse"> </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-10px align-items-center">
|
||||
<div class="col-8 control-label text-body fw-bold">Sidebar Fixed</div>
|
||||
<div class="col-4 d-flex">
|
||||
<div class="form-check form-switch ms-auto mb-0">
|
||||
<input type="checkbox" class="form-check-input" name="app-sidebar-fixed" id="appSidebarFixed" value="1" checked />
|
||||
<label class="form-check-label" for="appSidebarFixed"> </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-10px align-items-center">
|
||||
<div class="col-8 control-label text-body fw-bold">Sidebar Grid</div>
|
||||
<div class="col-4 d-flex">
|
||||
<div class="form-check form-switch ms-auto mb-0">
|
||||
<input type="checkbox" class="form-check-input" name="app-sidebar-grid" id="appSidebarGrid" value="1" />
|
||||
<label class="form-check-label" for="appSidebarGrid"> </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-10px align-items-center">
|
||||
<div class="col-8 control-label text-body fw-bold">Gradient Enabled</div>
|
||||
<div class="col-4 d-flex">
|
||||
<div class="form-check form-switch ms-auto mb-0">
|
||||
<input type="checkbox" class="form-check-input" name="app-gradient-enabled" id="appGradientEnabled" value="1" />
|
||||
<label class="form-check-label" for="appGradientEnabled"> </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END theme-switch -->
|
||||
|
||||
<div class="theme-panel-divider"></div>
|
||||
|
||||
<h5>Admin Design (6)</h5>
|
||||
<!-- BEGIN theme-version -->
|
||||
<div class="theme-version">
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/html/index_v2.html" class="theme-version-link active">
|
||||
<span style="background-image: url({% static 'img/theme/default.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/transparent/index_v2.html" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/transparent.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/apple/index_v2.html" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/apple.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/material/index_v2.html" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/material.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/facebook/index_v2.html" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/facebook.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/google/index_v2.html" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/google.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END theme-version -->
|
||||
|
||||
<div class="theme-panel-divider"></div>
|
||||
|
||||
<h5>Language Version (9)</h5>
|
||||
<!-- BEGIN theme-version -->
|
||||
<div class="theme-version">
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/html/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/html.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/ajax/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/ajax.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/angularjs/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/angular1x.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/angularjs19/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/angular10x.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/svelte/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/svelte.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="javascript:alert('Laravel Version only available in downloaded version.');" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/laravel.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="javascript:alert('Django Version only available in downloaded version.');" class="theme-version-link active">
|
||||
<span style="background-image: url({% static 'img/version/django.jpg' %});" class="theme-version-cover "></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/vue3/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/vuejs.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/react/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/reactjs.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="javascript:alert('.NET Core MVC Version only available in downloaded version.');" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/dotnet.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/admin/nextjs/" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/version/nextjs.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END theme-version -->
|
||||
|
||||
<div class="theme-panel-divider"></div>
|
||||
|
||||
<h5>Frontend Design (5)</h5>
|
||||
<!-- BEGIN theme-version -->
|
||||
<div class="theme-version">
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/frontend/one-page-parallax/" target="blank" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/one-page-parallax.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/frontend/e-commerce/" target="blank" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/e-commerce.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/frontend/blog/" target="blank" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/blog.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/frontend/forum/" target="blank" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/forum.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-version-item">
|
||||
<a href="https://seantheme.com/color-admin/frontend/corporate/" target="blank" class="theme-version-link">
|
||||
<span style="background-image: url({% static 'img/theme/corporate.jpg' %});" class="theme-version-cover"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END theme-version -->
|
||||
|
||||
<div class="theme-panel-divider"></div>
|
||||
|
||||
<a href="https://seantheme.com/color-admin/documentation/" class="btn btn-dark d-block w-100 rounded-pill mb-10px" target="_blank"><b>Documentation</b></a>
|
||||
<a href="javascript:;" class="btn btn-default d-block w-100 rounded-pill" data-toggle="reset-local-storage"><b>Reset Local Storage</b></a>
|
||||
{# <div class="theme-panel-divider"></div>#}
|
||||
{# #}
|
||||
{# <!-- BEGIN theme-switch -->#}
|
||||
{# <div class="row mt-10px align-items-center">#}
|
||||
{# <div class="col-8 control-label text-body fw-bold">Header Fixed</div>#}
|
||||
{# <div class="col-4 d-flex">#}
|
||||
{# <div class="form-check form-switch ms-auto mb-0">#}
|
||||
{# <input type="checkbox" class="form-check-input" name="app-header-fixed" id="appHeaderFixed" value="1" checked />#}
|
||||
{# <label class="form-check-label" for="appHeaderFixed"> </label>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <div class="row mt-10px align-items-center">#}
|
||||
{# <div class="col-8 control-label text-body fw-bold">Header Inverse</div>#}
|
||||
{# <div class="col-4 d-flex">#}
|
||||
{# <div class="form-check form-switch ms-auto mb-0">#}
|
||||
{# <input type="checkbox" class="form-check-input" name="app-header-inverse" id="appHeaderInverse" value="1" />#}
|
||||
{# <label class="form-check-label" for="appHeaderInverse"> </label>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <div class="row mt-10px align-items-center">#}
|
||||
{# <div class="col-8 control-label text-body fw-bold">Sidebar Fixed</div>#}
|
||||
{# <div class="col-4 d-flex">#}
|
||||
{# <div class="form-check form-switch ms-auto mb-0">#}
|
||||
{# <input type="checkbox" class="form-check-input" name="app-sidebar-fixed" id="appSidebarFixed" value="1" checked />#}
|
||||
{# <label class="form-check-label" for="appSidebarFixed"> </label>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <div class="row mt-10px align-items-center">#}
|
||||
{# <div class="col-8 control-label text-body fw-bold">Sidebar Grid</div>#}
|
||||
{# <div class="col-4 d-flex">#}
|
||||
{# <div class="form-check form-switch ms-auto mb-0">#}
|
||||
{# <input type="checkbox" class="form-check-input" name="app-sidebar-grid" id="appSidebarGrid" value="1" />#}
|
||||
{# <label class="form-check-label" for="appSidebarGrid"> </label>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <div class="row mt-10px align-items-center">#}
|
||||
{# <div class="col-8 control-label text-body fw-bold">Gradient Enabled</div>#}
|
||||
{# <div class="col-4 d-flex">#}
|
||||
{# <div class="form-check form-switch ms-auto mb-0">#}
|
||||
{# <input type="checkbox" class="form-check-input" name="app-gradient-enabled" id="appGradientEnabled" value="1" />#}
|
||||
{# <label class="form-check-label" for="appGradientEnabled"> </label>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <!-- END theme-switch -->#}
|
||||
{# #}
|
||||
{# <div class="theme-panel-divider"></div>#}
|
||||
{# #}
|
||||
{# <h5>Admin Design (6)</h5>#}
|
||||
{# <!-- BEGIN theme-version -->#}
|
||||
{# <div class="theme-version">#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/html/index_v2.html" class="theme-version-link active">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/default.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/transparent/index_v2.html" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/transparent.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/apple/index_v2.html" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/apple.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/material/index_v2.html" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/material.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/facebook/index_v2.html" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/facebook.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/google/index_v2.html" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/google.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <!-- END theme-version -->#}
|
||||
{# #}
|
||||
{# <div class="theme-panel-divider"></div>#}
|
||||
{##}
|
||||
{# <h5>Language Version (9)</h5>#}
|
||||
{# <!-- BEGIN theme-version -->#}
|
||||
{# <div class="theme-version">#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/html/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/html.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/ajax/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/ajax.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/angularjs/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/angular1x.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/angularjs19/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/angular10x.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/svelte/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/svelte.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="javascript:alert('Laravel Version only available in downloaded version.');" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/laravel.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="javascript:alert('Django Version only available in downloaded version.');" class="theme-version-link active">#}
|
||||
{# <span style="background-image: url({% static 'img/version/django.jpg' %});" class="theme-version-cover "></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/vue3/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/vuejs.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/react/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/reactjs.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="javascript:alert('.NET Core MVC Version only available in downloaded version.');" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/dotnet.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/admin/nextjs/" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/version/nextjs.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <!-- END theme-version -->#}
|
||||
{##}
|
||||
{# <div class="theme-panel-divider"></div>#}
|
||||
{##}
|
||||
{# <h5>Frontend Design (5)</h5>#}
|
||||
{# <!-- BEGIN theme-version -->#}
|
||||
{# <div class="theme-version">#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/frontend/one-page-parallax/" target="blank" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/one-page-parallax.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/frontend/e-commerce/" target="blank" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/e-commerce.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/frontend/blog/" target="blank" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/blog.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/frontend/forum/" target="blank" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/forum.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# <div class="theme-version-item">#}
|
||||
{# <a href="https://seantheme.com/color-admin/frontend/corporate/" target="blank" class="theme-version-link">#}
|
||||
{# <span style="background-image: url({% static 'img/theme/corporate.jpg' %});" class="theme-version-cover"></span>#}
|
||||
{# </a>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <!-- END theme-version -->#}
|
||||
{##}
|
||||
{# <div class="theme-panel-divider"></div>#}
|
||||
{##}
|
||||
{# <a href="https://seantheme.com/color-admin/documentation/" class="btn btn-dark d-block w-100 rounded-pill mb-10px" target="_blank"><b>Documentation</b></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-default d-block w-100 rounded-pill" data-toggle="reset-local-storage"><b>Reset Local Storage</b></a>#}
|
||||
</div>
|
||||
</div>
|
||||
<!-- END theme-panel -->
|
||||
Loading…
x
Reference in New Issue
Block a user