import base64 from io import BytesIO from typing import Annotated from fastapi import APIRouter, Depends, Response, UploadFile from sqlalchemy.ext.asyncio import AsyncSession from backend.dependecies import SessionDependency, CurrentUserDependency from backend.session import get_session from generators.deal_pdf_generator.generator import DealTechSpecPdfGenerator from models import User from parsers import DealParser from schemas.barcode import GetCardProductsBarcodesPdfRequest, GetCardProductsBarcodesPdfResponse from schemas.card import * from services.auth import get_current_user, authorized_user, guest_user from services.barcode import BarcodeService from services.billing import BillingService from services.card import CardsService card_router = APIRouter( prefix='/card', tags=['card'], ) # region Card @card_router.post( '/delete', response_model=CardDeleteResponse, operation_id='deleteCard', dependencies=[Depends(authorized_user)] ) async def delete( request: CardDeleteRequest, session: Annotated[AsyncSession, Depends(get_session)] ): return await CardsService(session).delete(request) @card_router.post( '/complete', response_model=CardCompleteResponse, operation_id='completeCard', dependencies=[Depends(authorized_user)] ) async def complete( request: CardCompleteRequest, session: SessionDependency, user: CurrentUserDependency ): return await CardsService(session).complete(user, request) @card_router.post( '/quickCreate', response_model=CardQuickCreateResponse, dependencies=[Depends(authorized_user)] ) async def quick_create( request: CardQuickCreateRequest, session: Annotated[AsyncSession, Depends(get_session)], user: Annotated[User, Depends(get_current_user)] ): return await CardsService(session).quick_create(request, user) @card_router.post( '/changeStatus', response_model=CardChangeStatusResponse, dependencies=[Depends(authorized_user)] ) async def change_status( request: CardChangeStatusRequest, session: Annotated[AsyncSession, Depends(get_session)], user: Annotated[User, Depends(get_current_user)] ): return await CardsService(session).change_status_manual(request, user) @card_router.get( '/summaries', response_model=CardSummaryResponse, operation_id='getCardSummaries', dependencies=[Depends(authorized_user)] ) async def get_summary( session: Annotated[AsyncSession, Depends(get_session)], full: Optional[bool] ): return await CardsService(session).get_summary(full) @card_router.post( '/summaries/reorder', response_model=CardSummaryResponse, operation_id='reorderCardSummaries', dependencies=[Depends(authorized_user)] ) async def reorder( session: Annotated[AsyncSession, Depends(get_session)], request: CardSummaryReorderRequest, user: Annotated[User, Depends(get_current_user)] ): return await CardsService(session).reorder(request, user) @card_router.get( '/get-all', response_model=CardGetAllResponse, operation_id='getAllCards', dependencies=[Depends(authorized_user)] ) async def get_all( session: Annotated[AsyncSession, Depends(get_session)] ): return await CardsService(session).get_all() # endpoint to get card by id @card_router.get( '/get/{card_id}', response_model=CardSchema, operation_id='getCardById', dependencies=[Depends(guest_user)] ) async def get_card_by_id( card_id: int, user: CurrentUserDependency, session: Annotated[AsyncSession, Depends(get_session)] ): return await CardsService(session).get_by_id(user, card_id) @card_router.post( '/update-general-info', response_model=CardUpdateGeneralInfoResponse, operation_id='update_card_general_info', dependencies=[Depends(authorized_user)] ) async def update_general_info( request: CardUpdateGeneralInfoRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency, ): return await CardsService(session).update_general_info(request, user) @card_router.post( '/update-products-and-services-general-info', response_model=ProductsAndServicesGeneralInfoResponse, operation_id='update_products_and_services_general_info', dependencies=[Depends(authorized_user)] ) async def update_products_and_services_general_info( request: ProductsAndServicesGeneralInfoRequest, session: Annotated[AsyncSession, Depends(get_session)], ): return await CardsService(session).update_products_and_services_general_info(request) @card_router.post( '/update-card-manager', response_model=UpdateCardManagerResponse, operation_id='update_card_manager', dependencies=[Depends(authorized_user)] ) async def update_card_manager( request: UpdateCardManagerRequest, session: Annotated[AsyncSession, Depends(get_session)], ): return await CardsService(session).update_card_manager(request) @card_router.post( '/update-card-client', response_model=UpdateCardClientResponse, operation_id='update_card_client', dependencies=[Depends(authorized_user)] ) async def update_card_client( request: UpdateCardClientRequest, session: Annotated[AsyncSession, Depends(get_session)], ): return await CardsService(session).update_card_client(request) @card_router.post( '/add-kit', response_model=CardAddKitResponse, operation_id='add_kit_to_card' ) async def add_kit_to_card( session: SessionDependency, request: CardAddKitRequest ): return await CardsService(session).add_kit_to_card(request) @card_router.post( '/create-guest-url', response_model=CardCreateGuestUrlResponse, operation_id='create_deal_guest_url', dependencies=[Depends(authorized_user)] ) async def create_guest_url( session: SessionDependency, request: CardCreateGuestUrlRequest, user: CurrentUserDependency ): return CardsService(session).create_guest_url(user, request) @card_router.get( '/billing-document/{deal_id}', operation_id='get_billing_document', # dependencies=[Depends(authorized_user)], ) async def get_billing_document( deal_id: int, session: Annotated[AsyncSession, Depends(get_session)], ): pdf_file: BytesIO = await BillingService(session).create_billing_document_pdf(deal_id) return Response(pdf_file.getvalue(), media_type='application/pdf') @card_router.get( '/tech-spec/{deal_id}', operation_id='get_deal_tech_spec', # dependencies=[Depends(authorized_user)], ) async def get_deal_tech_spec( deal_id: int, session: Annotated[AsyncSession, Depends(get_session)], ): pdf_file: BytesIO = await DealTechSpecPdfGenerator(session).create_deal_tech_spec_pdf(deal_id) return Response(pdf_file.getvalue(), media_type='application/pdf') @card_router.post( '/prefill', response_model=CardPrefillResponse, operation_id='prefill_card', dependencies=[Depends(authorized_user)] ) async def post_prefill_card( session: SessionDependency, request: CardPrefillRequest, user: CurrentUserDependency ): return await CardsService(session).prefill_card_products_and_services(user, request) @card_router.post( '/recalculate-price', response_model=CardRecalculatePriceResponse, operation_id='recalculate_card_price', ) async def recalculate_card_price( session: SessionDependency, request: CardRecalculatePriceRequest, ): return await CardsService(session).recalculate_price(request) @card_router.post( '/employee', response_model=ManageEmployeeResponse, operation_id='manage_employee', ) async def manage_employee( session: SessionDependency, request: ManageEmployeeRequest, ): return await CardsService(session).manage_employee(request) @card_router.get( '/employee/available/{card_id}', response_model=GetAvailableEmployeesToAssignResponse, operation_id='get_available_employees_to_assign', ) async def get_available_employees_to_assign( session: Annotated[AsyncSession, Depends(get_session)], card_id: int, ): return await CardsService(session).get_available_employees_to_assign(card_id) @card_router.post( '/prefill/excel/parse', response_model=ParseCardsExcelResponse, operation_id='parse_deals_excel', ) async def parse_deals_excel( session: Annotated[AsyncSession, Depends(get_session)], upload_file: UploadFile, ): file_bytes = upload_file.file.read() return await DealParser(session).parse(file_bytes) @card_router.post( '/prefill/excel/create', response_model=CreateCardsFromExcelResponse, operation_id='create_deals_excel', ) async def create_deals_from_excel( session: Annotated[AsyncSession, Depends(get_session)], request: CreateCardsFromExcelRequest, user: CurrentUserDependency, ): return await CardsService(session).create_cards_from_excel(request, user) # endregion # region Card services @card_router.post( '/services/add/multiple', response_model=CardAddServicesResponse, operation_id='add_multiple_card_services', dependencies=[Depends(guest_user)] ) async def services_add( request: CardAddServicesRequest, session: Annotated[AsyncSession, Depends(get_session)], ): return await CardsService(session).add_services(request) @card_router.post( '/services/add', response_model=CardAddServiceResponse, operation_id='add_card_service', dependencies=[Depends(guest_user)] ) async def services_add( request: CardAddServiceRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).add_service(user, request) @card_router.post( '/services/update-quantity', response_model=CardUpdateServiceQuantityResponse, operation_id='update_card_service_quantity', dependencies=[Depends(guest_user)] ) async def services_update_quantity( request: CardUpdateServiceQuantityRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).update_service_quantity(user, request) @card_router.post( '/services/update', response_model=CardUpdateServiceResponse, operation_id='update_card_service', dependencies=[Depends(guest_user)] ) async def services_update( request: CardUpdateServiceRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).update_service(user, request) @card_router.post( '/services/delete', response_model=CardDeleteServiceResponse, operation_id='delete_card_service', dependencies=[Depends(guest_user)] ) async def services_delete( request: CardDeleteServiceRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).delete_service(user, request) @card_router.post( '/services/delete/multiple', response_model=CardDeleteServicesResponse, operation_id='delete_multiple_card_services', dependencies=[Depends(guest_user)] ) async def services_delete( request: CardDeleteServicesRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).delete_services(user, request) @card_router.post( '/services/copy', response_model=CardServicesCopyResponse, operation_id='copy_product_services', dependencies=[Depends(guest_user)] ) async def services_copy( session: SessionDependency, request: CardServicesCopyRequest, user: CurrentUserDependency ): return await CardsService(session).copy_services(user, request) # endregion # region Card products @card_router.post( '/products/update-quantity', response_model=CardUpdateProductQuantityResponse, operation_id='update_card_product_quantity', dependencies=[Depends(guest_user)] ) async def products_update( request: CardUpdateProductQuantityRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).update_product_quantity(user, request) @card_router.post( '/products/add', response_model=CardAddProductResponse, operation_id='add_card_product', dependencies=[Depends(guest_user)] ) async def products_add( request: CardAddProductRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).add_product(user, request) @card_router.post( '/products/delete', response_model=CardDeleteProductResponse, operation_id='delete_card_product', dependencies=[Depends(guest_user)] ) async def products_delete( request: CardDeleteProductRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).delete_product(user, request) @card_router.post( '/products/delete/multiple', response_model=CardDeleteProductsResponse, operation_id='delete_multiple_card_products', dependencies=[Depends(guest_user)] ) async def products_delete( request: CardDeleteProductsRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).delete_products(user, request) @card_router.post( '/product/update', response_model=CardUpdateProductResponse, operation_id='update_card_product', dependencies=[Depends(guest_user)] ) async def products_update( request: CardUpdateProductRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency ): return await CardsService(session).update_product(user, request) @card_router.post( '/product/add-kit', response_model=CardProductAddKitResponse, operation_id='add_kit_to_card_product', dependencies=[Depends(guest_user)] ) async def add_kit_to_card_product( session: SessionDependency, request: CardProductAddKitRequest, user: CurrentUserDependency ): return await CardsService(session).add_kit_to_card_product(user, request) @card_router.post( '/barcodes/get-pdf', operation_id='get_card_products_barcodes_pdf', response_model=GetCardProductsBarcodesPdfResponse ) async def get_card_products_barcodes_pdf( request: GetCardProductsBarcodesPdfRequest, session: Annotated[AsyncSession, Depends(get_session)] ): filename, pdf_buffer = await BarcodeService(session).get_card_barcodes_pdf(request) pdf_buffer: BytesIO base64_string = base64.b64encode(pdf_buffer.read()).decode('utf-8') return GetCardProductsBarcodesPdfResponse( base64_string=base64_string, filename=filename, mime_type='application/pdf' ) # endregion