-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from daltemen/release/0.1.0
Release/0.1.0
- Loading branch information
Showing
31 changed files
with
1,011 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Tracked because this service won't be in production environment | ||
|
||
# == Databases Credentials | ||
DB_PASSWORD=secret | ||
DB_NAME=transactions | ||
DB_USERNAME=root | ||
DB_HOST=transactions-db | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
FROM python:3 | ||
|
||
ENV PYTHONUNBUFFERED 1 | ||
|
||
RUN mkdir /code | ||
|
||
WORKDIR /code | ||
|
||
COPY requirements.txt /code/ | ||
|
||
RUN pip install -r requirements.txt | ||
|
||
COPY . /code/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# transactions-alchemy-django | ||
Django with Alchemy Mysql Pandas Rest Framework example | ||
|
||
# Components | ||
|
||
Users: handling with sqlite (default db with django) | ||
Processors: handling with SQLAlchemy | ||
|
||
# Authentication and Credentials | ||
Please use these credentials to test | ||
|
||
username: admin | ||
|
||
password: admin | ||
|
||
This project use Basic Auth (It won't be in production) please take in mind | ||
|
||
# Considerations | ||
for django and django rest it's easier handle users with django users system then | ||
for practicality db.sqlite3 has been tracked to have a user to tests, although | ||
for the processors system works with sqlalchemy. | ||
|
||
### Prerequisites | ||
|
||
to run this project you need: | ||
* Docker and docker compose | ||
|
||
### Run with docker | ||
To run just run | ||
|
||
```bash | ||
docker-compose up | ||
``` | ||
|
||
### Run tests | ||
Tests don't have dependencies (They must not have) then you can run if you have | ||
python>=3.7 and requirements.txt dependencies with virtualenv | ||
|
||
```console | ||
pytest -s -v | ||
``` | ||
|
||
or if you prefer docker | ||
|
||
TODO: tests with docker | ||
|
||
# Curl Quickly Functional Tests | ||
|
||
## Process File | ||
|
||
It will relate transactions to user authenticated (i.e. admin) | ||
|
||
Process File | ||
|
||
`POST http://localhost:8000/v1/processors/files` | ||
|
||
You can use `transactions_example.csv` of this repository to test | ||
|
||
**Auth required** : YES (Basic Auth) | ||
|
||
**Response** `http status code 204` | ||
|
||
**Example** | ||
|
||
```console | ||
curl --request POST \ | ||
--url http://localhost:8000/v1/processors/files \ | ||
--header 'authorization: Basic YWRtaW46YWRtaW4=' \ | ||
--header 'content-type: multipart/form-data; boundary=---011000010111000001101001' \ | ||
--form file=<path of your file> | ||
``` | ||
|
||
## Get Transactions by User | ||
|
||
It will retrieve transactions related to user authenticated (i.e. admin) | ||
only supports search by transaction_id | ||
|
||
Process File | ||
|
||
`GET http://localhost:8000/v1/processors/transactions?limit=10&page=1&order_by=id&search=52fba4fa` | ||
|
||
**Auth required** : YES (Basic Auth) | ||
|
||
**Response** Get Example | ||
|
||
```json | ||
{ | ||
"count": 6, | ||
"page": 1, | ||
"next_page": 2, | ||
"transactions": [ | ||
{ | ||
"id": "0b6c0f19-3915-4fd7-93ca-c2be13b3939e", | ||
"transaction_id": "52fba4fa-3a01-4961-a809-e343dd4f9597", | ||
"transaction_date": "2020-06-01", | ||
"transaction_amount": 10000, | ||
"client_id": 1067, | ||
"client_name": "nombre cliente", | ||
"file_id": "d65c6de6-6423-4a97-a707-64382281c4a1", | ||
"user_id": 1 | ||
} | ||
] | ||
} | ||
``` | ||
|
||
**Example** | ||
|
||
```console | ||
curl --request GET \ | ||
--url 'http://localhost:8000/v1/processors/transactions?limit=10&page=1&order_by=id&search=word' \ | ||
--header 'authorization: Basic YWRtaW46YWRtaW4=' | ||
``` | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
version: '3.7' | ||
|
||
services: | ||
transactions-db: | ||
image: mysql:5.7 | ||
volumes: | ||
- db_data:/var/lib/mysql | ||
restart: always | ||
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci | ||
environment: | ||
MYSQL_ROOT_PASSWORD: $DB_PASSWORD | ||
MYSQL_DATABASE: $DB_NAME | ||
networks: | ||
- transactions_net | ||
ports: | ||
- 3307:3306 | ||
transactions-api: | ||
build: . | ||
command: python manage.py runserver 0.0.0.0:8000 | ||
volumes: | ||
- .:/code | ||
ports: | ||
- 8000:8000 | ||
env_file: | ||
- .env | ||
depends_on: | ||
- transactions-db | ||
networks: | ||
- transactions_net | ||
|
||
networks: | ||
transactions_net: | ||
name: transactions_net | ||
driver: bridge | ||
volumes: | ||
db_data: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env python | ||
"""Django's command-line utility for administrative tasks.""" | ||
import os | ||
import sys | ||
|
||
|
||
def main(): | ||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'transactions.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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.contrib import admin | ||
|
||
# Register your models here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from django.apps import AppConfig | ||
from processors.models import Base | ||
from transactions.settings import engine | ||
|
||
|
||
class ProcessorsConfig(AppConfig): | ||
name = "processors" | ||
|
||
def ready(self): | ||
try: | ||
Base.metadata.create_all(engine) | ||
except Exception as e: | ||
print(e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import datetime | ||
from dataclasses import dataclass | ||
from typing import Optional, List | ||
|
||
from pandas import DataFrame | ||
|
||
|
||
@dataclass | ||
class TransactionFrame: | ||
""" | ||
Transaction class in Frame Repr for domain objects | ||
""" | ||
|
||
data_frame: DataFrame | ||
|
||
|
||
@dataclass | ||
class Transaction: | ||
""" | ||
Transaction class for domain objects used by get | ||
""" | ||
|
||
id: str | ||
transaction_id: str | ||
transaction_date: str | ||
transaction_amount: int | ||
client_id: int | ||
client_name: str | ||
file_id: str | ||
user_id: int | ||
|
||
|
||
@dataclass | ||
class TransactionList: | ||
transactions: List[Transaction] | ||
count: int | ||
page: int | ||
next_page: int | ||
|
||
|
||
@dataclass | ||
class PaginatorDomain: | ||
page: int | ||
limit: int | ||
order_by: str | ||
search: str | ||
|
||
|
||
@dataclass | ||
class File: | ||
""" | ||
File class for domain objects | ||
""" | ||
|
||
filename: str | ||
user_id: int | ||
id: Optional[str] = None | ||
created_at: Optional[datetime.date] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
from abc import ABC, abstractmethod | ||
from dataclasses import dataclass | ||
from typing import List | ||
|
||
from pandas import DataFrame | ||
|
||
from processors.domain import ( | ||
File, | ||
TransactionFrame, | ||
Transaction, | ||
PaginatorDomain, | ||
TransactionList, | ||
) | ||
from processors.repository import ProcessorDBInterface | ||
|
||
|
||
@dataclass | ||
class FileInput: | ||
""" | ||
File Input Boundaries Of Manager | ||
""" | ||
|
||
name: str | ||
file_data_frame: DataFrame | ||
user_id: int | ||
|
||
|
||
@dataclass | ||
class ListerHelper: | ||
""" | ||
Helper to handle pagination, ordering and filtering | ||
""" | ||
|
||
page: int | ||
limit: int | ||
order_by: str | ||
search: str | ||
|
||
|
||
@dataclass | ||
class Paginator: | ||
count: int | ||
page: int | ||
next_page: int | ||
|
||
|
||
@dataclass | ||
class TransactionsOut(Paginator): | ||
transactions: List[Transaction] | ||
|
||
|
||
class ProcessorManagerInterface(ABC): | ||
""" | ||
Interface to handle access to db | ||
""" | ||
|
||
@abstractmethod | ||
def process_file(self, file_input: FileInput) -> bool: | ||
pass | ||
|
||
@abstractmethod | ||
def list_transactions(self, lister: ListerHelper, user_id: str) -> TransactionsOut: | ||
pass | ||
|
||
|
||
class ProcessorManager(ProcessorManagerInterface): | ||
def __init__(self, repo_db: ProcessorDBInterface): | ||
self.repository: ProcessorDBInterface = repo_db | ||
|
||
def process_file(self, file_input: FileInput) -> bool: | ||
file = self.repository.create_file( | ||
File(filename=file_input.name, user_id=file_input.user_id) | ||
) | ||
return self.repository.create_transactions( | ||
TransactionFrame(file_input.file_data_frame), file.id, file_input.user_id | ||
) | ||
|
||
def list_transactions(self, lister: ListerHelper, user_id: int) -> TransactionsOut: | ||
result: TransactionList = self.repository.get_transactions_by_user_id( | ||
PaginatorDomain(**lister.__dict__), user_id | ||
) | ||
return TransactionsOut( | ||
count=result.count, | ||
page=result.page, | ||
next_page=result.next_page, | ||
transactions=result.transactions, | ||
) |
Empty file.
Oops, something went wrong.