emile 1 year ago
parent 592fb22604
commit f25e523061

@ -46,6 +46,12 @@ class Order(models.Model):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
@property
def get_purchased_date(self):
first_orderitem = self.orderitem_set.first()
if first_orderitem:
return first_orderitem.purchased_at
return None
def save(self, *args, **kwargs):
if not self.order_id:
@ -111,7 +117,6 @@ class Invoice(models.Model):
else:
new_invoice_number = f"${current_year}-1425"
self.invoice_number = new_invoice_number
super().save(*args, **kwargs)

@ -1,3 +1,8 @@
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.register(Ticket)
admin.site.register(TicketUpdate)
admin.site.register(TicketAttachment)
admin.site.register(TicketReaction)

@ -0,0 +1,20 @@
# Generated by Django 4.2.5 on 2024-04-25 12:02
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0075_remove_ticketattachment_ticket_and_more'),
('customercore', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='ticket',
name='department',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='osinacore.department'),
),
]

@ -0,0 +1,30 @@
# Generated by Django 4.2.5 on 2024-04-25 12:13
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0075_remove_ticketattachment_ticket_and_more'),
('customercore', '0002_alter_ticket_department'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='customer',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='osinacore.customerprofile'),
),
migrations.AddField(
model_name='ticket',
name='status',
field=models.CharField(choices=[('Open', 'Open'), ('Working On', 'Working On'), ('Closed', 'Closed')], max_length=50, null=True),
),
migrations.AddField(
model_name='ticketreaction',
name='reaction',
field=models.CharField(choices=[('Happy', 'Happy'), ('Indifferent', 'Indifferent'), ('Sad', 'Sad')], max_length=50, null=True),
),
]

@ -0,0 +1,24 @@
# Generated by Django 4.2.5 on 2024-04-25 12:33
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('customercore', '0003_ticket_customer_ticket_status_and_more'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='ticket_number',
field=models.CharField(blank=True, max_length=400),
),
migrations.AlterField(
model_name='ticketattachment',
name='ticket_update',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='customercore.ticketupdate'),
),
]

@ -1,5 +1,6 @@
from django.db import models
from billing.models import *
from django.utils import timezone
# Create your models here.
class Ticket(models.Model):
@ -7,15 +8,36 @@ class Ticket(models.Model):
('General/Account/Billing', 'General/Account/Billing'),
('Project/Product', 'Project/Product'),
)
STATUS_CHOICES = (
('Open', 'Open'),
('Working On', 'Working On'),
('Closed', 'Closed'),
)
ticket_number = models.CharField(max_length=400, blank=True)
title = models.CharField(max_length=400)
description = models.TextField(null=True, blank=True)
status = models.CharField(max_length=50, choices=STATUS_CHOICES, null=True)
regarding = models.CharField(max_length=50, choices=REGARDING_CHOICES, null=True)
project = models.ForeignKey(Project, on_delete=models.SET_NULL, blank=True, null=True)
product = models.ForeignKey(Item, on_delete=models.SET_NULL, blank=True, null=True)
department = models.ForeignKey(Department, on_delete=models.SET_NULL,null=True)
department = models.ForeignKey(Department, on_delete=models.SET_NULL,null=True, blank=True)
opened_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
opened_date = models.DateTimeField()
customer = models.ForeignKey(CustomerProfile, on_delete=models.SET_NULL, null=True)
def save(self, *args, **kwargs):
if not self.ticket_number:
last_ticket = Ticket.objects.filter(opened_date__year=timezone.now().year).order_by('-ticket_number').first()
if last_ticket and last_ticket.ticket_number:
last_ticket_number = int(last_ticket.ticket_number[-4:])
new_ticket_number = last_ticket_number + 1
else:
new_ticket_number = 1
current_year_last_two_digits = str(timezone.now().year)[-2:]
self.ticket_number = f"{current_year_last_two_digits}{new_ticket_number:04}"
super().save(*args, **kwargs)
class TicketUpdate(models.Model):
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
@ -26,14 +48,15 @@ class TicketUpdate(models.Model):
class TicketAttachment(models.Model):
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE)
ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE, null=True, blank=True)
file = models.FileField()
class TicketReaction(models.Model):
REGARDING_CHOICES = (
REACTION_CHOICES = (
('Happy', 'Happy'),
('Indifferent', 'Indifferent'),
('Sad', 'Sad'),
)
reaction = models.CharField(max_length=50, choices=REACTION_CHOICES, null=True)
ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE)

@ -9,9 +9,8 @@
Create Ticket
</h1>
<form class="w-full flex flex-col gap-5 justify-center items-center mt-5" method="POST" action="">
<form class="w-full flex flex-col gap-5 justify-center items-center mt-5" method="POST" action="{% url 'customeraddticket' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="w-full">
<label class="text-gray-500">Title:</label>
<input required name="title" type="text"
@ -20,28 +19,40 @@
<div class="w-full">
<label class="text-gray-500">What is this regarding?</label>
<select class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" id="regardingSelectTag">
<select name="regarding" class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" id="regardingSelectTag">
<option value="General/Account/Billing">General/Account/Billing</option>
<option value="Product">Product</option>
<option value="Product">Product/Subscription</option>
<option value="Project">Project</option>
</select>
</div>
<!-- Projects Select Tag -->
<select class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md hidden" id="projectsSelectTag">
<option selected disabled>Choose one of your projects</option>
{% for customer_project in customer_projects %}
<option value="">{{customer_project.title}}</option>
{% endfor %}
</select>
<div class="w-full hidden" id="projectsSelectTag">
<label class="text-gray-500">Choose one of your projects:</label>
<select name="project" class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
{% if not customer_projects %}
<option value="" selected disabled>Select Project</option>
{% else %}
{% for customer_project in customer_projects %}
<option value="{{customer_project.id}}">{{customer_project.title}}</option>
{% endfor %}
{% endif %}
</select>
</div>
<!-- Products Select Tag -->
<select class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md hidden" id="productsSelectTag">
<option selected disabled>Choose one of your products</option>
{% for customer_product in customer_products %}
<option value="">{{customer_product.item.title}}</option>
{% endfor %}
</select>
<div class="w-full hidden" id="productsSelectTag">
<label class="text-gray-500">Choose one of your products/subscriptions:</label>
<select name="product" class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" >
{% if not customer_products %}
<option value="" selected disabled>Select Product</option>
{% else %}
{% for customer_product in customer_products %}
<option value="{{customer_product.item.id}}">{{customer_product.item.title}}</option>
{% endfor %}
{% endif %}
</select>
</div>
<div class="w-full">
@ -55,7 +66,7 @@
<label class="text-gray-500">Attach Files:</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="" type="file" class="file-input" hidden multiple />
<input name="files" type="file" class="file-input" hidden multiple />
<span class="file-name text-gray-500 text-base focus:outline-none outline-none">Upload
Document(s)</span>
<label

@ -30,7 +30,7 @@
Status
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
Actions
Date purchased
</th>
</tr>
</thead>
@ -58,15 +58,8 @@
<p class="text-white">{{order.status}}</p>
</td>
<td class="px-6 py-4">
<a href="{{order.invoice.pdf.url}}">
<div class="w-full flex justify-center items-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[25px] text-blue-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
</svg>
</div>
</a>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{order.get_purchased_date}}</p>
</td>
</tr>
{% endfor %}

@ -59,7 +59,7 @@
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<a href="{% url 'innercustomerticket' %}">
<a href="{% url 'customerticketdetails' %}">
<p class="text-secondosiblue cursor-pointer hover:text-gray-500 duration-300">My Account Balance</p>
</a>
</td>

@ -18,7 +18,7 @@ urlpatterns = [
# DETAILS
path('inner-customer-ticket/', views.inner_customer_ticket, name='innercustomerticket'),
path('inner-customer-ticket/', views.customer_ticket_details, name='customerticketdetails'),
# PRODUCTS URL

@ -9,6 +9,8 @@ import json
import random
import string
from billing.add.views import *
from .models import *
from django.db.models import Q
# Create your views here.
@customer_login_required
@ -33,6 +35,40 @@ def redirect_osicard(request):
def customer_add_ticket(request, *args, **kwargs):
customer_products = OrderItem.objects.filter(order__status='Completed', active__in=[True, None], item__type = 'Product', order__customer = request.user.customerprofile)
customer_projects = Project.objects.filter(customer=request.user.customerprofile)
if request.method == 'POST':
project = None
product = None
department = None
regarding = 'General/Account/Billing'
if request.POST.get('project'):
project = get_object_or_404(Project, id=request.POST.get('project'))
department = project.project_type.department
regarding = 'Project/Product'
elif request.POST.get('product'):
product = get_object_or_404(Item, id=request.POST.get('product'))
department = product.item_type.department
regarding = 'Project/Product'
ticket = Ticket(
status = 'Open',
customer = request.user.customerprofile,
title = request.POST.get('title'),
description = request.POST.get('description'),
regarding = regarding,
project = project,
product = product,
department = department,
opened_by = request.user,
opened_date = datetime.now()
)
ticket.save()
for file in request.FILES.getlist('files'):
ticket_attachment = TicketAttachment(
ticket=ticket,
file=file
)
ticket_attachment.save()
return redirect('customertickets')
context = {
'customer_products': customer_products,
@ -70,7 +106,7 @@ def all_products(request, *args, **kwargs):
@customer_login_required
def customer_orders(request, *args, **kwargs):
customer = request.user.customerprofile
orders = Order.objects.filter(customer=customer, status='Completed')
orders = Order.objects.filter(customer=customer, status='Completed').order_by()
context = {
@ -82,9 +118,12 @@ def customer_orders(request, *args, **kwargs):
@customer_login_required
def customer_tickets(request, *args, **kwargs):
open_tickets = Ticket.objects.filter(Q(status__in=['Open', 'Working On']) & Q(customer=request.user.customerprofile)).order_by('-id')
closed_tickets = Ticket.objects.filter(Q(status__in=['Closed']) & Q(customer=request.user.customerprofile)).order_by('-id')
context = {
'open_tickets': open_tickets,
'closed_tickets': closed_tickets,
}
return render(request, 'listing_pages/customer-tickets.html', context)
@ -93,7 +132,7 @@ def customer_tickets(request, *args, **kwargs):
# DETAILS
def inner_customer_ticket(request, *args, **kwargs):
def customer_ticket_details(request, *args, **kwargs):
context = {
@ -289,9 +328,6 @@ def check_order_status(request, merchant_id, order_id):
order_items = OrderItem.objects.filter(order=order)
for order_item in order_items:
order_item.purchased_at = datetime.now()
recurring_cycle = 30
due_date = order_item.purchased_at + timedelta(days=recurring_cycle)
order_item.due_at = due_date
if order_item.item.item_type.name == 'OSIMENU':
api_url = 'https://osimenu.com/api/create-subscription/'
random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=10))
@ -307,7 +343,8 @@ def check_order_status(request, merchant_id, order_id):
'mobile_number': request.user.customerprofile.mobile_number
},
'subscription': {
'plan': order_item.item.title
'plan': order_item.item.title,
'end_date': order_item.end_at
}
}
response = requests.post(api_url, json=api_data)

Binary file not shown.

@ -28,6 +28,7 @@ class PointAdmin(admin.ModelAdmin):
def task_assigned_to(self, obj):
return obj.task.assigned_to if obj.task else ''
admin.site.register(Reference)
admin.site.register(Business)
admin.site.register(CustomerProfile)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save