@chenchaolong/plugin-trade-compliance-workbench 1.0.42 → 1.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4062,18 +4062,10 @@ function analyticsAggregationStatement(scope, query, currentYear, purpose) {
4062
4062
  };
4063
4063
  }
4064
4064
  function analyticsDashboardJsonSql(query, tenant, organization, from, to) {
4065
- const amount = 'COALESCE("metricAmountCny", 0)';
4066
- const paid = query.mode === 'PURCHASE' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricPaidCny", 0)' : '0';
4067
- const unpaid = query.mode === 'PURCHASE' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricUnpaidCny", 0)' : '0';
4068
- const refunded = query.mode === 'PURCHASE' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricRefundedCny", 0)' : '0';
4069
- const unrefunded = query.mode === 'PURCHASE' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricUnrefundedCny", 0)' : '0';
4070
- const received = query.mode === 'SALES' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricReceivedCny", 0)' : '0';
4071
- const unreceived = query.mode === 'SALES' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricUnreceivedCny", 0)' : '0';
4072
- const purchaseTotal = query.mode === 'PURCHASE' ? amount : '0';
4073
- const salesTotal = query.mode === 'SALES' ? amount : '0';
4065
+ void query;
4074
4066
  const customerContractReviewCount = `(SELECT COUNT(*) FROM plugin_trade_compliance_import_task task WHERE task."tenantId" = ${tenant} AND task."organizationId" = ${organization} AND task."deletedAt" IS NULL AND task."documentType" = 'CUSTOMER_CONTRACT' AND task.status = 'AWAITING_REVIEW')`;
4075
4067
  const purchaseContractReviewCount = `(SELECT COUNT(*) FROM plugin_trade_compliance_import_task task WHERE task."tenantId" = ${tenant} AND task."organizationId" = ${organization} AND task."deletedAt" IS NULL AND task."documentType" = 'PURCHASE_CONTRACT' AND task.status = 'AWAITING_REVIEW')`;
4076
- const productRiskCount = `(SELECT COUNT(DISTINCT match."purchaseOrderLineId") FROM plugin_trade_compliance_product_match match WHERE match."tenantId" = ${tenant} AND match."organizationId" = ${organization} AND match."deletedAt" IS NULL)`;
4068
+ const productRiskCount = `(SELECT COUNT(DISTINCT match."purchaseOrderLineId") FROM plugin_trade_compliance_product_match match INNER JOIN plugin_trade_compliance_purchase_order_line line ON line.id = match."purchaseOrderLineId" AND line."tenantId" = match."tenantId" AND line."organizationId" = match."organizationId" AND line."deletedAt" IS NULL INNER JOIN plugin_trade_compliance_purchase_order purchase ON purchase.id = line."purchaseOrderId" AND purchase."tenantId" = line."tenantId" AND purchase."organizationId" = line."organizationId" AND purchase."deletedAt" IS NULL AND purchase."orderDate" BETWEEN ${from} AND ${to} WHERE match."tenantId" = ${tenant} AND match."organizationId" = ${organization} AND match."deletedAt" IS NULL)`;
4077
4069
  const sanctionHitCount = `(SELECT COUNT(*) FROM plugin_trade_compliance_company_sanction_match match WHERE match."tenantId" = ${tenant} AND match."organizationId" = ${organization} AND match."deletedAt" IS NULL)`;
4078
4070
  const salesFileReviewCount = `(SELECT COUNT(*) FROM plugin_trade_compliance_generated_sales_file file WHERE file."tenantId" = ${tenant} AND file."organizationId" = ${organization} AND file."deletedAt" IS NULL AND file."lastEditedAt" IS NULL)`;
4079
4071
  const complianceTodoCount = `(${customerContractReviewCount} + ${purchaseContractReviewCount} + ${productRiskCount} + ${sanctionHitCount} + ${salesFileReviewCount})`;
@@ -4110,15 +4102,57 @@ function analyticsDashboardJsonSql(query, tenant, organization, from, to) {
4110
4102
  GROUP BY EXTRACT(MONTH FROM purchase."orderDate")::int
4111
4103
  ) sales_month USING (month_no)
4112
4104
  ) monthly)`;
4113
- return `jsonb_build_object(
4105
+ return `(WITH purchase_scope AS (
4106
+ SELECT purchase.id, purchase."supplierId", supplier.name AS "supplierName", purchase."contractNo", purchase."orderDate",
4107
+ purchase."contractAmountCny" AS "purchaseTotalCny", purchase."paidAmountCny" AS "paidCny",
4108
+ GREATEST(purchase."contractAmountCny" - purchase."paidAmountCny", 0) AS "unpaidCny",
4109
+ purchase."refundedAmountCny" AS "refundedCny",
4110
+ GREATEST((SELECT COALESCE(SUM(refund_line."lineAmountTaxIncluded" / (1 + COALESCE(refund_line."vatRate", 0)) * COALESCE(refund_line."refundRate", 0)), 0) FROM plugin_trade_compliance_purchase_order_line refund_line WHERE refund_line."purchaseOrderId" = purchase.id AND refund_line."tenantId" = purchase."tenantId" AND refund_line."organizationId" = purchase."organizationId" AND refund_line."deletedAt" IS NULL) - purchase."refundedAmountCny", 0) AS "unrefundedCny"
4111
+ FROM plugin_trade_compliance_purchase_order purchase
4112
+ INNER JOIN plugin_trade_compliance_supplier supplier ON supplier.id = purchase."supplierId" AND supplier."tenantId" = purchase."tenantId" AND supplier."organizationId" = purchase."organizationId" AND supplier."deletedAt" IS NULL
4113
+ WHERE purchase."tenantId" = ${tenant} AND purchase."organizationId" = ${organization} AND purchase."deletedAt" IS NULL AND purchase."orderDate" BETWEEN ${from} AND ${to}
4114
+ ), sales_scope AS (
4115
+ SELECT raw.*, GREATEST(raw."salesTotalCny" - raw."receivedCny", 0) AS "unreceivedCny", GREATEST(raw."salesTotalCny" - raw."purchaseTotalCny", 0) AS "estimatedGrossProfitCny"
4116
+ FROM (
4117
+ SELECT contract.id AS "customerContractId", purchase.id AS "purchaseOrderId", customer.id AS "customerId", customer.name AS "customerName",
4118
+ COALESCE((SELECT sales_file."salesOrderNoSnapshot" FROM plugin_trade_compliance_generated_sales_file sales_file WHERE sales_file."customerContractId" = contract.id AND sales_file."purchaseOrderId" = purchase.id AND sales_file."tenantId" = contract."tenantId" AND sales_file."organizationId" = contract."organizationId" AND sales_file."deletedAt" IS NULL ORDER BY sales_file."generatedAt" DESC LIMIT 1), contract."contractNo") AS "salesOrderNo", purchase."orderDate",
4119
+ purchase."contractAmountCny" AS "purchaseTotalCny",
4120
+ (SELECT COALESCE(SUM(ROUND(ROUND(sales_line."unitPriceTaxIncluded" * (1 + COALESCE(manual."pricingProfitRateOverride", customer."defaultPricingProfitRate")), 0) * sales_line.quantity, 0)), 0) FROM plugin_trade_compliance_purchase_order_line sales_line WHERE sales_line."purchaseOrderId" = purchase.id AND sales_line."tenantId" = purchase."tenantId" AND sales_line."organizationId" = purchase."organizationId" AND sales_line."deletedAt" IS NULL) AS "salesTotalCny",
4121
+ COALESCE(manual."receivedAmountCny", 0) AS "receivedCny"
4122
+ FROM plugin_trade_compliance_customer_contract contract
4123
+ INNER JOIN plugin_trade_compliance_customer customer ON customer.id = contract."customerId" AND customer."tenantId" = contract."tenantId" AND customer."organizationId" = contract."organizationId" AND customer."deletedAt" IS NULL
4124
+ INNER JOIN plugin_trade_compliance_purchase_order purchase ON purchase."tenantId" = contract."tenantId" AND purchase."organizationId" = contract."organizationId" AND purchase."deletedAt" IS NULL AND contract."normalizedContractNo" = regexp_replace(purchase."normalizedContractNo", '(-[0-9]+)?C$', '') || 'X'
4125
+ LEFT JOIN plugin_trade_compliance_derived_sales_manual manual ON manual."customerContractId" = contract.id AND manual."purchaseOrderId" = purchase.id AND manual."tenantId" = contract."tenantId" AND manual."organizationId" = contract."organizationId" AND manual."deletedAt" IS NULL
4126
+ WHERE contract."tenantId" = ${tenant} AND contract."organizationId" = ${organization} AND contract."deletedAt" IS NULL AND purchase."orderDate" BETWEEN ${from} AND ${to}
4127
+ AND (manual."pricingProfitRateOverride" IS NOT NULL OR (customer."pricingProfitRateStatus" = 'CONFIGURED' AND customer."defaultPricingProfitRate" IS NOT NULL))
4128
+ ) raw
4129
+ ), global_purchase AS (
4130
+ SELECT COALESCE(SUM("purchaseTotalCny"), 0) AS "purchaseTotalCny", COALESCE(SUM("paidCny"), 0) AS "paidCny", COALESCE(SUM("unpaidCny"), 0) AS "unpaidCny", COALESCE(SUM("refundedCny"), 0) AS "refundedCny", COALESCE(SUM("unrefundedCny"), 0) AS "unrefundedCny"
4131
+ FROM purchase_scope
4132
+ ), global_sales AS (
4133
+ SELECT COALESCE(SUM("salesTotalCny"), 0) AS "salesTotalCny", COALESCE(SUM("receivedCny"), 0) AS "receivedCny", COALESCE(SUM("unreceivedCny"), 0) AS "unreceivedCny", COALESCE(SUM("estimatedGrossProfitCny"), 0) AS "estimatedGrossProfitCny"
4134
+ FROM sales_scope
4135
+ ), customer_top AS (
4136
+ SELECT "customerId", MIN("customerName") AS "customerName", SUM("salesTotalCny") AS "salesAmountCny", SUM("estimatedGrossProfitCny") AS "estimatedGrossProfitCny", SUM("unreceivedCny") AS "unreceivedCny", COUNT(*)::bigint AS "orderCount", MAX("orderDate") AS "latestOrderDate"
4137
+ FROM sales_scope GROUP BY "customerId" ORDER BY SUM("salesTotalCny") DESC LIMIT 5
4138
+ ), supplier_top AS (
4139
+ SELECT purchase_scope."supplierId", MIN(purchase_scope."supplierName") AS "supplierName", SUM(purchase_scope."unpaidCny") AS "unpaidCny", COUNT(*)::bigint AS "purchaseOrderCount",
4140
+ COUNT(DISTINCT product_match.id)::bigint AS "productRiskHitCount", COUNT(DISTINCT sanction_match.id)::bigint AS "sanctionHitCount"
4141
+ FROM purchase_scope
4142
+ LEFT JOIN plugin_trade_compliance_purchase_order_line line ON line."purchaseOrderId" = purchase_scope.id AND line."tenantId" = ${tenant} AND line."organizationId" = ${organization} AND line."deletedAt" IS NULL
4143
+ LEFT JOIN plugin_trade_compliance_product_match product_match ON product_match."purchaseOrderLineId" = line.id AND product_match."tenantId" = ${tenant} AND product_match."organizationId" = ${organization} AND product_match."deletedAt" IS NULL
4144
+ LEFT JOIN plugin_trade_compliance_company_sanction_match sanction_match ON sanction_match."supplierId" = purchase_scope."supplierId" AND sanction_match."tenantId" = ${tenant} AND sanction_match."organizationId" = ${organization} AND sanction_match."deletedAt" IS NULL
4145
+ GROUP BY purchase_scope."supplierId" ORDER BY SUM(purchase_scope."unpaidCny") DESC LIMIT 5
4146
+ )
4147
+ SELECT jsonb_build_object(
4114
4148
  'kpis', jsonb_build_object(
4115
- 'purchaseTotalCny', ${purchaseTotal}, 'salesTotalCny', ${salesTotal},
4116
- 'receivedCny', ${received}, 'unreceivedCny', ${unreceived}, 'paidCny', ${paid}, 'unpaidCny', ${unpaid},
4117
- 'refundedCny', ${refunded}, 'unrefundedCny', ${unrefunded},
4118
- 'estimatedGrossProfitCny', GREATEST(${salesTotal} - ${purchaseTotal}, 0),
4119
- 'estimatedGrossProfitRate', CASE WHEN ${salesTotal} > 0 THEN GREATEST(${salesTotal} - ${purchaseTotal}, 0) / ${salesTotal} ELSE 0 END,
4149
+ 'purchaseTotalCny', (SELECT "purchaseTotalCny" FROM global_purchase), 'salesTotalCny', (SELECT "salesTotalCny" FROM global_sales),
4150
+ 'receivedCny', (SELECT "receivedCny" FROM global_sales), 'unreceivedCny', (SELECT "unreceivedCny" FROM global_sales), 'paidCny', (SELECT "paidCny" FROM global_purchase), 'unpaidCny', (SELECT "unpaidCny" FROM global_purchase),
4151
+ 'refundedCny', (SELECT "refundedCny" FROM global_purchase), 'unrefundedCny', (SELECT "unrefundedCny" FROM global_purchase),
4152
+ 'estimatedGrossProfitCny', (SELECT "estimatedGrossProfitCny" FROM global_sales),
4153
+ 'estimatedGrossProfitRate', CASE WHEN (SELECT "salesTotalCny" FROM global_sales) > 0 THEN (SELECT "estimatedGrossProfitCny" FROM global_sales) / (SELECT "salesTotalCny" FROM global_sales) ELSE 0 END,
4120
4154
  'complianceTodoCount', ${complianceTodoCount},
4121
- 'riskExposureCny', (${unreceived} + ${unpaid})
4155
+ 'riskExposureCny', ((SELECT "unreceivedCny" FROM global_sales) + (SELECT "unpaidCny" FROM global_purchase) + (SELECT "unrefundedCny" FROM global_purchase))
4122
4156
  ),
4123
4157
  'monthlyTrend', ${monthlyTrend},
4124
4158
  'todos', jsonb_build_array(
@@ -4131,19 +4165,22 @@ function analyticsDashboardJsonSql(query, tenant, organization, from, to) {
4131
4165
  'riskDistribution', jsonb_build_array(
4132
4166
  jsonb_build_object('key', 'product-risk', 'label', '管控商品命中', 'count', ${productRiskCount}),
4133
4167
  jsonb_build_object('key', 'sanction-hit', 'label', '制裁公司命中', 'count', ${sanctionHitCount}),
4134
- jsonb_build_object('key', 'sales-file-review', 'label', '销售文件待复核', 'count', ${salesFileReviewCount})
4168
+ jsonb_build_object('key', 'customer-contract-review', 'label', '客户合同待审核', 'count', ${customerContractReviewCount}),
4169
+ jsonb_build_object('key', 'purchase-contract-review', 'label', '采购合同待审核', 'count', ${purchaseContractReviewCount}),
4170
+ jsonb_build_object('key', 'sales-file-review', 'label', '销售文件待复核', 'count', ${salesFileReviewCount}),
4171
+ jsonb_build_object('key', 'capital-risk', 'label', '未收/未付资金风险', 'count', (SELECT COUNT(*) FROM sales_scope WHERE "unreceivedCny" > 0) + (SELECT COUNT(*) FROM purchase_scope WHERE "unpaidCny" > 0), 'amountCny', ((SELECT "unreceivedCny" FROM global_sales) + (SELECT "unpaidCny" FROM global_purchase)))
4135
4172
  ),
4136
- 'customerValueTop5', '[]'::jsonb,
4137
- 'receivableRiskTop5', '[]'::jsonb,
4138
- 'supplierRiskTop5', '[]'::jsonb,
4139
- 'salesFileReviews', '[]'::jsonb,
4140
- 'riskOrders', '[]'::jsonb,
4173
+ 'customerValueTop5', (SELECT COALESCE(jsonb_agg(jsonb_build_object('customerId', customer_top."customerId", 'customerName', customer_top."customerName", 'salesAmountCny', customer_top."salesAmountCny", 'estimatedGrossProfitCny', customer_top."estimatedGrossProfitCny", 'estimatedGrossProfitRate', CASE WHEN customer_top."salesAmountCny" > 0 THEN customer_top."estimatedGrossProfitCny" / customer_top."salesAmountCny" ELSE 0 END, 'unreceivedCny', customer_top."unreceivedCny", 'riskStatus', CASE WHEN customer_top."unreceivedCny" >= 100000 THEN 'HIGH' WHEN customer_top."unreceivedCny" > 0 THEN 'MEDIUM' ELSE 'LOW' END) ORDER BY customer_top."salesAmountCny" DESC), '[]'::jsonb) FROM customer_top),
4174
+ 'receivableRiskTop5', (SELECT COALESCE(jsonb_agg(jsonb_build_object('customerId', customer_top."customerId", 'customerName', customer_top."customerName", 'unreceivedCny', customer_top."unreceivedCny", 'orderCount', customer_top."orderCount", 'latestOrderDate', customer_top."latestOrderDate") ORDER BY customer_top."unreceivedCny" DESC), '[]'::jsonb) FROM customer_top WHERE customer_top."unreceivedCny" > 0),
4175
+ 'supplierRiskTop5', (SELECT COALESCE(jsonb_agg(jsonb_build_object('supplierId', supplier_top."supplierId", 'supplierName', supplier_top."supplierName", 'unpaidCny', supplier_top."unpaidCny", 'sanctionHitCount', supplier_top."sanctionHitCount", 'productRiskHitCount', supplier_top."productRiskHitCount", 'purchaseOrderCount', supplier_top."purchaseOrderCount") ORDER BY supplier_top."unpaidCny" DESC), '[]'::jsonb) FROM supplier_top WHERE supplier_top."unpaidCny" > 0 OR supplier_top."sanctionHitCount" > 0 OR supplier_top."productRiskHitCount" > 0),
4176
+ 'salesFileReviews', (SELECT COALESCE(jsonb_agg(jsonb_build_object('fileId', file.id, 'fileName', file."fileName", 'fileType', file."fileType", 'salesOrderNo', file."salesOrderNoSnapshot", 'reason', '生成后尚未在线审核确认', 'generatedAt', file."generatedAt") ORDER BY file."generatedAt" DESC), '[]'::jsonb) FROM (SELECT * FROM plugin_trade_compliance_generated_sales_file file WHERE file."tenantId" = ${tenant} AND file."organizationId" = ${organization} AND file."deletedAt" IS NULL AND file."lastEditedAt" IS NULL ORDER BY file."generatedAt" DESC LIMIT 5) file),
4177
+ 'riskOrders', (SELECT COALESCE(jsonb_agg(risk_item.item), '[]'::jsonb) FROM (SELECT jsonb_build_object('orderKey', 'sales:' || sales_scope."purchaseOrderId"::text, 'orderNo', sales_scope."salesOrderNo", 'partyName', sales_scope."customerName", 'riskType', '未收款风险', 'riskAmountCny', sales_scope."unreceivedCny", 'status', '待跟进') AS item, sales_scope."unreceivedCny" AS amount FROM sales_scope WHERE sales_scope."unreceivedCny" > 0 UNION ALL SELECT jsonb_build_object('orderKey', 'purchase:' || purchase_scope.id::text, 'orderNo', purchase_scope."contractNo", 'partyName', purchase_scope."supplierName", 'riskType', '未付款风险', 'riskAmountCny', purchase_scope."unpaidCny", 'status', '待跟进') AS item, purchase_scope."unpaidCny" AS amount FROM purchase_scope WHERE purchase_scope."unpaidCny" > 0 ORDER BY amount DESC LIMIT 5) risk_item),
4141
4178
  'dataSources', jsonb_build_array(
4142
4179
  jsonb_build_object('label', '采购订单', 'description', '采购金额、付款记录、退税记录'),
4143
4180
  jsonb_build_object('label', '销售订单', 'description', '销售金额、收款记录、客户合同关联'),
4144
4181
  jsonb_build_object('label', '合规风险', 'description', '目录匹配、制裁匹配、合同审核、销售文件复核')
4145
4182
  )
4146
- )`;
4183
+ ))`;
4147
4184
  }
4148
4185
  function analyticsDetailFromRaw(row, query) {
4149
4186
  const base = { key: String(row.key), label: String(row.label), orderCount: Number(row.orderCount), amountCny: moneyString(row.amountCny) };