Initial commit: JDE Scoping Tool migration project

Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
This commit is contained in:
Joseph Doherty
2026-01-02 07:43:29 -05:00
commit 26ff8d9b4f
1761 changed files with 596509 additions and 0 deletions
@@ -0,0 +1,45 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// SQL query constants for the CMS Oracle database.
/// </summary>
public static class CmsQueries
{
/// <summary>
/// Gets Manufacturing Information System (MIS) data from CMS database.
/// Complex 10-table JOIN through CMS schema (INFODBA).
/// </summary>
public const string SqlGetMisData = @"
SELECT DISTINCT
mis.P_PART_NUMBER AS ItemNumber,
mis.P_OPERATION_NUMBER AS SequenceNumber,
item.PITEM_ID AS MISNumber,
itemrev.PITEM_REVISION_ID AS RevID,
TRIM(mis.P_SITE) AS BranchCode,
zim_test_details.P_SEQ_NUMBER AS CharNumber,
zim_test_details.P_TEST_DESC AS TestDescription,
zim_test_details.P_SAMPL_TYPE AS SamplingType,
zim_test_details.P_SAMPL_VALUE AS SamplingValue,
zim_test_details.P_TOOLS AS ToolsGauges,
zim_test_details.P_WORK_INTR AS WorkInstructions,
Status.PNAME AS Status,
Status.PDATE_RELEASED AS ReleaseDate
FROM INFODBA.PITEM item
INNER JOIN INFODBA.PITEMREVISION itemrev ON (item.PUID = itemrev.RITEMS_TAGU)
INNER JOIN INFODBA.PRELEASE_STATUS_LIST listing ON (itemrev.PUID = listing.PUID)
INNER JOIN INFODBA.PRELEASESTATUS Status ON (listing.PVALU_0 = Status.PUID)
INNER JOIN INFODBA.PIMANRELATION imanrel ON (itemrev.PUID = imanrel.RPRIMARY_OBJECTU)
INNER JOIN INFODBA.PFORM form ON (imanrel.RSECONDARY_OBJECTU = form.PUID)
INNER JOIN INFODBA.PZIMMERMISDETAILS zim_mis ON (form.RDATA_FILEU = zim_mis.PUID)
INNER JOIN INFODBA.P_TEST_DETAILS test_details ON (zim_mis.PUID = test_details.PUID)
INNER JOIN INFODBA.P_PART_ASSOCIATION ppa ON (ppa.PUID = test_details.PUID)
INNER JOIN INFODBA.PMISDATAOBJECT mis ON (mis.PUID = ppa.PVALU_0)
INNER JOIN INFODBA.PZIMTESTDETAILS zim_test_details ON (test_details.PVALU_0 = zim_test_details.PUID)
WHERE Status.PNAME IN ('Current', 'BackLevel')";
/// <summary>
/// Gets MIS data updated since specified date from CMS database.
/// </summary>
public const string SqlGetMisDataFiltered = SqlGetMisData + @"
AND Status.PDATE_RELEASED >= :lastUpdateDT";
}
@@ -0,0 +1,113 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Inventory related SQL queries (Lots, Lot Usages, Lot Locations, Items)
/// </summary>
public static partial class JdeQueries
{
/// <summary>
/// Gets all lots from production schema.
/// </summary>
public const string SqlGetLots = @"
SELECT TRIM(lot.IOLOTN) AS LotNumber,
TRIM(lot.IOMCU) AS BranchCode,
lot.IOITM AS ShortItemNumber,
TRIM(lot.IOLITM) AS ItemNumber,
lot.IOVEND AS SupplierCode,
lot.IOLOTS AS StatusCode,
TRIM(lot.IOLOT1) AS Memo1,
TRIM(lot.IOLOT2) AS Memo2,
TRIM(lot.IOLOT3) AS Memo3,
lot.IOUPMJ AS LastUpdateDate,
lot.IOTDAY AS LastUpdateTime
FROM {ProductionSchema}.F4108 lot
WHERE TRIM(lot.IOLOTN) IS NOT NULL AND
TRIM(lot.IOMCU) IS NOT NULL";
/// <summary>
/// Gets lots updated since specified date from production schema.
/// </summary>
public const string SqlGetLotsFiltered = SqlGetLots + @"
AND (lot.IOUPMJ > :dateUpdated OR
(lot.IOUPMJ = :dateUpdated AND lot.IOTDAY >= :timeUpdated))";
/// <summary>
/// Gets all lot usages (cardex) from production schema.
/// </summary>
public const string SqlGetLotUsages = @"
SELECT lu.ILUKID AS UniqueId,
lu.ILDOCO AS WorkOrderNumber,
TRIM(lu.ILLOTN) AS LotNumber,
TRIM(lu.ILMCU) AS BranchCode,
lu.ILITM AS ShortItemNumber,
lu.ILTRQT AS Quantity,
lu.ILTRDJ AS LastUpdateDate,
lu.ILTDAY AS LastUpdateTime
FROM {ProductionSchema}.F4111 lu
WHERE lu.ILDCT = 'IM' AND
TRIM(lu.ILLOTN) IS NOT NULL";
/// <summary>
/// Gets lot usages updated since specified date from production schema.
/// </summary>
public const string SqlGetLotUsagesFiltered = SqlGetLotUsages + @"
AND (lu.ILTRDJ > :dateUpdated OR
(lu.ILTRDJ = :dateUpdated AND lu.ILTDAY >= :timeUpdated))";
/// <summary>
/// Gets all lot usages from archive schema.
/// </summary>
public const string SqlGetLotUsagesArchive = @"
SELECT lu.ILUKID AS UniqueId,
lu.ILDOCO AS WorkOrderNumber,
TRIM(lu.ILLOTN) AS LotNumber,
TRIM(lu.ILMCU) AS BranchCode,
lu.ILITM AS ShortItemNumber,
lu.ILTRQT AS Quantity,
lu.ILTRDJ AS LastUpdateDate,
lu.ILTDAY AS LastUpdateTime
FROM {ArchiveSchema}.F4111 lu
WHERE lu.ILDCT = 'IM' AND
TRIM(lu.ILLOTN) IS NOT NULL";
/// <summary>
/// Gets all lot locations from production schema.
/// </summary>
public const string SqlGetLotLocations = @"
SELECT TRIM(il.LILOTN) AS LotNumber,
il.LIITM AS ShortItemNumber,
TRIM(il.LIMCU) AS BranchCode,
COALESCE(TRIM(il.LILOCN), ' ') AS Location,
il.LIUPMJ AS LastUpdateDate,
il.LITDAY AS LastUpdateTime
FROM {ProductionSchema}.F41021 il
WHERE TRIM(il.LILOTN) IS NOT NULL";
/// <summary>
/// Gets lot locations updated since specified date from production schema.
/// </summary>
public const string SqlGetLotLocationsFiltered = SqlGetLotLocations + @"
AND (il.LIUPMJ > :dateUpdated OR
(il.LIUPMJ = :dateUpdated AND il.LITDAY >= :timeUpdated))";
/// <summary>
/// Gets all items from production schema.
/// </summary>
public const string SqlGetItems = @"
SELECT pn.IMITM AS ShortItemNumber,
TRIM(pn.IMLITM) AS ItemNumber,
TRIM(pn.IMDSC1) AS Description,
TRIM(pn.IMPRP4) AS PlanningFamily,
TRIM(pn.IMSTKT) AS StockingType,
pn.IMUPMJ AS LastUpdateDate,
pn.IMTDAY AS LastUpdateTime
FROM {ProductionSchema}.F4101 pn
WHERE TRIM(pn.IMLITM) IS NOT NULL";
/// <summary>
/// Gets items updated since specified date from production schema.
/// </summary>
public const string SqlGetItemsFiltered = SqlGetItems + @"
AND (pn.IMUPMJ > :dateUpdated OR
(pn.IMUPMJ = :dateUpdated AND pn.IMTDAY >= :timeUpdated))";
}
@@ -0,0 +1,50 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Lookup related SQL queries (Status Codes, Function Codes)
/// </summary>
public static partial class JdeQueries
{
/// <summary>
/// Gets all work order status codes from production schema.
/// Status codes are stored in UDC table F0005 with SY='00' and RT='SS'.
/// </summary>
public const string SqlGetStatusCodes = @"
SELECT TRIM(sc.DRKY) AS Code,
TRIM(sc.DRDL01) AS Description,
sc.DRUPMJ AS LastUpdateDate,
sc.DRUPMT AS LastUpdateTime
FROM {ProductionSchema}.F0005 sc
WHERE TRIM(sc.DRSY) = '00' AND
sc.DRRT = 'SS' AND
TRIM(sc.DRKY) IS NOT NULL";
/// <summary>
/// Gets status codes updated since specified date from production schema.
/// </summary>
public const string SqlGetStatusCodesFiltered = SqlGetStatusCodes + @"
AND (sc.DRUPMJ > :dateUpdated OR
(sc.DRUPMJ = :dateUpdated AND sc.DRUPMT >= :timeUpdated))";
/// <summary>
/// Gets all function codes from production schema.
/// Function codes are stored in F00192 (MES codes table).
/// Uses LISTAGG to concatenate multiple descriptions for same code.
/// </summary>
public const string SqlGetFunctionCodes = @"
SELECT Code,
TRIM(LISTAGG(Description, ' ') WITHIN GROUP(ORDER BY Description) ||
CASE WHEN MAX(total_lengthb) > 4000 THEN '...' ELSE '' END) AS Description,
SYSDATE AS LastUpdateDt
FROM (
SELECT TRIM(fc.CFKY) AS Code,
TRIM(ASCIISTR(fc.CFDS80)) AS Description,
SUM(LENGTHB(TRIM(fc.CFDS80))+1) OVER(PARTITION BY TRIM(fc.CFKY) ORDER BY TRIM(fc.CFDS80)) - 1 cumul_lengthb,
SUM(LENGTHB(TRIM(fc.CFDS80))+1) OVER(PARTITION BY TRIM(fc.CFKY)) - 1 total_lengthb,
COUNT(*) OVER(PARTITION BY TRIM(fc.CFKY)) num_values
FROM {ProductionSchema}.F00192 fc
WHERE TRIM(fc.CFKY) IS NOT NULL
)
WHERE total_lengthb <= 4000 OR cumul_lengthb <= 4000 - length('...')
GROUP BY Code";
}
@@ -0,0 +1,95 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Organization related SQL queries (Users, Business Units, Org Hierarchy, Route Masters)
/// </summary>
public static partial class JdeQueries
{
/// <summary>
/// Gets all JDE users from production schema.
/// Uses CTE to get unique users with most recent address book record.
/// </summary>
public const string SqlGetUsers = @"
WITH USER_CTE AS (
SELECT ab.ABAN8 AS AddressNumber,
TRIM(pro.ULUSER) AS UserId,
TRIM(ab.ABALPH) AS FullName,
ab.ABUPMJ AS LastUpdateDate,
ab.ABUPMT AS LastUpdateTime,
ROW_NUMBER() OVER (PARTITION BY ab.ABAN8 ORDER BY ab.ABUPMJ DESC, ab.ABUPMT DESC) RN
FROM {ProductionSchema}.F0101 ab
LEFT OUTER JOIN {ProductionSchema}.F0092 pro ON (ab.ABAN8 = pro.ULAN8)
WHERE ab.ABATE = 'Y'
)
SELECT AddressNumber,
UserId,
FullName,
LastUpdateDate,
LastUpdateTime
FROM USER_CTE
WHERE RN = 1";
/// <summary>
/// Gets all business units of specified type from production schema.
/// Type codes: 'WC' = Work Center, 'PC' = Profit Center, 'BR' = Branch
/// </summary>
public const string SqlGetBusinessUnits = @"
SELECT TRIM(wc.MCMCU) AS Code,
TRIM(wc.MCDL01) AS Description,
wc.MCUPMJ AS LastUpdateDate,
wc.MCUPMT AS LastUpdateTime
FROM {ProductionSchema}.F0006 wc
WHERE wc.MCSTYL = :typeCode";
/// <summary>
/// Gets business units of specified type updated since specified date from production schema.
/// </summary>
public const string SqlGetBusinessUnitsFiltered = SqlGetBusinessUnits + @"
AND (wc.MCUPMJ > :dateUpdated OR
(wc.MCUPMJ = :dateUpdated AND wc.MCUPMT >= :timeUpdated))";
/// <summary>
/// Gets all organization hierarchy records from production schema.
/// Maps work centers to profit centers and branches.
/// </summary>
public const string SqlGetOrgHierarchy = @"
SELECT TRIM(oh.IWMCUW) AS ProfitCenterCode,
TRIM(oh.IWMCU) AS WorkCenterCode,
TRIM(oh.IWMMCU) AS BranchCode,
oh.IWUPMJ AS LastUpdateDate,
oh.IWTDAY AS LastUpdateTime
FROM {ProductionSchema}.F30006 oh
WHERE TRIM(oh.IWMCU) IS NOT NULL AND
TRIM(oh.IWMMCU) IS NOT NULL";
/// <summary>
/// Gets org hierarchy records updated since specified date from production schema.
/// </summary>
public const string SqlGetOrgHierarchyFiltered = SqlGetOrgHierarchy + @"
AND (oh.IWUPMJ > :dateUpdated OR
(oh.IWUPMJ = :dateUpdated AND oh.IWTDAY >= :timeUpdated))";
/// <summary>
/// Gets all route masters from production schema.
/// </summary>
public const string SqlGetRouteMasters = @"
SELECT TRIM(rm.IRMMCU) AS BranchCode,
TRIM(rm.IRKITL) AS ItemNumber,
TRIM(rm.IRTRT) AS RoutingType,
rm.IROPSQ / 10.0 AS SequenceNumber,
TRIM(rm.IRURRF) AS FunctionCode,
TRIM(rm.IRMCU) AS WorkCenterCode,
rm.IREFFF AS StartDateDate,
rm.IREFFT AS EndDateDate,
rm.IRUPMJ AS LastUpdateDate,
rm.IRTDAY AS LastUpdateTime
FROM {ProductionSchema}.F3003 rm
WHERE TRIM(rm.IRKITL) IS NOT NULL";
/// <summary>
/// Gets route masters updated since specified date from production schema.
/// </summary>
public const string SqlGetRouteMastersFiltered = SqlGetRouteMasters + @"
AND (rm.IRUPMJ > :dateUpdated OR
(rm.IRUPMJ = :dateUpdated AND rm.IRTDAY >= :timeUpdated))";
}
@@ -0,0 +1,234 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Work order related SQL queries (Work Orders, Steps, Times, Routings, Components)
/// </summary>
public static partial class JdeQueries
{
/// <summary>
/// Gets all work orders from production schema.
/// </summary>
public const string SqlGetWorkorders = @"
SELECT wo.WADOCO AS WorkOrderNumber,
TRIM(wo.WAMMCU) AS BranchCode,
TRIM(wo.WALOTN) AS LotNumber,
TRIM(wo.WALITM) AS ItemNumber,
wo.WAITM AS ShortItemNumber,
TRIM(wo.WAPARS) AS ParentWorkOrderNumber,
wo.WAUORG / 100.0 AS OrderQuantity,
wo.WASOBK / 100.0 AS HeldQuantity,
wo.WASOQS / 100.0 AS ShippedQuantity,
TRIM(wo.WASRST) AS StatusCode,
CASE wo.WADCG WHEN 0 THEN TO_DATE('1900-01-01', 'YYYY-MM-DD')
ELSE TO_DATE(wo.WADCG+1900000,'YYYYDDD') END AS StatusCodeUpdateDT,
CASE wo.WATRDJ WHEN 0 THEN TO_DATE('1900-01-01', 'YYYY-MM-DD')
ELSE TO_DATE(wo.WATRDJ+1900000,'YYYYDDD') END AS IssueDate,
CASE wo.WASTRT WHEN 0 THEN TO_DATE('1900-01-01', 'YYYY-MM-DD')
ELSE TO_DATE(wo.WASTRT+1900000,'YYYYDDD') END AS StartDate,
TRIM(wo.WATRT) AS RoutingType,
wo.WAUPMJ AS LastUpdateDate,
wo.WATDAY AS LastUpdateTime
FROM {ProductionSchema}.F4801 wo";
/// <summary>
/// Gets work orders updated since specified date from production schema.
/// </summary>
public const string SqlGetWorkordersFiltered = SqlGetWorkorders + @"
WHERE (wo.WAUPMJ > :dateUpdated OR
(wo.WAUPMJ = :dateUpdated AND wo.WATDAY >= :timeUpdated))";
/// <summary>
/// Gets all work orders from archive schema.
/// </summary>
public const string SqlGetWorkordersArchive = @"
SELECT wo.WADOCO AS WorkOrderNumber,
TRIM(wo.WAMMCU) AS BranchCode,
TRIM(wo.WALOTN) AS LotNumber,
TRIM(wo.WALITM) AS ItemNumber,
wo.WAITM AS ShortItemNumber,
TRIM(wo.WAPARS) AS ParentWorkOrderNumber,
wo.WAUORG / 100.0 AS OrderQuantity,
wo.WASOBK / 100.0 AS HeldQuantity,
wo.WASOQS / 100.0 AS ShippedQuantity,
TRIM(wo.WASRST) AS StatusCode,
CASE wo.WADCG WHEN 0 THEN TO_DATE('1900-01-01', 'YYYY-MM-DD')
ELSE TO_DATE(wo.WADCG+1900000,'YYYYDDD') END AS StatusCodeUpdateDT,
CASE wo.WATRDJ WHEN 0 THEN TO_DATE('1900-01-01', 'YYYY-MM-DD')
ELSE TO_DATE(wo.WATRDJ+1900000,'YYYYDDD') END AS IssueDate,
CASE wo.WASTRT WHEN 0 THEN TO_DATE('1900-01-01', 'YYYY-MM-DD')
ELSE TO_DATE(wo.WASTRT+1900000,'YYYYDDD') END AS StartDate,
TRIM(wo.WATRT) AS RoutingType,
wo.WAUPMJ AS LastUpdateDate,
wo.WATDAY AS LastUpdateTime
FROM {ArchiveSchema}.F4801 wo";
/// <summary>
/// Gets work order steps from production schema.
/// </summary>
public const string SqlGetWorkorderSteps = @"
SELECT wos.WLDOCO AS WorkOrderNumber,
wos.WLOPSQ/10 AS StepNumber,
TRIM(wos.WLMCU) AS WorkCenterCode,
TRIM(wos.WLMMCU) AS BranchCode,
TRIM(wos.WLDSC1) AS StepDescription,
TRIM(mes.CFDS80) AS FunctionOperationDescription,
wos.WLOPSC AS StepTypeCode,
CASE wos.WLSTRT WHEN 0 THEN NULL
ELSE TO_DATE(wos.WLSTRT+1900000,'YYYYDDD') END AS StartDT,
CASE wos.WLSTRX WHEN 0 THEN NULL
ELSE TO_DATE(wos.WLSTRX+1900000,'YYYYDDD') END AS EndDT,
TRIM(wos.WLURRF) AS FunctionCode,
wos.WLSOCN / 100.0 AS ScrappedQuantity,
wos.WLUPMJ AS LastUpdateDate,
wos.WLTDAY AS LastUpdateTime
FROM {ProductionSchema}.F3112 wos
LEFT OUTER JOIN {ProductionSchema}.F00192 mes ON (wos.WLURRF = mes.CFKY)
WHERE TRIM(wos.WLMCU) IS NOT NULL AND
TRIM(wos.WLMMCU) IS NOT NULL";
/// <summary>
/// Gets work order steps updated since specified date from production schema.
/// </summary>
public const string SqlGetWorkorderStepsFiltered = SqlGetWorkorderSteps + @"
AND (wos.WLUPMJ > :dateUpdated OR
(wos.WLUPMJ = :dateUpdated AND wos.WLTDAY >= :timeUpdated))";
/// <summary>
/// Gets work order steps from archive schema.
/// </summary>
public const string SqlGetWorkorderStepsArchive = @"
SELECT wos.WLDOCO AS WorkOrderNumber,
wos.WLOPSQ/10 AS StepNumber,
TRIM(wos.WLMCU) AS WorkCenterCode,
TRIM(wos.WLMMCU) AS BranchCode,
TRIM(wos.WLDSC1) AS StepDescription,
TRIM(mes.CFDS80) AS FunctionOperationDescription,
wos.WLOPSC AS StepTypeCode,
CASE wos.WLSTRT WHEN 0 THEN NULL
ELSE TO_DATE(wos.WLSTRT+1900000,'YYYYDDD') END AS StartDT,
CASE wos.WLSTRX WHEN 0 THEN NULL
ELSE TO_DATE(wos.WLSTRX+1900000,'YYYYDDD') END AS EndDT,
TRIM(wos.WLURRF) AS FunctionCode,
wos.WLSOCN / 100.0 AS ScrappedQuantity,
wos.WLUPMJ AS LastUpdateDate,
wos.WLTDAY AS LastUpdateTime
FROM {ArchiveSchema}.F3112 wos
LEFT OUTER JOIN {ProductionSchema}.F00192 mes ON (wos.WLURRF = mes.CFKY)
WHERE TRIM(wos.WLMCU) IS NOT NULL AND
TRIM(wos.WLMMCU) IS NOT NULL";
/// <summary>
/// Gets work order time transactions from production schema.
/// </summary>
public const string SqlGetWorkorderTimes = @"
SELECT wot.WTUKID AS UniqueID,
wot.WTDOCO AS WorkOrderNumber,
wot.WTOPSQ/10 AS StepNumber,
TRIM(wot.WTMCU) AS WorkCenterCode,
TRIM(wot.WTMMCU) AS BranchCode,
wot.WTAN8 AS AddressNumber,
CASE wot.WTDGL WHEN 0 THEN NULL
ELSE TO_DATE(wot.WTDGL+1900000,'YYYYDDD') END AS GlDate,
wot.WTUPMJ AS LastUpdateDate,
wot.WTTDAY AS LastUpdateTime
FROM {ProductionSchema}.F31122 wot
WHERE TRIM(wot.WTMCU) IS NOT NULL AND
TRIM(wot.WTMMCU) IS NOT NULL";
/// <summary>
/// Gets work order times updated since specified date from production schema.
/// </summary>
public const string SqlGetWorkorderTimesFiltered = SqlGetWorkorderTimes + @"
AND (wot.WTUPMJ > :dateUpdated OR
(wot.WTUPMJ = :dateUpdated AND wot.WTTDAY >= :timeUpdated))";
/// <summary>
/// Gets work order time transactions from archive schema.
/// </summary>
public const string SqlGetWorkorderTimesArchive = @"
SELECT wot.WTUKID AS UniqueID,
wot.WTDOCO AS WorkOrderNumber,
wot.WTOPSQ/10 AS StepNumber,
TRIM(wot.WTMCU) AS WorkCenterCode,
TRIM(wot.WTMMCU) AS BranchCode,
wot.WTAN8 AS AddressNumber,
CASE wot.WTDGL WHEN 0 THEN NULL
ELSE TO_DATE(wot.WTDGL+1900000,'YYYYDDD') END AS GlDate,
wot.WTUPMJ AS LastUpdateDate,
wot.WTTDAY AS LastUpdateTime
FROM {ArchiveSchema}.F31122 wot
WHERE TRIM(wot.WTMCU) IS NOT NULL AND
TRIM(wot.WTMMCU) IS NOT NULL";
/// <summary>
/// Gets work order routing transactions from production schema.
/// </summary>
public const string SqlGetWorkorderRoutings = @"
SELECT TRIM(woz.SZEDUS) AS UserID,
TRIM(woz.SZEDBT) AS BatchNumber,
TRIM(woz.SZEDTN) AS TransactionNumber,
woz.SZEDLN AS LineNumber,
woz.SZOPSQ / 10.0 AS StepNumber,
TRIM(woz.SZMCU) AS WorkCenterCode,
woz.SZDOCO AS WorkOrderNumber,
TRIM(woz.SZTRT) AS RoutingType,
TRIM(woz.SZMMCU) AS BranchCode,
TRIM(woz.SZDSC1) AS StepDescription,
TRIM(woz.SZURRF) AS FunctionCode,
woz.SZTRDJ AS TransactionDate_Date,
woz.SZUPMJ AS LastUpdateDate,
woz.SZTDAY AS LastUpdateTime
FROM {ProductionSchema}.F3112Z1 woz
WHERE woz.SZTYTN = 'JDERTG' AND
woz.SZDRIN = '2' AND
woz.SZTNAC = '02' AND
woz.SZPID = 'ER31410' AND
TRIM(woz.SZEDUS) IS NOT NULL AND
TRIM(woz.SZEDBT) IS NOT NULL AND
TRIM(woz.SZEDTN) IS NOT NULL AND
TRIM(woz.SZMCU) IS NOT NULL";
/// <summary>
/// Gets work order routings updated since specified date from production schema.
/// </summary>
public const string SqlGetWorkorderRoutingsFiltered = SqlGetWorkorderRoutings + @"
AND (woz.SZUPMJ > :dateUpdated OR
(woz.SZUPMJ = :dateUpdated AND woz.SZTDAY >= :timeUpdated))";
/// <summary>
/// Gets work order component usage from production schema.
/// </summary>
public const string SqlGetWorkorderComponents = @"
SELECT woc.WMUKID AS UniqueID,
woc.WMDOCO AS WorkOrderNumber,
TRIM(woc.WMLOTN) AS LotNumber,
TRIM(woc.WMCMCU) AS BranchCode,
woc.WMCPIT AS ShortItemNumber,
woc.WMTRQT / 100.0 AS Quantity,
woc.WMUPMJ AS LastUpdateDate,
woc.WMTDAY AS LastUpdateTime
FROM {ProductionSchema}.F3111 woc
WHERE TRIM(woc.WMLOTN) IS NOT NULL";
/// <summary>
/// Gets work order components updated since specified date from production schema.
/// </summary>
public const string SqlGetWorkorderComponentsFiltered = SqlGetWorkorderComponents + @"
AND (woc.WMUPMJ > :dateUpdated OR
(woc.WMUPMJ = :dateUpdated AND woc.WMTDAY >= :timeUpdated))";
/// <summary>
/// Gets work order component usage from archive schema.
/// </summary>
public const string SqlGetWorkorderComponentsArchive = @"
SELECT woc.WMUKID AS UniqueID,
woc.WMDOCO AS WorkOrderNumber,
TRIM(woc.WMLOTN) AS LotNumber,
TRIM(woc.WMCMCU) AS BranchCode,
woc.WMCPIT AS ShortItemNumber,
woc.WMTRQT / 100.0 AS Quantity,
woc.WMUPMJ AS LastUpdateDate,
woc.WMTDAY AS LastUpdateTime
FROM {ArchiveSchema}.F3111 woc
WHERE TRIM(woc.WMLOTN) IS NOT NULL";
}
@@ -0,0 +1,9 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// SQL query constants for the JDE Oracle database.
/// Schema placeholders ({ProductionSchema}, {ArchiveSchema}, {StageSchema}) are replaced at runtime.
/// </summary>
public static partial class JdeQueries
{
}
@@ -0,0 +1,111 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Data sync and maintenance SQL queries
/// </summary>
public static partial class LotFinderQueries
{
/// <summary>
/// Gets the last data update record for each table/update type combination.
/// </summary>
public const string SqlGetLastDataUpdates = @"
WITH DU_CTE AS (
SELECT du.*,
ROW_NUMBER() OVER (PARTITION BY du.TableName, du.UpdateType ORDER BY du.StartDT DESC) RN
FROM dbo.DataUpdate AS du
)
SELECT cte.SourceSystem,
cte.SourceData,
cte.TableName,
cte.StartDT,
cte.EndDT,
cte.UpdateType,
cte.WasSuccessful,
cte.NumberRecords
FROM DU_CTE cte
WHERE cte.RN = 1";
/// <summary>
/// Gets column metadata for a table.
/// </summary>
public const string SqlGetTableColumns = @"
SELECT c.name AS Name,
CASE t2.name
WHEN 'varchar' THEN 'VARCHAR(' + CAST(c.max_length AS VARCHAR(10)) + ')'
WHEN 'decimal' THEN 'DECIMAL(' + CAST(c.precision AS VARCHAR(4)) + ',' + CAST(c.scale AS VARCHAR(4)) + ')'
ELSE UPPER(t2.name)
END AS Definition
FROM sys.columns c
INNER JOIN sys.types AS t2 ON (c.system_type_id = t2.system_type_id)
INNER JOIN sys.tables t ON (c.object_id = t.object_id)
WHERE t.name = @name
ORDER BY c.column_id";
/// <summary>
/// Gets primary key columns for a table.
/// </summary>
public const string SqlGetTablePrimaryKey = @"
SELECT COLUMN_NAME AS Name
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1 AND
TABLE_NAME = @name
ORDER BY ORDINAL_POSITION";
/// <summary>
/// Rebuilds all indices on a table. Use string.Format to inject table name.
/// </summary>
public const string SqlRebuildIndices = "ALTER INDEX ALL ON {0} REBUILD WITH (FILLFACTOR = 95);";
/// <summary>
/// Post-processing script to set MIS data obsoletion dates.
/// </summary>
public const string SqlPostprocessMisData = @"
SET ANSI_WARNINGS OFF;
WITH cte AS (
SELECT md.MisNumber, md.RevID, md.Status, MIN(md.ReleaseDate) Released
FROM dbo.MisData AS md
GROUP BY md.MisNumber, md.RevID, md.Status
)
UPDATE dbo.MisData
SET ObsoleteDate = bl.Released
FROM cte bl
WHERE MisData.MisNumber = bl.MisNumber AND
MisData.RevID = bl.RevID AND
MisData.Status = 'Current' AND
bl.Status = 'BackLevel';
WITH cte AS (
SELECT md.MisNumber, md.RevID, md.Status, MIN(md.ReleaseDate) Released
FROM dbo.MisData AS md
GROUP BY md.MisNumber, md.RevID, md.Status
)
UPDATE dbo.MisData
SET ObsoleteDate = (SELECT TOP 1 nl.Released
FROM cte nl
WHERE MisData.MisNumber = nl.MisNumber AND
MisData.RevID < nl.RevID AND
MisData.Status = nl.Status
ORDER BY nl.RevID)
WHERE ObsoleteDate IS NULL;
ALTER INDEX [PK_MisData] ON [dbo].[MisData] REBUILD;";
/// <summary>
/// Inserts a new data update tracking record.
/// </summary>
public const string SqlInsertDataUpdate = @"
INSERT INTO dbo.DataUpdate (SourceSystem, SourceData, TableName, StartDT, UpdateType)
VALUES (@sourceSystem, @sourceData, @tableName, @startDT, @updateType);
SELECT CAST(SCOPE_IDENTITY() AS BIGINT);";
/// <summary>
/// Completes a data update tracking record.
/// </summary>
public const string SqlCompleteDataUpdate = @"
UPDATE dbo.DataUpdate
SET EndDT = @endDT,
WasSuccessful = @wasSuccessful,
NumberRecords = @numberRecords
WHERE ID = @id";
}
@@ -0,0 +1,131 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Reference data lookup SQL queries
/// </summary>
public static partial class LotFinderQueries
{
/// <summary>
/// Searches items by number or description.
/// </summary>
public const string SqlSearchItems = @"
SELECT TOP 25
i.ShortItemNumber,
i.ItemNumber,
i.Description,
i.LastUpdateDT
FROM dbo.Item AS i
WHERE i.ItemNumber LIKE '%' + @filter + '%' OR
i.Description LIKE '%' + @filter + '%'
ORDER BY i.ItemNumber";
/// <summary>
/// Looks up items by exact item numbers using table-valued parameter.
/// </summary>
public const string SqlLookupItems = @"
SELECT i.ShortItemNumber,
i.ItemNumber,
i.Description,
i.LastUpdateDT
FROM dbo.Item AS i
INNER JOIN @itemNumbers AS i2 ON (i.ItemNumber = i2.ItemNumber)
ORDER BY i.ItemNumber";
/// <summary>
/// Looks up work orders by work order numbers using table-valued parameter.
/// </summary>
public const string SqlLookupWorkorders = @"
SELECT *
FROM dbo.WorkOrder AS wo
INNER JOIN @workOrderNumbers wo2 ON (wo.WorkOrderNumber = wo2.WorkOrderNumber)";
/// <summary>
/// Searches work centers by code or description.
/// </summary>
public const string SqlSearchWorkCenters = @"
SELECT TOP 25
wc.Code,
wc.Description,
wc.LastUpdateDT
FROM dbo.WorkCenter AS wc
WHERE wc.Code LIKE '%' + @filter + '%' OR
wc.Description LIKE '%' + @filter + '%'
ORDER BY wc.Code";
/// <summary>
/// Looks up work centers by codes using table-valued parameter.
/// </summary>
public const string SqlLookupWorkCenters = @"
SELECT wc.Code,
wc.Description,
wc.LastUpdateDT
FROM dbo.WorkCenter AS wc
INNER JOIN @workCenterCodes wc2 ON (wc.Code = wc2.Code)
ORDER BY wc.Code";
/// <summary>
/// Searches profit centers by code or description.
/// </summary>
public const string SqlSearchProfitCenters = @"
SELECT TOP 25
pc.Code,
pc.Description,
pc.LastUpdateDT
FROM dbo.ProfitCenter AS pc
WHERE pc.Code LIKE '%' + @filter + '%' OR
pc.Description LIKE '%' + @filter + '%'
ORDER BY pc.Code";
/// <summary>
/// Looks up profit centers by codes using table-valued parameter.
/// </summary>
public const string SqlLookupProfitCenters = @"
SELECT pc.Code,
pc.Description,
pc.LastUpdateDT
FROM dbo.ProfitCenter AS pc
INNER JOIN @profitCenterCodes AS pc2 ON (pc.Code = pc2.Code)
ORDER BY pc.Code";
/// <summary>
/// Searches users by user ID, full name, or address number.
/// </summary>
public const string SqlSearchUsers = @"
SELECT TOP 25
u.AddressNumber,
COALESCE(u.UserID,' ') AS UserID,
u.FullName,
u.LastUpdateDT
FROM dbo.JdeUser AS u
WHERE u.UserID LIKE '%' + @filter + '%' OR
u.FullName LIKE '%' + @filter + '%' OR
CAST(u.AddressNumber AS VARCHAR(10)) LIKE '%' + @filter + '%'
ORDER BY u.UserID, u.FullName";
/// <summary>
/// Looks up users by user IDs or address numbers using table-valued parameter.
/// </summary>
public const string SqlLookupUsers = @"
SELECT u.AddressNumber,
u.UserID,
u.FullName,
u.LastUpdateDT
FROM dbo.JdeUser AS u
INNER JOIN @userIDs u2 ON (u.UserID = u2.UserName OR CAST(u.AddressNumber AS VARCHAR(20)) = u2.UserName)
ORDER BY u.UserID";
/// <summary>
/// Looks up lots by lot number and item number using table-valued parameter.
/// </summary>
public const string SqlLookupLots = @"
SELECT DISTINCT
l.LotNumber,
l.BranchCode,
l.ShortItemNumber,
l.ItemNumber,
l.SupplierCode,
l.LastUpdateDT
FROM dbo.Lot AS l
INNER JOIN @lotNumbers ln ON (l.LotNumber = ln.ComponentLotNumber AND
((l.ItemNumber IS NULL AND ln.ItemNumber IS NULL) OR l.ItemNumber = ln.ItemNumber))";
}
@@ -0,0 +1,76 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// Search management SQL queries
/// </summary>
public static partial class LotFinderQueries
{
/// <summary>
/// Gets a user's searches (lightweight - no criteria or results).
/// </summary>
public const string SqlGetUserSearches = @"
SELECT s.ID,
s.Name,
s.Status,
s.SubmitDT,
s.StartDT,
s.EndDT
FROM dbo.Search s
WHERE s.UserName = @userName
ORDER BY s.SubmitDT";
/// <summary>
/// Gets all queued searches (Status less than 3 = New, Submitted, Started).
/// </summary>
public const string SqlGetQueuedSearches = @"
SELECT s.ID,
s.UserName,
s.Name,
s.Status,
s.SubmitDT,
s.StartDT,
s.EndDT
FROM dbo.Search s
WHERE s.Status < 3
ORDER BY s.SubmitDT";
/// <summary>
/// Gets a single search by ID with criteria.
/// </summary>
public const string SqlGetSearch = @"
SELECT s.UserName,
s.Name,
s.Status,
s.SubmitDT,
s.StartDT,
s.EndDT,
s.Criteria as CriteriaJSON
FROM dbo.Search s
WHERE s.ID = @id";
/// <summary>
/// Gets the binary results for a search.
/// </summary>
public const string SqlGetSearchResults = @"
SELECT s.Results
FROM dbo.Search AS s
WHERE s.ID = @id";
/// <summary>
/// Updates search status.
/// </summary>
public const string SqlUpdateSearchStatus = @"
UPDATE dbo.Search
SET Status = @status,
StartDT = CASE WHEN @status = 2 THEN GETUTCDATE() ELSE StartDT END,
EndDT = CASE WHEN @status >= 3 THEN GETUTCDATE() ELSE EndDT END
WHERE ID = @id";
/// <summary>
/// Updates search results.
/// </summary>
public const string SqlUpdateSearchResults = @"
UPDATE dbo.Search
SET Results = @results
WHERE ID = @id";
}
@@ -0,0 +1,8 @@
namespace JdeScoping.DataAccess.Queries;
/// <summary>
/// SQL query constants for the LotFinder SQL Server cache database.
/// </summary>
public static partial class LotFinderQueries
{
}