using System.Threading; using System.Threading.Tasks; namespace PayRollBLL.SAPPaySlip.Client { /// /// Contract for the SAP ZPY_PAYSLIP_SRV HTTP client. /// /// Never throws on network or HTTP-level errors — all failures are captured in /// so the BLL can surface precise, actionable messages. /// Only propagates (caller-initiated cancellation). /// public interface ISapPaySlipApiClient { Task GetAsync( string employeeId, string fiscalYear, string month, string username, string password, string sapClient, CancellationToken ct); } /// /// Result of a single SAP PaySlip API call. /// /// When is false, inspect the error fields in order: /// 1. == 0 → network failure; read /// 2. != 0 → HTTP error; read , /// , and /// is always set for debugging. /// public sealed class SapPaySlipApiResultDTO { /// True only when SAP returned HTTP 2xx with a parseable body. public bool IsSuccess { get; init; } /// /// HTTP status code returned by SAP. /// Zero (0) means a network-level failure occurred before any HTTP response was received. /// public int StatusCode { get; init; } /// Raw response body from SAP (may be JSON, HTML, or empty). public string ResponseBody { get; init; } = string.Empty; /// /// SAP OData error code parsed from the JSON error envelope /// (e.g. "HTTP/400", "/ZPY/PAYSLIP/001"). /// Null when the body was empty or not a SAP OData JSON error. /// public string? SapErrorCode { get; init; } /// /// Human-readable error message from error.message.value in the SAP OData envelope. /// This is the exact text SAP sends — surface it directly to the caller. /// public string? SapErrorMessage { get; init; } /// /// SAP transaction ID from error.innererror.transactionid. /// Provide this to the SAP BASIS team to locate the server-side log entry. /// public string? SapTransactionId { get; init; } /// /// Human-readable description of the network failure, set only when /// == 0. Classifies DNS failures, refused connections, /// TLS errors, and request timeouts precisely. /// public string? NetworkFailureReason { get; init; } /// Full URI that was attempted — always set for debugging and error reporting. public string AttemptedUri { get; init; } = string.Empty; } }