diff --git a/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc b/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc index 806d9875..60df04cc 100644 Binary files a/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc and b/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc differ diff --git a/osinaweb/billing/add/__pycache__/views.cpython-312.pyc b/osinaweb/billing/add/__pycache__/views.cpython-312.pyc index cf57796e..c75e4a38 100644 Binary files a/osinaweb/billing/add/__pycache__/views.cpython-312.pyc and b/osinaweb/billing/add/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/customercore/__pycache__/models.cpython-312.pyc b/osinaweb/customercore/__pycache__/models.cpython-312.pyc index e392277b..7f8cc970 100644 Binary files a/osinaweb/customercore/__pycache__/models.cpython-312.pyc and b/osinaweb/customercore/__pycache__/models.cpython-312.pyc differ diff --git a/osinaweb/customercore/__pycache__/urls.cpython-312.pyc b/osinaweb/customercore/__pycache__/urls.cpython-312.pyc index 765c5e3f..b6c389f3 100644 Binary files a/osinaweb/customercore/__pycache__/urls.cpython-312.pyc and b/osinaweb/customercore/__pycache__/urls.cpython-312.pyc differ diff --git a/osinaweb/customercore/__pycache__/views.cpython-312.pyc b/osinaweb/customercore/__pycache__/views.cpython-312.pyc index ecbe78f1..99fd72b9 100644 Binary files a/osinaweb/customercore/__pycache__/views.cpython-312.pyc and b/osinaweb/customercore/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/customercore/add/__pycache__/urls.cpython-312.pyc b/osinaweb/customercore/add/__pycache__/urls.cpython-312.pyc new file mode 100644 index 00000000..b5f3c52b Binary files /dev/null and b/osinaweb/customercore/add/__pycache__/urls.cpython-312.pyc differ diff --git a/osinaweb/customercore/add/__pycache__/views.cpython-312.pyc b/osinaweb/customercore/add/__pycache__/views.cpython-312.pyc new file mode 100644 index 00000000..5f65b0ae Binary files /dev/null and b/osinaweb/customercore/add/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/customercore/add/urls.py b/osinaweb/customercore/add/urls.py new file mode 100644 index 00000000..9a6df5fb --- /dev/null +++ b/osinaweb/customercore/add/urls.py @@ -0,0 +1,11 @@ +from django.urls import path, include +from . import views + + +urlpatterns = [ + # ADD + path('ticket/', views.customer_add_ticket, name='customeraddticket'), + path('customer/ticketupdate//', views.customer_add_ticket_update, name='customeraddticketupdate'), + path('ticketupdatereaction///', views.customer_add_ticket_update_reaction, name='customeraddticketupdatereaction'), + +] \ No newline at end of file diff --git a/osinaweb/customercore/add/views.py b/osinaweb/customercore/add/views.py new file mode 100644 index 00000000..c4bee3ee --- /dev/null +++ b/osinaweb/customercore/add/views.py @@ -0,0 +1,175 @@ +from django.shortcuts import render, get_object_or_404 +from customercore.decorators import * +from customercore.models import * +from django.core.mail import send_mail +from django.template.loader import render_to_string +from django.utils.html import strip_tags +from django.conf import settings + + +@customer_login_required +def customer_add_ticket(request, *args, **kwargs): + customer_orders = Order.objects.filter(customer=request.user.customerprofile) + customer_orders_with_last_status = customer_orders.annotate(max_status_date=Max('orderstatus__date')) + customer_orders_completed = customer_orders_with_last_status.filter(orderstatus__status='Completed',orderstatus__date=F('max_status_date')) + customer_products = OrderItem.objects.filter(active__in=[True, None], item__type = 'Product', order__customer = request.user.customerprofile, order__in=customer_orders_completed ) + customer_projects = Project.objects.filter(customer=request.user.customerprofile) + support_department = get_object_or_404(Department, name='Support') + + if request.method == 'POST': + project = None + product = None + departments = [support_department] + regarding = 'General/Account/Billing' + if request.POST.get('project') and request.POST.get('regarding') == 'Project': + project = get_object_or_404(Project, id=request.POST.get('project')) + project_types = project.project_type.all() + departments = [project_type.department for project_type in project_types] + regarding = 'Project/Product' + elif request.POST.get('product') and request.POST.get('regarding') == 'Product': + product = get_object_or_404(Item, id=request.POST.get('product')) + departments = [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, + opened_by = request.user, + opened_date = datetime.now() + ) + ticket.save() + ticket.departments.set(departments) + + ticket_status = TicketStatus( + ticket = ticket, + status = 'Open', + added_by = request.user, + date_added = datetime.now() + ) + ticket_status.save() + for file in request.FILES.getlist('files'): + ticket_attachment = TicketAttachment( + ticket=ticket, + file=file + ) + ticket_attachment.save() + + + department_ids = [dept.id for dept in departments] + staff_profiles = StaffProfile.objects.filter(staff_position__department__id__in=department_ids, active=True) + print(staff_profiles) + for staff in staff_profiles: + subject = f"New Ticket Opened: {ticket.title}" + html_message = render_to_string('email_templates/new_ticket.html', { + 'ticket': ticket, + 'staff_first_name': staff.user.first_name + }) + plain_message = strip_tags(html_message) + from_email = settings.DEFAULT_FROM_EMAIL + to_email = staff.user.email + + send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) + return redirect('customerticketdetails', ticket_number=ticket.ticket_number) + + context = { + 'customer_products': customer_products, + 'customer_projects': customer_projects, + + } + + return render(request, 'add_templates/customer-add-ticket.html', context) + + + +@customer_login_required +def customer_add_ticket_update(request, ticket_id): + ticket = get_object_or_404(Ticket, id=ticket_id) + + + if request.method == 'POST': + ticket_update = TicketUpdate( + ticket = ticket, + description = request.POST.get('description'), + added_by = request.user, + date_added = datetime.now(), + ) + ticket_update.save() + for file in request.FILES.getlist('files'): + ticket_attachment = TicketAttachment( + ticket_update=ticket_update, + file=file + ) + ticket_attachment.save() + + + if ticket.ticket_members.exists(): + members_ids = ticket.ticket_members.values_list('id', flat=True) + staff_profiles = StaffProfile.objects.filter(id__in=members_ids) + else: + department_ids = ticket.departments.values_list('id', flat=True) + staff_profiles = StaffProfile.objects.filter(staff_position__department__id__in=department_ids, active=True) + + + for staff in staff_profiles: + subject = f"New Ticket Update: {ticket.title}" + html_message = render_to_string('email_templates/new_ticket_update.html', { + 'ticket_update': ticket_update, + 'staff_first_name': staff.user.first_name + }) + plain_message = strip_tags(html_message) + from_email = settings.DEFAULT_FROM_EMAIL + to_email = staff.user.email + + send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) + + + return redirect('customerticketdetails', ticket_number=ticket.ticket_number) + + context = { + 'ticket': ticket, + } + + return render(request, 'add_templates/customer-add-ticket.html', context) + + + +@customer_login_required +def customer_add_ticket_update_reaction(request, reaction_type, ticketupdate_id): + ticket_update = get_object_or_404(TicketUpdate, id=ticketupdate_id) + + existing_reaction = TicketUpdateReaction.objects.filter(ticket_update=ticket_update, customer=request.user).first() + + if existing_reaction: + # If the existing reaction type is equal to the new reaction, delete it + if existing_reaction.reaction == reaction_type: + existing_reaction.delete() + else: + # If not, delete all previous reactions and add a new one + TicketUpdateReaction.objects.filter(ticket_update=ticket_update, customer=request.user).delete() + reaction = TicketUpdateReaction.objects.create( + ticket_update=ticket_update, + reaction=reaction_type, + customer=request.user + ) + else: + # If there's no existing reaction, simply add the new one + reaction = TicketUpdateReaction.objects.create( + ticket_update=ticket_update, + reaction=reaction_type, + customer=request.user + ) + + return redirect('customerticketdetails', ticket_number=ticket_update.ticket.ticket_number) + + + + + + + + + diff --git a/osinaweb/customercore/edit/urls.py b/osinaweb/customercore/edit/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/customercore/edit/views.py b/osinaweb/customercore/edit/views.py new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/customercore/migrations/0017_tickettask.py b/osinaweb/customercore/migrations/0017_tickettask.py new file mode 100644 index 00000000..904ba4bf --- /dev/null +++ b/osinaweb/customercore/migrations/0017_tickettask.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.4 on 2024-05-22 12:17 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('customercore', '0016_rename_ticketstatusupdate_ticketstatus'), + ('osinacore', '0081_status_task'), + ] + + operations = [ + migrations.CreateModel( + name='TicketTask', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='osinacore.task')), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='customercore.ticketupdate')), + ], + ), + ] diff --git a/osinaweb/customercore/migrations/__pycache__/0017_tickettask.cpython-312.pyc b/osinaweb/customercore/migrations/__pycache__/0017_tickettask.cpython-312.pyc new file mode 100644 index 00000000..a89c9609 Binary files /dev/null and b/osinaweb/customercore/migrations/__pycache__/0017_tickettask.cpython-312.pyc differ diff --git a/osinaweb/customercore/models.py b/osinaweb/customercore/models.py index 63e4ea4a..848343ce 100644 --- a/osinaweb/customercore/models.py +++ b/osinaweb/customercore/models.py @@ -79,4 +79,10 @@ class TicketUpdateReaction(models.Model): ) customer = models.ForeignKey(User, on_delete=models.CASCADE, null=True) reaction = models.CharField(max_length=50, choices=REACTION_CHOICES, null=True) - ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE) \ No newline at end of file + ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE) + + + +class TicketTask(models.Model): + ticket = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE) + task = models.ForeignKey(Task, on_delete=models.CASCADE) \ No newline at end of file diff --git a/osinaweb/customercore/templates/add_templates/cutomer-add-ticket-task.html b/osinaweb/customercore/templates/add_templates/cutomer-add-ticket-task.html new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/customercore/urls.py b/osinaweb/customercore/urls.py index 80c27439..290267c5 100644 --- a/osinaweb/customercore/urls.py +++ b/osinaweb/customercore/urls.py @@ -4,15 +4,11 @@ from . import views urlpatterns = [ path('payment/', include('customercore.payment.urls')), + path('add/', include('customercore.add.urls')), path('redirect-osimenu/', views.redirect_osimenu, name='redirectosimenu'), path('redirect-osicard/', views.redirect_osicard, name='redirectosicard'), - # ADD - path('add/ticket/', views.customer_add_ticket, name='customeraddticket'), - path('customer/add/ticketupdate//', views.customer_add_ticket_update, name='customeraddticketupdate'), - - # LISTING path('my-invoices/', views.customer_invoices, name='customerinvoices'), path('products/', views.all_products, name='products'), @@ -23,7 +19,6 @@ urlpatterns = [ # DETAILS path('my-tickets//', views.customer_ticket_details, name='customerticketdetails'), - path('addticketupdatereaction///', views.customer_add_ticket_update_reaction, name='customeraddticketupdatereaction'), path('my-orders//', views.customer_order_details, name='customerorderdetails'), path('my-projects//', views.customer_project_details, name='customerprojectdetails'), diff --git a/osinaweb/customercore/views.py b/osinaweb/customercore/views.py index 516a813a..179f8c19 100644 --- a/osinaweb/customercore/views.py +++ b/osinaweb/customercore/views.py @@ -6,10 +6,7 @@ from .models import * from django.db.models import Q from django.http import Http404 from django.db.models import OuterRef, Subquery -from django.core.mail import send_mail -from django.template.loader import render_to_string -from django.utils.html import strip_tags -from django.conf import settings + # Create your views here. @@ -29,168 +26,6 @@ def redirect_osicard(request): return redirect(url) - -# ADD -@customer_login_required -def customer_add_ticket(request, *args, **kwargs): - customer_orders = Order.objects.filter(customer=request.user.customerprofile) - customer_orders_with_last_status = customer_orders.annotate(max_status_date=Max('orderstatus__date')) - customer_orders_completed = customer_orders_with_last_status.filter(orderstatus__status='Completed',orderstatus__date=F('max_status_date')) - customer_products = OrderItem.objects.filter(active__in=[True, None], item__type = 'Product', order__customer = request.user.customerprofile, order__in=customer_orders_completed ) - customer_projects = Project.objects.filter(customer=request.user.customerprofile) - support_department = get_object_or_404(Department, name='Support') - - if request.method == 'POST': - project = None - product = None - departments = [support_department] - regarding = 'General/Account/Billing' - if request.POST.get('project') and request.POST.get('regarding') == 'Project': - project = get_object_or_404(Project, id=request.POST.get('project')) - departments = [project.project_type.department] - regarding = 'Project/Product' - elif request.POST.get('product') and request.POST.get('regarding') == 'Product': - product = get_object_or_404(Item, id=request.POST.get('product')) - departments = [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, - opened_by = request.user, - opened_date = datetime.now() - ) - ticket.save() - ticket.departments.set(departments) - - ticket_status = TicketStatus( - ticket = ticket, - status = 'Open', - added_by = request.user, - date_added = datetime.now() - ) - ticket_status.save() - for file in request.FILES.getlist('files'): - ticket_attachment = TicketAttachment( - ticket=ticket, - file=file - ) - ticket_attachment.save() - - - department_ids = [dept.id for dept in departments] - staff_profiles = StaffProfile.objects.filter(staff_position__department__id__in=department_ids, active=True) - print(staff_profiles) - for staff in staff_profiles: - subject = f"New Ticket Opened: {ticket.title}" - html_message = render_to_string('email_templates/new_ticket.html', { - 'ticket': ticket, - 'staff_first_name': staff.user.first_name - }) - plain_message = strip_tags(html_message) - from_email = settings.DEFAULT_FROM_EMAIL - to_email = staff.user.email - - send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) - return redirect('customerticketdetails', ticket_number=ticket.ticket_number) - - context = { - 'customer_products': customer_products, - 'customer_projects': customer_projects, - - } - - return render(request, 'add_templates/customer-add-ticket.html', context) - - - -@customer_login_required -def customer_add_ticket_update(request, ticket_id): - ticket = get_object_or_404(Ticket, id=ticket_id) - - - if request.method == 'POST': - ticket_update = TicketUpdate( - ticket = ticket, - description = request.POST.get('description'), - added_by = request.user, - date_added = datetime.now(), - ) - ticket_update.save() - for file in request.FILES.getlist('files'): - ticket_attachment = TicketAttachment( - ticket_update=ticket_update, - file=file - ) - ticket_attachment.save() - - - if ticket.ticket_members.exists(): - members_ids = ticket.ticket_members.values_list('id', flat=True) - staff_profiles = StaffProfile.objects.filter(id__in=members_ids) - else: - department_ids = ticket.departments.values_list('id', flat=True) - staff_profiles = StaffProfile.objects.filter(staff_position__department__id__in=department_ids, active=True) - - - for staff in staff_profiles: - subject = f"New Ticket Update: {ticket.title}" - html_message = render_to_string('email_templates/new_ticket_update.html', { - 'ticket_update': ticket_update, - 'staff_first_name': staff.user.first_name - }) - plain_message = strip_tags(html_message) - from_email = settings.DEFAULT_FROM_EMAIL - to_email = staff.user.email - - send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) - - - return redirect('customerticketdetails', ticket_number=ticket.ticket_number) - - context = { - 'ticket': ticket, - } - - return render(request, 'add_templates/customer-add-ticket.html', context) - - - -@customer_login_required -def customer_add_ticket_update_reaction(request, reaction_type, ticketupdate_id): - ticket_update = get_object_or_404(TicketUpdate, id=ticketupdate_id) - - existing_reaction = TicketUpdateReaction.objects.filter(ticket_update=ticket_update, customer=request.user).first() - - if existing_reaction: - # If the existing reaction type is equal to the new reaction, delete it - if existing_reaction.reaction == reaction_type: - existing_reaction.delete() - else: - # If not, delete all previous reactions and add a new one - TicketUpdateReaction.objects.filter(ticket_update=ticket_update, customer=request.user).delete() - reaction = TicketUpdateReaction.objects.create( - ticket_update=ticket_update, - reaction=reaction_type, - customer=request.user - ) - else: - # If there's no existing reaction, simply add the new one - reaction = TicketUpdateReaction.objects.create( - ticket_update=ticket_update, - reaction=reaction_type, - customer=request.user - ) - - return redirect('customerticketdetails', ticket_number=ticket_update.ticket.ticket_number) - - - - # LISTING @customer_login_required def customer_invoices(request, *args, **kwargs): @@ -356,35 +191,6 @@ def customer_ticket_details(request, ticket_number): return render(request, 'details_templates/inner-customer-ticket.html', context) -@customer_login_required -def customer_add_ticket_update_reaction(request, reaction_type, ticketupdate_id): - ticket_update = get_object_or_404(TicketUpdate, id=ticketupdate_id) - - existing_reaction = TicketUpdateReaction.objects.filter(ticket_update=ticket_update, customer=request.user).first() - - if existing_reaction: - # If the existing reaction type is equal to the new reaction, delete it - if existing_reaction.reaction == reaction_type: - existing_reaction.delete() - else: - # If not, delete all previous reactions and add a new one - TicketUpdateReaction.objects.filter(ticket_update=ticket_update, customer=request.user).delete() - reaction = TicketUpdateReaction.objects.create( - ticket_update=ticket_update, - reaction=reaction_type, - customer=request.user - ) - else: - # If there's no existing reaction, simply add the new one - reaction = TicketUpdateReaction.objects.create( - ticket_update=ticket_update, - reaction=reaction_type, - customer=request.user - ) - - return redirect('customerticketdetails', ticket_number=ticket_update.ticket.ticket_number) - - # PRODUCTS diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index fd6347e1..a830643d 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osinacore/__pycache__/models.cpython-312.pyc b/osinaweb/osinacore/__pycache__/models.cpython-312.pyc index 2e759118..2ada3c16 100644 Binary files a/osinaweb/osinacore/__pycache__/models.cpython-312.pyc and b/osinaweb/osinacore/__pycache__/models.cpython-312.pyc differ diff --git a/osinaweb/osinacore/add/__pycache__/views.cpython-312.pyc b/osinaweb/osinacore/add/__pycache__/views.cpython-312.pyc index 1b824b25..1e89b23c 100644 Binary files a/osinaweb/osinacore/add/__pycache__/views.cpython-312.pyc and b/osinaweb/osinacore/add/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/osinacore/add/views.py b/osinaweb/osinacore/add/views.py index ab75e8d3..a16ecafb 100644 --- a/osinaweb/osinacore/add/views.py +++ b/osinaweb/osinacore/add/views.py @@ -653,68 +653,73 @@ def add_reaction(request, status_id, emoji): @staff_login_required def add_ticket(request, customer_id): - customer= get_object_or_404(CustomerProfile, id=customer_id) + customer = get_object_or_404(CustomerProfile, id=customer_id) customer_orders = Order.objects.filter(customer=customer) customer_orders_with_last_status = customer_orders.annotate(max_status_date=Max('orderstatus__date')) - customer_orders_completed = customer_orders_with_last_status.filter(orderstatus__status='Completed',orderstatus__date=F('max_status_date')) - customer_products = OrderItem.objects.filter(active__in=[True, None], item__type = 'Product', order__customer = customer, order__in=customer_orders_completed) + customer_orders_completed = customer_orders_with_last_status.filter(orderstatus__status='Completed', orderstatus__date=F('max_status_date')) + customer_products = OrderItem.objects.filter(active__in=[True, None], item__type='Product', order__customer=customer, order__in=customer_orders_completed) customer_projects = Project.objects.filter(customer=customer) departments = Department.objects.all().order_by('name') + if request.method == 'POST': project = None product = None - if request.POST.get('department'): - department = get_object_or_404(Department, id=request.POST.get('department')) + department_ids = request.POST.getlist('departments') # Changed to get a list of department IDs + selected_departments = Department.objects.filter(id__in=department_ids) regarding = 'General/Account/Billing' + if request.POST.get('project'): project = get_object_or_404(Project, id=request.POST.get('project')) - if not department: - department = project.project_type.department regarding = 'Project/Product' + elif request.POST.get('product'): product = get_object_or_404(Item, id=request.POST.get('product')) - if not department: - department = project.project_type.department regarding = 'Project/Product' + ticket = Ticket( - status = 'Open', - customer = customer, - 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() + status='Open', + customer=customer, + title=request.POST.get('title'), + description=request.POST.get('description'), + regarding=regarding, + project=project, + product=product, + opened_by=request.user, + opened_date=datetime.now() ) ticket.save() - ticket_status_update = TicketUpdate( - ticket = ticket, - status = 'Open', - added_by = request.user, - date_added = datetime.now() + + ticket.departments.set(selected_departments) # Assign multiple departments + + ticket_status_update = TicketStatus( + ticket=ticket, + status='Open', + added_by=request.user, + date_added=datetime.now() ) ticket_status_update.save() + for file in request.FILES.getlist('files'): ticket_attachment = TicketAttachment( ticket=ticket, file=file ) ticket_attachment.save() + return redirect('ticketdetails', ticket_number=ticket.ticket_number) context = { - 'customer_products' : customer_products, - 'customer_projects' : customer_projects, + 'customer_products': customer_products, + 'customer_projects': customer_projects, 'customer': customer, - 'departments' : departments + 'departments': departments } return render(request, 'add_templates/add-ticket.html', context) + @staff_login_required def add_ticket_update(request, ticket_id): ticket = get_object_or_404(Ticket, id=ticket_id) diff --git a/osinaweb/osinacore/templates/add-edit-main.html b/osinaweb/osinacore/templates/add-edit-main.html index 6286d95a..3fbc6cfd 100644 --- a/osinaweb/osinacore/templates/add-edit-main.html +++ b/osinaweb/osinacore/templates/add-edit-main.html @@ -131,13 +131,6 @@ - -
-

Tickets

-
-
-
@@ -154,15 +147,29 @@
-
-
- - - -

Support

+
-
-
- - - -

Support

+ + +