Skip to content

Commit

Permalink
Payments | Final version (#413)
Browse files Browse the repository at this point in the history
* Service: payments. Fix review comments (#51)

* initial commit/base project config

* Update README.md

* add apps

* Created models for payment_accounts and transactions apps

* Fixed wrong value settings naming

* Bug fixes after pull request review

* Create refill functional

* Add rollbar for log

* Fixed style errors after review:
  - deleted empty string after class declaration
  - proper declaration of long strings
  - deleted default django comment

* Transfer business logic in services

* docker without root

* Refactoring after review

---------

Co-authored-by: range <alexadush@yandex.ru>
Co-authored-by: lsoulworkerl <prosto2002vitalik@gmail.com>
Co-authored-by: fenx4 <phenx4@gmail.com>
Co-authored-by: fenx4 <127792143+fenx4@users.noreply.github.com>

* Payments | Add Celery and Redis (#76)

Add Celery and Redis

* Payments | multistage build slim (#80)

* Payments | dockerfile rebuilding

add in settings.py :
  -STATIC_ROOT
  -change Datebase{}
in docker-compose change port for transactions on "5433"
add start.sh for running server
change entrypoint.sh, script which check db status in comments still didn't work
Dockerfile: alpine>>slim for bash, now file have less layers and more easy to read it.

* Payments | docker multistage slim

change base image alpine >> slim
add to README env arguments for postgresql db,
celery args right or not?
about entrypoint scripts and start sh will discuss on meet

* Payments | Create CI/CD and modificate docker-compose (#97)

- edit readme.md file
- modificate docker-compose, now we have ngnix, gunicorn and localtunnel
- created CI/CD, it checks flake8 and run to check docker-compose, that it runs fine
- cosmetic changes in code for linter(flake8)

* Payments | Edit .gitignore file and add migrations (#99)

* CI/CD for payments

* Update payments_action.yml

* Update payments_action.yml

* Fix start.sh

* fix start.sh with Docerfile

* Moun host directory, edit entrypoint to run server

* Add localtunnel

* Cosmetic changes for linter

* Cosmetic changes for linter #1

* Create .env.example for docker ci/cd

* Update payments_action.yml

* Fix docker files

* Cosmetic changes

* Create .env.example

* Cosmetic changes

* Cosmetic changes

* Add some settings to .env file

* readme

* readme

* Edit README file

* Update .env.example

* Add migrations

* Edit migrations for CI/CD

* Removed static ignore

* Payments| Create transactions  (#100)

* Create transactions (#2)

* Refactored code style:
  - changed docker compose settings naming
  - moved calculation of commission to separate CalculatePaymentCommissionView and serialzier
  - updated django model BalanceChange so by default it would put zero
  - created typehints for functions in files in payment_acceptance.py and create_payment.py
  - created separated file for schemas

* - Added serializer and dataclasses for incoming data from yookassa
- Added handle exceptions durring parsing data in serializers
-

* - Added model of Invoice
- Created class for construction Invoice
- Refactored process of balance deposit
- Added function to purchiase items

* - Added additional app for external payment communication
- Moved serializers YookassaPaymentAcceptanceSerializer and all depende serializes to new app
- Moved Yookassa creation of conformition url to new app
- Created Invoice model to bound new Transactions
- Created new View for creation of Invoice
- Added classs to process balance change and invoce change
- Added fucntion purchaised items

* - In payment_processor fixed transaction parse process
- Fixed import of celery app in external_payments tasks

* Create transactions (#4)

* - Added function to calculate value without commission
- Fixed type hints for YookassaPaymentInfo

* isort

maybe fixed

* - Fixed field names for dataclasses and serializers
- Pined dependencies in requirements.txt
- Added method to rename  builtin field name for incoming json

* Refactored payment acceptance process, instead of function added class PaymentAcceptance and to handle income invoice data IncomeInvoiceHandler

* - Bug fixed in creation process of Transactions and BalanceChanges.
- PaymentTypes and YookassaPayment types merged in one data class
- Created test view and serializer for creation of purchase_items

* - moved increase balance, parse_model and decrease balance to utils in apps base
- created MoneyField and MoenySerializerField for models based on DecimalField, and replaced in all django models and serializers

---------

Co-authored-by: fenx4 <127792143+fenx4@users.noreply.github.com>

* - Deleted extra dependency from requirements.txt
- Renamed var names in .env.example
- Added nested .gitignore
- Renamed BalanceChangeHandler to IncomeBalanceHandler
- uncomment task creation in execution process

---------

Co-authored-by: fenx4 <127792143+fenx4@users.noreply.github.com>

* Payments | Fix (#112)

- edit readme file
- add black, add-railing-comma, isort to pre-commit (use black isort rule, not flake8)
- update files by black

* Payments | Abstract class (#135)

* Abstract class (#5)

* - renamed dataclasses and schema classes to proper names
- added abstract class for external services
- inherited from it and create YookassaPayment class with method to interact with external services
- created base dataclass and serializers service_payments and moved to base directory
- moved creation of payment data to newly created YookassaPayment class from functions

* - added method handel_payment_response into base abstract payment class
- created data class ResponseParsedData
- into YookassaPayment added handel_payment_response to procced income data
- Added YookassaResponseParser and InvoiceValidator to handle payment response
- Deleted IncomeInvoiceHandle and BalanceChangeHandler
- added function into accept_payment.py proceed_payment_response to work with busines logic
- execute invoice operation mooved to invoice_execution
- change in schemas
- replace decimal fields in serializers to MoneySerializerField

* Changes after review:
- moved yookassa configuration to YookassaPayment
- updated imports

* Style fix

* Ignore W503 error

* Updated import in balance_change

* Removed E501 from pre-commit and payments_action

* Payments | Rename models (#147)

Create new models:
- balance service map
- payment service
- payment commission
Edit Transaction -> ItemPurchase

* Payments | create view for users (#136)

Api for creating user accounts in payments db

* Payments | Rename all files with prefix 'transaction'    (#161)

Edited files with prefix transaction to item_purchase

* Split settings (#163)

Split settings.py for django into package with: base.py, drf.py, celery.py, logger.py, database.py, busines_settings.py

* Payments | Create owner model with fixtures (#165)

- create Owner model with fixture
- create fixtures for PaymentService and PaymentCommission
- edit comission field in PaymentCommission (Float -> Decimal)
- add fields: is_paid and created_date in Invoice
- in ItemPurchase replaced (is_frozen, is_accepted) -> (status)
- fix functions return
- add handler in add_change_balance_method
- add annotation for add_change_balance_method

* Payments | Added function to output balance of user  (#187)

Added function to output balance of user

* Payments | Edit models, add djmoney (#194)

* Create owner model with fixtures (#2)

* Fix total_price, need to return Decimal

* Owner model

* Fix commission in PaymentCommission

* Commission field fix

* Update field in item purchase

* Add currency to Account

* Fix returns of functions

* Edit model fields

* Create migrations with fixtures

* Create CommissionField and create custom method for withdraw/deposit (#3)

* Add handler in add_change_balance_method (#4)

Add handler in add_change_balance_method

* Add annotation for add_change_balance_method (#5)

* Add djmoney (#6)

* Fix MoneySerializatorField (#7)

Fix MoneySerializerField

* Payments | Added function to view of users balance (#217)

* Split money serializator and example for pydantic with env (#224)

* Split serializer for amount and amount

* Create example for env with pydantic

* Payments | Create Payout (#226)

* Payout (#7)

- Create PrePayoutClass
- Added PayOut class to work with yookassa
- Added view to handle income payout request
- Added serializers for income request to payout
- Created Pydantic models YookassaPayoutModel, PayoutDestination, AmountModel to handle income payout data
- Update all Balance Change creations to use OperationType enum
- Added abstract class for payout
- Create enum for supported currencies
- Created YookassaPayOut class, refactored process of calling env settings for yookassa shop data
- Refactored .env.example filed
- Added supported currencies into business_settings.py
- Created manager for BalanceChangeManager and added function get_payout_amount_for_last_month inside
- Created NotValidAccountNumberError exception
- Moved payout validation to PayOutValidator class
- PayoutProcessor class created and added method to create payout
- Moved payout date from settings into Owner model
- Added typehints for PayoutProcessor and PayoutValidator
- Added save method to Owner model to prevent creating more than one Owner instance
- Renamed busines_settings.py to business_settings.py
- Updated _is_enough_funds for django_money field
- Fixes after review
- Added TODO comments
- Changed account_number to CharField
- Removed min_value=500

* - Change MoneySerializer to MoneyAmountSerializer into AmountPayoutSerializer

* -Deleted busines_settings.py
-Fixed example for yookassa config

* Payments | Invoice Refactoring (#235)

* - Renamed PayOutLimitExceededError to AttemptsLimitExceededError and moved to based app
- Refactored Invoice to correctly work with commission
- Added validation to prevent abusing of creation new Invoices
- Validation to check if developer account already exists
- Added support for MoneyField

* - Created multiple_select_or_404 to fetch several objects from database in one query
- Removed MoneySerializerField from base app
- Added schema MoneyDataClass and serializer MoneySerializer
- Added support for MoneySerializer while creating Invoice and ItemPurchase
- PurchaseItemsSerializer and ItemPaymentData replaced MoneyAmountSerializerField with MoneySerializer same for schema
- Added BalanceSerializer, removed AccountBalanceSerializer and MoneySerializer in payment_accounts
- Removed AccountBalanceViewSet, retrieve single balance moved to BalanceViewSet

* Payments | Check yookassa response (#254)

* Check yookassa response

* Refactoring check_yookassa_response

* Check that payment_id and object isn't None

* Payments | Payout (#264)

* - Updated migrations
- Added class DRFtoDataClassConverter
- Added error DifferentStructureError
- Updated Yookassa -> yookassa in fixtures, to make it same as in PayoutServices
- Changed increase_user_balance and decrease_user_balance to return BalanceChange
- Added OperationType to BalanceServiceMap
- Updated payout process after response from yookassa in PayoutProcessor class, creating db records
- Updated vies in payment_acceptance package to use DRFtoDataClassConverter

* Ranamed DRFtoDataClassConverter to DRFtoDataClassMixin

* Payments | Refund, change Invoice input JSON (#265)

- Create task get_item_for_self_user
- Edit serializers, schemas, ItemPurchaseRequest for PurchaseItemView to get correct JSON
- Create RefundView to receive a refund request
- Create RefundProccesor to process a refund request

* Docker and fixtures (#11) (#278)

- All fixtures now in folder apps/base/fixtures
- Base folder - base fixtures to work with yookassa
- Test folder - test fixtures for test our app
- Left only one Dockerfile and move to base dir
- Dockerfile multistaging -> one stage
- Created docker-compose.override.yml
- Add beat container for celery beat

* Payments | Added PayoutData (#283)

* Payout (#8)

- Created Dajngo model PayoutData with fixtures
- Recreated migrations
- Added PayoutDataObjectViewSet viewset for PayoutData for single object
- Added viewset PayoutDataCreateViewSet
- Created serializers PayoutDataSerializer and CreatePayoutDataSerializer
- Replaces PayoutType dataclass with PayoutType from PayoutData model
- Updated increase_user_balance and decrease_user_balance to return balance_change_objects
- Into DRFtoDataClassMixin added support for pydantic
- Fixed bugs to handel payout process

* - Updated payout fixtures with new primary keys
- Updated default value for MoneyField and removed default_money variable
- Renew migrations
- Updated docker-compose.override.yml with env values for payments_db
- Fixed entrypoint.sh to properly load data from envs
- Renamed constraint in PayoutData
- Refactored validate method to check for digits for yoomoney payout type
- Renamed PayoutDataCreateViewSet to PayoutDataCreateView
- Refactored partial_update for PayoutDataViewSet

* Update payout.json

* Payments | Urls for admin panel (#301)

* Refund (#9)

* Check yookassa response

* Refactoring check_yookassa_response

* Check that payment_id and object isn't None

* Add refund

* Edit json

* return settings

* edit after review (#10)

* Update payment_acceptance.py

* edit after review

* Admin (#14)

* Views for custom admin

* fix blank lines

* Fix views

* Payments | Delete else (#327)

Payments| The create method in the UserAccountAPIView class has been redefined. Changed the error returned when creating an account that already exists in the database

* Payments | New api -- item-purchase-history   (#325)

* Added default admin panel

* added api - item-purchase-history

* fix by linters

* fixed issues in api - item-purchase-history

* fixed issues in api - item-purchase-history

---------

Co-authored-by: koval.dmitriy <Vjkj3bkmyjtzqwj>

* Payments | edited files names  (#309)


* change datas to data

* Edit db port 5433 -> 5432

---------

Co-authored-by: SouLWorkeR <prosto2002vitalik@gmail.com>

* Payements | Gift (#320)

* Gift (#9)

- Changed name edit_change_balance to accept_balance_change
- Added ItemPurchaseStatusChanger to validate income request for ItemsPurchase update through view
- Changed name gift_item_to_other_user to cancel_gift_item and added logic
- get_item_for_self_user task added vcalidations
- RefundData updated to ItemPurchaseData
- Into TransferHistory added new field account_from with GenericForeignKey
- Refund.py in item_purchase deleted and added new file item_purchase_completer with ItemPurchaseCompleter to finish process for item_purchase models
- updated invoice_execution.py, all db operations execute in transaction inside execute_invoice_operations
- Added MultipleObjectsReturned into ItemPurchaseCompleter to handel scenario where it's several ItemPurchases
- Added assert_never to handel not implemented ItemPurchase.ItemPurchaseStatus

* - Fixed bug in multiple_select_or_404
- Moved ItemPurchaseStatusChanger from classes to item_purchase_completer
- Updated TransferHistory to work correctly with two generic keys, added TransferHistoryManager to simplify creation of new TransferHistory records
- Updated RefundSerializer and ItemPurchaseData with fields user_uuid_from and user_uuid_to
- ItemPurchaseUpdaterViewSet renamed to ItemPurchaseUpdateView
- Fixed fixtures for TransferHistory

* Payments | Added payout history view (#335)

* Payments| Correction of an error when creating an account whose UUID is already in the database

Payments| The create method in the UserAccountAPIView class has been redefined. Changed the error returned when creating an account that already exists in the database

* Deleted else

* Payments| Add payout history view

Changes:
-in urls append path 'payout_history/<uuid:user_uuid>/'
-in views append class PayoutHistoryPagination and PayoutHistoryView for path 'payout_history/<uuid:user_uuid>/'
-in serializers append PayoutHistorySerializer for classPayoutHistoryView

* Changes: The PayoutHistoryView class uses constants from the model (#3)

* Changes: The PayoutHistoryView class uses constants from the model (#4)

* Payments | Code optimization 

Change:
-base.serializer.py redefined the to_representation method for getting the currency code
-payment_accounts.serializer.py change PayoutHistorySerializer, in the sum field, instead of serializer.Serializer Method Field, we use MoneySerializer
-payment_accounts.views.py change PayoutHistoryView and delete PayoutHistoryPagination

* Payments | Add VNE003 (#6)

* Serialiser

* Serialiser 2

* Change:
-base.serializer.py redefined the to_representation method for getting the currency code

* add # noqa: VNE003

* Payments | Add payout_day_of_month validation (#340)

* Payments| Correction of an error when creating an account whose UUID is already in the database

Payments| The create method in the UserAccountAPIView class has been redefined. Changed the error returned when creating an account that already exists in the database

* Deleted else

* Payments| Add payout history view

Changes:
-in urls append path 'payout_history/<uuid:user_uuid>/'
-in views append class PayoutHistoryPagination and PayoutHistoryView for path 'payout_history/<uuid:user_uuid>/'
-in serializers append PayoutHistorySerializer for classPayoutHistoryView

* Changes: The PayoutHistoryView class uses constants from the model (#3)

* Changes: The PayoutHistoryView class uses constants from the model (#4)

* Payments | Code optimization 

Change:
-base.serializer.py redefined the to_representation method for getting the currency code
-payment_accounts.serializer.py change PayoutHistorySerializer, in the sum field, instead of serializer.Serializer Method Field, we use MoneySerializer
-payment_accounts.views.py change PayoutHistoryView and delete PayoutHistoryPagination

* Payments | Add VNE003 (#6)

* Serialiser

* Serialiser 2

* Change:
-base.serializer.py redefined the to_representation method for getting the currency code

* add # noqa: VNE003

* Payments | Add payout_day_of_month validation 

Validation for the maximum date (max=28) and minimum date (min=1) has been added to the payout_day_of_month field

* Payments | Added migrations

* Payments | Changed to viesets  (#341)


---------

Co-authored-by: SouLWorkeR <prosto2002vitalik@gmail.com>

* Payments | Refactor serializers (#358)

* Serializers (#11)

- Method to_representation of MoneyAmountSerializerField check for exception before return response
- Created CurrencySerializer: MoneySerializer, AmountPayoutSerializer inherit from it
- Moved AmountPayoutSerializer to based serializers
- Added dataclass YookassaMoneyDataClass
- Added support to yookassa for new serializers

* - set business_settings to default values

* Payments | Added celery task auto payout (#344)

* added celery task auto payout, and django signal to change payday in the database

* Payments | Del user and added balance refill history (#369)

* renamed serializer and view

* Payments | PaymentCommission v2 (#362)


---------

Co-authored-by: koval.dmitriy <Vjkj3bkmyjtzqwj>

* Payments | Fix bug balances (#373)

* fix post balance bug

* - Renamed PayoutSerializer to WithdrawSerializer and removed payout_destination_data from it< (#376)

- YookassaPayoutModel to inherit from WithdrawModel representation for WithdrawSerializer
- PayoutProcessor fetch payout data from db for user request
- yookassa service create_payout_data with combination of WithdrawModel and PayoutDestination
- PayoutProcessor expect to receive WithdrawModel instance and later fetch PayoutData by himself not from serializer
- In PayoutView more expected 404 for more verbose error

* rename serializer (#392)

* Payments | Permissions with gspot-django-auth (#384)

* added user permission with gspot-django-auth

* changed authentication_classes

* update gspot-django-auth==0.1.4

---------

Co-authored-by: koval.dmitriy <Vjkj3bkmyjtzqwj>
Co-authored-by: Коваль Дмитрий <koval.dmitriy@stemsc.com>
Co-authored-by: SouLWorkeR <prosto2002vitalik@gmail.com>

---------

Co-authored-by: Omelchenko Michael <socanime@gmail.com>
Co-authored-by: Evgeniy Alehnovich <evgeniy_alehnovich@proton.me>
Co-authored-by: range <alexadush@yandex.ru>
Co-authored-by: fenx4 <phenx4@gmail.com>
Co-authored-by: fenx4 <127792143+fenx4@users.noreply.github.com>
Co-authored-by: RS <107695726+SultanovRuslan86@users.noreply.github.com>
Co-authored-by: range-kun <64254111+range-kun@users.noreply.github.com>
Co-authored-by: SalimAliev <128320682+SalimAliev@users.noreply.github.com>
Co-authored-by: Criativve <35040312+Criativve@users.noreply.github.com>
Co-authored-by: Uzhn <114041199+Uzhn@users.noreply.github.com>
Co-authored-by: Коваль Дмитрий <koval.dmitriy@stemsc.com>
  • Loading branch information
12 people authored Sep 18, 2023
1 parent 67bc9c3 commit 3914ef7
Show file tree
Hide file tree
Showing 96 changed files with 4,478 additions and 206 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/payments_action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
run: pip install -r backend/payments/flake8-requirements.txt
- name: Test with flake8
run: |
cd backend/payments && python -m flake8 --ignore=E501
cd backend/payments && python -m flake8 --ignore=W503 --max-line-length=100
- name: Build and run containers
run: |
cd backend/payments && docker-compose up -d --build --env-file ./.env.example
9 changes: 0 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,3 @@ make.bat

doc-dev
.vscode/*

# users ignore
backend/users/static
backend/users/logs
backend/users/media
backend/users/db
backend/users/venv
backend/users/env
backend/users/.env
25 changes: 22 additions & 3 deletions backend/payments/.env.example
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
#djagno
SECRET_KEY='django'
DEBUG=True
ALLOWED_HOSTS='*'
JWT_SECRET_KEY='Token'
account_id=111111
shop_secret_key='test_1111111111'
rollbar_access_token='1111111111'

#yookassa
SHOP_ACCOUNT_ID=111111
SHOP_SECRET_KEY='test_1111111111'
GATE_AWAY_ACCOUNT_ID=123456
GATE_AWAY_SECRET_KEY=your_gate_away_secret_key

#logger
ROLLBAR_ACCESS_TOKEN='1111111111'

#database

POSTGRES_PASSWORD=postgres
POSTGRES_DB=payment
POSTGRES_USER=postgres
POSTGRES_PORT=5432
POSTGRES_HOST=payments_db

#redis
REDIS='redis://redis:6379/'

#node
SUBDOMAIN='yoursubdomain'

#services urls
GAMES_DOMAIN='https://alpha.g-spot.website/api/v*/games'
GAMES_REFUND='/refund_url'
CANCEL_GIFT='/cancel_gift_url'
3 changes: 3 additions & 0 deletions backend/payments/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/payment_response_example.py
/static
celerybeat-schedule
49 changes: 32 additions & 17 deletions backend/payments/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
files: 'backend/payments*'
repos:
- repo: https://github.com/pycqa/flake8.git
rev: 6.0.0
hooks:
- id: flake8
args: [
"--ignore=E501"
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
args: [--skip-string-normalization, --line-length=100]
language_version: python3.11
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.4.0
hooks:
- id: add-trailing-comma
- repo: https://github.com/timothycrosley/isort
rev: 5.12.0
hooks:
- id: isort
args: [--profile=black]
- repo: https://github.com/pycqa/flake8.git
rev: 6.0.0
hooks:
- id: flake8
args: [
"--max-line-length=100", '--ignore=W503'
]
additional_dependencies: [
"flake8-bugbear",
"flake8-builtins",
"pep8-naming",
"flake8-commas",
"flake8-quotes",
"flake8-todo",
"flake8-django",
"flake8-cognitive-complexity",
]
additional_dependencies: [
"flake8-bugbear",
"flake8-builtins",
"pep8-naming",
"flake8-commas",
"flake8-quotes",
"flake8-todo",
"flake8-django",
"flake8-cognitive-complexity",
"flake8-isort",
]
22 changes: 22 additions & 0 deletions backend/payments/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM python:3.11-slim AS builder

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential libpq-dev \
&& rm -rf /var/lib/apt/lists/*

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

RUN useradd -U app \
&& mkdir -p /home/app/web/static \
&& chown -R app:app /home/app

WORKDIR /home/app/web
COPY --chown=app:app . .

EXPOSE 8000

CMD ["sh", "./scripts/entrypoint.sh"]
43 changes: 37 additions & 6 deletions backend/payments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ Django image reads settings from environment variables, default settings for tes
- `SECRET_KEY` - salt for hash generation. The value can be an arbitrary string.
- `DEBUG` - configuring Django to enable debug mode.
- `ALLOWED_HOSTS` - list of allowed hosts.
- `account_id` - id of your [yookassa](https://yookassa.ru/yooid/signin/step/login?origin=Checkout&returnUrl=https%3A%2F%2Fyookassa.ru%2Fmy%3Fget-auth%3Dyes) store.
- `shop_secret_key` - api key of your [yookassa](https://yookassa.ru/yooid/signin/step/login?origin=Checkout&returnUrl=https%3A%2F%2Fyookassa.ru%2Fmy%3Fget-auth%3Dyes) store.
- `rollbar_access_token` - токен ключ [rollbar](https://rollbar.com/) для логирования событий.
- `SHOP_AСCOUNT_ID` - id of your [yookassa](https://yookassa.ru/yooid/signin/step/login?origin=Checkout&returnUrl=https%3A%2F%2Fyookassa.ru%2Fmy%3Fget-auth%3Dyes) store.
- `SHOP_SECRET_KEY` - api key of your [yookassa](https://yookassa.ru/yooid/signin/step/login?origin=Checkout&returnUrl=https%3A%2F%2Fyookassa.ru%2Fmy%3Fget-auth%3Dyes) store.
- `ROLLBAR_ACCESS_TOKEN` - token [rollbar](https://rollbar.com/) for logging events.
- `POSTGRES_DB` - db of postgres.
- `POSTGRES_USER` - user for postgres.
- `POSTGRES_PASSWORD` - password for postgres.
- `POSTGRES_PORT` - port for postgres.
- `POSTGRES_HOST` - host for postgres, if local - localhost, if docker - name of container.
- `REDIS` - broker for celery, variable in **settings.py -> CELERY_BROKER_URL**.
- `SUBDOMAIN` - for localtunnel, use it for yookassa.
- `GAMES_DOMAIN` - game service domain.
- `GAMES_REFUND` - send message for change frozen status to service games.

## How to run local-version

Expand All @@ -27,7 +29,7 @@ Django image reads settings from environment variables, default settings for tes

```shell
python -m venv venv ## windows
./venv/scripts/activavte ## windows
./venv/scripts/activate ## windows

virtualenv venv ## linux
source ../venv/bin/activate ## linux
Expand Down Expand Up @@ -79,7 +81,7 @@ Subsequently, all indexed files will be checked with `Flake8` before committing.

To check with `Flake8` the files indexed for the commit run:
```shell
pre-commit run
pre-commit run --all-files
```
If it's necessary to skip using `pre-commit hook`, the commit should run with the `-n` or `--no-verify` flag:
```shell
Expand Down Expand Up @@ -156,4 +158,33 @@ Or if you start project local you need to use [`ngrok`](https://ngrok.com/) or n
5. At last, you need to put this link in yookassa settings and you're done:

![alt text](https://i.pinimg.com/originals/90/1a/27/901a279e9df3b0da2bcac4f236fc3a4b.png)
-

## Fixtures

Our app has fixtures:
- base - fixtures with commissions for services
- test - test data to test our app

### Linux

Base fixtures run in entrypoint for container but you also can run them by your own:

```shell
python manage.py apps/base/fixtures/base/*.json
```

Test fixtures don't apply automatically you need to run them by command:

```shell
python manage.py apps/base/fixtures/test/*.json
```

### Windows

If you use Windows, you can't apply all fixtures by one command, you need to apply them by one, for example:

```shell
python manage.py apps/base/fixtures/test/invoices.json
```

---
Empty file.
59 changes: 59 additions & 0 deletions backend/payments/apps/base/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from abc import ABC, abstractmethod

import rollbar
from apps.base.exceptions import DifferentStructureError
from dacite import from_dict


class AbstractPaymentService(ABC):
@abstractmethod
def request_balance_deposit_url(self, payment_data):
pass

@abstractmethod
def handel_payment_response(self):
pass

@abstractmethod
def parse_income_data(self, **kwargs):
pass

@abstractmethod
def validate_income_data(self, parsed_data):
pass


class AbstractPayoutService(ABC):
@abstractmethod
def request_payout(self, payout_data):
pass


class DRFtoDataClassMixin:
def convert_data(self, request, dataclass_model):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return self.__convert_drf_to_dataclass(dataclass_model, serializer)

def __convert_drf_to_dataclass(self, data_model, serializer: dict):
# TODO change to pydantic, add typehint for pydantic model # noqa: T000
try:
data_model_data = from_dict(
data_model,
serializer.validated_data,
)
except AttributeError:
data_model_data = data_model(**serializer.validated_data)
except KeyError as error:
rollbar.report_message(
f'Schemas and serializers got different structure. Got next error: {str(error)}',
'error',
)
raise DifferentStructureError
return data_model_data


class ListAdminMixin(object):
def __init__(self, model, admin_site):
self.list_display = [field.name for field in model._meta.fields]
super(ListAdminMixin, self).__init__(model, admin_site)
6 changes: 6 additions & 0 deletions backend/payments/apps/base/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AttemptsLimitExceededError(Exception):
pass


class DifferentStructureError(Exception):
pass
101 changes: 101 additions & 0 deletions backend/payments/apps/base/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from django.conf import settings
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db.models import DecimalField
from djmoney.models import fields
from rest_framework import serializers


class MoneyField(fields.MoneyField):
def __init__(
self,
verbose_name=None,
name=None,
max_digits=settings.MAX_BALANCE_DIGITS,
default_currency=settings.DEFAULT_CURRENCY,
decimal_places=2,
default=fields.Money('0.00', settings.DEFAULT_CURRENCY), # noqa B008
**kwargs,
):
super().__init__(
verbose_name=verbose_name,
name=name,
max_digits=max_digits,
default_currency=default_currency,
decimal_places=decimal_places,
default=default,
**kwargs,
)


class CommissionField(DecimalField):
def __init__(
self,
verbose_name=None,
name=None,
max_digits=5,
decimal_places=2,
default=0,
**kwargs,
):
kwargs['validators'] = (
MinValueValidator(0, message='Should be positive value'),
MaxValueValidator(
100,
message=f'Should be not greater than {100}',
),
)

super().__init__(
verbose_name=verbose_name,
name=name,
max_digits=max_digits,
decimal_places=decimal_places,
default=default,
**kwargs,
)


class MoneyAmountSerializerField(serializers.DecimalField):
def __init__(
self,
min_value=0,
max_digits=settings.MAX_BALANCE_DIGITS,
decimal_places=2,
**kwargs,
):
super().__init__(
max_digits,
decimal_places,
min_value,
**kwargs,
)

def to_representation(self, obj):
try:
value = super().to_representation(obj.value)
except AttributeError:
value = super().to_representation(obj)
return value

def to_internal_value(self, data):
amount = super().to_internal_value(data)
return amount

def get_value(self, dictionary):
return dictionary.get(f'{self.field_name}')


class CommissionSerializerField(serializers.DecimalField):
def __init__(
self,
min_value=0,
max_value=100,
decimal_places=2,
**kwargs,
):
super().__init__(
min_value,
max_value,
decimal_places,
**kwargs,
)
Loading

0 comments on commit 3914ef7

Please sign in to comment.