using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FrameworkDAL.Query.SystemJob
{
public class SystemJobQB
{
public const string GET_SYSTEMJOB = @"SELECT
S.SYSJOBID AS SysJobId,
S.SYSJOBTYPE AS SysJobType,
S.MENUID AS MenuId,
S.WEBSERVICEID AS WebServiceId,
S.PARAMETERS AS Parameters,
S.SUBMITTEDBYID AS SubmittedById,
S.SUBMITTEDON AS SubmittedOn,
S.RUNSTATUS AS RunStatus,
S.PRIORITY AS Priority,
S.RETRYCOUNT AS RetryCount,
S.MAXRETRIES AS MaxRetries,
S.QUEUENAME AS QueueName,
S.LASTUPDATED AS LastUpdate,
S.PINNED AS Pinned,
S.PUBLISH AS Publish,
S.RESULTLOCATION AS ResultLocation,
S.RESULTFORMAT AS ResultFormat,
S.STARTTIME AS StartTime,
S.ENDTIME AS EndTime,
S.EXPIRYAT AS ExpiryAt,
S.ERRORMESSAGE AS ErrorMessage,
S.CREATEDBYID AS SysJobCreatedById,
S.CREATEDON AS SysJobCreatedOn,
S.MODIFIEDBYID AS SysJobModifiedById,
S.MODIFIEDON AS SysJobModifiedOn,
S.SORTORDER AS SysJobSortOrder,
S.STATUS AS SysJobStatus,
S.VERSION AS SysJobVersion,
S.SOURCETYPE AS SysJobSourceType,
S.TENANTID AS SysJobTenantId,
S.DELIVERYCHANNEL AS DeliveryChannel,
S.DELIVERYDESTINATION AS DeliveryDestination
FROM TSYSJOB S
WHERE S.SYSJOBID = @SysJobId;";
public const string GET_SELECTLIST_SYSTEMJOB = @"
SELECT
S.SYSJOBID AS SysJobId,
S.SYSJOBTYPE AS SysJobType,
S.MENUID AS MenuId,
S.RUNSTATUS AS RunStatus,
S.PRIORITY AS Priority,
S.QUEUENAME AS QueueName
FROM TSYSJOB S
WHERE S.STATUS = 1
ORDER BY S.SORTORDER;";
public const string SAVE_SYSTEMJOB = @"INSERT INTO TSYSJOB (
SYSJOBTYPE,
MENUID,
WEBSERVICEID,
PARAMETERS,
SUBMITTEDBYID,
SUBMITTEDON,
RUNSTATUS,
PRIORITY,
RETRYCOUNT,
MAXRETRIES,
QUEUENAME,
LASTUPDATED,
PINNED,
PUBLISH,
RESULTLOCATION,
RESULTFORMAT,
STARTTIME,
ENDTIME,
EXPIRYAT,
ERRORMESSAGE,
CREATEDBYID,
CREATEDON,
MODIFIEDBYID,
MODIFIEDON,
SORTORDER,
STATUS,
VERSION,
SOURCETYPE,
TENANTID,
DELIVERYCHANNEL,
DELIVERYDESTINATION )
VALUES (
@SysJobType,
@MenuId,
@WebServiceId,
@Parameters,
@SubmittedById,
@SubmittedOn,
@RunStatus,
@Priority,
@RetryCount,
@MaxRetries,
@QueueName,
@LastUpdate,
@Pinned,
@Publish,
@ResultLocation,
@ResultFormat,
@StartTime,
@EndTime,
@ExpiryAt,
@ErrorMessage,
@SysJobCreatedById,
@SysJobCreatedOn,
@SysJobModifiedById,
@SysJobModifiedOn,
@SysJobSortOrder,
@SysJobStatus,
@SysJobVersion,
@SysJobSourceType,
@SysJobTenantId,
@DeliveryChannel,
@DeliveryDestination );
SELECT CAST(SCOPE_IDENTITY() AS INT);";
public const string UPDATE_SYSTEMJOB= @"UPDATE TSYSJOB SET
SYSJOBTYPE =@SysJobType,
MENUID = @MenuId,
WEBSERVICEID = @WebServiceId,
PARAMETERS = @Parameters,
SUBMITTEDBYID = @SubmittedById,
SUBMITTEDON = @SubmittedOn,
RUNSTATUS = @RunStatus,
PRIORITY = @Priority,
RETRYCOUNT = @RetryCount,
MAXRETRIES = @MaxRetries,
QUEUENAME = @QueueName,
LASTUPDATED = @LastUpdate,
PINNED = @Pinned,
PUBLISH = @Publish,
RESULTLOCATION = @ResultLocation,
RESULTFORMAT = @ResultFormat,
STARTTIME = @StartTime,
ENDTIME = @EndTime,
EXPIRYAT = @ExpiryAt,
ERRORMESSAGE = @ErrorMessage,
MODIFIEDBYID = @SysJobModifiedById,
MODIFIEDON = @SysJobModifiedOn,
SORTORDER = @SysJobSortOrder,
STATUS = @SysJobStatus,
VERSION = @SysJobVersion,
SOURCETYPE = @SysJobSourceType,
TENANTID = @SysJobTenantId,
DELIVERYCHANNEL = @DeliveryChannel,
DELIVERYDESTINATION = @DeliveryDestination
WHERE SYSJOBID = @SysJobId; ";
public const string DELETE_SYSTEMJOB = @"DELETE FROM TSYSJOB
WHERE SYSJOBID = @SysJobId
AND TENANTID = @SysJobTenantId;";
// ── Executor queries ─────────────────────────────────────────────────
///
/// Load pending TSYSJOB rows for the executor (RUNSTATUS=0).
/// Also loads the web service URL template for immediate dispatch.
/// Required index: TSYSJOB (TENANTID, RUNSTATUS, PRIORITY)
///
public const string GET_PENDING_JOBS = @"
SELECT TOP (@BatchSize)
S.SYSJOBID AS SysJobId,
S.SYSJOBTYPE AS SysJobType,
S.WEBSERVICEID AS WebServiceId,
S.PARAMETERS AS Parameters,
S.SUBMITTEDBYID AS SubmittedById,
S.PRIORITY AS Priority,
S.RETRYCOUNT AS RetryCount,
S.MAXRETRIES AS MaxRetries,
S.QUEUENAME AS QueueName,
S.TENANTID AS SysJobTenantId,
S.DELIVERYCHANNEL AS DeliveryChannel,
S.DELIVERYDESTINATION AS DeliveryDestination,
S.RESULTFORMAT AS ResultFormat,
W.URITEMPLATE AS WebServiceUriTemplate,
W.SECONDURITEMPLATE AS WebServiceSecondUriTemplate,
W.METHODTYPE AS WebServiceMethodType
FROM TSYSJOB S
LEFT JOIN MWEBSERVICE W ON W.WEBSERVICEID = S.WEBSERVICEID
WHERE S.RUNSTATUS = 0 -- Pending only (excludes Cancelled=4)
AND S.TENANTID = @SysJobTenantId
AND (S.STARTTIME IS NULL OR S.STARTTIME <= GETUTCDATE()) -- honor a future schedule time
ORDER BY S.PRIORITY DESC, S.SUBMITTEDON ASC";
///
/// Whether a WebServiceId is actually wired for background execution — a real,
/// non-sentinel MWEBSERVICE row with a usable URITEMPLATE. Lets the frontend disable
/// the "Job" button with an honest message instead of accepting a submission that the
/// executor can only ever fail on (see SysJobExecutorQuartzJob.CallWebServiceAsync's
/// "No MWEBSERVICE configured" branch).
///
public const string CHECK_JOB_ELIGIBILITY = @"
SELECT WEBSERVICEID AS WebServiceId, URITEMPLATE AS UriTemplate, SECONDURITEMPLATE AS SecondUriTemplate
FROM MWEBSERVICE
WHERE WEBSERVICEID = @WebServiceId";
///
/// Claim a job atomically (mark InProgress) for a specific worker.
/// Only claims if still Pending — prevents double-pickup under concurrency.
///
public const string CLAIM_JOB = @"
UPDATE TSYSJOB SET
RUNSTATUS = 1,
STARTTIME = GETUTCDATE(),
LASTUPDATED = GETUTCDATE(),
MODIFIEDBYID = @SysJobModifiedById,
MODIFIEDON = GETUTCDATE()
WHERE SYSJOBID = @SysJobId
AND TENANTID = @SysJobTenantId
AND RUNSTATUS = 0";
///
/// Mark job Completed (RUNSTATUS=2) with result location.
/// RESULTLOCATION conventions:
/// att:{attachmentId} — file stored in DMS/TATTACHMENT (preferred for report outputs)
/// redis:{key} — file stored in IDistributedCache (short-lived results)
/// /path/to/file — legacy filesystem path
/// NULL — no file output (fire-and-forget jobs)
/// Only updates if still InProgress (RUNSTATUS=1) — prevents overwriting a cancel.
///
public const string COMPLETE_JOB = @"
UPDATE TSYSJOB SET
RUNSTATUS = 2,
ENDTIME = GETUTCDATE(),
LASTUPDATED = GETUTCDATE(),
RESULTLOCATION = @ResultLocation,
ERRORMESSAGE = NULL,
MODIFIEDBYID = @SysJobModifiedById,
MODIFIEDON = GETUTCDATE()
WHERE SYSJOBID = @SysJobId
AND TENANTID = @SysJobTenantId
AND RUNSTATUS = 1;";
///
/// Mark job Failed (RUNSTATUS=3) or reset to Pending (RUNSTATUS=0) for retry.
///
public const string FAIL_OR_RETRY_JOB = @"
UPDATE TSYSJOB SET
RUNSTATUS = @RunStatus,
ENDTIME = GETUTCDATE(),
LASTUPDATED = GETUTCDATE(),
RETRYCOUNT = RETRYCOUNT + 1,
ERRORMESSAGE = @ErrorMessage,
MODIFIEDBYID = @SysJobModifiedById,
MODIFIEDON = GETUTCDATE()
WHERE SYSJOBID = @SysJobId
AND TENANTID = @SysJobTenantId
AND RUNSTATUS = 1;";
// ── List / filter queries ─────────────────────────────────────────────
///
/// Paginated, filtered job list.
/// Shows own jobs plus jobs shared with the requesting user.
/// Required indexes: IX_TSYSJOB_RunStatus_TenantId, IX_TSYSJOB_SubmittedOn_TenantId
///
public const string GET_LIST_SYSTEMJOB = @"
WITH PagedJobs AS (
SELECT
S.SYSJOBID AS SysJobId,
S.SYSJOBTYPE AS SysJobType,
S.MENUID AS MenuId,
M.MENUNAME AS MenuName,
S.QUEUENAME AS QueueName,
S.PRIORITY AS Priority,
S.RUNSTATUS AS RunStatus,
S.SUBMITTEDON AS SubmittedOn,
U.USERNAME AS SubmittedByName,
S.STARTTIME AS StartTime,
S.ENDTIME AS EndTime,
S.ERRORMESSAGE AS ErrorMessage,
S.RETRYCOUNT AS RetryCount,
S.MAXRETRIES AS MaxRetries,
S.RESULTLOCATION AS ResultLocation,
S.RESULTFORMAT AS ResultFormat,
S.CANCELLEDAT AS CancelledAt,
S.DELIVERYCHANNEL AS DeliveryChannel,
S.DELIVERYDESTINATION AS DeliveryDestination,
CASE WHEN S.SUBMITTEDBYID = @UserId THEN 0 ELSE 1 END AS IsShared,
SHU.USERNAME AS SharedByName,
SH.CANEXECUTE AS CanExecute,
SH.CANVIEWRESULT AS CanViewResult,
ROW_NUMBER() OVER (ORDER BY S.SUBMITTEDON DESC, S.SYSJOBID DESC) AS RowNum
FROM TSYSJOB S
LEFT JOIN MUSER U ON U.USERID = S.SUBMITTEDBYID
LEFT JOIN MMENU M ON M.MENUID = S.MENUID
LEFT JOIN TSYSJOBSHARE SH ON SH.SYSJOBID = S.SYSJOBID AND SH.SHAREDWITHUSERID = @UserId
LEFT JOIN MUSER SHU ON SHU.USERID = SH.SHAREDBYID
WHERE (
S.SUBMITTEDBYID = @UserId
OR EXISTS (
SELECT 1 FROM TSYSJOBSHARE SH
WHERE SH.SYSJOBID = S.SYSJOBID
AND SH.SHAREDWITHUSERID = @UserId
)
)
AND (@RunStatus IS NULL OR @RunStatus = -1 OR S.RUNSTATUS = @RunStatus)
AND (@SysJobType IS NULL OR @SysJobType = '' OR S.SYSJOBTYPE = @SysJobType)
AND (@QueueName IS NULL OR @QueueName = '' OR S.QUEUENAME = @QueueName)
AND (@DateFrom IS NULL OR S.SUBMITTEDON >= @DateFrom)
AND (@DateTo IS NULL OR S.SUBMITTEDON <= @DateTo)
AND (@SearchText IS NULL OR @SearchText = '' OR S.PARAMETERS LIKE '%' + @SearchText + '%'
OR S.ERRORMESSAGE LIKE '%' + @SearchText + '%')
)
SELECT
SysJobId, SysJobType, MenuId, MenuName, QueueName, Priority, RunStatus,
SubmittedOn, SubmittedByName, StartTime, EndTime, ErrorMessage,
RetryCount, MaxRetries, ResultLocation, ResultFormat, CancelledAt, IsShared,
DeliveryChannel, DeliveryDestination, SharedByName, CanExecute, CanViewResult
FROM PagedJobs
WHERE (@FirstNumber = -1 AND @MaxResult = -1)
OR (RowNum BETWEEN @FirstNumber AND @MaxResult);";
///
/// Total count for GET_LIST_SYSTEMJOB (same WHERE, no pagination).
///
public const string GET_LIST_COUNT_SYSTEMJOB = @"
SELECT COUNT(*)
FROM TSYSJOB S
WHERE S.TENANTID = @SysJobTenantId
AND (
S.SUBMITTEDBYID = @UserId
OR EXISTS (
SELECT 1 FROM TSYSJOBSHARE SH
WHERE SH.SYSJOBID = S.SYSJOBID
AND SH.SHAREDWITHUSERID = @UserId
AND SH.TENANTID = @SysJobTenantId
)
)
AND (@RunStatus IS NULL OR @RunStatus = -1 OR S.RUNSTATUS = @RunStatus)
AND (@SysJobType IS NULL OR @SysJobType = '' OR S.SYSJOBTYPE = @SysJobType)
AND (@QueueName IS NULL OR @QueueName = '' OR S.QUEUENAME = @QueueName)
AND (@DateFrom IS NULL OR S.SUBMITTEDON >= @DateFrom)
AND (@DateTo IS NULL OR S.SUBMITTEDON <= @DateTo)
AND (@SearchText IS NULL OR @SearchText = '' OR S.PARAMETERS LIKE '%' + @SearchText + '%'
OR S.ERRORMESSAGE LIKE '%' + @SearchText + '%');";
// ── Cancel query ──────────────────────────────────────────────────────
///
/// Cancel a job — only if still Pending (0) or InProgress (1).
/// Sets RUNSTATUS=4 (Cancelled).
///
public const string CANCEL_JOB = @"
UPDATE TSYSJOB SET
RUNSTATUS = 4,
CANCELLEDAT = GETUTCDATE(),
LASTUPDATED = GETUTCDATE(),
MODIFIEDBYID = @SysJobModifiedById,
MODIFIEDON = GETUTCDATE()
WHERE SYSJOBID = @SysJobId
AND TENANTID = @SysJobTenantId
AND RUNSTATUS IN (0, 1);";
// ── Summary / dashboard query ─────────────────────────────────────────
///
/// Counts jobs by status for the dashboard summary tile.
///
public const string GET_JOB_SUMMARY = @"
SELECT
COUNT(CASE WHEN RUNSTATUS = 0 THEN 1 END) AS Pending,
COUNT(CASE WHEN RUNSTATUS = 1 THEN 1 END) AS InProgress,
COUNT(CASE WHEN RUNSTATUS = 2 THEN 1 END) AS Completed,
COUNT(CASE WHEN RUNSTATUS = 3 THEN 1 END) AS Failed,
COUNT(CASE WHEN RUNSTATUS = 4 THEN 1 END) AS Cancelled,
COUNT(*) AS Total
FROM TSYSJOB
WHERE TENANTID = @SysJobTenantId
AND (@DateFrom IS NULL OR SUBMITTEDON >= @DateFrom)
AND (@DateTo IS NULL OR SUBMITTEDON <= @DateTo);";
}
}