From 1d2ee676ff9960f243b04e4e9d73523469b30f5b Mon Sep 17 00:00:00 2001 From: fakz9 Date: Fri, 27 Oct 2023 06:04:15 +0300 Subject: [PATCH] ebanutsya --- .gitignore | 1 + app.py | 10 ++++++++-- assemblr.log | 12 ++++++++++++ config.py | 2 +- constants.py | 9 +++++++++ database/models.py | 14 ++++++++++++++ logger.py | 34 ++++++++++++++++++++++++++++++++++ routes/__init__.py | 2 ++ routes/auth.py | 13 +++---------- routes/barcode.py | 12 ++++++++++++ routes/orders.py | 17 +++++++++++++++++ routes/utils.py | 12 ++++++++++++ settings.py | 4 ++++ singleton.py | 7 +++++++ sipro/__init__.py | 1 + sipro/api/__init__.py | 0 sipro/api/barcode.py | 10 ++++++++++ sipro/api/client.py | 39 +++++++++++++++++++++++++++++++++++++++ sipro/api/orders.py | 10 ++++++++++ 19 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 assemblr.log create mode 100644 constants.py create mode 100644 logger.py create mode 100644 routes/barcode.py create mode 100644 routes/orders.py create mode 100644 routes/utils.py create mode 100644 singleton.py create mode 100644 sipro/__init__.py create mode 100644 sipro/api/__init__.py create mode 100644 sipro/api/barcode.py create mode 100644 sipro/api/client.py create mode 100644 sipro/api/orders.py diff --git a/.gitignore b/.gitignore index cda00b8..7f536a4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ __pycache__/ .git/ .env test.* +test/ diff --git a/app.py b/app.py index e597f91..405e5b4 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,4 @@ -from flask import Flask +from flask import Flask, request from flask_cors import CORS from flask_jwt_extended import JWTManager from flask_migrate import Migrate @@ -23,9 +23,15 @@ server_session = Session(app) CORS(app, supports_credentials=True) jwt = JWTManager(app) blueprints = [ - (routes.auth_blueprint, '/auth') + (routes.auth_blueprint, '/auth'), + (routes.orders_blueprint, '/orders'), + (routes.barcode_blueprint, '/barcode'), ] + + + + for blueprint, url_prefix in blueprints: app.register_blueprint(blueprint, url_prefix=url_prefix) diff --git a/assemblr.log b/assemblr.log new file mode 100644 index 0000000..0082954 --- /dev/null +++ b/assemblr.log @@ -0,0 +1,12 @@ +10-15 00:21 - assemblr - INFO - SiproClient successfully initialized +10-15 00:31 - assemblr - INFO - SiproClient successfully initialized +10-15 00:31 - assemblr - INFO - SiproClient successfully initialized +10-15 00:31 - assemblr - INFO - SiproClient successfully initialized +10-15 00:31 - assemblr - INFO - SiproClient successfully initialized +10-27 03:01 - assemblr - INFO - SiproClient successfully initialized +10-27 04:50 - assemblr - INFO - SiproClient successfully initialized +10-27 04:51 - assemblr - INFO - SiproClient successfully initialized +10-27 05:36 - assemblr - INFO - SiproClient successfully initialized +10-27 05:37 - assemblr - INFO - SiproClient successfully initialized +10-27 05:38 - assemblr - INFO - SiproClient successfully initialized +10-27 05:57 - assemblr - INFO - SiproClient successfully initialized diff --git a/config.py b/config.py index 7a5380e..28926f4 100644 --- a/config.py +++ b/config.py @@ -17,5 +17,5 @@ class FlaskConfig: SESSION_PERMANENT = False SESSION_USE_SIGNER = True SESSION_REDIS = redis.from_url('redis://127.0.0.1:6379') - + JWT_ACCESS_TOKEN_EXPIRES = 86400 # SQLALCHEMY_ECHO = True diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..b351fe0 --- /dev/null +++ b/constants.py @@ -0,0 +1,9 @@ +from pathlib import Path +import os +import sys + +APP_PATH = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) else os.path.dirname(__file__) + +LOGGER_NAME = 'assemblr' +LOG_FILE = Path(APP_PATH) / Path(f'{LOGGER_NAME}.log') +MAX_LOG_FILE_SIZE_BYTES = 400 * 1024 ** 2 diff --git a/database/models.py b/database/models.py index 22db4a5..a4b41f8 100644 --- a/database/models.py +++ b/database/models.py @@ -13,6 +13,20 @@ class User(db.Model): sipro_id = db.Column(db.Integer, nullable=True, comment='ID пользователя в SIPRO') +class Assembly(db.Model): + __tablename__ = 'assemblies' + id = db.Column(db.Integer, primary_key=True, comment='ID сборки') + + created_at = db.Column(db.DateTime, nullable=False, comment='Дата и время начала сборки') + ended_at = db.Column(db.DateTime, nullable=False, comment='Дата и время конца сборки') + + user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) + user = db.relationship('User', backref='assemblies') + + order_id = db.Column(db.Integer, nullable=False, comment='ID заказа в базе данных') + + + class Barcode(db.Model): __tablename__ = 'barcodes' id = db.Column(db.Integer, primary_key=True, comment='ID пользователя') diff --git a/logger.py b/logger.py new file mode 100644 index 0000000..18e34c2 --- /dev/null +++ b/logger.py @@ -0,0 +1,34 @@ +from logging.handlers import RotatingFileHandler +from singleton import Singleton + +import logging +import constants + + +class Logger(metaclass=Singleton): + def __init__(self): + self.logger = logging.getLogger(constants.LOGGER_NAME) + self.logger.setLevel(logging.DEBUG) + + file_handler = RotatingFileHandler(constants.LOG_FILE, + maxBytes=constants.MAX_LOG_FILE_SIZE_BYTES, + encoding='UTF-8', + backupCount=1) + file_handler.setLevel(logging.DEBUG) + + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + + formatter = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + datefmt='%m-%d %H:%M') + file_handler.setFormatter(formatter) + console_handler.setFormatter(formatter) + + self.logger.addHandler(file_handler) + self.logger.addHandler(console_handler) + + def get_logger(self): + return self.logger + + +logger_instance = Logger().get_logger() diff --git a/routes/__init__.py b/routes/__init__.py index f88a74b..85076e3 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -1 +1,3 @@ from routes.auth import auth_blueprint +from routes.orders import orders_blueprint +from routes.barcode import barcode_blueprint diff --git a/routes/auth.py b/routes/auth.py index 5247442..4243a7d 100644 --- a/routes/auth.py +++ b/routes/auth.py @@ -29,16 +29,9 @@ def login_endpoint(): login = data.get('login') user = User.query.filter_by(login=login).first() if not user: - return jsonify(ok=False), 401 + return jsonify(ok=False, accessToken=''), 401 password = data.get('password') if not check_password_hash(user.password_hash, password): - return jsonify(ok=False), 401 + return jsonify(ok=False, accessToken=''), 401 access_token = create_access_token(identity=user.id) - return jsonify(access_token=access_token) - - -@auth_blueprint.get('/protected') -@jwt_required() -def protected_endpoint(): - print(type(get_jwt_identity())) - return 'test' + return jsonify(ok=True, accessToken=access_token) diff --git a/routes/barcode.py b/routes/barcode.py new file mode 100644 index 0000000..bb3b527 --- /dev/null +++ b/routes/barcode.py @@ -0,0 +1,12 @@ +from flask import Blueprint, jsonify, request +from routes.utils import jwt_protect_blueprint +import sipro.api.barcode + +barcode_blueprint = jwt_protect_blueprint(Blueprint('barcode', __name__)) + + +@barcode_blueprint.get('/searchProducts') +def search_product(): + args = request.args + barcode = args.get('barcode') + return sipro.api.barcode.get_products_by_barcode(barcode) diff --git a/routes/orders.py b/routes/orders.py new file mode 100644 index 0000000..d59ff0d --- /dev/null +++ b/routes/orders.py @@ -0,0 +1,17 @@ +from flask import Blueprint, jsonify, request +from routes.utils import jwt_protect_blueprint +import sipro.api.orders + +orders_blueprint = jwt_protect_blueprint(Blueprint('orders', __name__)) + + +@orders_blueprint.get('/') +def get_order(order_id: int): + return jsonify(id=order_id) + + +@orders_blueprint.get('/getBySupplierProductId') +def get_orders_by_supplier_product_id(): + args = request.args + supplier_product_id = args.get('supplierProductId') + return sipro.api.orders.get_orders_by_supplier_product_id(supplier_product_id) diff --git a/routes/utils.py b/routes/utils.py new file mode 100644 index 0000000..ee122db --- /dev/null +++ b/routes/utils.py @@ -0,0 +1,12 @@ +from functools import wraps + +from flask import Blueprint +from flask_jwt_extended import verify_jwt_in_request + + +def jwt_protect_blueprint(blueprint) -> Blueprint: + @blueprint.before_request + def require_token(): + verify_jwt_in_request() + + return blueprint diff --git a/settings.py b/settings.py index 90ea6fc..2ce642f 100644 --- a/settings.py +++ b/settings.py @@ -19,3 +19,7 @@ MY_HOST = os.environ.get('MY_HOST') # Flask settings SECRET_KEY = os.environ.get('SECRET_KEY') + +# Sipro settings +SIPRO_API_URL = os.environ.get('SIPRO_API_URL') +SIPRO_API_TOKEN = os.environ.get('SIPRO_API_TOKEN') diff --git a/singleton.py b/singleton.py new file mode 100644 index 0000000..3776cb9 --- /dev/null +++ b/singleton.py @@ -0,0 +1,7 @@ +class Singleton(type): + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instances[cls] diff --git a/sipro/__init__.py b/sipro/__init__.py new file mode 100644 index 0000000..af22d1e --- /dev/null +++ b/sipro/__init__.py @@ -0,0 +1 @@ +from sipro import api diff --git a/sipro/api/__init__.py b/sipro/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sipro/api/barcode.py b/sipro/api/barcode.py new file mode 100644 index 0000000..9b7547a --- /dev/null +++ b/sipro/api/barcode.py @@ -0,0 +1,10 @@ +from sipro.api.client import get_client + +client = get_client() +router = '/barcode' + + +def get_products_by_barcode(barcode: str) -> list[dict]: + method = f'{router}/getProducts?barcode={barcode}' + response = client.method('GET', method) + return response diff --git a/sipro/api/client.py b/sipro/api/client.py new file mode 100644 index 0000000..a3ef9c7 --- /dev/null +++ b/sipro/api/client.py @@ -0,0 +1,39 @@ +import requests + +import settings +from logger import logger_instance + + +class SiproClient: + _instance = None + + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(SiproClient, cls).__new__(cls) + return cls._instance + + def __init__(self, api_url: str, token: str): + if not hasattr(self, 'initialized'): + self.api_url = api_url + self.token = token + self.initialized = True + logger_instance.info('SiproClient successfully initialized') + + def method(self, http_method: str, method: str, data: dict = None): + url = self.api_url + '/assemblr' + method + headers = {'Authorization': self.token} + return requests.request(http_method, url, headers=headers, json=data).json() + + def ping(self) -> str: + return self.method('GET', '/ping').get('response') + + +sipro_config = { + 'api_url': settings.SIPRO_API_URL, + 'token': settings.SIPRO_API_TOKEN, +} +sipro_client = SiproClient(**sipro_config) + + +def get_client() -> SiproClient: + return sipro_client diff --git a/sipro/api/orders.py b/sipro/api/orders.py new file mode 100644 index 0000000..9fc3173 --- /dev/null +++ b/sipro/api/orders.py @@ -0,0 +1,10 @@ +from sipro.api.client import get_client + +client = get_client() +router = '/orders' + + +def get_orders_by_supplier_product_id(supplier_product_id: str) -> list[dict]: + method = f'{router}/getBySupplierProductId?supplierProductId={supplier_product_id}' + response = client.method('GET', method) + return response