Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions docs/user/dashboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
Sponsorship Dashboard – User Flow

Who uses it

-Organizing team members with access to Sponsorships.

Entry

-Navigate to Sponsorship → Manage Sponsorship Profiles (/sponsorship/list/).

-Land on a table of sponsors with columns: Organization, Main Contact, Type (tier), Company Description, Amount to Pay, Payment Status, Application Status.

-Find the right sponsors

-Search box → type org or contact name → Search.

Filters (optional):

-Sponsorship Type: Supporter / Partner / Champion / …

-Application Status: Pending / Approved / Rejected

-Payment Status: Not Paid / Awaiting Payment / Partial / Paid

Click Search to apply. Use Reset (or clear URL) to remove filters.

Sort by clicking a column header (click again to flip ASC/DESC). Common sorts: Amount to Pay, Payment Status, Application Status.

Review & act

Scan badges to see state at a glance:

Payment: Paid, Awaiting Payment, Not Paid, Partial

Application: Pending, Approved, Rejected

Payment tracking quick checks

Filter Payment Status = Awaiting Payment to see who needs nudging.

Sort by Amount to Pay (DESC) to prioritize largest obligations.

After recording a payment on the detail page, the row returns as Paid on refresh.

Typical workflows

Triage new applicants: Filter Application Status = Pending → open each → approve/reject.

Chase payments: Filter Payment Status = Not Paid/Awaiting → sort by Amount to Pay → open record → send reminder/mark partial.

Tier review: Filter by Sponsorship Type to see distribution and gaps.

Empty/edge cases

If no results match, you’ll see an empty-state message. Clear filters or adjust search.

Pagination appears when results exceed a page; sorting/filters persist across pages.

Sharing views

The dashboard uses URL query params (e.g., ?q=acme&tier=champion&pay_status=awaiting). Copy the URL to share the exact filtered/sorted view with teammates.

71 changes: 71 additions & 0 deletions docs/user/sponsor.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,76 @@ First of all, please review all the available [sponsorship tiers](https://2025.c

The rest is TBD.

"""Sponsorship Management System
This document covers the complete sponsorship workflow for both sponsors and conference organizers.
Overview
The sponsorship system allows organizations to apply for conference sponsorship and enables organizers to manage applications, track payments, and coordinate sponsor benefits.

For Sponsors

Navigation Flow for New Sponsors

mermaidgraph TD

A[Visit Conference Website] --> B{User Signed In?}
B -->|No| C[Click 'Create Sponsorship Profile']
B -->|Yes| F[Access User Portal]
C --> D[Redirected to Sign In/Sign Up Page]
D --> E{New User?}
E -->|Yes| G[Click 'Sign Up' & Create Account]
E -->|No| H[Sign In with Credentials]
G --> I[Complete Account Verification]
H --> F
I --> F[Access User Portal]
F --> J[Click 'Sponsor Us Now']
J --> K[Fill Out Sponsorship Form]
K --> L[Submit Application]

Getting Started
To become a sponsor, you'll need:

-An active user account on the conference platform
-Your organization's information and logo
-A clear understanding of your desired sponsorship level

Sponsorship Levels
-The conference offers six sponsorship tiers: Champion, Supporter, Connector, Booster, Partner, and Individual. Each level has different pricing and benefits packages.

How to Apply

-Visit the Conference Website

-Navigate to the main conference website

-Start the Sponsorship Process

-Click "Create Sponsorship Profile"

-If not signed in, you'll be redirected to sign in/sign up

-Sign In or Create Account

-New Users: Sign up and verify your account
-Existing Users: Log in with your credentials

-Access Your Portal

-You'll be directed to your user portal dashboard

-Apply for Sponsorship

-Click "Sponsor Us Now" in the portal

-Fill out the sponsorship application form

-Submit your application


After Submission

Confirmation: You'll see a success message confirming your submission
Status: Your application status starts as "Pending"
Contact: Conference organizers will contact you within 2-3 business days
Next Steps: You'll receive information about payment and benefit coordination


Empty file added docs/user/sponsor_email.md
Empty file.
34 changes: 34 additions & 0 deletions sponsorship/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,38 @@ class Meta:
"sponsorship_type",
"logo",
"company_description",
"amount_to_pay",
]

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

# Add CSS classes and attributes
self.fields["sponsorship_type"].widget.attrs.update(
{"class": "form-control", "id": "id_sponsorship_type"}
)

self.fields["amount_to_pay"].widget.attrs.update(
{
"class": "form-control",
"id": "id_amount_to_pay",
"step": "0.01",
"min": "0",
}
)

# Make amount field not required initially (will be set via JavaScript)
self.fields["amount_to_pay"].required = False

def clean_amount_to_pay(self):
"""Ensure amount_to_pay is provided and valid"""
amount = self.cleaned_data.get("amount_to_pay")
if amount is None or amount <= 0:
raise forms.ValidationError("Please enter a valid amount.")
return amount

def get_sponsorship_prices_json(self):
"""Return sponsorship prices as JSON string for JavaScript"""
import json

return json.dumps(SponsorshipProfile.get_sponsorship_prices())
20 changes: 20 additions & 0 deletions sponsorship/migrations/0002_sponsorshipprofile_amount_to_pay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 5.1.7 on 2025-08-11 05:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("sponsorship", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="sponsorshipprofile",
name="amount_to_pay",
field=models.DecimalField(
blank=True, decimal_places=2, default=0.0, max_digits=10, null=True
),
),
]
26 changes: 26 additions & 0 deletions sponsorship/migrations/0003_sponsorshipprofile_payment_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 5.1.7 on 2025-08-11 05:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("sponsorship", "0002_sponsorshipprofile_amount_to_pay"),
]

operations = [
migrations.AddField(
model_name="sponsorshipprofile",
name="payment_status",
field=models.CharField(
choices=[
("not_paid", "Not Paid"),
("paid", "Paid"),
("awaiting", "Awaiting Payment"),
],
default="not_paid",
max_length=20,
),
),
]
44 changes: 44 additions & 0 deletions sponsorship/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ class SponsorshipProfile(models.Model):
("cancelled", "Cancelled"),
]

PAYMENT_STATUS_CHOICES = [
("not_paid", "Not Paid"),
("paid", "Paid"),
("awaiting", "Awaiting Payment"),
]

SPONSORSHIP_PRICES = {
"Champion": 10000.00,
"Supporter": 5000.00,
"Connector": 2500.00,
"Booster": 1000.00,
"Partner": 500.00,
"Individual": 100.00,
}

user = models.OneToOneField(
User, on_delete=models.CASCADE, related_name="sponsorship_user"
)
Expand All @@ -32,6 +47,9 @@ class SponsorshipProfile(models.Model):
sponsorship_type = models.CharField(max_length=20, choices=SPONSORSHIP_TYPES)
# sponsorship_tier = models.ForeignKey("SponsorshipTier", on_delete=models.SET_NULL, null=True, blank = True)
logo = models.ImageField(upload_to="sponsor_logos/", null=True, blank=True)
amount_to_pay = models.DecimalField(
max_digits=10, decimal_places=2, default=0.00, null=True, blank=True
)
company_description = models.TextField()
application_status = models.CharField(
max_length=20,
Expand All @@ -43,10 +61,36 @@ class SponsorshipProfile(models.Model):
],
default="pending",
)
payment_status = models.CharField(
max_length=20,
choices=PAYMENT_STATUS_CHOICES,
default="not_paid",
)

def __str__(self):
return self.organization_name

@classmethod
def get_sponsorship_prices(cls):
"""Return the sponsorship pricing dictionary"""
return cls.SPONSORSHIP_PRICES

def get_default_amount(self):
"""Get the default amount for this sponsorship type"""
return self.SPONSORSHIP_PRICES.get(self.sponsorship_type, 0.00)

def save(self, *args, **kwargs):
"""Override save to auto-set amount if not provided"""
if self.amount_to_pay is None or self.amount_to_pay == 0:
self.amount_to_pay = self.get_default_amount()
super().save(*args, **kwargs)

@property
def sponsorship_type_display_with_price(self):
"""Return sponsorship type with its default price for display"""
price = self.SPONSORSHIP_PRICES.get(self.sponsorship_type, 0)
return f"{self.get_sponsorship_type_display()} (${price:,.2f})"


# class SponsorshipTier(models.Model):
# amount = models.DecimalField(max_digits=10, decimal_places=2)
Expand Down
90 changes: 89 additions & 1 deletion sponsorship/templates/sponsorship/sponsorship_profile_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,93 @@ <h2>
Submit
</button>
</form>
<!-- Auto-fill JavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('Auto-fill script loaded');

// Sponsorship prices
const prices = {
'Champion': 10000.00,
'Supporter': 5000.00,
'Connector': 2500.00,
'Booster': 1000.00,
'Partner': 500.00,
'Individual': 100.00
};

// Find form elements - Django typically creates IDs like id_fieldname
const sponsorshipField = document.querySelector('#id_sponsorship_type');
const amountField = document.querySelector('#id_amount_to_pay');

console.log('Sponsorship field:', sponsorshipField);
console.log('Amount field:', amountField);

if (!sponsorshipField || !amountField) {
console.error('Form fields not found');
return;
}

// Function to update amount
function updateAmount() {
const selectedType = sponsorshipField.value;
console.log('Selected type:', selectedType);

if (selectedType && prices[selectedType]) {
const price = prices[selectedType];
amountField.value = price.toFixed(2);
console.log('Set amount to:', price);

// Visual feedback - briefly highlight the field
amountField.style.backgroundColor = '#d4edda';
amountField.style.transition = 'background-color 0.3s';

setTimeout(() => {
amountField.style.backgroundColor = '';
}, 2000);

// Show success message
showMessage('Amount auto-filled to $' + price.toFixed(2) + ' for ' + selectedType + ' sponsorship');
}
}

// Function to show message
function showMessage(text) {
// Remove existing message
const existingMsg = document.querySelector('.auto-fill-msg');
if (existingMsg) {
existingMsg.remove();
}

// Create message element
const msgDiv = document.createElement('div');
msgDiv.className = 'auto-fill-msg alert alert-info';
msgDiv.style.marginTop = '10px';
msgDiv.innerHTML = '<strong>Info:</strong> ' + text + ' (You can still modify this amount if needed)';

// Insert after the amount field's parent paragraph
const amountParagraph = amountField.closest('p');
if (amountParagraph) {
amountParagraph.parentNode.insertBefore(msgDiv, amountParagraph.nextSibling);
}

// Auto-remove after 5 seconds
setTimeout(() => {
if (msgDiv.parentNode) {
msgDiv.remove();
}
}, 5000);
}

// Listen for changes
sponsorshipField.addEventListener('change', updateAmount);

// Auto-fill on page load if a type is already selected
if (sponsorshipField.value) {
updateAmount();
}

console.log('Auto-fill setup complete');
});
</script>
{% endblock content %}
<!-- Compare this snippet from sponsorship/templates/sponsorship/sponsorship_profile_form.html: -->
Loading
Loading