Merge pull request #84 from WDI-Ideas/feature/module_1
Feature/module 1
This commit is contained in:
@@ -364,7 +364,12 @@ class IAmPrincipalResourceLinkForm(IAmPrincipalForm):
|
||||
class CreateCustomerForm(forms.Form):
|
||||
first_name = forms.CharField(max_length=255, required=True, label='First Name')
|
||||
last_name = forms.CharField(max_length=255, required=True, label='Last Name')
|
||||
business_name = forms.CharField(max_length=200, required=True, label="Business Name")
|
||||
email = forms.EmailField(required=True, label='Email')
|
||||
phone_no = PhoneNumberField(
|
||||
widget=forms.TextInput(),
|
||||
label="Phone No"
|
||||
)
|
||||
preferences = forms.ModelMultipleChoiceField(
|
||||
queryset=EventCategory.objects.all(),
|
||||
widget=forms.widgets.SelectMultiple(
|
||||
@@ -383,6 +388,14 @@ class CreateCustomerForm(forms.Form):
|
||||
label=_('Free period end date'),
|
||||
help_text=_('Enter the end date of the free period')
|
||||
)
|
||||
address_line1 = forms.CharField(widget=forms.Textarea(attrs={'rows': 4, 'cols': 40}))
|
||||
city = forms.CharField(max_length=200, required=False, label="Region")
|
||||
country = forms.CharField(max_length=200, required=False, label="Country")
|
||||
website = forms.URLField(max_length=255, required=False, label="Website")
|
||||
linkedin_profile = forms.URLField(max_length=200, required=False, label="LinkedIn")
|
||||
facebook_profile = forms.URLField(max_length=200, required=False, label="Facebook")
|
||||
instagram_profile = forms.URLField(max_length=200, required=False, label="Instagram")
|
||||
twitter_profile = forms.URLField(max_length=200, required=False, label="Twitter")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -391,7 +404,12 @@ class CreateCustomerForm(forms.Form):
|
||||
class UpdateCustomerForm(forms.Form):
|
||||
first_name = forms.CharField(max_length=255, required=True, label='First Name')
|
||||
last_name = forms.CharField(max_length=255, required=True, label='Last Name')
|
||||
business_name = forms.CharField(max_length=200, required=True, label="Business Name")
|
||||
email = forms.EmailField(required=True, label='Email', widget=forms.TextInput(attrs={'readonly': 'readonly'}))
|
||||
phone_no = PhoneNumberField(
|
||||
widget=forms.TextInput(),
|
||||
label="Phone No"
|
||||
)
|
||||
preferences = forms.ModelMultipleChoiceField(
|
||||
queryset=EventCategory.objects.all(),
|
||||
widget=forms.widgets.SelectMultiple(
|
||||
@@ -410,6 +428,14 @@ class UpdateCustomerForm(forms.Form):
|
||||
label=_('Free period end date'),
|
||||
help_text=_('Enter the end date of the free period')
|
||||
)
|
||||
address_line1 = forms.CharField(widget=forms.Textarea(attrs={'rows': 4, 'cols': 40}))
|
||||
city = forms.CharField(max_length=200, required=False, label="Region")
|
||||
country = forms.CharField(max_length=200, required=False, label="Country")
|
||||
website = forms.URLField(max_length=255, required=False, label="Website")
|
||||
linkedin_profile = forms.URLField(max_length=200, required=False, label="LinkedIn")
|
||||
facebook_profile = forms.URLField(max_length=200, required=False, label="Facebook")
|
||||
instagram_profile = forms.URLField(max_length=200, required=False, label="Instagram")
|
||||
twitter_profile = forms.URLField(max_length=200, required=False, label="Twitter")
|
||||
active = forms.BooleanField(required=False, label='Active', help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
18
accounts/migrations/0014_iamprincipal_business_name.py
Normal file
18
accounts/migrations/0014_iamprincipal_business_name.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.2 on 2024-08-11 16:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0013_iamprincipalextendeddata_pwd_changed_post_transfer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='iamprincipal',
|
||||
name='business_name',
|
||||
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Business Name'),
|
||||
),
|
||||
]
|
||||
18
accounts/migrations/0015_iamprincipal_twitter_profile.py
Normal file
18
accounts/migrations/0015_iamprincipal_twitter_profile.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.2 on 2024-08-12 08:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0014_iamprincipal_business_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='iamprincipal',
|
||||
name='twitter_profile',
|
||||
field=models.URLField(blank=True, max_length=255, null=True, verbose_name='Principal Twitter'),
|
||||
),
|
||||
]
|
||||
@@ -320,6 +320,8 @@ class IAmPrincipal(AbstractUser):
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
business_name = models.CharField(verbose_name="Business Name", max_length=200, blank=True, null=True)
|
||||
twitter_profile = models.URLField(verbose_name="Principal Twitter", max_length=255, null=True, blank=True)
|
||||
|
||||
USERNAME_FIELD = "email"
|
||||
REQUIRED_FIELDS = []
|
||||
|
||||
@@ -627,11 +627,21 @@ class CustomerCreateView(LoginRequiredMixin, generic.View):
|
||||
email=form.cleaned_data.get('email'),
|
||||
first_name=form.cleaned_data.get('first_name'),
|
||||
last_name=form.cleaned_data.get('last_name'),
|
||||
business_name=form.cleaned_data.get('business_name'),
|
||||
phone_no=form.cleaned_data.get('phone_no'),
|
||||
password=make_password("goodtimes#2024"),
|
||||
username=form.cleaned_data.get("email"),
|
||||
email_verified=True,
|
||||
register_complete=True,
|
||||
principal_type=IAmPrincipalType.objects.get(name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER),
|
||||
address_line1=form.cleaned_data.get("address_line1"),
|
||||
city=form.cleaned_data.get("city"),
|
||||
country=form.cleaned_data.get("country"),
|
||||
website=form.cleaned_data.get("website"),
|
||||
linkedin_profile=form.cleaned_data.get("linkedin_profile"),
|
||||
facebook_profile=form.cleaned_data.get("facebook_profile"),
|
||||
instagram_profile=form.cleaned_data.get("instagram_profile"),
|
||||
twitter_profile=form.cleaned_data.get("twitter_profile"),
|
||||
)
|
||||
|
||||
# generate referralcode of manager
|
||||
@@ -648,7 +658,7 @@ class CustomerCreateView(LoginRequiredMixin, generic.View):
|
||||
principal_preference = PrincipalPreference.objects.create(principal=principal_obj)
|
||||
principal_preference.preferred_categories.set(form.cleaned_data.get("preferences"))
|
||||
|
||||
principal_subscription= PrincipalSubscription.objects.create(
|
||||
principal_subscription = PrincipalSubscription.objects.create(
|
||||
start_date=form.cleaned_data.get("free_start_date"),
|
||||
end_date=form.cleaned_data.get("free_end_date"),
|
||||
principal=principal_obj,
|
||||
@@ -660,6 +670,7 @@ class CustomerCreateView(LoginRequiredMixin, generic.View):
|
||||
messages.success(self.request, constants.REGISTRATION_SUCCESS)
|
||||
return redirect(self.success_url)
|
||||
except Exception as e:
|
||||
print("errror is ", e)
|
||||
messages.error(self.request, str(e))
|
||||
context = self.get_context_data(form=form)
|
||||
return render(request, self.template_name, context=context)
|
||||
@@ -685,12 +696,28 @@ class CustomerUpdateView(LoginRequiredMixin, generic.View):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
principal_id = kwargs.get("pk")
|
||||
try:
|
||||
principal_obj = IAmPrincipal.objects.get(pk=principal_id)
|
||||
except Exception as e:
|
||||
messages.error(request, f"No Record of id {principal_id} is found")
|
||||
return redirect(self.success_url)
|
||||
|
||||
print(f"principal address is {principal_obj.address_line1}")
|
||||
|
||||
initial_data = {
|
||||
"first_name": principal_obj.first_name,
|
||||
"last_name": principal_obj.last_name,
|
||||
"email": principal_obj.email,
|
||||
"business_name": principal_obj.business_name,
|
||||
"phone_no": principal_obj.phone_no,
|
||||
"address_line1": principal_obj.address_line1,
|
||||
"city": principal_obj.city,
|
||||
"country": principal_obj.country,
|
||||
"website": principal_obj.website,
|
||||
"linkedin_profile": principal_obj.linkedin_profile,
|
||||
"facebook_profile": principal_obj.facebook_profile,
|
||||
"instagram_profile": principal_obj.instagram_profile,
|
||||
"twitter_profile": principal_obj.twitter_profile,
|
||||
"active": principal_obj.is_active
|
||||
}
|
||||
|
||||
@@ -714,8 +741,12 @@ class CustomerUpdateView(LoginRequiredMixin, generic.View):
|
||||
return render(request, self.template_name, context=context)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
customer_id = kwargs.get("pk")
|
||||
principal_obj = IAmPrincipal.objects.get(pk=customer_id)
|
||||
principal_id = kwargs.get("pk")
|
||||
try:
|
||||
principal_obj = IAmPrincipal.objects.get(pk=principal_id)
|
||||
except Exception as e:
|
||||
messages.error(request, f"No Record of customer id {principal_id} is found")
|
||||
return redirect(self.success_url)
|
||||
form = self.form_class(request.POST)
|
||||
if not form.is_valid():
|
||||
context = self.get_context_data(form=form)
|
||||
@@ -725,6 +756,16 @@ class CustomerUpdateView(LoginRequiredMixin, generic.View):
|
||||
# update principal data
|
||||
principal_obj.first_name = form.cleaned_data.get('first_name')
|
||||
principal_obj.last_name = form.cleaned_data.get('last_name')
|
||||
principal_obj.business_name = form.cleaned_data.get("business_name")
|
||||
principal_obj.phone_no = form.cleaned_data.get("phone_no")
|
||||
principal_obj.address_line1 = form.cleaned_data.get("address_line1")
|
||||
principal_obj.city = form.cleaned_data.get("city")
|
||||
principal_obj.country = form.cleaned_data.get("country")
|
||||
principal_obj.website = form.cleaned_data.get("website")
|
||||
principal_obj.linkedin_profile = form.cleaned_data.get("linkedin_profile")
|
||||
principal_obj.facebook_profile = form.cleaned_data.get("facebook_profile")
|
||||
principal_obj.instagram_profile = form.cleaned_data.get("instagram_profile")
|
||||
principal_obj.twitter_profile = form.cleaned_data.get("twitter_profile")
|
||||
principal_obj.save()
|
||||
|
||||
# update principal preferences record
|
||||
@@ -881,26 +922,75 @@ from django.http import HttpResponse
|
||||
# wb.save(response)
|
||||
# return response
|
||||
|
||||
|
||||
# from openpyxl.styles import Font
|
||||
def export_excel_template(request):
|
||||
# Define the columns and create an empty DataFrame
|
||||
columns = ['First Name', 'Last Name', 'Email', 'Preferences(should be seperated by comma)', 'Free period start date(YYYY-MM-DD)', 'Free period end date(YYYY-MM-DD)']
|
||||
# Define the columns for the Customer Registration sheet
|
||||
columns = [
|
||||
'First Name',
|
||||
'Last Name',
|
||||
'Business Name',
|
||||
'Email',
|
||||
'Phone No',
|
||||
'Preferences (should be separated by comma)',
|
||||
'Free period start date (YYYY-MM-DD)',
|
||||
'Free period end date (YYYY-MM-DD)',
|
||||
'Address',
|
||||
'Region',
|
||||
'Country',
|
||||
'Website',
|
||||
'LinkedIn',
|
||||
'Facebook',
|
||||
'Instagram',
|
||||
'Twitter',
|
||||
]
|
||||
df = pd.DataFrame(columns=columns)
|
||||
|
||||
# Create a workbook and select the active worksheet
|
||||
# Create a workbook and add the Customer Registration worksheet
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = 'Customer Registration'
|
||||
ws_customer = wb.active
|
||||
ws_customer.title = 'Manager Onboarding'
|
||||
|
||||
# Write the column headers
|
||||
# Write the column headers for the Customer Registration sheet
|
||||
for col_num, column_title in enumerate(df.columns, 1):
|
||||
cell = ws.cell(row=1, column=col_num, value=column_title)
|
||||
cell = ws_customer.cell(row=1, column=col_num, value=column_title)
|
||||
cell.font = Font(bold=True)
|
||||
|
||||
# Create the Readme worksheet
|
||||
ws_readme = wb.create_sheet(title='Readme')
|
||||
|
||||
# Add information about each field to the Readme sheet
|
||||
readme_data = [
|
||||
['Field Name', 'Description'],
|
||||
['First Name', 'The first name of the customer. This is a required field.'],
|
||||
['Last Name', 'The last name of the customer. This is a required field.'],
|
||||
['Business Name', 'The official name of the customer\'s business or organization.'],
|
||||
['Email', 'The email address of the customer. This must be a unique email not already used in the system. This is a required Field'],
|
||||
['Phone No', 'The business phone number. It should include the country code if applicable.'],
|
||||
['Category', 'A comma-separated list of event categories the customer is interested in. These should match existing categories in the system. This is a required Field'],
|
||||
['Free period start date', 'The start date of the customer\'s free trial period, formatted as YYYY-MM-DD.'],
|
||||
['Free period end date', 'The end date of the customer\'s free trial period, formatted as YYYY-MM-DD. This date must be later than the start date.'],
|
||||
['Address', 'The complete business address, including street, city, and postal code.'],
|
||||
['Region', 'The geographic region where the business operates.'],
|
||||
['Country', 'The country where the business is based.'],
|
||||
['Website', 'The URL of the business\'s official website. Ensure it includes "http://" or "https://".'],
|
||||
['LinkedIn', 'The LinkedIn profile URL of the business. Ensure it includes "http://" or "https://".'],
|
||||
['Facebook', 'The Facebook page URL of the business. Ensure it includes "http://" or "https://".'],
|
||||
['Instagram', 'The Instagram profile URL of the business. Ensure it includes "http://" or "https://".'],
|
||||
['Twitter', 'The Twitter handle or profile URL of the business. Ensure it includes "http://" or "https://".'],
|
||||
]
|
||||
|
||||
# Write the Readme data to the Readme worksheet
|
||||
for row_num, row_data in enumerate(readme_data, 1):
|
||||
for col_num, cell_value in enumerate(row_data, 1):
|
||||
cell = ws_readme.cell(row=row_num, column=col_num, value=cell_value)
|
||||
if row_num == 1: # Make the header bold
|
||||
cell.font = Font(bold=True)
|
||||
|
||||
# Save the workbook to a bytes buffer
|
||||
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||
response['Content-Disposition'] = 'attachment; filename=customer_registration_template.xlsx'
|
||||
wb.save(response)
|
||||
|
||||
return response
|
||||
|
||||
class CustomerTransferView(LoginRequiredMixin, generic.View):
|
||||
@@ -921,7 +1011,7 @@ class CustomerTransferView(LoginRequiredMixin, generic.View):
|
||||
|
||||
# Send the email
|
||||
try:
|
||||
temp_password="goodtimes#2024"
|
||||
temp_password = "goodtimes#2024"
|
||||
principal_obj.password = make_password(temp_password)
|
||||
principal_obj.save()
|
||||
email_service.load_template(
|
||||
@@ -968,12 +1058,19 @@ class CustomerImportView(LoginRequiredMixin, generic.View):
|
||||
excel_file = request.FILES['file']
|
||||
|
||||
wb = load_workbook(filename=excel_file)
|
||||
ws = wb.active
|
||||
|
||||
# Check if the specific sheet exists
|
||||
if 'Manager Onboarding' not in wb.sheetnames:
|
||||
form.add_error('file', 'The required sheet "Manager Onboarding" is not present in the uploaded file.')
|
||||
return render(request, self.template_name, context=context)
|
||||
|
||||
# Load the "Manager Onboarding" worksheet
|
||||
ws = wb['Manager Onboarding']
|
||||
|
||||
error_log = []
|
||||
|
||||
principals = []
|
||||
preferences_l = []
|
||||
preferences_list = []
|
||||
subscriptions = []
|
||||
principal_type = IAmPrincipalType.objects.get(name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER)
|
||||
free_subscription = Subscription.objects.filter(is_free=True, active=True).first()
|
||||
@@ -983,7 +1080,7 @@ class CustomerImportView(LoginRequiredMixin, generic.View):
|
||||
return render(request, self.template_name, context=context)
|
||||
|
||||
for idx, row in enumerate(ws.iter_rows(min_row=2, values_only=True), start=2):
|
||||
first_name, last_name, email, preferences, start_date, end_date = row
|
||||
first_name, last_name, business_name, email, phone_no, preferences, start_date, end_date, address, region, country, website, linkedin, facebook, instagram, twitter = row
|
||||
print(f"{first_name}, {last_name, email, preferences, start_date, end_date}")
|
||||
|
||||
# validate all data
|
||||
@@ -1017,16 +1114,26 @@ class CustomerImportView(LoginRequiredMixin, generic.View):
|
||||
username=email.strip(),
|
||||
email_verified=True,
|
||||
register_complete=True,
|
||||
principal_type=principal_type
|
||||
principal_type=principal_type,
|
||||
business_name=business_name,
|
||||
phone_no=str(phone_no),
|
||||
address_line1=address,
|
||||
city=region,
|
||||
country=country,
|
||||
website=website,
|
||||
linkedin_profile=linkedin,
|
||||
facebook_profile=facebook,
|
||||
instagram_profile=instagram,
|
||||
twitter_profile=twitter
|
||||
)
|
||||
principals.append(principal)
|
||||
|
||||
# Collect preferences to be set later
|
||||
preferences_l.append((principal, event_categories, start_date, end_date))
|
||||
preferences_list.append((principal, event_categories, start_date, end_date))
|
||||
|
||||
if error_log:
|
||||
context = self.get_context_data(form=form, error_log=error_log)
|
||||
messages.error(request, "No recore is created check error log and fix the error in the file ")
|
||||
messages.error(request, "No record is created check error log and fix the error in the file ")
|
||||
return render(request, self.template_name, context=context)
|
||||
|
||||
# Use transaction.atomic to ensure all-or-nothing
|
||||
@@ -1039,7 +1146,7 @@ class CustomerImportView(LoginRequiredMixin, generic.View):
|
||||
principals = IAmPrincipal.objects.filter(email__in=[p.email for p in principals])
|
||||
|
||||
# Create subscriptions and preferences
|
||||
for principal, event_categories, start_date, end_date in preferences_l:
|
||||
for principal, event_categories, start_date, end_date in preferences_list:
|
||||
principal = principals.get(email=principal.email)
|
||||
|
||||
# Generate referral code for the manager
|
||||
|
||||
@@ -35,10 +35,18 @@
|
||||
<div class="col-md-3">Last Name</div>
|
||||
<div class="col-md-9">{{principal_obj.last_name}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Business Name</div>
|
||||
<div class="col-md-9">{{principal_obj.business_name}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Email Address</div>
|
||||
<div class="col-md-9">{{principal_obj.email}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Phone No</div>
|
||||
<div class="col-md-9">{{principal_obj.phone_no}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Preferences</div>
|
||||
<div class="col-md-9">
|
||||
@@ -61,6 +69,38 @@
|
||||
<div class="col-md-3">End Date</div>
|
||||
<div class="col-md-9">{% if principal_subscription %}{{ principal_subscription.end_date }}{% else %}No subscription found{% endif %}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Address</div>
|
||||
<div class="col-md-9">{{principal_obj.address_line1}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Region</div>
|
||||
<div class="col-md-9">{{principal_obj.city}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Country</div>
|
||||
<div class="col-md-9">{{principal_obj.country}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Website</div>
|
||||
<div class="col-md-9">{{principal_obj.website}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Facebook</div>
|
||||
<div class="col-md-9">{{principal_obj.facebook_profile}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">LinkedIn</div>
|
||||
<div class="col-md-9">{{principal_obj.linkedin_profile}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Instagram</div>
|
||||
<div class="col-md-9">{{principal_obj.instagram_profile}}</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">Twitter</div>
|
||||
<div class="col-md-9">{{principal_obj.twitter_profile}}</div>
|
||||
</div>
|
||||
{% if principal_obj.extended_data and not principal_obj.extended_data.is_transferred and principal_obj.extended_data.is_onboarded and principal_obj.principal_type.name == 'event_manager' %}
|
||||
<div class="col text-end">
|
||||
<a class="btn btn-dark mb-2 me-4" href="{% url 'accounts:customer_transfer' principal_obj.id %}">
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
</td> -->
|
||||
<td class="text-center">
|
||||
<ul class="table-controls">
|
||||
{% if data_obj.extended_data.is_onboarded%}
|
||||
<li><a href="{% url 'accounts:customer_edit' data_obj.id%}" class="bs-tooltip"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" title=""
|
||||
data-original-title="Edit" data-bs-original-title="Edit"
|
||||
@@ -141,6 +142,7 @@
|
||||
d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z">
|
||||
</path>
|
||||
</svg></a></li>
|
||||
{%endif%}
|
||||
<li><a href="{% url 'accounts:customer_detail' data_obj.id%}" class="bs-tooltip" data-bs-toggle="tooltip" data-bs-placement="top" title="" data-original-title="View" data-bs-original-title="View" aria-label="View">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>
|
||||
</a></li>
|
||||
|
||||
Reference in New Issue
Block a user