Skip to main content

Overview

The cancellation service (Cancelación) reverses previously registered healthcare transactions. Like registration, it supports both complete and partial cancellation scenarios where individual items within a transaction may have different outcomes.

Cancellation Request

Method Signature

public Hl7Result<CancelacionResponse> cancelarPrestacion(
    CancelacionRequest request
)
Source: Hl7Service.java:52-63
Cancellation requires an active authenticated session and should reference a valid previously registered transaction.

CancelacionRequest Structure

Operation Data

modo
String
required
Operation mode - typically “N” for normal cancellation
creden
Long
required
Patient credential number (numeric format)
tipo
Integer
required
Transaction type code
alta
String
Original service date/time (can be empty for cancellation)
manual
Manual
Manual processing flag:
  • Manual.MANUAL (“0”)
  • Manual.CAPITADOR (“C”)
  • Manual.COMSULTA (“L”)

Cancellation-Specific Data

ticketExt
Integer
External ticket number - typically 0 for cancellation
cancelCab
Integer
Transaction number to cancel (cabecera level)
cancelModo
String
Cancellation mode - typically “N” for normal
errorExt
Integer
External error code (if applicable)

Technical Data

termId
String
Terminal identifier
interNro
Integer
Internal transaction number

Provider Data

cuit
Long
Provider CUIT (tax identification number)

HL7 Free Parameters

param1
String
Custom parameter 1 (up to 255 characters)
param2
String
Custom parameter 2 (up to 255 characters)

Request Example

CancelacionRequest request = new CancelacionRequest();

// Operation data
request.setModo("N");
request.setCreden(7180171001151L);
request.setTipo(2);
request.setAlta("");  // Can be empty for cancellation
request.setManual(Manual.MANUAL);

// Cancellation-specific
request.setTicketExt(0);
request.setCancelCab(123456);  // Transaction to cancel
request.setCancelModo("N");

// Technical data
request.setTermId("TERM-001");
request.setInterNro(200);

// Provider
request.setCuit(20123456789L);

// Optional parameters
request.setParam1("Cancellation reason");
request.setParam2("Additional info");
The cancelCab field must reference a valid, previously registered transaction number obtained from a successful registration response.

Cancellation Response

Response Structure

The cancellation response mirrors the registration structure with cabecera and detalle: Source: CancelacionResponse.java
public class CancelacionResponse {
    private CancelacionCabecera cabecera;
    private CancelacionDetalle[] detalle;
}

Cabecera (Header) Fields

transac
Long
Cancellation transaction number (different from original registration)
transacAlta
String
Cancellation transaction creation timestamp
rechaCabecera
Integer
Header rejection code. If greater than 0, the cancellation is rejected.
rechaCabeDeno
String
Human-readable rejection reason for header rejection
apeNom
String
Patient’s last name and first name
planCodi
String
Patient’s plan code
pmi
String
Patient Medical Identifier
edad
Integer
Patient age
sexo
String
Patient sex
gravado
String
Taxable status indicator
leyimp
String
Tax law applicability

Detalle (Detail) Fields

transac
Long
Detail-level cancellation transaction number
recha
Integer
Detail item rejection code. If greater than 0, this specific item cancellation is rejected.
denoItem
String
Human-readable rejection reason for this specific item

Validation Logic

Cancellation validation follows the same pattern as registration, supporting partial outcomes: Source: Hl7Service.java:171-209
private Hl7Result<CancelacionResponse> validarCancelacion(
    CancelacionResponse r
) {
    if (r == null || r.getCabecera() == null) {
        return errorRespuestaInvalida();
    }
    
    CancelacionCabecera cab = r.getCabecera();
    
    // Check for header rejection
    if (cab.getRechaCabecera() != null && cab.getRechaCabecera() > 0) {
        return Hl7Result.rejected(
            r,
            Hl7Error.functional(
                String.valueOf(cab.getRechaCabecera()),
                cab.getRechaCabeDeno()
            )
        );
    }
    
    // Check for detail item rejections
    List<Hl7ItemError> detalles = new ArrayList<>();
    
    if (r.getDetalle() != null) {
        for (CancelacionDetalle d : r.getDetalle()) {
            if (d.getRecha() != null && d.getRecha() > 0) {
                detalles.add(
                    new Hl7ItemError(
                        String.valueOf(d.getRecha()),
                        d.getDenoItem(),
                        Hl7ItemErrorOrigin.DETALLE
                    )
                );
            }
        }
    }
    
    return detalles.isEmpty()
        ? Hl7Result.ok(r)
        : Hl7Result.partial(r, detalles);
}

Validation Flow

  1. Null Check: Verify response and cabecera exist
  2. Header Rejection: Check if rechaCabecera > 0
    • If rejected: Return REJECTED status (cancellation failed)
    • If approved: Continue to detail validation
  3. Detail Item Validation: Check each detail item’s recha field
  4. Result Determination:
    • All items cancelled: OK status
    • Some items failed: PARTIAL status
    • Header rejected: REJECTED status
A PARTIAL result means the cancellation transaction was created, but only some items were cancelled successfully.

Error Handling Scenarios

Header Rejection (Complete Failure)

When the entire cancellation is rejected at the header level:
if (result.getStatus() == Hl7Status.REJECTED) {
    Hl7Error error = result.getIssue().get();
    System.err.println("Cancellation rejected:");
    System.err.println("Code: " + error.getCode());
    System.err.println("Reason: " + error.getMessage());
    
    // Original transaction remains active
}
Common rejection reasons:
  • Transaction already cancelled
  • Transaction not found
  • Cancellation not permitted for this transaction type
  • Time window for cancellation expired

Partial Cancellation (Detail Rejections)

When some items cannot be cancelled:
if (result.isPartial()) {
    CancelacionResponse response = result.getData().get();
    List<Hl7ItemError> failedItems = result.getDetails();
    
    System.out.println("Cancellation transaction: " + 
        response.getCabecera().getTransac());
    
    System.out.println("Items that could not be cancelled:");
    for (Hl7ItemError item : failedItems) {
        System.err.println("  Code: " + item.getCode());
        System.err.println("  Reason: " + item.getMessage());
    }
    
    // Some items were cancelled, others remain active
}

Complete Success

All items successfully cancelled:
if (result.isOk()) {
    CancelacionResponse response = result.getData().get();
    Long cancelTransac = response.getCabecera().getTransac();
    
    System.out.println("Cancellation successful!");
    System.out.println("Cancellation transaction: " + cancelTransac);
    
    // Original transaction is now fully cancelled
}

Complete Usage Example

import com.hl7client.model.dto.request.hl7.CancelacionRequest;
import com.hl7client.model.dto.request.hl7.Manual;
import com.hl7client.model.dto.response.hl7.CancelacionResponse;
import com.hl7client.model.dto.response.hl7.CancelacionCabecera;
import com.hl7client.model.result.Hl7Result;
import com.hl7client.model.result.Hl7Status;
import com.hl7client.model.result.Hl7ItemError;
import com.hl7client.service.Hl7Service;

public class CancellationExample {
    
    private final Hl7Service hl7Service;
    
    public void cancelTransaction(
        Long credential,
        Integer originalTransactionId,
        String reason
    ) {
        // Build cancellation request
        CancelacionRequest request = new CancelacionRequest();
        request.setModo("N");
        request.setCreden(credential);
        request.setTipo(2);
        request.setAlta("");
        request.setManual(Manual.MANUAL);
        
        // Cancellation-specific fields
        request.setTicketExt(0);
        request.setCancelCab(originalTransactionId);
        request.setCancelModo("N");
        
        // Technical data
        request.setTermId(getTerminalId());
        request.setInterNro(generateInterNro());
        
        // Provider
        request.setCuit(getProviderCuit());
        
        // Reason for cancellation
        request.setParam1(reason);
        
        // Execute cancellation
        Hl7Result<CancelacionResponse> result = 
            hl7Service.cancelarPrestacion(request);
        
        // Handle response
        if (result.isOk()) {
            handleCompleteSuccess(result.getData().get());
            
        } else if (result.isPartial()) {
            handlePartialCancellation(
                result.getData().get(),
                result.getDetails()
            );
            
        } else if (result.getStatus() == Hl7Status.REJECTED) {
            handleRejection(
                result.getData().get(),
                result.getIssue().get()
            );
            
        } else if (result.isError()) {
            handleTechnicalError(result.getIssue().get());
        }
    }
    
    private void handleCompleteSuccess(CancelacionResponse response) {
        CancelacionCabecera cab = response.getCabecera();
        
        System.out.println("Cancellation successful!");
        System.out.println("Cancellation transaction: " + cab.getTransac());
        System.out.println("Patient: " + cab.getApeNom());
        System.out.println("PMI: " + cab.getPmi());
        
        // Update database to mark original transaction as cancelled
        markTransactionAsCancelled(
            request.getCancelCab(),
            cab.getTransac()
        );
        
        notifySuccessfulCancellation();
    }
    
    private void handlePartialCancellation(
        CancelacionResponse response,
        List<Hl7ItemError> failedItems
    ) {
        CancelacionCabecera cab = response.getCabecera();
        
        System.out.println("Partial cancellation");
        System.out.println("Cancellation transaction: " + cab.getTransac());
        
        System.out.println("\nItems that could not be cancelled:");
        for (Hl7ItemError item : failedItems) {
            System.err.println("  Code: " + item.getCode());
            System.err.println("  Reason: " + item.getMessage());
        }
        
        // Store cancellation transaction
        storeCancellationTransaction(
            request.getCancelCab(),
            cab.getTransac(),
            failedItems
        );
        
        // Notify user about partial outcome
        notifyPartialCancellation(failedItems.size());
    }
    
    private void handleRejection(
        CancelacionResponse response,
        Hl7Error error
    ) {
        System.err.println("Cancellation rejected:");
        System.err.println("Code: " + error.getCode());
        System.err.println("Reason: " + error.getMessage());
        
        // Original transaction remains active
        logCancellationFailure(
            request.getCancelCab(),
            error.getCode(),
            error.getMessage()
        );
        
        // Determine if retry is appropriate
        if (isRetryableRejection(error.getCode())) {
            promptRetry(error.getMessage());
        } else {
            notifyPermanentRejection(error.getMessage());
        }
    }
    
    private void handleTechnicalError(Hl7Error error) {
        System.err.println("Technical error: " + error.getMessage());
        System.err.println("Origin: " + error.getOrigin());
        
        if (error.isSession()) {
            promptReauthentication();
        } else {
            // Network or server error - safe to retry
            scheduleRetry();
        }
    }
}

Best Practices

Verify the transaction exists and is eligible for cancellation:
// Check transaction exists in local database
Transaction original = database.getTransaction(transactionId);
if (original == null) {
    throw new IllegalArgumentException(
        "Transaction not found: " + transactionId
    );
}

// Check transaction is not already cancelled
if (original.isCancelled()) {
    throw new IllegalStateException(
        "Transaction already cancelled: " + transactionId
    );
}

// Proceed with cancellation
cancelarPrestacion(transactionId);
Always store the cancellation transaction number for audit trail:
if (result.isOk() || result.isPartial()) {
    Long originalTransac = request.getCancelCab();
    Long cancelTransac = result.getData().get()
        .getCabecera().getTransac();
    
    // Link cancellation to original
    database.linkCancellation(
        originalTransac,
        cancelTransac,
        new Date()
    );
}
When some items cannot be cancelled, provide clear feedback:
if (result.isPartial()) {
    List<Hl7ItemError> failed = result.getDetails();
    
    StringBuilder message = new StringBuilder();
    message.append("Partially cancelled. ");
    message.append(failed.size())
        .append(" item(s) could not be cancelled:\n");
    
    for (Hl7ItemError item : failed) {
        message.append("  - ")
            .append(item.getMessage())
            .append("\n");
    }
    
    showUserMessage(message.toString());
}
Prevent duplicate cancellation attempts:
public void safeCancelTransaction(Integer transactionId) {
    // Check if already cancelled
    if (database.isCancelled(transactionId)) {
        System.out.println(
            "Transaction already cancelled: " + transactionId
        );
        return;
    }
    
    // Attempt cancellation
    Hl7Result<CancelacionResponse> result = 
        cancelarPrestacion(transactionId);
    
    // Handle result...
}
Always document why a transaction is being cancelled:
CancelacionRequest request = new CancelacionRequest();
// ... set required fields

// Document the reason
request.setParam1("Patient requested cancellation");
request.setParam2("Cancelled by: Dr. Smith");

// This helps with auditing and compliance

Common Error Scenarios

Transaction Not Found

{
  "rechaCabecera": 404,
  "rechaCabeDeno": "Transacción no encontrada"
}
Cause: The cancelCab value doesn’t reference a valid transaction. Resolution: Verify the transaction number is correct and exists in the system.

Transaction Already Cancelled

{
  "rechaCabecera": 409,
  "rechaCabeDeno": "Transacción ya cancelada"
}
Cause: Attempting to cancel a transaction that’s already been cancelled. Resolution: Check local database status before attempting cancellation.

Cancellation Time Window Expired

{
  "rechaCabecera": 400,
  "rechaCabeDeno": "Período de cancelación expirado"
}
Cause: The transaction is too old to be cancelled. Resolution: Contact support for manual cancellation or adjustment.

See Also

Build docs developers (and LLMs) love