import datetime from flask import Blueprint, request, jsonify from flask_jwt_extended import get_jwt_identity from sqlalchemy.orm import joinedload import database from database.enums import AssemblyState from routes.utils import jwt_protect_blueprint import sipro.api.orders import utils.balance assembly_blueprint = jwt_protect_blueprint(Blueprint('assembly', __name__)) @assembly_blueprint.post('/create') def create_assembly(): try: data: dict = request.json order_id: int = data.get('orderId') user_id = get_jwt_identity() existing_assembly = (database.Assembly.query. options(joinedload(database.Assembly.user)). filter_by(order_id=order_id). first()) if existing_assembly: response = { 'ok': False, 'message': 'Сборка этого товара уже была запущена', 'assemblyId': existing_assembly.id, 'statusCode': 'ASSEMBLY_ALREADY_EXISTS', 'userName': existing_assembly.user.login } return jsonify(response) need_crpt_for_order_response = sipro.api.orders.need_crpt_by_order_id(order_id) need_crpt_value = need_crpt_for_order_response.get('needCrpt') if need_crpt_value: valid_app = request.headers.get('CrptAvailable') if not valid_app: response = { 'ok': False, 'message': 'Для сборки этого заказа необходимо приложение с поддержкой Честного Знака', 'assemblyId': -1, 'statusCode': 'USER_ALREADY_HAS_ACTIVE_ASSEMBLY', } return jsonify(response) active_assembly = database.Assembly.query.filter(database.Assembly.user_id == user_id, database.Assembly.is_active == True).first() if active_assembly: response = { 'ok': False, 'message': 'Вы не можете запустить сборку заказа, так как у вас уже есть активная сборка', 'assemblyId': active_assembly.id, 'statusCode': 'USER_ALREADY_HAS_ACTIVE_ASSEMBLY' } return jsonify(response) assembled_assembly = ( database.Assembly.query .filter( database.Assembly.order_id == order_id, database.Assembly.ended_at != None ) .first() ) if assembled_assembly: response = { 'ok': False, 'message': 'Вы уже собирали этот товар', 'assemblyId': assembled_assembly.id, 'statusCode': 'USER_ALREADY_HAS_ACTIVE_ASSEMBLY', } return jsonify(response) assembly = database.Assembly(user_id=user_id, order_id=order_id, state=AssemblyState.NOT_STARTED, created_at=datetime.datetime.now(), is_active=True) database.db.session.add(assembly) database.db.session.commit() response = { 'ok': True, 'message': 'Сборка успешно запущена!', 'assemblyId': assembly.id, 'statusCode': 'CREATED' } return jsonify(response) except Exception as e: response = { 'ok': False, 'message': f'Неизвестная ошибка: {e}', 'assemblyId': -1, 'statusCode': 'INVALID_EXCEPTION' } return jsonify(response) def close_assembly_by_id( assembly_id: int, ): if not assembly_id or (not isinstance(assembly_id, int)): response = { 'ok': False, 'message': 'Неверно указан ID сборки' } return jsonify(response) assembly = database.db.session.get(database.Assembly, assembly_id) if not assembly: response = { 'ok': False, 'message': 'Указанная сборка не найдена' } return jsonify(response) assembly.is_active = False assembly.ended_at = datetime.datetime.now() database.db.session.commit() order_id = assembly.order_id sipro_response = sipro.api.orders.close_order(order_id) reward = sipro_response.get('reward') ok = sipro_response.get('ok') if ok: utils.balance.add_top_up(user_id=assembly.user_id, amount=reward, description=f'Начисление за сборку заказа {order_id}', json_data={'order_id': order_id}, commit=True) return sipro_response @assembly_blueprint.post('/close') def close_assembly(): args = request.json assembly_id = args.get('assemblyId') sipro_response = close_assembly_by_id(int(assembly_id)) return sipro_response @assembly_blueprint.post('/cancel') def cancel_assembly(): try: user_id = get_jwt_identity() assembly = database.Assembly.query.filter(database.Assembly.user_id == user_id, database.Assembly.is_active == True).first() if not assembly: response = { 'ok': False, 'message': 'У вас нет активных сборок' } return jsonify(response) order_id = assembly.order_id sipro_response = sipro.api.orders.cancel_order_assembly(order_id) if not sipro_response.get('ok'): response = { 'ok': False, 'message': f'Ошибка: {sipro_response.get("message")}' } return jsonify(response) database.db.session.delete(assembly) database.db.session.commit() response = { 'ok': True, 'message': 'Сборка успешно отменена!' } return jsonify(response) except Exception as e: response = { 'ok': False, 'message': f'Неизвестная ошибка: {e}' } return jsonify(response) @assembly_blueprint.post('/cancelById') def cancel_assembly_by_id(): try: assembly_id = request.json.get('assemblyId') assembly = database.db.session.get(database.Assembly, assembly_id) if not assembly: response = { 'ok': False, 'message': f'Сборка {assembly_id} не найдена' } return jsonify(response) database.db.session.delete(assembly) database.db.session.commit() response = { 'ok': True, 'message': f'Сборка {assembly_id} успешно отменена!' } return jsonify(response) except Exception as e: response = { 'ok': False, 'message': f'Неудалось отменить сборку, ошибка: {e}' } return jsonify(response) @assembly_blueprint.get('/hasActive') def user_has_active_assembly(): user_id = get_jwt_identity() assemblies_count = database.Assembly.query.filter(database.Assembly.user_id == user_id, database.Assembly.is_active == True).count() return jsonify(has=assemblies_count > 0) @assembly_blueprint.get('/getActive') def get_active_assembly(): user_id = get_jwt_identity() assembly = database.Assembly.query.filter(database.Assembly.user_id == user_id, database.Assembly.is_active == True).first() response = { 'databaseId': assembly.id, 'createdAt': str(assembly.created_at), 'endedAt': str(assembly.ended_at), 'orderId': assembly.order_id, 'isActive': assembly.is_active, 'state': assembly.state } return jsonify(response) @assembly_blueprint.post('/confirmCurrent') def confirm_current_assembly(): # confirm current assembly for user user_id = get_jwt_identity() assembly = database.Assembly.query.filter(database.Assembly.user_id == user_id, database.Assembly.is_active == True).first() if not assembly: response = { 'ok': False, 'message': 'У вас нет активных сборок' } return jsonify(response) close_assembly_by_id(assembly.id) response = { 'ok': True, 'message': 'Сборка успешно завершена!', } return response @assembly_blueprint.post('/confirm') def confirm_assembly(): user_id = get_jwt_identity() args: dict = request.json assembly_id = args.get('assemblyId') if not assembly_id or (not isinstance(assembly_id, int)): response = { 'ok': False, 'message': 'ID сборки указан неверно' } return jsonify(response) assembly = database.db.session.get(database.Assembly, assembly_id) if not assembly: response = { 'ok': False, 'message': 'Неудалось найти указанную сборку' } return jsonify(response) if assembly.user_id != user_id: response = { 'ok': False, 'message': 'Вы не можете закрыть сборку чужого пользователя' } return jsonify(response) order_id = assembly.order_id return sipro.api.orders.ship_order(order_id) @assembly_blueprint.post('/updateState') def update_assembly_state(): try: args = request.json state = args.get('state') assembly_id = args.get('assemblyId') rows_to_update = [{ 'id': assembly_id, 'state': state }] database.db.session.bulk_update_mappings(database.Assembly, rows_to_update) database.db.session.commit() return jsonify(ok=True) except Exception as e: print('Error while updating') return jsonify(ok=False) @assembly_blueprint.get('/needCrpt') def need_crpt(): order_product_id = request.args.get('orderProductId') return sipro.api.orders.need_crpt(order_product_id) @assembly_blueprint.post('/attachCrpt') def attach_crpt(): order_product_id = request.json.get('orderProductId') crpt = request.json.get('crpt') return sipro.api.orders.attach_crpt(order_product_id, crpt)