emile 3 weeks ago
parent ed8e9d72fd
commit 6b0df34cdd

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,19 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="5">
<item index="0" class="java.lang.String" itemvalue="requests" />
<item index="1" class="java.lang.String" itemvalue="python-dotenv" />
<item index="2" class="java.lang.String" itemvalue="gunicorn" />
<item index="3" class="java.lang.String" itemvalue="django" />
<item index="4" class="java.lang.String" itemvalue="django_ckeditor_5" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPep8Inspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" />
</profile>
</component>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.13 (osinaweb)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (osinaweb)" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/osinaweb.iml" filepath="$PROJECT_DIR$/.idea/osinaweb.iml" />
</modules>
</component>
</project>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="FacetManager">
<facet type="django" name="Django">
<configuration>
<option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="osinaweb/settings.py" />
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
<option name="environment" value="&lt;map/&gt;" />
<option name="doNotUseTestRunner" value="false" />
<option name="trackFilePattern" value="migrations" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.13 (osinaweb)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" />
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/osinacore/templates" />
</list>
</option>
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

Binary file not shown.

@ -7,6 +7,8 @@ urlpatterns = [
path('status/', views.add_status_modal, name='addstatusmodal'), path('status/', views.add_status_modal, name='addstatusmodal'),
path('customer/', views.add_customer, name='addcustomer'), path('customer/', views.add_customer, name='addcustomer'),
path('business/', views.add_business, name='addbusiness'), path('business/', views.add_business, name='addbusiness'),
path('addressbook/', views.add_addressbook, name='addaddressbook'),
path('staff/', views.add_staff, name='adduser'), path('staff/', views.add_staff, name='adduser'),

@ -894,3 +894,51 @@ def add_ticket_update(request, ticket_id):
} }
return render(request, 'add_templates/customer-add-ticket.html', context) return render(request, 'add_templates/customer-add-ticket.html', context)
@staff_login_required
def add_addressbook(request):
customers = CustomerProfile.objects.all().order_by('-id')
business_types = BusinessType.objects.all().order_by('-id')
if request.method == 'POST':
customer_id = request.POST.get('customer')
customer = get_object_or_404(CustomerProfile, id=customer_id)
name = request.POST.get('name')
email = request.POST.get('email')
financial_number = request.POST.get('financial_number')
phone_number = request.POST.get('phone_number')
vat = request.POST.get('vat')
if vat:
vat = True
else:
vat = False
commercial_registration = request.POST.get('commercial_registration')
website = request.POST.get('website')
logo = request.FILES.get('logo')
business_type_id = request.POST.get('type')
business_type = get_object_or_404(BusinessType, id=business_type_id)
business = Business(
customer=customer,
name=name,
email=email,
financial_number=financial_number,
vat=vat,
commercial_registration=commercial_registration,
website=website,
type=business_type,
logo=logo,
phone_number=phone_number,
)
business.save()
return redirect('businesses')
context = {
'customers': customers,
'business_types': business_types,
}
return render(request, 'add_templates/add-business.html', context)

@ -0,0 +1,110 @@
{% extends "add-edit-main.html" %}
{%load static%}
{% block content %}
<div class="w-full">
<div class="w-full h-full shadow-md rounded-md py-5 px-3 bg-white">
<h1 class="text-3xl text-secondosiblue text-center font-semibold">
Add Business
</h1>
<form method="POST" action="{% url 'addaddressbook' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="w-full flex flex-col gap-5">
<div class="w-full">
<label class="text-gray-500">Logo:</label>
<div class="inbox-box border border-gray-300 w-full rounded-md px-3 mt-1">
<div class="flex items-center justify-between">
<input name="logo" required type="file" class="file-input" accept="image/*" hidden />
<span class="file-name text-gray-500 text-base focus:outline-none outline-none">Upload
Logo</span>
<label
class="file-label bg-transparent text-gray-500 border border-white h-14 cursor-pointer flex items-center">
<i class="fa fa-upload" style="font-size: 25px;"></i>
</label>
</div>
</div>
</div>
<div class="w-full">
<label class="text-gray-500">Customer:</label>
<select name="customer" id="business_type"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md text-gray-500 mt-1">
<option value="" selected disabled>Select Customer</option>
{% for customer in customers %}
<option value="{{ customer.id }}">{{ customer.user.first_name }} {{ customer.user.last_name }}</option>
{% endfor %}
</select>
</div>
<div class="w-full">
<label class="text-gray-500">Name:</label>
<input name="name" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Email:</label>
<input name="email" type="email"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Financial Number:</label>
<input name="financial_number" type="number"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Commercial Registration:</label>
<input name="commercial_registration" type="commercial_registration"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Mobile Number:</label>
<input name="phone_number" type="number"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Website:</label>
<input name="website" type="url"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
</div>
<div class="w-full">
<label class="text-gray-500">Type:</label>
<select name="type" id="business_type"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md text-gray-500 mt-1">
<option value="" selected disabled>Select Business Type</option>
{% for business_type in business_types %}
<option value="{{ business_type.id }}">{{ business_type.name }}</option>
{% endfor %}
</select>
</div>
<div class="w-full flex justify-start items-center gap-2 mt-1">
<input name="vat" type="checkbox" >
<label class="text-slate-800">VAT</label>
</div>
<div class="w-full flex justify-center items-center mt-3">
<button type="submit"
class="w-fit py-1 px-5 bg-osiblue rounded-md outline-none text-white border border-osiblue text-xl cursor-pointer hover:bg-white hover:text-osiblue duration-300">Save</button>
</div>
</div>
</form>
</div>
</div>
<!-------------- JS SCRIPTS --------------->
<script type="text/javascript" src='{% static "js/inputs/upload-input-tag.js" %}'></script>
{% endblock content %}

@ -0,0 +1,118 @@
{% extends "main.html" %}
{%load static%}
{% block title %}My Projects{% endblock %}
{% block content %}
<div class="w-full xxlg1:w-[75%]">
<div class="w-full h-fit bg-white rounded-md shadow-md p-5">
<h1 class="text-secondosiblue text-[25px]">Address Book</h1>
<!-- FILTERING -->
<div
class="w-full py-4 px-3 bg-gray-200 rounded-md shadow-md mt-4 flex flex-col s:flex-row justify-between gap-3 items-center">
<div class="w-full s:w-fit flex justify-start items-center gap-5">
<div class="relative h-fit w-full s:w-fit flex items-center">
<input type="text" placeholder="Enter Name"
class="py-2 px-3 border border-gray-300 rounded-md outline-none w-full s:w-[300px] h-[40px] relative">
<button
class="text-gray-500 text-xl outline-none border-none cursor-pointer absolute right-2 bg-white">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<div class="w-full s:w-fit">
<a href="{% url 'addaddressbook' %}" class="text-blue-500 hover:text-blue-800 hover:underline"></a>
<button
class="w-full s:w-fit text-base px-3 py-2 bg-osiblue text-white outline-none border border-osiblue rounded-md cursor-pointer hover:bg-white hover:text-osiblue duration-300">Add
</button>
</a>
</div>
</div>
<div class="overflow-x-auto border border-gray-300 rounded-md mt-5 tableContainer" id="customersContainer">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Name
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Country
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Contact
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
Actions
</th>
</tr>
</thead>
<!-- TABLE BODY -->
<tbody class="bg-white divide-y divide-gray-200">
<!-- 1st row -->
{% for address in addresses %}
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<div class="w-full flex flex-col justify-center items-center gap-3">
<div class="w-[50px] h-[50px] bg-slate-600 rounded-full">
<img src='{{business.logo.url}}' alt="Business Logo"
class="w-full h-full object-cover rounded-full">
</div>
<p class="text-secondosiblue">{{ address.first_name }} {{ address.middle_name }} {{ address.last_name }}</p>
</div>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
{% for c in address.contact_set.all %}
<p class="text-secondosiblue">{{c.type}}: {{c.contact}}</p>
{% endfor %}
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{address.type.name}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<a href="{% url 'businessdetails' business.business_id %}">
<div class="cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
</div>
</a>
<a href="{% url 'editbusiness' business.business_id %}">
<div class="cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
</svg>
</div>
</a>
<div class="cursor-pointer deleteBusinessButton"
data-modal-url="{% url 'deletebusinessmodal' business.id %}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[18px] text-red-500 hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}

@ -466,6 +466,49 @@
<p class="text-white">Activity</p> <p class="text-white">Activity</p>
</div> </div>
</a> </a>
<a class="w-full" href="{% url 'addressbook' %}">
<div class="w-full flex justify-start items-center gap-3 border-b border-slate-600 py-3">
<svg class="w-[25px] text-white" viewBox="0 -0.5 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 7V17C7.5 18.1046 8.39543 19 9.5 19H17.5C18.6046 19 19.5 18.1046 19.5 17V7C19.5 5.89543 18.6046 5 17.5 5H9.5C8.39543 5 7.5 5.89543 7.5 7Z" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.5 10C15.5 11.1046 14.6046 12 13.5 12C12.3954 12 11.5 11.1046 11.5 10C11.5 8.89543 12.3954 8 13.5 8C14.6046 8 15.5 8.89543 15.5 10Z" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.05108 16.3992C6.71926 16.6471 6.65126 17.1171 6.89919 17.4489C7.14713 17.7807 7.61711 17.8487 7.94892 17.6008L7.05108 16.3992ZM19.0511 17.6008C19.3829 17.8487 19.8529 17.7807 20.1008 17.4489C20.3487 17.1171 20.2807 16.6471 19.9489 16.3992L19.0511 17.6008ZM5.5 8.25C5.08579 8.25 4.75 8.58579 4.75 9C4.75 9.41421 5.08579 9.75 5.5 9.75V8.25ZM7.5 9.75C7.91421 9.75 8.25 9.41421 8.25 9C8.25 8.58579 7.91421 8.25 7.5 8.25V9.75ZM5.5 11.25C5.08579 11.25 4.75 11.5858 4.75 12C4.75 12.4142 5.08579 12.75 5.5 12.75V11.25ZM7.5 12.75C7.91421 12.75 8.25 12.4142 8.25 12C8.25 11.5858 7.91421 11.25 7.5 11.25V12.75ZM5.5 14.25C5.08579 14.25 4.75 14.5858 4.75 15C4.75 15.4142 5.08579 15.75 5.5 15.75V14.25ZM7.5 15.75C7.91421 15.75 8.25 15.4142 8.25 15C8.25 14.5858 7.91421 14.25 7.5 14.25V15.75ZM7.94892 17.6008C11.2409 15.141 15.7591 15.141 19.0511 17.6008L19.9489 16.3992C16.1245 13.5416 10.8755 13.5416 7.05108 16.3992L7.94892 17.6008ZM5.5 9.75H7.5V8.25H5.5V9.75ZM5.5 12.75H7.5V11.25H5.5V12.75ZM5.5 15.75H7.5V14.25H5.5V15.75Z" fill="#fff"/>
</svg>
<p class="text-white">Address Book</p>
</div>
</a>
<div class="w-full menu-container">
<div
class="menuItem w-full flex justify-between items-center border-b border-slate-600 py-3 cursor-pointer">
<div class="w-full flex justify-start items-center gap-3">
<svg class="w-[25px] text-white" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12" stroke="#fff" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 11L21.2 2.80005" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.9999 6.83V2H17.1699" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<p class="text-white">Sales</p>
</div>
<div>
<i class="angleDown fa fa-angle-down" style="font-size: 18px; color: white;"></i>
<i class="angleUp fa fa-angle-up"
style="font-size: 18px; color: white; display: none;"></i>
</div>
</div>
<div class="menuDropdownItems w-full h-fit p-3 hidden duration-300">
<a href="{% url 'departments' %}">
<div
class="w-full flex justify-start items-center gap-3 text-white border-b border-slate-600 py-2 cursor-pointer">
<p class="text-white">Prospecting Lists</p>
</div>
</a>
</div>
</div>
</div> </div>
</div> </div>

@ -81,7 +81,7 @@ urlpatterns = [
path('edit/', include('osinacore.edit.urls')), path('edit/', include('osinacore.edit.urls')),
path('delete/', include('osinacore.delete.urls')), path('delete/', include('osinacore.delete.urls')),
path('knowledge_base/', include('osinacore.knowledge_base.urls')), path('knowledge_base/', include('osinacore.knowledge_base.urls')),
path('addressbook/', views.addressbook, name='addressbook'),
#Fetch urls #Fetch urls
path('get_tasks/<int:epic_id>/', views.get_tasks, name='get_tasks'), path('get_tasks/<int:epic_id>/', views.get_tasks, name='get_tasks'),

@ -1,4 +1,6 @@
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from addressbook.models import AddressBook
from .models import * from .models import *
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import login as auth_login from django.contrib.auth import login as auth_login
@ -259,6 +261,8 @@ def businesses(request):
} }
return render(request, 'listing_pages/businesses.html', context) return render(request, 'listing_pages/businesses.html', context)
@staff_login_required @staff_login_required
def staffs(request): def staffs(request):
staffs = StaffProfile.objects.all().order_by('-staff_id') staffs = StaffProfile.objects.all().order_by('-staff_id')
@ -853,3 +857,11 @@ def fetch_projects_by_status(request, status=None):
@staff_login_required
def addressbook(request):
addresses = AddressBook.objects.all()
context = {
'addresses' : addresses,
}
return render(request, 'listing_pages/adressbooks.html', context)

@ -0,0 +1,10 @@
django==5.2
Pillow==11.1.0
firebase-admin==6.7.0
daphne==4.1.2
djangorestframework==3.16.0
fcm-django==2.2.1
django-colorfield==0.13.0
django-cors-headers==4.7.0
channels==4.2.2
weasyprint==65.0

@ -3364,6 +3364,11 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity)); color: rgb(255 255 255 / var(--tw-text-opacity));
} }
.hover\:text-blue-800:hover {
--tw-text-opacity: 1;
color: rgb(30 64 175 / var(--tw-text-opacity));
}
.hover\:underline:hover { .hover\:underline:hover {
text-decoration-line: underline; text-decoration-line: underline;
} }
@ -3457,10 +3462,6 @@ video {
height: 45px; height: 45px;
} }
.s\:h-\[55px\] {
height: 55px;
}
.s\:h-\[60px\] { .s\:h-\[60px\] {
height: 60px; height: 60px;
} }

Loading…
Cancel
Save