using SqlSugar;
namespace Admin.NET.Plugin.AiDOP.DataPlatform;
///
/// 第三方推送贴源行进入中立层。只投影已登记来源,未登记的实体直接跳过。
///
public sealed class InboundNeutralProjectionService : ITransient
{
private readonly ISqlSugarClient _db;
private readonly MdpNeutralSourceGate _gate;
public InboundNeutralProjectionService(ISqlSugarClient db, MdpNeutralSourceGate gate)
{
_db = db;
_gate = gate;
}
public async Task ProjectAsync(string entityCode, long tenantId, string sourceCode, CancellationToken cancellationToken = default)
=> await ProjectAsync(
entityCode, tenantId, sourceCode, MdpSourceIdentity.ApiInbound, cancellationToken);
public async Task ProjectAsync(
string entityCode,
long tenantId,
string sourceCode,
string writtenBy,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var code = (entityCode ?? "").Trim().ToUpperInvariant();
var neutral = MdpSourceIdentity.NeutralCode(null, sourceCode);
writtenBy = string.IsNullOrWhiteSpace(writtenBy) ? MdpSourceIdentity.ApiInbound : writtenBy.Trim();
switch (code)
{
case "S6_WORK_ORDER_LINE":
if (await _gate.AllowsAsync(tenantId, "WO_LINE_PROD", neutral, cancellationToken: cancellationToken))
await ProjectWorkOrderAsync(tenantId, neutral, writtenBy, "PROD_TASK", "mdp_stg_wo_line", cancellationToken);
break;
case "S7_SALES_ORDER_LINE":
if (await _gate.AllowsAsync(tenantId, "WO_LINE_SALES", neutral, cancellationToken: cancellationToken))
await ProjectWorkOrderAsync(tenantId, neutral, writtenBy, "SALES_ORDER", "mdp_stg_wo_line", cancellationToken);
break;
case "S6_REPORT_TXN":
if (await _gate.AllowsAsync(tenantId, "S6_REPORT", neutral, cancellationToken: cancellationToken))
await ProjectReportAsync(tenantId, neutral, writtenBy, cancellationToken);
break;
case "S5_WORK_ORDER_BOM":
if (await _gate.AllowsAsync(tenantId, "WO_BOM", neutral, cancellationToken: cancellationToken))
await ProjectBomAsync(tenantId, neutral, writtenBy, cancellationToken);
break;
case "S7_FQC_TASK_TXN":
if (await _gate.AllowsAsync(tenantId, "FQC_TASK", neutral, cancellationToken: cancellationToken))
await ProjectFqcAsync(tenantId, neutral, writtenBy, cancellationToken);
break;
case "S5_INVENTORY_BALANCE_MONTHLY":
if (await _gate.AllowsAsync(tenantId, "INV_BAL_MONTHLY", neutral, cancellationToken: cancellationToken))
await ProjectBalanceMonthlyAsync(tenantId, neutral, writtenBy, cancellationToken);
break;
case "S2_WORK_ORDER_SCHEDULE":
if (await _gate.AllowsAsync(tenantId, "WO_SCHEDULE", neutral, cancellationToken: cancellationToken))
await ProjectScheduleAsync(tenantId, neutral, cancellationToken);
break;
case "S3_PURCHASE_ORDER":
if (await _gate.AllowsAsync(tenantId, "PURCHASE", neutral, cancellationToken: cancellationToken))
await ProjectPurchaseOrderAsync(tenantId, neutral, cancellationToken);
break;
case "S3_PURCHASE_RECEIPT":
if (await _gate.AllowsAsync(tenantId, "PURCHASE", neutral, cancellationToken: cancellationToken))
await ProjectPurchaseReceiptAsync(tenantId, neutral, cancellationToken);
break;
case "S4_SHIPMENT":
case "S4_IQC":
case "S4_RETURN":
case "S4_SHORTAGE":
if (await _gate.AllowsAsync(tenantId, "SUPPLIER_DELIVERY", neutral, cancellationToken: cancellationToken))
await ProjectSupplierDeliveryAsync(code, tenantId, neutral, cancellationToken);
break;
case "S5_INVENTORY_TXN":
if (await _gate.AllowsAsync(tenantId, "INV_TRANS", neutral, cancellationToken: cancellationToken))
await _db.Ado.ExecuteCommandAsync(
ProjectApiInventorySql(),
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", neutral),
new SugarParameter("@writtenBy", writtenBy),
new SugarParameter("@now", DateTime.Now));
break;
}
}
private async Task ProjectWorkOrderAsync(long tenantId, string source, string writtenBy, string docType, string staging, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync(staging)) return;
await _db.Ado.ExecuteCommandAsync(
$"""
INSERT INTO mdp_std_work_order_line
(tenant_id, factory_id, source_system, written_by, domain, doc_type, src_doc_type_raw,
order_no, line_no, task_no, item_code, qty_planned, plan_finish_date,
closed_flag, void_flag, approved_flag, source_row_id, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src, @writtenBy,
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Domain')),'null'),''),
@doc, @doc,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.OrderNo')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.LineNo')),'null') AS SIGNED),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.OrderNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.QtyPlanned')),'null') AS DECIMAL(18,6)),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PlanFinishDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
IF(IFNULL(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ClosedFlag')),'0') IN ('1','true'), 1, 0),
IF(IFNULL(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.VoidFlag')),'0') IN ('1','true'), 1, 0),
1,
IFNULL(s.source_row_id, s.source_biz_key), s.source_biz_key, IFNULL(s.sync_batch_id,''), NOW()
FROM {staging} s
WHERE s.tenant_id=@tid AND IFNULL(s.process_status,'PENDING')<>'DONE'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), item_code=VALUES(item_code),
qty_planned=VALUES(qty_planned), sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source),
new SugarParameter("@writtenBy", writtenBy),
new SugarParameter("@doc", docType));
}
private async Task ProjectReportAsync(long tenantId, string source, string writtenBy, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_s6_report")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_s6_report
(tenant_id, factory_id, source_system, written_by, work_order_no, report_date, report_qty,
source_row_id, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src, @writtenBy,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.WorkOrderNo')),'null'),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReportDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReportQty')),'null') AS DECIMAL(18,6)),
IFNULL(s.source_row_id, s.source_biz_key), s.source_biz_key, IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_s6_report s
WHERE s.tenant_id=@tid AND s.source_table='S6_REPORT_TXN'
ON DUPLICATE KEY UPDATE source_system=VALUES(source_system),
report_qty=VALUES(report_qty), sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source),
new SugarParameter("@writtenBy", writtenBy));
}
private async Task ProjectScheduleAsync(long tenantId, string source, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_schedule")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_work_order_schedule
(tenant_id, factory_id, source_system, doc_type, work_order, item_code,
qty_ordered, qty_completed, due_date, status, prod_line,
source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DocType')),'null'),'PROD_TASK'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.WorkOrder')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.QtyOrdered')),'null') AS DECIMAL(18,6)),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.QtyCompleted')),'null') AS DECIMAL(18,6)),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DueDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Status')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ProdLine')),'null'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')),
IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_schedule s
WHERE s.tenant_id=@tid AND s.source_table='S2_WORK_ORDER_SCHEDULE'
AND IFNULL(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.WorkOrder')),'') NOT IN ('','null')
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), item_code=VALUES(item_code),
qty_ordered=VALUES(qty_ordered), qty_completed=VALUES(qty_completed),
due_date=VALUES(due_date), sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source));
}
private async Task ProjectPurchaseOrderAsync(long tenantId, string source, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_purchase_order")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_purchase_order
(tenant_id, factory_id, source_system, po_no, po_line, supplier_code, item_code,
order_qty, due_date, order_date, status, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoLine')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SupplierCode')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.OrderQty')),'null') AS DECIMAL(18,6)),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DueDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.OrderDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Status')),'null'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')),
IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_purchase_order s
WHERE s.tenant_id=@tid AND s.source_table='S3_PURCHASE_ORDER'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), order_qty=VALUES(order_qty),
status=VALUES(status), sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source));
}
private async Task ProjectPurchaseReceiptAsync(long tenantId, string source, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_purchase_receipt")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_purchase_receipt
(tenant_id, factory_id, source_system, domain, receiver, line, item_num,
qty_received, pur_ord, supp, rct_date, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Domain')),'null'),''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Receiver')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Line')),'null') AS SIGNED),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.QtyReceived')),'null') AS DECIMAL(18,6)),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SupplierCode')),'null'),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReceiptDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')),
IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_purchase_receipt s
WHERE s.tenant_id=@tid AND s.source_table='S3_PURCHASE_RECEIPT'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), qty_received=VALUES(qty_received),
sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source));
}
private async Task ProjectSupplierDeliveryAsync(string entityCode, long tenantId, string source, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var (table, std, sql) = entityCode switch
{
"S4_IQC" => ("mdp_stg_s4_iqc", "mdp_std_s4_iqc", """
INSERT INTO mdp_std_s4_iqc
(tenant_id, factory_id, source_system, po_no, po_line, supplier_code, item_code,
receipt_qty, defect_qty, qc_result, receipt_date, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoLine')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SupplierCode')),'null'),''),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),''),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReceiptQty')),'null') AS DECIMAL(18,6)),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DefectQty')),'null') AS DECIMAL(18,6)),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.QcResult')),'null'),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReceiptDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')), IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_s4_iqc s
WHERE s.tenant_id=@tid AND s.source_table='S4_IQC'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), receipt_qty=VALUES(receipt_qty),
defect_qty=VALUES(defect_qty), sync_time=VALUES(sync_time)
"""),
"S4_RETURN" => ("mdp_stg_s4_return", "mdp_std_s4_return", """
INSERT INTO mdp_std_s4_return
(tenant_id, factory_id, source_system, po_no, po_line, supplier_code, item_code,
return_qty, return_reason, return_status, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoLine')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SupplierCode')),'null'),''),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),''),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReturnQty')),'null') AS DECIMAL(18,6)),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReturnReason')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ReturnStatus')),'null'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')), IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_s4_return s
WHERE s.tenant_id=@tid AND s.source_table='S4_RETURN'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), return_qty=VALUES(return_qty),
sync_time=VALUES(sync_time)
"""),
"S4_SHORTAGE" => ("mdp_stg_s4_shortage", "mdp_std_s4_shortage", """
INSERT INTO mdp_std_s4_shortage
(tenant_id, factory_id, source_system, work_order, supplier_code, item_code,
shortage_qty, risk_level, need_date, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.WorkOrder')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SupplierCode')),'null'),''),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),''),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ShortageQty')),'null') AS DECIMAL(18,6)),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.RiskLevel')),'null'),'MEDIUM'),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.NeedDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')), IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_s4_shortage s
WHERE s.tenant_id=@tid AND s.source_table='S4_SHORTAGE'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), shortage_qty=VALUES(shortage_qty),
sync_time=VALUES(sync_time)
"""),
_ => ("mdp_stg_s4_shipment", "mdp_std_s4_shipment", """
INSERT INTO mdp_std_s4_shipment
(tenant_id, factory_id, source_system, shipment_no, po_no, po_line, supplier_code, item_code,
ship_qty, ship_date, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ShipmentNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PoLine')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SupplierCode')),'null'),''),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),''),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ShipQty')),'null') AS DECIMAL(18,6)),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ShipDate')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')), IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_s4_shipment s
WHERE s.tenant_id=@tid AND s.source_table='S4_SHIPMENT'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), ship_qty=VALUES(ship_qty),
ship_date=VALUES(ship_date), sync_time=VALUES(sync_time)
""")
};
_ = std;
if (!await TableExistsAsync(table)) return;
await _db.Ado.ExecuteCommandAsync(sql, new SugarParameter("@tid", tenantId), new SugarParameter("@src", source));
}
private async Task ProjectBomAsync(long tenantId, string source, string writtenBy, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_wo_bom")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_work_order_bom
(tenant_id, factory_id, source_system, written_by, domain, order_no, order_line_no,
item_code, qty_required, unit, source_row_id, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src, @writtenBy,
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Domain')),'null'),''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.OrderNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.LineNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.QtyRequired')),'null') AS DECIMAL(18,6)),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Unit')),'null'),
IFNULL(s.source_row_id, s.source_biz_key),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')),
IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_wo_bom s
WHERE s.tenant_id=@tid AND s.source_table='S5_WORK_ORDER_BOM'
AND IFNULL(s.process_status,'PENDING')<>'DONE'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), item_code=VALUES(item_code), qty_required=VALUES(qty_required),
unit=VALUES(unit), sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source),
new SugarParameter("@writtenBy", writtenBy));
}
private async Task ProjectFqcAsync(long tenantId, string source, string writtenBy, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_fqc_pull")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_fqc_task
(tenant_id, source_system, written_by, bill_no, production_order_no, material_code, qty,
sales_order_no, domain, source_row_id, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, @src, @writtenBy,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BillNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ProductionOrderNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.MaterialCode')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Qty')),'null') AS DECIMAL(18,6)),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SalesOrderNo')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Domain')),'null'),
IFNULL(s.source_row_id, s.source_biz_key),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')),
IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_fqc_pull s
WHERE s.tenant_id=@tid AND s.source_table='S7_FQC_TASK_TXN'
AND IFNULL(s.process_status,'PENDING')<>'DONE'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), material_code=VALUES(material_code),
qty=VALUES(qty), sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source),
new SugarParameter("@writtenBy", writtenBy));
}
private async Task ProjectBalanceMonthlyAsync(long tenantId, string source, string writtenBy, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (!await TableExistsAsync("mdp_stg_inv_bal_monthly")) return;
await _db.Ado.ExecuteCommandAsync(
"""
INSERT INTO mdp_std_inventory_balance_monthly
(tenant_id, factory_id, source_system, written_by, period_ym,
category_code, category_name, warehouse_code, warehouse_name, item_code,
avg_balance_amount, issue_cost_amount, source_biz_key, sync_batch_id, sync_time)
SELECT @tid, 1, @src, @writtenBy,
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.PeriodYm')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.CategoryCode')),'null'),''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.CategoryName')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.WarehouseCode')),'null'),''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.WarehouseName')),'null'),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'),''),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.AvgBalanceAmount')),'null') AS DECIMAL(18,6)),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.IssueCostAmount')),'null') AS DECIMAL(18,6)),
IFNULL(s.source_biz_key, IFNULL(s.source_row_id,'')),
IFNULL(s.sync_batch_id,''), NOW()
FROM mdp_stg_inv_bal_monthly s
WHERE s.tenant_id=@tid AND s.source_table='S5_INVENTORY_BALANCE_MONTHLY'
AND IFNULL(s.process_status,'PENDING')<>'DONE'
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), avg_balance_amount=VALUES(avg_balance_amount),
issue_cost_amount=VALUES(issue_cost_amount),
sync_time=VALUES(sync_time)
""",
new SugarParameter("@tid", tenantId),
new SugarParameter("@src", source),
new SugarParameter("@writtenBy", writtenBy));
}
private static string ProjectApiInventorySql()
{
const string biz = "NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BizDocType')),'null')";
const string trans = "NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.TransType')),'null')";
const string src = "COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SrcTransType')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BizDocType')),'null'))";
return $"""
INSERT INTO mdp_std_inv_trans
(tenant_id, source_system, written_by, domain, src_rec_id, item_num, qty_change, location,
lot_serial, create_user, begin_balance, end_balance, doc_qty, line_closed_flag,
trans_time, eff_date, approved_time, approved_flag, void_flag, summary_flag,
biz_doc_type, src_biz_doc_type_raw, trans_type, src_trans_type_raw, ref_task_no,
history_from, as_of, sync_batch_id, dimension1, dimension2)
SELECT
@tid, @src, @writtenBy,
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Domain')),'null'),''),
s.source_row_id,
COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.code')),'null')),
CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Qty')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.sl')),'null')) AS DECIMAL(18,6)),
COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Location')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Loc')),'null')),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.LotSerial')),'null'),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.CreateUser')),'null'),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BeginBalance')),'null') AS DECIMAL(18,6)),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.EndBalance')),'null') AS DECIMAL(18,6)),
CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DocQty')),'null') AS DECIMAL(18,6)),
IFNULL(CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.LineClosedFlag')),'null') AS SIGNED), 0),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.TransTime')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.addtime')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DocDate')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.date0')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
IFNULL(
STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ApprovedTime')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.shtime')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
@now),
IFNULL(CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ApprovedFlag')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.shyn')),'null')) AS SIGNED), 1),
IFNULL(CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.VoidFlag')),'null') AS SIGNED), 0),
IFNULL(CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SummaryFlag')),'null') AS SIGNED), 0),
{NeutralTransTypeCodes.KnownBizDocCase(biz)},
{biz},
{NeutralTransTypeCodes.ApiTransTypeCase(trans, biz)},
{src},
COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.RefTaskNo')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.rwnoid')),'null')),
@now, @now, IFNULL(s.sync_batch_id,''),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Dimension1')),'null'), ''),
IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Dimension2')),'null'), '')
FROM mdp_stg_inv_trans_inbound s
WHERE s.tenant_id=@tid
AND s.source_table='S5_INVENTORY_TXN'
AND s.source_row_id IS NOT NULL AND s.source_row_id<>''
ON DUPLICATE KEY UPDATE
source_system=VALUES(source_system), written_by=VALUES(written_by),
item_num=VALUES(item_num), qty_change=VALUES(qty_change), location=VALUES(location),
lot_serial=VALUES(lot_serial), create_user=VALUES(create_user),
begin_balance=VALUES(begin_balance), end_balance=VALUES(end_balance),
doc_qty=VALUES(doc_qty), line_closed_flag=VALUES(line_closed_flag),
dimension1=VALUES(dimension1), dimension2=VALUES(dimension2),
approved_time=VALUES(approved_time), approved_flag=VALUES(approved_flag),
void_flag=VALUES(void_flag), summary_flag=VALUES(summary_flag),
biz_doc_type=VALUES(biz_doc_type), src_biz_doc_type_raw=VALUES(src_biz_doc_type_raw),
trans_type=VALUES(trans_type), src_trans_type_raw=VALUES(src_trans_type_raw),
ref_task_no=VALUES(ref_task_no), sync_batch_id=VALUES(sync_batch_id), as_of=VALUES(as_of)
""";
}
private async Task TableExistsAsync(string table)
{
var n = await _db.Ado.GetIntAsync(
"SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=@t",
new SugarParameter("@t", table));
return n > 0;
}
}