from fastapi import APIRouter from core.sap import forward_to_sapb1 from core.crud_router import make_crud_router router = APIRouter( tags=["Catálogos"] ) for _resource in ("Warehouses", "SalesTaxCodes", "FactoringIndicators"): router.include_router( make_crud_router( _resource, tags=["Catálogos"], supports_get_by_key=False, supports_create=False, supports_patch=False, ) ) @router.get("/api/Currencies") async def get_currencies(): return forward_to_sapb1( method="GET", endpoint_path="Currencies", params={"$select": "Code,Name", "$top": 200} ).json() @router.get("/api/BusinessPartnerGroups") async def get_business_partner_groups(): return forward_to_sapb1( method="GET", endpoint_path="BusinessPartnerGroups", params={"$select": "Number,GroupName"} ).json() @router.get("/api/Sunat/BusinessPartners/DocumentType") async def get_sunat_businesspartners_document_type(): sap_params = { "$skip": 0, "$top": 200, "$inlinecount": "allpages" } sap_params["$filter"] = "TableName eq 'OCRD' and Name eq 'EXX_TIPODOCU'" base_headers = {"B1S-PageSize": "200"} return forward_to_sapb1( method="GET", endpoint_path="UserFieldsMD", params=sap_params, extra_headers=base_headers ).json() @router.get("/api/Catalogs/UdfValidValues") async def get_udf_valid_values(table_name: str, field_name: str): """ Genérico para cualquier campo de usuario (UDF) con lista de valores válidos: recibe la tabla SAP (ej. 'OWTQ') y el nombre del campo sin el prefijo 'U_' (ej. 'SIS_TIPDESP'), y devuelve sus valores válidos vía Service Layer (UserFieldsMD.ValidValuesMD), normalizados a {Code, Name} para poder usarse con useSapCatalog igual que las tablas de usuario. Equivale a lo que en HANA sería CUFD (por AliasID/TableID) + UFD1 (por FieldID), pero sin necesidad de acceso directo a HANA. """ def _escape(value: str) -> str: return value.replace("'", "''") sap_params = { "$skip": 0, "$top": 200, "$inlinecount": "allpages", } sap_params["$filter"] = ( f"TableName eq '{_escape(table_name)}' and Name eq '{_escape(field_name)}'" ) base_headers = {"B1S-PageSize": "200"} response = forward_to_sapb1( method="GET", endpoint_path="UserFieldsMD", params=sap_params, extra_headers=base_headers, ).json() fields = response.get("value", []) valid_values = fields[0].get("ValidValuesMD", []) if fields else [] return { "value": [ {"Code": v["Value"], "Name": v["Description"]} for v in valid_values ] } @router.get("/api/PriceLists") async def get_price_lists(): """ Listas de precio de SAP, normalizadas a {Code, Name} (PriceListNo / PriceListName) para poder reusar el hook useSapCatalog del frontend igual que con las tablas de usuario y los UDF. """ sap_params = { "$select": "PriceListNo,PriceListName", "$top": 200, } response = forward_to_sapb1( method="GET", endpoint_path="PriceLists", params=sap_params, ).json() return { "value": [ {"Code": pl["PriceListNo"], "Name": pl["PriceListName"]} for pl in response.get("value", []) ] } @router.get("/api/CompanyService/DefaultWarehouse") async def get_default_warehouse(): """ Almacén por defecto de la compañía (CompanyService_GetAdminInfo es un FunctionImport de Service Layer que, pese al nombre "Get", solo se invoca por POST). Se normaliza a un único campo para que el frontend no tenga que conocer el resto de AdminInfo. """ response = forward_to_sapb1( method="POST", endpoint_path="CompanyService_GetAdminInfo", json_data={}, ).json() return {"DefaultWarehouse": response.get("DefaultWarehouse")} @router.get("/api/ItemGroups") async def get_item_groups(): sap_params = { "$skip": 0, "$top": 200, "$inlinecount": "allpages" } sap_params["$select"] = "Number,GroupName" base_headers = {"B1S-PageSize": "200"} return forward_to_sapb1( method="GET", endpoint_path="ItemGroups", params=sap_params, extra_headers=base_headers ).json() #