Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
frchrist committed Mar 12, 2023
0 parents commit 78d7991
Show file tree
Hide file tree
Showing 34 changed files with 760 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*/__pycache__
.env
/.venv/
Empty file added api/__init__.py
Empty file.
9 changes: 9 additions & 0 deletions api/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.contrib import admin
from .models import Product, Invoice, ProductInInvoice

# Register your models here.
admin.site.register(Product)
admin.site.register(Invoice)

admin.site.register(ProductInInvoice)

6 changes: 6 additions & 0 deletions api/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'
45 changes: 45 additions & 0 deletions api/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Generated by Django 4.1.7 on 2023-03-12 00:09

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Product',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=225)),
('price', models.DecimalField(decimal_places=2, max_digits=8)),
('is_deleted', models.BooleanField(default=False)),
('description', models.TextField(blank=True, default='', null=True)),
],
),
migrations.CreateModel(
name='ProductInInvoice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('quantity', models.IntegerField()),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='in_invoice', to='api.product')),
],
),
migrations.CreateModel(
name='Invoice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('client', models.CharField(default='', max_length=25)),
('ref', models.CharField(default='', max_length=20)),
('total_amount', models.PositiveBigIntegerField(blank=True)),
('type', models.CharField(choices=[('pro forma', 'pro forma'), ('facture', 'facture')], default='facture', max_length=15)),
('is_deleted', models.BooleanField(default=False)),
('product_in_invoice', models.ManyToManyField(related_name='invoices', to='api.productininvoice')),
],
),
]
17 changes: 17 additions & 0 deletions api/migrations/0002_remove_invoice_total_amount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.1.7 on 2023-03-12 01:08

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('api', '0001_initial'),
]

operations = [
migrations.RemoveField(
model_name='invoice',
name='total_amount',
),
]
Empty file added api/migrations/__init__.py
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added api/migrations/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
71 changes: 71 additions & 0 deletions api/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from django.db import models
from datetime import date, datetime
from django.db.models.signals import pre_save
# Create your models here.




class Product(models.Model):
name = models.CharField(max_length=225)
price = models.DecimalField(max_digits=8, decimal_places=2)
# quantity = models.IntegerField(helper_text="Quantité en Stock")
is_deleted = models.BooleanField(default=False)
description = models.TextField(null=True, blank=True, default="")


def __str__(self):
return self.name

class ProductInInvoice(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='in_invoice')
quantity = models.IntegerField()

def __str__(self):
return f"{self.product.name} - {self.quantity}"





class Invoice(models.Model):
client = models.CharField(max_length=25, default="")
ref = models.CharField(max_length=20, default="")

type = models.CharField(choices=(("pro forma", "pro forma"), ("facture", "facture")),
max_length=15, default="facture")
is_deleted = models.BooleanField(default=False)
product_in_invoice = models.ManyToManyField(to=ProductInInvoice, related_name="invoices")

def __str__(self):
return f"Facture #{self.ref}"

@property
def amount(self):
return sum([int(invoice_product.product.price) * int(invoice_product.quantity) for invoice_product in self.product_in_invoice.all()])
# sum_ = 0
# for invoice_product in self.article_in_invoice.all():
# sum_ += int(invoice_product.product.price) * int(invoice_product.quantity)



# class InvoiceProduct(models.Model):
# invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='article_in_invoice')
# product = models.ForeignKey(ProductInInvoice, on_delete=models.CASCADE, related_name='invoice_products')
# # quantity = models.IntegerField()




def create_invoice_number(sender, instance, *args,**kwargs) -> None:
prefix = f"KG/{datetime.now().year}/"
FIX : int = 1000
count = sender.objects.count() + FIX
number : str = f"{prefix}{count}"
instance.ref = number



pre_save.connect(receiver=create_invoice_number, sender=Invoice)


15 changes: 15 additions & 0 deletions api/process.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# importing the necessary libraries
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa

# defining the function to convert an HTML file to a PDF file
def html_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
57 changes: 57 additions & 0 deletions api/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from rest_framework import serializers
from .models import Product, Invoice,ProductInInvoice

class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = "__all__"

class WriteProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ("id", "name", "price", "description")
read_only_fields = ("price", "description")


class ProductInInvoiceSerializer(serializers.ModelSerializer):
product = WriteProductSerializer()
# product = serializers.SlugRelatedField(queryset=Product.objects.all(), slug_field="name")
class Meta:
model = ProductInInvoice
fields = "__all__"


# class ProductInvoiceSerializer(serializers.ModelSerializer):
# quantity = serializers.IntegerField()
# class Meta:
# model = Product
# fields = ("name")


class InvoiceSerializer(serializers.ModelSerializer):
product_in_invoice = ProductInInvoiceSerializer(many=True)
# product = WriteProductSerializer(many=True)

amount = serializers.ReadOnlyField()
ref = serializers.ReadOnlyField()
is_deleted = serializers.ReadOnlyField()
# extra_kwargs = {"product" : {"write_only" : True}}



class Meta:
model = Invoice
fields = '__all__'
# read_only_fields = ("product_in_invoice",)

def create(self, validated_data):
products_data = validated_data.pop('product_in_invoice')
invoice = Invoice.objects.create(**validated_data)
for product_data in products_data:
pro_data = product_data.get("product")
pro = Product.objects.get(name=pro_data.get("name"))
product = ProductInInvoice.objects.create(product=pro, quantity=product_data.get("quantity"))
# quantity = product_data.get('quantity', 1)
invoice.product_in_invoice.add(product)
# InvoiceProduct.objects.create(invoice=invoice, product=product, quantity=quantity)
return invoice
3 changes: 3 additions & 0 deletions api/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
17 changes: 17 additions & 0 deletions api/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.urls import path, include
from rest_framework import routers



from api.views import InvoiceList, ProductViewSet, InvoiceViewSet

router = routers.DefaultRouter()

router.register("product",ProductViewSet)
router.register("invoice",InvoiceViewSet)


urlpatterns = [
path("", include(router.urls)),
path("ivs", InvoiceList.as_view(), name="ivs")
]
72 changes: 72 additions & 0 deletions api/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from django.shortcuts import render
from django.http import HttpResponse
from rest_framework import mixins
from rest_framework import generics
from rest_framework import viewsets
from rest_framework import renderers
from .process import html_to_pdf

from api.models import Invoice, Product
from api.serializers import InvoiceSerializer, ProductSerializer


class ProductViewSet(viewsets.ModelViewSet):
# renderer_classes = [renderers.JSONRenderer]

queryset = Product.objects.all()
serializer_class = ProductSerializer


class InvoiceList(mixins.ListModelMixin,mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Invoice.objects.all()
serializer_class = InvoiceSerializer

def get(self, request, *args, **kwargs):
return self.list(request,
args, kwargs)

class InvoiceViewSet(viewsets.ModelViewSet):
# renderer_classes = [renderers.JSONRenderer]
queryset = Invoice.objects.all()
serializer_class = InvoiceSerializer

# def get_queryset(self):
# genres = Invoice.objects.get(pk=self.kwargs.get('pk', None))
# movies = Movie.objects.filter(genres=genres)
# return movies




# Create your views here.

# class invoiceAPIView(generics.RetrieveAPIView):
# def get(self, request, *args, **kwargs):
# pdf = html_to_pdf("api/invoice.html")
# return HttpResponse(pdf, content_type="application/pdf")



# class InvoiceList(mixins.ListModelMixin,mixins.CreateModelMixin, generics.GenericAPIView):
# queryset = Invoice.objects.all()
# serializer_class = InvoiceSerializer

# def post(self, request, *args, **kwargs):
# self.serializer_class = CreateInvoiceSerializer
# return self.create(request, args, kwargs)

# def get(self, request, *args, **kwargs):
# return self.list(request,
# args, kwargs)


# class ProductList(mixins.ListModelMixin,mixins.CreateModelMixin, generics.GenericAPIView):
# queryset = Product.objects.all()
# serializer_class = ProductSerializer

# def post(self, request, *args, **kwargs):
# return self.create(request, args, kwargs)

# def get(self, request, *args, **kwargs):
# return self.list(request,
# args, kwargs)
3 changes: 3 additions & 0 deletions build_files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# build_files.sh
pip install -r requirements.txt
python3.9 manage.py collectstatic
Binary file added db.sqlite3
Binary file not shown.
22 changes: 22 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == '__main__':
main()
Empty file added server/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions server/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
ASGI config for server project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings')

application = get_asgi_application()

app = application
Loading

0 comments on commit 78d7991

Please sign in to comment.