diff --git a/.DS_Store b/.DS_Store index f1fcd393..b10de2d5 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/osinaweb/.DS_Store b/osinaweb/.DS_Store index 2e84bc6a..2dc331ea 100644 Binary files a/osinaweb/.DS_Store and b/osinaweb/.DS_Store differ diff --git a/osinaweb/billing/.DS_Store b/osinaweb/billing/.DS_Store new file mode 100644 index 00000000..a7b7da6a Binary files /dev/null and b/osinaweb/billing/.DS_Store differ diff --git a/osinaweb/billing/__pycache__/models.cpython-310.pyc b/osinaweb/billing/__pycache__/models.cpython-310.pyc index 9e7b5544..c7c0d551 100644 Binary files a/osinaweb/billing/__pycache__/models.cpython-310.pyc and b/osinaweb/billing/__pycache__/models.cpython-310.pyc differ diff --git a/osinaweb/billing/__pycache__/urls.cpython-310.pyc b/osinaweb/billing/__pycache__/urls.cpython-310.pyc index dfe42e93..50de5028 100644 Binary files a/osinaweb/billing/__pycache__/urls.cpython-310.pyc and b/osinaweb/billing/__pycache__/urls.cpython-310.pyc differ diff --git a/osinaweb/billing/__pycache__/views.cpython-310.pyc b/osinaweb/billing/__pycache__/views.cpython-310.pyc index 70bf2185..9d21722b 100644 Binary files a/osinaweb/billing/__pycache__/views.cpython-310.pyc and b/osinaweb/billing/__pycache__/views.cpython-310.pyc differ diff --git a/osinaweb/billing/add/__pycache__/urls.cpython-310.pyc b/osinaweb/billing/add/__pycache__/urls.cpython-310.pyc new file mode 100644 index 00000000..0092be93 Binary files /dev/null and b/osinaweb/billing/add/__pycache__/urls.cpython-310.pyc differ diff --git a/osinaweb/billing/add/__pycache__/views.cpython-310.pyc b/osinaweb/billing/add/__pycache__/views.cpython-310.pyc new file mode 100644 index 00000000..2860681e Binary files /dev/null and b/osinaweb/billing/add/__pycache__/views.cpython-310.pyc differ diff --git a/osinaweb/billing/add/urls.py b/osinaweb/billing/add/urls.py new file mode 100644 index 00000000..c29906c6 --- /dev/null +++ b/osinaweb/billing/add/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from billing.add import views + + +urlpatterns = [ + path('product', views.add_product, name='addproduct'), + path('service', views.add_service, name='addservice'), + path('order', views.add_order, name='addorder'), +] diff --git a/osinaweb/billing/add/views.py b/osinaweb/billing/add/views.py new file mode 100644 index 00000000..48cff91f --- /dev/null +++ b/osinaweb/billing/add/views.py @@ -0,0 +1,63 @@ +from django.shortcuts import render, get_object_or_404, redirect +from osinacore.models import * +from billing.models import * +from django.http import JsonResponse, HttpResponse +from django.template.loader import get_template +from weasyprint import HTML + + +def add_product (request, *args, **kwargs): + item_types = ProjectType.objects.all().order_by('name') + if request.method == 'POST': + title = request.POST.get('title') + description = request.POST.get('description') + + item_type_id = request.POST.get('item_type') + item_type = get_object_or_404(ProjectType, id=item_type_id) + + amount = request.POST.get('amount') + recurring = request.POST.get('recurring') + + Item.objects.create( + type='Product', + title=title, + description = description, + item_type = item_type, + amount = amount, + recurring = recurring, + ) + return redirect('items') + context = { + 'item_types' : item_types, + + } + return render(request, 'add_templates/add-product.html', context) + + + +def add_service (request, *args, **kwargs): + context = { + + } + return render(request, 'add_templates/add-service.html', context) + + +def add_order (request, *args, **kwargs): + customers = CustomerProfile.objects.all().order_by('-id') + + context = { + 'customers': customers, + } + + return render(request, 'add_templates/add-order.html', context) + + +def add_invoice_pdf(request): + template = get_template('details_templates/invoice-details.html') + context = {} + html_string = template.render(context) + + pdf = HTML(string=html_string).write_pdf() + response = HttpResponse(pdf, content_type='application/pdf') + response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"' + return response \ No newline at end of file diff --git a/osinaweb/billing/delete/urls.py b/osinaweb/billing/delete/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/billing/delete/views.py b/osinaweb/billing/delete/views.py new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/billing/edit/urls.py b/osinaweb/billing/edit/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/billing/edit/views.py b/osinaweb/billing/edit/views.py new file mode 100644 index 00000000..e69de29b diff --git a/osinaweb/billing/migrations/0026_rename_type_item_item_type_remove_order_paid.py b/osinaweb/billing/migrations/0026_rename_type_item_item_type_remove_order_paid.py new file mode 100644 index 00000000..a31aa7b2 --- /dev/null +++ b/osinaweb/billing/migrations/0026_rename_type_item_item_type_remove_order_paid.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.5 on 2024-04-12 17:48 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0025_remove_item_project_item_customer'), + ] + + operations = [ + migrations.RenameField( + model_name='item', + old_name='type', + new_name='item_type', + ), + migrations.RemoveField( + model_name='order', + name='paid', + ), + ] diff --git a/osinaweb/billing/migrations/0027_item_type.py b/osinaweb/billing/migrations/0027_item_type.py new file mode 100644 index 00000000..b4e3697c --- /dev/null +++ b/osinaweb/billing/migrations/0027_item_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.5 on 2024-04-12 17:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0026_rename_type_item_item_type_remove_order_paid'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='type', + field=models.CharField(choices=[('Product', 'Product'), ('Service', 'Service')], max_length=200, null=True), + ), + ] diff --git a/osinaweb/billing/migrations/__pycache__/0026_rename_type_item_item_type_remove_order_paid.cpython-310.pyc b/osinaweb/billing/migrations/__pycache__/0026_rename_type_item_item_type_remove_order_paid.cpython-310.pyc new file mode 100644 index 00000000..d0d88df0 Binary files /dev/null and b/osinaweb/billing/migrations/__pycache__/0026_rename_type_item_item_type_remove_order_paid.cpython-310.pyc differ diff --git a/osinaweb/billing/migrations/__pycache__/0027_item_type.cpython-310.pyc b/osinaweb/billing/migrations/__pycache__/0027_item_type.cpython-310.pyc new file mode 100644 index 00000000..42efbe7f Binary files /dev/null and b/osinaweb/billing/migrations/__pycache__/0027_item_type.cpython-310.pyc differ diff --git a/osinaweb/billing/models.py b/osinaweb/billing/models.py index 1ad96577..0df4aa70 100644 --- a/osinaweb/billing/models.py +++ b/osinaweb/billing/models.py @@ -17,10 +17,11 @@ class Item(models.Model): ('Product', 'Product'), ('Service', 'Service'), ) + type = models.CharField(max_length=200, choices=TYPE, null=True) title = models.CharField(max_length=200) description = models.TextField(blank=True) customer = models.ForeignKey(CustomerProfile, null=True, blank=True, on_delete=models.CASCADE) - type = models.ForeignKey(ProjectType, on_delete=models.CASCADE, null=True, blank=True) + item_type = models.ForeignKey(ProjectType, on_delete=models.CASCADE, null=True, blank=True) amount = models.FloatField(null=True) recurring = models.BooleanField(default=False) def __str__(self): @@ -38,7 +39,6 @@ class Order(models.Model): status = models.CharField(max_length=200, choices=STATUS, default='None') order_id = models.CharField(max_length=100, null=True, blank=True) due_date = models.DateField(null=True) - paid = models.BooleanField(null=True, default=False) @property def get_cart_total(self): orderitems = self.orderitem_set.all() diff --git a/osinaweb/billing/templates/.DS_Store b/osinaweb/billing/templates/.DS_Store new file mode 100644 index 00000000..efbd10e1 Binary files /dev/null and b/osinaweb/billing/templates/.DS_Store differ diff --git a/osinaweb/billing/templates/add_templates/add-product.html b/osinaweb/billing/templates/add_templates/add-product.html index 23c71010..00551e91 100644 --- a/osinaweb/billing/templates/add_templates/add-product.html +++ b/osinaweb/billing/templates/add_templates/add-product.html @@ -8,55 +8,48 @@ Add Product -
+ {% csrf_token %}
-
-
- - -
- -
- - - - + + {% for type in item_types %} + + {% endfor %}
-
-
diff --git a/osinaweb/billing/templates/invoice-details.html b/osinaweb/billing/templates/details_templates/invoice-details.html similarity index 90% rename from osinaweb/billing/templates/invoice-details.html rename to osinaweb/billing/templates/details_templates/invoice-details.html index befbb82e..3d84361c 100644 --- a/osinaweb/billing/templates/invoice-details.html +++ b/osinaweb/billing/templates/details_templates/invoice-details.html @@ -21,7 +21,7 @@
-
+
diff --git a/osinaweb/billing/templates/listing_pages/items.html b/osinaweb/billing/templates/listing_pages/items.html index 981e953c..1c1cee9d 100644 --- a/osinaweb/billing/templates/listing_pages/items.html +++ b/osinaweb/billing/templates/listing_pages/items.html @@ -41,10 +41,6 @@ class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap"> Title - - Customer - Type @@ -61,21 +57,18 @@ + {% for product in products %} -

Item 1

+

{{product.title}}

-

Nataly

+

{{product.item_type}}

-

Type

- - - -

222

+

${{product.amount}}

@@ -97,6 +90,7 @@ + {% endfor %} diff --git a/osinaweb/billing/urls.py b/osinaweb/billing/urls.py index 2565e7b6..36de696f 100644 --- a/osinaweb/billing/urls.py +++ b/osinaweb/billing/urls.py @@ -1,36 +1,20 @@ -from django.contrib import admin + from django.urls import path, include -from django.conf.urls import handler404 -from django.conf.urls.static import static -from django.conf import settings from billing import views urlpatterns = [ - - + path('add/', include('billing.add.urls')), # LISTING path('items', views.items, name='items'), path('orders', views.orders, name='orders'), path('invoices', views.invoices, name='invoices'), - - # ADD - path('add-product', views.add_product, name='addproduct'), - path('add-service', views.add_service, name='addservice'), - path('add-order', views.add_order, name='addorder'), - - - path('fetch-customer-items//', views.fetch_customer_items, name='fetch_customer_items'), - path('fetch-invoice-details//', views.fetch_invoice_details, name='fetchinvoicedetails'), - - + # DETAILS path('invoice-details//', views.invoice_details, name='invoicedetails'), - path('generate-pdf/', views.generate_pdf, name='generate-pdf'), - - + path('fetch-customer-items//', views.fetch_customer_items, name='fetch_customer_items'), ] diff --git a/osinaweb/billing/views.py b/osinaweb/billing/views.py index 7b5b3223..918ad6eb 100644 --- a/osinaweb/billing/views.py +++ b/osinaweb/billing/views.py @@ -9,7 +9,9 @@ from weasyprint import HTML # LISTING def items (request, *args, **kwargs): + products = Item.objects.filter(type='Product').order_by('-id') context = { + 'products': products, } return render(request, 'listing_pages/items.html', context) @@ -32,31 +34,17 @@ def invoices (request, *args, **kwargs): return render(request, 'listing_pages/invoices.html', context) +#DETAILS +def invoice_details (request, invoice_id): + invoice = get_object_or_404(Invoice, id=invoice_id) - -# ADD -def add_product (request, *args, **kwargs): - context = { - - } - return render(request, 'add_templates/add-product.html', context) - - -def add_service (request, *args, **kwargs): context = { - + 'invoice' : invoice, } - return render(request, 'add_templates/add-service.html', context) - -def add_order (request, *args, **kwargs): - customers = CustomerProfile.objects.all().order_by('-id') + return render(request, 'invoice-details.html', context) - context = { - 'customers': customers, - } - return render(request, 'add_templates/add-order.html', context) @@ -74,51 +62,3 @@ def fetch_customer_items(request, customer_id): } return JsonResponse(data) - - - - -def fetch_invoice_details(request, invoice_id): - invoice = get_object_or_404(Invoice, id=invoice_id) - order = invoice.order - order_items = OrderItem.objects.filter(order=order) - - order_total = order.get_cart_total - - data = { - 'invoice_number': invoice.invoice_number, - 'order_id': order.order_id, - 'order_total' : order_total, - 'date_created': invoice.date_created, - 'customer_first_name': order.customer.user.first_name, - 'customer_last_name': order.customer.user.last_name, - 'customer_email': order.customer.user.email, - 'order_items': list(order_items.values()), # Convert QuerySet to list of dictionaries - } - - return JsonResponse(data) - - - -def invoice_details (request, invoice_id): - invoice = get_object_or_404(Invoice, id=invoice_id) - - context = { - 'invoice' : invoice, - } - - return render(request, 'invoice-details.html', context) - - - - - -def generate_pdf(request): - template = get_template('invoice-details.html') - context = {} - html_string = template.render(context) - - pdf = HTML(string=html_string).write_pdf() - response = HttpResponse(pdf, content_type='application/pdf') - response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"' - return response \ No newline at end of file diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index 84e97bda..5cccc217 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osinacore/__pycache__/models.cpython-310.pyc b/osinaweb/osinacore/__pycache__/models.cpython-310.pyc index 4c2ab01f..9a0be126 100644 Binary files a/osinaweb/osinacore/__pycache__/models.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/models.cpython-310.pyc differ diff --git a/osinaweb/osinacore/__pycache__/views.cpython-310.pyc b/osinaweb/osinacore/__pycache__/views.cpython-310.pyc index b31e93aa..d5ac0563 100644 Binary files a/osinaweb/osinacore/__pycache__/views.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/views.cpython-310.pyc differ diff --git a/osinaweb/osinacore/add/__pycache__/urls.cpython-310.pyc b/osinaweb/osinacore/add/__pycache__/urls.cpython-310.pyc index 2f6854cf..97bc80f9 100644 Binary files a/osinaweb/osinacore/add/__pycache__/urls.cpython-310.pyc and b/osinaweb/osinacore/add/__pycache__/urls.cpython-310.pyc differ diff --git a/osinaweb/osinacore/add/__pycache__/views.cpython-310.pyc b/osinaweb/osinacore/add/__pycache__/views.cpython-310.pyc index 5211a8cf..b0a6a704 100644 Binary files a/osinaweb/osinacore/add/__pycache__/views.cpython-310.pyc and b/osinaweb/osinacore/add/__pycache__/views.cpython-310.pyc differ diff --git a/osinaweb/osinacore/add/urls.py b/osinaweb/osinacore/add/urls.py index 59b7659c..07fd2fac 100644 --- a/osinaweb/osinacore/add/urls.py +++ b/osinaweb/osinacore/add/urls.py @@ -27,6 +27,7 @@ urlpatterns = [ path('businesstype/', views.add_businesstype_modal, name='addbusinesstypemodal'), path('reference/', views.add_reference_modal, name='addreferencemodal'), path('tag/', views.add_tag_modal, name='addtagmodal'), + path('reaction///', views.add_reaction, name='add_reaction'), diff --git a/osinaweb/osinacore/add/views.py b/osinaweb/osinacore/add/views.py index 9f95d034..56174ee7 100644 --- a/osinaweb/osinacore/add/views.py +++ b/osinaweb/osinacore/add/views.py @@ -616,7 +616,7 @@ def add_reference_modal(request, *args, **kwargs): - +@staff_login_required def add_tag_modal(request, *args, **kwargs): if request.method == 'POST': name = request.POST.get('name') @@ -633,6 +633,20 @@ def add_tag_modal(request, *args, **kwargs): +@staff_login_required +def add_reaction(request, status_id, emoji): + status = get_object_or_404(Status, pk=status_id) + user = request.user + existing_reaction = Reaction.objects.filter(status=status, user=user).first() + if existing_reaction: + # If the user has already reacted, update the reaction + existing_reaction.emoji = emoji + existing_reaction.save() + return JsonResponse({'message': 'Reaction updated successfully.'}) + else: + # If the user hasn't reacted yet, create a new reaction + new_reaction = Reaction.objects.create(status=status, emoji=emoji, user=user) + return JsonResponse({'message': 'Reaction added successfully.'}) diff --git a/osinaweb/osinacore/models.py b/osinaweb/osinacore/models.py index 414ff569..71012844 100644 --- a/osinaweb/osinacore/models.py +++ b/osinaweb/osinacore/models.py @@ -21,12 +21,17 @@ class Reference(models.Model): return f"{parts[2]}-{parts[1]}-{parts[0]}" + class Tag(models.Model): name = models.CharField(max_length=50) + def __str__(self): + return self.name class BusinessType(models.Model): name = models.CharField(max_length=50) + def __str__(self): + return self.name class Business(models.Model): @@ -39,7 +44,9 @@ class Business(models.Model): website = models.URLField(null=True) type = models.ForeignKey(BusinessType, on_delete=models.CASCADE, null=True, blank=True) logo = models.ImageField() - business_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation + business_id = models.CharField(max_length=20, null=True, blank=True) + def __str__(self): + return self.name class Meta: verbose_name_plural = u'Businesses' def __str__(self): @@ -102,7 +109,6 @@ class StaffProfile(models.Model): intern = models.BooleanField(default=False) active = models.BooleanField(default=True) staff_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation - def __str__(self): return self.user.username def save(self, *args, **kwargs): @@ -119,6 +125,8 @@ class StaffProfile(models.Model): class ProjectType(models.Model): name = models.CharField(max_length=50) + def __str__(self): + return self.name @@ -138,7 +146,9 @@ class Project(models.Model): status = models.CharField(max_length=200, choices=STATUS_CHOICES) start_date = models.CharField(max_length=200) end_date = models.CharField(max_length=200) - project_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation + project_id = models.CharField(max_length=20, null=True, blank=True) + def __str__(self): + return self.name def save(self, *args, **kwargs): if not self.project_id: # Get the last two digits of the current year @@ -156,6 +166,8 @@ class Milestone(models.Model): project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True) start_date = models.DateField() end_date = models.DateField() + def __str__(self): + return self.title class Epic(models.Model): @@ -169,6 +181,8 @@ class Epic(models.Model): project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True) start_date = models.CharField(max_length=200) end_date = models.CharField(max_length=200) + def __str__(self): + return self.title class ProjectRequirement(models.Model): @@ -176,6 +190,8 @@ class ProjectRequirement(models.Model): project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True) date = models.DateField(null=True, auto_now=True) added_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) + def __str__(self): + return self.content class ProjectFile(models.Model): @@ -302,6 +318,8 @@ class Status(models.Model): date = models.CharField(max_length=40) time = models.CharField(max_length=40) staff = models.ForeignKey(StaffProfile, on_delete=models.CASCADE, null=True,blank=True, related_name='staff') + def __str__(self): + return self.text class Reaction(models.Model): diff --git a/osinaweb/osinacore/views.py b/osinaweb/osinacore/views.py index a2cfb82a..1c6489f0 100644 --- a/osinaweb/osinacore/views.py +++ b/osinaweb/osinacore/views.py @@ -10,10 +10,9 @@ from django.http import JsonResponse from .models import Task, Epic from django.template.loader import render_to_string from .custom_context import calculate_time_ago -from django.core.validators import validate_email -from django.core.exceptions import ValidationError from django.template.loader import get_template from .decorators import * +from django.contrib import messages def login_with_email(request, email, key): @@ -27,7 +26,7 @@ def login_with_email(request, email, key): else: pass -from django.contrib import messages + # Pages views def signin(request): if request.user.is_authenticated: