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, PaginationDependency 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, user_deals_viewer, user_deal_editor 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.post( '/summaries', response_model=CardSummaryResponse, operation_id='getCardSummaries', ) async def get_summary( session: Annotated[AsyncSession, Depends(get_session)], request: GetCardSummariesRequest, pagination: PaginationDependency, user: CurrentUserDependency, ): return await CardsService(session).get_summary(request, pagination, user) @card_router.post( '/summaries/reorder', response_model=ReorderResponse, 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', ) async def update_products_and_services_general_info( request: ProductsAndServicesGeneralInfoRequest, session: Annotated[AsyncSession, Depends(get_session)], user: CurrentUserDependency, ): return await CardsService(session).update_products_and_services_general_info(request, user) @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, ): return await CardsService(session).create_guest_url(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', dependencies=[Depends(user_deal_editor)], ) 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', dependencies=[Depends(user_deal_editor)], ) 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', dependencies=[Depends(authorized_user)] ) 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', dependencies=[Depends(authorized_user)], ) 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