# 基础资料导入导出。七个资源共用服务,路由权限必须保持字面量,供契约扫描。 from typing import Annotated from fastapi import File, Form, Query, Request, Response, UploadFile from fastapi.responses import StreamingResponse from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType from common.router import APIRouterPro from common.vo import ResponseBaseModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_business.dependency.test_batch_dependency import TestBatchScopeDependency from module_business.domain.test_batch_scope import TestBatchScope from module_business.entity.vo.master_vo import ( CustomerPageQueryModel, LinePageQueryModel, PalletPageQueryModel, SitePageQueryModel, StrainPageQueryModel, TunnelPageQueryModel, WarehousePageQueryModel, ) from module_business.service.master_excel_service import MasterExcelResource, MasterExcelService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil _EXCEL_RESPONSES = { 200: { 'description': '流式返回 excel 文件', 'content': {'application/octet-stream': {}}, } } strain_excel_controller = APIRouterPro( prefix='/master/strain', order_num=110, tags=['基础资料-菌种管理'], dependencies=[PreAuthDependency()], ) customer_excel_controller = APIRouterPro( prefix='/master/customer', order_num=111, tags=['基础资料-客户管理'], dependencies=[PreAuthDependency()], ) site_excel_controller = APIRouterPro( prefix='/master/site', order_num=112, tags=['基础资料-客户现场管理'], dependencies=[PreAuthDependency()], ) line_excel_controller = APIRouterPro( prefix='/master/line', order_num=113, tags=['基础资料-产线管理'], dependencies=[PreAuthDependency()], ) warehouse_excel_controller = APIRouterPro( prefix='/master/warehouse', order_num=114, tags=['基础资料-仓库管理'], dependencies=[PreAuthDependency()], ) pallet_excel_controller = APIRouterPro( prefix='/master/pallet', order_num=115, tags=['基础资料-托盘管理'], dependencies=[PreAuthDependency()], ) tunnel_excel_controller = APIRouterPro( prefix='/master/tunnel', order_num=116, tags=['基础资料-隧道管理'], dependencies=[PreAuthDependency()], ) async def _import_excel( resource: MasterExcelResource, file: UploadFile, update_support: bool, db: AsyncSession, current_user: CurrentUserModel, scope: TestBatchScope, preview: bool = False, ) -> Response: if preview: preview_result = await MasterExcelService.preview_import( db, resource, file, update_support, current_user, scope ) logger.info('导入校验完成') return ResponseUtil.success(msg='校验完成,尚未写入', data=preview_result) result = await MasterExcelService.import_resource( db, resource, file, update_support, current_user, scope ) logger.info(result.message) return ResponseUtil.success(msg=result.message) async def _export_excel( resource: MasterExcelResource, query: BaseModel, db: AsyncSession, scope: TestBatchScope, ) -> Response: binary = await MasterExcelService.export_resource(db, resource, query, scope) logger.info('导出成功') return ResponseUtil.streaming(data=bytes2file_response(binary)) def _template_excel(resource: MasterExcelResource) -> Response: logger.info('获取成功') return ResponseUtil.streaming(data=bytes2file_response(MasterExcelService.build_template(resource))) @strain_excel_controller.post( '/importData', summary='批量导入菌种接口', description='用于按模板批量导入菌种', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:strain:import')], ) @Log(title='菌种管理', business_type=BusinessType.IMPORT) async def import_master_strain_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('strain', file, update_support, query_db, current_user, scope, preview) @strain_excel_controller.post( '/importTemplate', summary='获取菌种导入模板接口', description='用于下载菌种导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:strain:import')], ) async def export_master_strain_template(request: Request) -> Response: return _template_excel('strain') @strain_excel_controller.post( '/export', summary='导出菌种列表接口', description='用于按当前筛选条件导出全部菌种', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:strain:export')], ) @Log(title='菌种管理', business_type=BusinessType.EXPORT) async def export_master_strain_excel( request: Request, strain_page_query: Annotated[StrainPageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('strain', strain_page_query, query_db, scope) @customer_excel_controller.post( '/importData', summary='批量导入客户接口', description='用于按模板批量导入客户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:customer:import')], ) @Log(title='客户管理', business_type=BusinessType.IMPORT) async def import_master_customer_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('customer', file, update_support, query_db, current_user, scope, preview) @customer_excel_controller.post( '/importTemplate', summary='获取客户导入模板接口', description='用于下载客户导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:customer:import')], ) async def export_master_customer_template(request: Request) -> Response: return _template_excel('customer') @customer_excel_controller.post( '/export', summary='导出客户列表接口', description='用于按当前筛选条件导出全部客户', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:customer:export')], ) @Log(title='客户管理', business_type=BusinessType.EXPORT) async def export_master_customer_excel( request: Request, customer_page_query: Annotated[CustomerPageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('customer', customer_page_query, query_db, scope) @site_excel_controller.post( '/importData', summary='批量导入客户现场接口', description='用于按模板批量导入客户现场', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:site:import')], ) @Log(title='客户现场管理', business_type=BusinessType.IMPORT) async def import_master_site_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('site', file, update_support, query_db, current_user, scope, preview) @site_excel_controller.post( '/importTemplate', summary='获取客户现场导入模板接口', description='用于下载客户现场导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:site:import')], ) async def export_master_site_template(request: Request) -> Response: return _template_excel('site') @site_excel_controller.post( '/export', summary='导出客户现场列表接口', description='用于按当前筛选条件导出全部客户现场', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:site:export')], ) @Log(title='客户现场管理', business_type=BusinessType.EXPORT) async def export_master_site_excel( request: Request, site_page_query: Annotated[SitePageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('site', site_page_query, query_db, scope) @line_excel_controller.post( '/importData', summary='批量导入产线接口', description='用于按模板批量导入产线', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:line:import')], ) @Log(title='产线管理', business_type=BusinessType.IMPORT) async def import_master_line_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('line', file, update_support, query_db, current_user, scope, preview) @line_excel_controller.post( '/importTemplate', summary='获取产线导入模板接口', description='用于下载产线导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:line:import')], ) async def export_master_line_template(request: Request) -> Response: return _template_excel('line') @line_excel_controller.post( '/export', summary='导出产线列表接口', description='用于按当前筛选条件导出全部产线', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:line:export')], ) @Log(title='产线管理', business_type=BusinessType.EXPORT) async def export_master_line_excel( request: Request, line_page_query: Annotated[LinePageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('line', line_page_query, query_db, scope) @warehouse_excel_controller.post( '/importData', summary='批量导入仓库接口', description='用于按模板批量导入仓库', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:warehouse:import')], ) @Log(title='仓库管理', business_type=BusinessType.IMPORT) async def import_master_warehouse_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('warehouse', file, update_support, query_db, current_user, scope, preview) @warehouse_excel_controller.post( '/importTemplate', summary='获取仓库导入模板接口', description='用于下载仓库导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:warehouse:import')], ) async def export_master_warehouse_template(request: Request) -> Response: return _template_excel('warehouse') @warehouse_excel_controller.post( '/export', summary='导出仓库列表接口', description='用于按当前筛选条件导出全部仓库', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:warehouse:export')], ) @Log(title='仓库管理', business_type=BusinessType.EXPORT) async def export_master_warehouse_excel( request: Request, warehouse_page_query: Annotated[WarehousePageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('warehouse', warehouse_page_query, query_db, scope) @pallet_excel_controller.post( '/importData', summary='批量导入托盘接口', description='用于按模板批量导入托盘', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:pallet:import')], ) @Log(title='托盘管理', business_type=BusinessType.IMPORT) async def import_master_pallet_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('pallet', file, update_support, query_db, current_user, scope, preview) @pallet_excel_controller.post( '/importTemplate', summary='获取托盘导入模板接口', description='用于下载托盘导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:pallet:import')], ) async def export_master_pallet_template(request: Request) -> Response: return _template_excel('pallet') @pallet_excel_controller.post( '/export', summary='导出托盘列表接口', description='用于按当前筛选条件导出全部托盘', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:pallet:export')], ) @Log(title='托盘管理', business_type=BusinessType.EXPORT) async def export_master_pallet_excel( request: Request, pallet_page_query: Annotated[PalletPageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('pallet', pallet_page_query, query_db, scope) @tunnel_excel_controller.post( '/importData', summary='批量导入隧道接口', description='用于按模板批量导入隧道', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('master:tunnel:import')], ) @Log(title='隧道管理', business_type=BusinessType.IMPORT) async def import_master_tunnel_excel( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], query_db: Annotated[AsyncSession, DBSessionDependency()], current_user: Annotated[CurrentUserModel, CurrentUserDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency(write=True)], preview: Annotated[bool, Query(description='只校验不写入')] = False, ) -> Response: return await _import_excel('tunnel', file, update_support, query_db, current_user, scope, preview) @tunnel_excel_controller.post( '/importTemplate', summary='获取隧道导入模板接口', description='用于下载隧道导入模板', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:tunnel:import')], ) async def export_master_tunnel_template(request: Request) -> Response: return _template_excel('tunnel') @tunnel_excel_controller.post( '/export', summary='导出隧道列表接口', description='用于按当前筛选条件导出全部隧道', response_class=StreamingResponse, responses=_EXCEL_RESPONSES, dependencies=[UserInterfaceAuthDependency('master:tunnel:export')], ) @Log(title='隧道管理', business_type=BusinessType.EXPORT) async def export_master_tunnel_excel( request: Request, tunnel_page_query: Annotated[TunnelPageQueryModel, Form()], query_db: Annotated[AsyncSession, DBSessionDependency()], scope: Annotated[TestBatchScope, TestBatchScopeDependency()], ) -> Response: return await _export_excel('tunnel', tunnel_page_query, query_db, scope)