Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setupm transactions #3

Merged
merged 1 commit into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gds/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
'django.contrib.staticfiles',
#apps
'stock',
'transactions',

#3rd part apps
'allauth',
Expand Down
1 change: 1 addition & 0 deletions gds/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
path('__debug__/', include("debug_toolbar.urls")),
path('accounts/', include('allauth.urls')),
path('stock/', include('stock.urls')),
path('transactions/', include('transactions.urls')),
]
18 changes: 18 additions & 0 deletions stock/migrations/0002_gas_minimum_threshold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0 on 2023-12-28 22:12

from django.db import migrations, models


class Migration(migrations.Migration):

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

operations = [
migrations.AddField(
model_name='gas',
name='minimum_threshold',
field=models.PositiveIntegerField(default=50),
),
]
1 change: 1 addition & 0 deletions stock/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Gas(models.Model):
quantity = models.PositiveIntegerField()
price = models.DecimalField(max_digits=8, decimal_places=2)
supplier = models.CharField(max_length=100, null=True, blank=True)
minimum_threshold = models.PositiveIntegerField(default= 50)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)

Expand Down
13 changes: 13 additions & 0 deletions stock/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.mail import send_mail
from .models import Gas

@receiver(post_save, sender=Gas)
def send_stock_alert(sender, instance, **kwargs):
if instance.quantity < instance.minimum_threshold:
subject = f"Gas stock alert: {instance.name}"
message = f"The stock of {instance.name} is below {instance.minimum_threshold} units."
from_email = "[email protected]"
recipient_list = ["[email protected]"]
send_mail(subject, message, from_email, recipient_list)
Empty file.
Empty file.
Empty file.
Empty file.
Empty file added transactions/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions transactions/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.contrib import admin
from .models import Transaction

@admin.register(Transaction)
class TransactionAdmin(admin.ModelAdmin):
list_display = ('customer', 'quantity', 'product', 'created', 'updated', 'get_total_cost')
list_filter = ('product', 'created', 'updated')
search_fields = ('customer', 'product__name')
readonly_fields = ('total_cost',)

def get_total_cost(self, obj):
return obj.total_cost()
get_total_cost.short_description = 'Total Cost'
9 changes: 9 additions & 0 deletions transactions/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.apps import AppConfig


class TransactionsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'transactions'

def ready(self):
import transactions.signals
28 changes: 28 additions & 0 deletions transactions/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 5.0 on 2023-12-28 21:51

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


class Migration(migrations.Migration):

initial = True

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

operations = [
migrations.CreateModel(
name='Transaction',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('customer', models.CharField(max_length=100)),
('quantity', models.DecimalField(decimal_places=2, max_digits=10)),
('unit_cost', models.DecimalField(decimal_places=2, max_digits=10)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transaction', to='stock.gas')),
],
),
]
17 changes: 17 additions & 0 deletions transactions/migrations/0002_remove_transaction_unit_cost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.0 on 2023-12-28 22:20

from django.db import migrations


class Migration(migrations.Migration):

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

operations = [
migrations.RemoveField(
model_name='transaction',
name='unit_cost',
),
]
Empty file.
17 changes: 17 additions & 0 deletions transactions/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.db import models

class Transaction(models.Model):
customer = models.CharField(max_length=100)
quantity = models.DecimalField(max_digits=10, decimal_places=2)
product = models.ForeignKey('stock.Gas', on_delete=models.CASCADE, related_name='transaction' )
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)

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

def total_cost(self):
try:
return self.quantity * self.product.price
except Exception as e:
return 0.00
14 changes: 14 additions & 0 deletions transactions/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Transaction

@receiver(post_save, sender=Transaction)
def reduce_stock_quantity(sender, instance, created, **kwargs):
if created: # New transaction
instance.product.quantity -= instance.quantity
instance.product.save()
else: # Existing transaction
original_transaction = Transaction.objects.get(pk=instance.pk)
quantity_diff = instance.quantity - original_transaction.quantity
instance.product.quantity -= quantity_diff
instance.product.save()
35 changes: 35 additions & 0 deletions transactions/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from django.test import TestCase
from django.utils import timezone
from .models import Transaction
from stock.models import Gas

class TransactionModelTest(TestCase):
def setUp(self):
self.gas = Gas.objects.create(name='Gas A', quantity=100,price=1.50)
self.transaction = Transaction.objects.create(
customer='John Doe',
quantity=10,
product=self.gas
)

def test_total_cost(self):
expected_total_cost = self.transaction.quantity * self.transaction.product.price
self.assertEqual(self.transaction.total_cost(), expected_total_cost)

def test_stock_reduction_on_create(self):
initial_quantity = self.gas.quantity
new_transaction = Transaction.objects.create(
customer='Jane Smith',
quantity=20,
product=self.gas
)
updated_quantity = self.gas.quantity
self.assertEqual(updated_quantity, initial_quantity - new_transaction.quantity)

def test_stock_reduction_on_update(self):
initial_quantity = self.gas.quantity
updated_quantity = 15
self.transaction.quantity = updated_quantity
self.transaction.save()
self.gas.refresh_from_db()
self.assertEqual(self.gas.quantity, initial_quantity - (updated_quantity - self.transaction.quantity))
11 changes: 11 additions & 0 deletions transactions/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.urls import path
from . import views

app_name = 'transactions'

urlpatterns = [
path('', views.TransactionListView.as_view(), name='transaction_list'),
path('create/', views.TransactionCreateView.as_view(), name='transaction_create'),
path('<int:pk>/update/', views.TransactionUpdateView.as_view(), name='transaction_update'),
path('<int:pk>/delete/', views.TransactionDeleteView.as_view(), name='transaction_delete'),
]
25 changes: 25 additions & 0 deletions transactions/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from .models import Transaction
from django.urls import reverse_lazy

class TransactionListView(ListView):
model = Transaction
template_name = 'transactions/index.html'
context_object_name = 'transactions'

class TransactionCreateView(CreateView):
model = Transaction
template_name = 'transactions/create.html'
fields = ['date', 'product', 'quantity', 'unit_cost']
success_url = reverse_lazy('transactions:transaction_list')

class TransactionUpdateView(UpdateView):
model = Transaction
template_name = 'transactions/update.html'
fields = ['date', 'product', 'quantity', 'unit_cost']
success_url = reverse_lazy('transactions:transaction_list')

class TransactionDeleteView(DeleteView):
model = Transaction
template_name = 'transactions/delete.html'
success_url = reverse_lazy('transactions:transaction_list')