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

Add core app #1

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ac3da43
feat: add models
ahmed-arb Jan 20, 2023
dabc6b2
Feat: add books api
ahmed-arb Jan 23, 2023
008a898
Feat: add auth backend
ahmed-arb Jan 23, 2023
1063a30
feat!: change BookViewSet permission method
ahmed-arb Jan 23, 2023
044e041
feat: add book loan view
ahmed-arb Jan 23, 2023
8d6fc0a
feat: update book stock
ahmed-arb Jan 24, 2023
bc6f012
feat: validate book loan request
ahmed-arb Jan 24, 2023
2ace28d
feat: add import csv data command
ahmed-arb Jan 24, 2023
a008a62
cron job setup
ahmed-arb Jan 24, 2023
8754897
feat: send reminder emails
ahmed-arb Jan 25, 2023
98ec492
feat: add book request api
ahmed-arb Jan 25, 2023
23821e5
feat: BookRequest signal
ahmed-arb Jan 26, 2023
0a5e9fb
add formatting and docstrings
ahmed-arb Jan 30, 2023
8415527
add docstrings
ahmed-arb Jan 31, 2023
1c38dcb
Update select_related in core/cron.py
ahmed-arb Feb 27, 2023
2e507ea
model changes
ahmed-arb Feb 27, 2023
1e406c9
Merge branch 'add-core-app' of https://github.com/ahmed-arb/LMS-API i…
ahmed-arb Feb 27, 2023
849c89f
change book filter query in core/serializers.py
ahmed-arb Feb 27, 2023
eeda78f
Update requirements.txt
ahmed-arb Feb 27, 2023
33a2e89
Merge branch 'add-core-app' of https://github.com/ahmed-arb/LMS-API i…
ahmed-arb Feb 27, 2023
2339d19
add logging
ahmed-arb Feb 27, 2023
5d4c4b2
Feat!: remove librarian model
ahmed-arb Feb 27, 2023
18ade71
add read serializers for book loans and request
ahmed-arb Mar 1, 2023
24b07ad
add data migration
ahmed-arb Mar 3, 2023
af2c9a0
change enumeration types in models.py
ahmed-arb Mar 6, 2023
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
18 changes: 0 additions & 18 deletions .github/linters/.python-black

This file was deleted.

5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,8 @@ GitHub.sublime-settings
!.vscode/launch.json
!.vscode/extensions.json
.history

uploads/
files/
logs/
sandbox.py
18 changes: 0 additions & 18 deletions .pre-commit-config.yaml

This file was deleted.

9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"python.linting.pylintEnabled": true,
"python.linting.pylintArgs": [
"--load-plugins=pylint_django",
"--max-line-length=120",
"--disable=django-not-configured",
"--django-settings-module=lms.settings"
]
}
12 changes: 3 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ You first need an env ☘️

```python
# create the env
conda create --name libraryenv
conda create --name lms

# install requirements
pip install -r requirements.txt
Expand All @@ -19,6 +19,8 @@ accordingly. Otherwise you just need a .env file with DB credentials.
Migrate models to your db

```python
python manage.py makemigrations

python manage.py migrate
```

Expand All @@ -27,11 +29,3 @@ Start the app
```python
python manage.py runserver
```

### Documentation 📝:

Complete docs of the API are available at the endpoint:

```
http://{HOST}/docs
```
Empty file added core/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions core/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""core admin panel"""

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from core.models import User


@admin.register(User)
class UserAdmin(BaseUserAdmin):
"""Over ride user view in admin panel"""

add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("username", "email", "password1", "password2"),
},
),
)
14 changes: 14 additions & 0 deletions core/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Core config of LMS"""

from django.apps import AppConfig


class CoreConfig(AppConfig):
"""This class defines core app configs"""

default_auto_field = "django.db.models.BigAutoField"
name = "core"

def ready(self) -> None:
"""Sets up imports and pre-requisites for this app"""
import core.signals
28 changes: 28 additions & 0 deletions core/cron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
""" This module has all core app corn jobs"""

from datetime import datetime
import logging

from templated_mail.mail import BaseEmailMessage

from core.models import BookLoan


logger = logging.getLogger(__name__)


def email_overdue_books():
"""cron job for emailing user which have a book overdue"""
today = datetime.now()
loan_queryset = BookLoan.objects.select_related('book', 'user').filter(date_due__lt=today)

for loan in loan_queryset:
message = BaseEmailMessage(
template_name="emails/overdue_books.html",
context={
"name": loan.user,
"book": loan.book,
},
)
message.send([loan.user.email])
logger.info("email sent to %s for %s due: %s", loan.user.email, loan.book, loan.date_due)
Empty file added core/management/__init__.py
Empty file.
Empty file.
45 changes: 45 additions & 0 deletions core/management/commands/import_books_from_csv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import csv
from typing import Any, Optional

from django.core.management.base import BaseCommand, CommandParser

from core.serializers import BookSerializer
from core.models import Book


class Command(BaseCommand):
help = "Import books form csv"

def add_arguments(self, parser: CommandParser) -> None:
parser.add_argument("file_path", nargs=1, type=str)

def handle(self, *args: Any, **options: Any) -> Optional[str]:
self.file_path = options['file_path'][0]
self.prepare()
self.main()
self.finalize()

def prepare(self):
self.imported_counter = 0
self.skipped_counter = 0

def main(self):
self.stdout.write("=== Importing Books ===\n\n")

with open(self.file_path, 'r') as f:
reader = csv.DictReader(f)

for index, row in enumerate(reader):
serializer = BookSerializer(data=row)
if serializer.is_valid():
self.imported_counter += 1
serializer.save()
self.stdout.write(f'{index} {row["name"]} SAVED')
else:
self.skipped_counter += 1
self.stdout.write(f'{index} {row["name"]} SKIPPED {serializer.errors}')

def finalize(self):
self.stdout.write("----------------------")
self.stdout.write(f"Books imported: {self.imported_counter}")
self.stdout.write(f"Books skipped: {self.skipped_counter}")
Comment on lines +43 to +45
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we can use print here

Loading