api product funcional
Wed Jan 08 2025 11:04:30 GMT+0000 (Coordinated Universal Time)
Saved by @rcrespocode
@RestResource(urlMapping='/api/products/*') global with sharing class ProductApi { // GET: Recuperar productos por External_ID__c (sin captura de log) @HttpGet global static List<Product2> getProducts() { RestRequest req = RestContext.request; String externalId = req.requestURI.substringAfterLast('/'); if (String.isNotBlank(externalId)) { // Recuperar producto por External_ID__c List<Product2> products = [SELECT Id, Name, ProductCode, Description, IsActive, External_ID__c FROM Product2 WHERE External_ID__c = :externalId]; return products; } else { // Recuperar todos los productos si no se proporciona External_ID__c List<Product2> products = [SELECT Id, Name, ProductCode, Description, IsActive, External_ID__c FROM Product2]; return products; } } // PATCH: Crear o actualizar un producto y establecer su precio usando solo External_ID__c @HttpPatch global static Product2 upsertProduct( String externalId, String name, String productCode, String description, Boolean isActive, Decimal price ) { RestRequest req = RestContext.request; Product2 product = null; try { if (String.isBlank(externalId)) { throw new CustomException('El campo External_ID__c es obligatorio para realizar un upsert.'); } if (price == null || price < 0) { throw new CustomException('El precio debe ser un valor positivo.'); } // Crear o actualizar el producto basado en External_ID__c product = new Product2( External_ID__c = externalId, Name = name, ProductCode = productCode, Description = description, IsActive = isActive ); upsert product External_ID__c; // Buscar el Standard Pricebook List<Pricebook2> standardPricebookList = [SELECT Id FROM Pricebook2 WHERE IsStandard = true LIMIT 1]; if (standardPricebookList.isEmpty()) { throw new CustomException('No se encontró el Standard Pricebook.'); } Pricebook2 standardPricebook = standardPricebookList[0]; // Verificar si ya existe un PricebookEntry para este producto List<PricebookEntry> existingEntries = [ SELECT Id, UnitPrice FROM PricebookEntry WHERE Product2Id = :product.Id AND Pricebook2Id = :standardPricebook.Id ]; if (existingEntries.isEmpty()) { // Crear un nuevo PricebookEntry si no existe PricebookEntry newEntry = new PricebookEntry( Pricebook2Id = standardPricebook.Id, Product2Id = product.Id, UnitPrice = price, IsActive = true ); insert newEntry; } else { // Actualizar el PricebookEntry existente PricebookEntry existingEntry = existingEntries[0]; existingEntry.UnitPrice = price; update existingEntry; } // Log success logIntegrationDetails('PATCH', req, product, null); // No hay error, pasamos null para la excepción return product; } catch (Exception e) { // Log error logIntegrationDetails('PATCH', req, null, e); // Capturamos el error y lo pasamos al log throw e; // Vuelve a lanzar la excepción para que se maneje como corresponde } } // DELETE: Eliminar un producto por External_ID__c @HttpDelete global static void deleteProduct() { RestRequest req = RestContext.request; String productIdOrExternalId = req.requestURI.substringAfterLast('/'); if (String.isBlank(productIdOrExternalId)) { throw new CustomException('Debe proporcionar el ID o el External_ID__c para eliminar.'); } Product2 productToDelete; if (productIdOrExternalId.startsWith('a') && productIdOrExternalId.length() == 18) { // Buscar por Id estándar productToDelete = [SELECT Id, IsDeleted FROM Product2 WHERE Id = :productIdOrExternalId AND IsDeleted = false LIMIT 1]; } else { // Buscar por External_ID__c productToDelete = [SELECT Id, IsDeleted FROM Product2 WHERE External_ID__c = :productIdOrExternalId AND IsDeleted = false LIMIT 1]; } // Si el producto no existe o está eliminado, lanzamos una excepción if (productToDelete == null || productToDelete.IsDeleted) { throw new CustomException('El producto no existe o ha sido eliminado.'); } // Eliminar cualquier PricebookEntry relacionado en el Standard Pricebook List<Pricebook2> standardPricebookList = [SELECT Id FROM Pricebook2 WHERE IsStandard = true LIMIT 1]; if (!standardPricebookList.isEmpty()) { Pricebook2 standardPricebook = standardPricebookList[0]; List<PricebookEntry> entriesToDelete = [ SELECT Id FROM PricebookEntry WHERE Product2Id = :productToDelete.Id AND Pricebook2Id = :standardPricebook.Id ]; delete entriesToDelete; } delete productToDelete; // Registrar el log de la integración try { logIntegrationDetails('DELETE', req, productToDelete, null); } catch (Exception e) { // Si algo sale mal, capturamos la excepción y la mostramos (aunque puede que ya esté registrada) System.debug('Error al registrar el log: ' + e.getMessage()); } } // Método auxiliar para registrar los detalles de las solicitudes y respuestas en Integration_Log__c private static void logIntegrationDetails(String operation, RestRequest req, SObject response, Exception e) { // Crear el log de la solicitud y la respuesta Integration_Log__c log = new Integration_Log__c(); // Si ocurrió un error, capturamos la excepción if (e != null) { log.Estado__c = 'Error'; log.Response__c = 'Error: ' + e.getMessage(); // Guardamos el mensaje de la excepción en Response__c } else { log.Estado__c = 'Success'; // Si todo fue exitoso, lo marcamos como "Success" log.Response__c = JSON.serialize(response); // Serializamos la respuesta } // Asignar el nombre del log con el nombre del objeto y la fecha actual String logName = (response != null ? response.getSObjectType().getDescribe().getName() : 'UnknownObject') + ' - ' + DateTime.now().format(); log.Name = logName; // Capturamos los parámetros de la solicitud log.Request__c = 'Params: ' + req.params; // Si se está creando/actualizando un producto, asociamos el producto con el log if (response instanceof Product2) { log.Product__c = ((Product2) response).Id; } insert log; // Insertamos el log en la base de datos } // Clase de excepción personalizada global class CustomException extends Exception {} }
Comments