@chenchaolong/plugin-trade-compliance-workbench 1.0.39 → 1.0.41

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.
@@ -3188,7 +3188,7 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
3188
3188
  qb.andWhere(`row.${key} <= :range_${key}_to`, { [`range_${key}_to`]: range.to });
3189
3189
  }
3190
3190
  filters.apply?.(qb);
3191
- const [items, total] = await qb.orderBy('row.createdAt', 'DESC').skip((page - 1) * pageSize).take(pageSize).getManyAndCount();
3191
+ const [items, total] = await qb.orderBy('row.updatedAt', 'DESC').addOrderBy('row.id', 'DESC').skip((page - 1) * pageSize).take(pageSize).getManyAndCount();
3192
3192
  return { items, total, page, pageSize };
3193
3193
  }
3194
3194
  async pagedCatalogQuery(entity, batchEntity, scope, query, filters) {
@@ -3213,7 +3213,7 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
3213
3213
  if (hasQueryValue(range.to))
3214
3214
  qb.andWhere(`row.${key} <= :range_${key}_to`, { [`range_${key}_to`]: range.to });
3215
3215
  }
3216
- const [items, total] = await qb.orderBy('row.createdAt', 'DESC').skip((page - 1) * pageSize).take(pageSize).getManyAndCount();
3216
+ const [items, total] = await qb.orderBy('row.updatedAt', 'DESC').addOrderBy('row.id', 'DESC').skip((page - 1) * pageSize).take(pageSize).getManyAndCount();
3217
3217
  const batchIds = [...new Set(items.map(item => item.batchId).filter((id) => Boolean(id)))];
3218
3218
  const batches = batchIds.length ? await this.dataSource.getRepository(batchEntity).find({ where: { ...activeScope(scope), id: In(batchIds) } }) : [];
3219
3219
  const fileNames = new Map(batches.map(batch => [batch.id, batch.sourceFileName]));
@@ -4053,7 +4053,7 @@ function analyticsAggregationStatement(scope, query, currentYear, purpose) {
4053
4053
  : query.mode === 'PURCHASE'
4054
4054
  ? 'SUM("amountCny") OVER () AS "metricAmountCny", SUM("paidCny") OVER () AS "metricPaidCny", SUM("unpaidCny") OVER () AS "metricUnpaidCny", SUM("refundedCny") OVER () AS "metricRefundedCny", SUM("unrefundedCny") OVER () AS "metricUnrefundedCny"'
4055
4055
  : 'SUM("amountCny") OVER () AS "metricAmountCny", SUM("receivedCny") OVER () AS "metricReceivedCny", SUM("unreceivedCny") OVER () AS "metricUnreceivedCny"';
4056
- const dashboardJson = analyticsDashboardJsonSql(query, tenant, organization);
4056
+ const dashboardJson = analyticsDashboardJsonSql(query, tenant, organization, from, to);
4057
4057
  const start = (query.page - 1) * query.pageSize + 1;
4058
4058
  const end = start + query.pageSize - 1;
4059
4059
  return {
@@ -4061,7 +4061,7 @@ function analyticsAggregationStatement(scope, query, currentYear, purpose) {
4061
4061
  parameters
4062
4062
  };
4063
4063
  }
4064
- function analyticsDashboardJsonSql(query, tenant, organization) {
4064
+ function analyticsDashboardJsonSql(query, tenant, organization, from, to) {
4065
4065
  const amount = 'COALESCE("metricAmountCny", 0)';
4066
4066
  const paid = query.mode === 'PURCHASE' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricPaidCny", 0)' : '0';
4067
4067
  const unpaid = query.mode === 'PURCHASE' && query.dimension !== 'PRODUCT' ? 'COALESCE("metricUnpaidCny", 0)' : '0';
@@ -4077,6 +4077,39 @@ function analyticsDashboardJsonSql(query, tenant, organization) {
4077
4077
  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
4078
  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
4079
  const complianceTodoCount = `(${customerContractReviewCount} + ${purchaseContractReviewCount} + ${productRiskCount} + ${sanctionHitCount} + ${salesFileReviewCount})`;
4080
+ const monthlyTrend = `(SELECT COALESCE(jsonb_agg(jsonb_build_object(
4081
+ 'month', monthly.month_no,
4082
+ 'purchaseAmountCny', monthly."purchaseAmountCny",
4083
+ 'salesAmountCny', monthly."salesAmountCny",
4084
+ 'estimatedGrossProfitCny', GREATEST(monthly."salesAmountCny" - monthly."purchaseAmountCny", 0),
4085
+ 'receivedCny', monthly."receivedCny"
4086
+ ) ORDER BY monthly.month_no), '[]'::jsonb)
4087
+ FROM (
4088
+ SELECT month_no,
4089
+ COALESCE(purchase_month."purchaseAmountCny", 0) AS "purchaseAmountCny",
4090
+ COALESCE(sales_month."salesAmountCny", 0) AS "salesAmountCny",
4091
+ COALESCE(sales_month."receivedCny", 0) AS "receivedCny"
4092
+ FROM generate_series(1, 12) AS month_no
4093
+ LEFT JOIN (
4094
+ SELECT EXTRACT(MONTH FROM purchase."orderDate")::int AS month_no, SUM(purchase."contractAmountCny") AS "purchaseAmountCny"
4095
+ FROM plugin_trade_compliance_purchase_order purchase
4096
+ WHERE purchase."tenantId" = ${tenant} AND purchase."organizationId" = ${organization} AND purchase."deletedAt" IS NULL AND purchase."orderDate" BETWEEN ${from} AND ${to}
4097
+ GROUP BY EXTRACT(MONTH FROM purchase."orderDate")::int
4098
+ ) purchase_month USING (month_no)
4099
+ LEFT JOIN (
4100
+ SELECT EXTRACT(MONTH FROM purchase."orderDate")::int AS month_no,
4101
+ SUM(ROUND(ROUND(line."unitPriceTaxIncluded" * (1 + COALESCE(manual."pricingProfitRateOverride", customer."defaultPricingProfitRate")), 0) * line.quantity, 0)) AS "salesAmountCny",
4102
+ SUM(COALESCE(manual."receivedAmountCny", 0)) AS "receivedCny"
4103
+ FROM plugin_trade_compliance_customer_contract contract
4104
+ 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
4105
+ 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'
4106
+ 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
4107
+ INNER JOIN plugin_trade_compliance_purchase_order_line line ON line."purchaseOrderId" = purchase.id AND line."tenantId" = purchase."tenantId" AND line."organizationId" = purchase."organizationId" AND line."deletedAt" IS NULL
4108
+ WHERE contract."tenantId" = ${tenant} AND contract."organizationId" = ${organization} AND contract."deletedAt" IS NULL AND purchase."orderDate" BETWEEN ${from} AND ${to}
4109
+ AND (manual."pricingProfitRateOverride" IS NOT NULL OR (customer."pricingProfitRateStatus" = 'CONFIGURED' AND customer."defaultPricingProfitRate" IS NOT NULL))
4110
+ GROUP BY EXTRACT(MONTH FROM purchase."orderDate")::int
4111
+ ) sales_month USING (month_no)
4112
+ ) monthly)`;
4080
4113
  return `jsonb_build_object(
4081
4114
  'kpis', jsonb_build_object(
4082
4115
  'purchaseTotalCny', ${purchaseTotal}, 'salesTotalCny', ${salesTotal},
@@ -4087,7 +4120,7 @@ function analyticsDashboardJsonSql(query, tenant, organization) {
4087
4120
  'complianceTodoCount', ${complianceTodoCount},
4088
4121
  'riskExposureCny', (${unreceived} + ${unpaid})
4089
4122
  ),
4090
- 'monthlyTrend', '[]'::jsonb,
4123
+ 'monthlyTrend', ${monthlyTrend},
4091
4124
  'todos', jsonb_build_array(
4092
4125
  jsonb_build_object('key', 'customer-contract-review', 'label', '客户合同待审核', 'count', ${customerContractReviewCount}, 'priority', 'high', 'description', 'AI 解析完成但未人工确认的客户合同'),
4093
4126
  jsonb_build_object('key', 'purchase-contract-review', 'label', '采购合同待审核', 'count', ${purchaseContractReviewCount}, 'priority', 'high', 'description', '上传完成但未审核入库的采购合同'),