>,total:int} */ public function prices(array $filters, int $page, int $limit): array { $where = [ "ISNULL(d.[delete], 0) = 0", 'price_info.latest_price IS NOT NULL', ]; $bindings = []; if (($filters['raw_name'] ?? '') !== '') { $where[] = 'd.name LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['raw_name']); } if (($filters['raw_code'] ?? '') !== '') { $where[] = 'd.number LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['raw_code']); } if (($filters['production_code'] ?? '') !== '') { $where[] = 'd.proNumber LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['production_code']); } if (($filters['supplier'] ?? '') !== '') { $where[] = 'supplier_info.target_supplier LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['supplier']); } $whereSql = implode(' AND ', $where); $page = max($page, 1); $limit = min(max($limit, 1), 100); $offset = ($page - 1) * $limit; $sql = "WITH source_rows AS ( SELECT d.name AS raw_name, d.number AS raw_code, d.proNumber AS production_code, CAST(price_info.latest_price AS decimal(18,2)) AS latest_price, supplier_info.target_supplier, ROW_NUMBER() OVER (ORDER BY d.number, d.proNumber) AS row_no, COUNT(*) OVER () AS total_count FROM [dbo].[pm_edgeBandData] d OUTER APPLY ( SELECT TOP 1 ad.giveSupplierName AS target_supplier FROM [dbo].[pm_edgeBandApplyDetail] ad WHERE ad.proNumber = d.proNumber AND ISNULL(ad.giveSupplierName, '') <> '' ORDER BY ad.inDate DESC, ad.Id DESC ) supplier_info OUTER APPLY ( SELECT TOP 1 p.priceA AS latest_price FROM [dbo].[pm_edgeBandProfitInfo] p WHERE p.name = d.name AND p.giveSupplierName = supplier_info.target_supplier AND ISNULL(p.priceA, 0) > 0 ORDER BY p.inDate DESC, p.id DESC ) price_info WHERE {$whereSql} ) SELECT raw_name, raw_code, production_code, latest_price, target_supplier, total_count FROM source_rows WHERE row_no BETWEEN ? AND ? ORDER BY row_no"; $rows = $this->query()->select($sql, array_merge($bindings, [$offset + 1, $offset + $limit])); foreach ($rows as &$row) { $row['price_type'] = '采购价'; $row['factory_type'] = '封边条厂'; } return $this->pageResult($rows); } /** @return array{data:array>,total:int} */ public function details(array $filters, int $page, int $limit): array { $where = ["d.number LIKE 'FBT%'"]; $bindings = []; if (($filters['date'] ?? '') !== '') { $where[] = 'CONVERT(date, d.inDate) = ?'; $bindings[] = $filters['date']; } if (($filters['production_code'] ?? '') !== '') { $where[] = 'd.number LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['production_code']); } if (($filters['raw_name'] ?? '') !== '') { $where[] = 'd.name LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['raw_name']); } if (($filters['return_flag'] ?? '') === 'return') { $where[] = 'COALESCE(d.inCount, d.deliveryCount, 0) < 0'; } elseif (($filters['return_flag'] ?? '') === 'normal') { $where[] = 'COALESCE(d.inCount, d.deliveryCount, 0) >= 0'; } if (($filters['outbound_supplier'] ?? '') !== '') { $where[] = 'd.giveSupplier LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['outbound_supplier']); } if (($filters['arrival_supplier'] ?? '') !== '') { $where[] = 'd.arrSupplier LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['arrival_supplier']); } if (($filters['outbound_no'] ?? '') !== '') { $where[] = "(ISNULL(d.deliveryNo, '') LIKE ? ESCAPE '\\' OR ISNULL(d.sendNo, '') LIKE ? ESCAPE '\\')"; $needle = $this->contains($filters['outbound_no']); $bindings[] = $needle; $bindings[] = $needle; } $whereSql = implode(' AND ', $where); $page = max($page, 1); $limit = min(max($limit, 1), 100); $offset = ($page - 1) * $limit; $sql = "WITH source_rows AS ( SELECT CONVERT(varchar(19), d.inDate, 120) AS inbound_date, d.number AS production_code, d.name AS raw_name, CAST(ISNULL(d.deliveryCount, 0) AS decimal(18,2)) AS outbound_quantity, ISNULL(d.giveSupplier, '') AS outbound_supplier, ISNULL(d.arrSupplier, '') AS arrival_supplier, CONVERT(varchar(10), d.date, 120) AS batch_date, ISNULL(d.deliveryNo, '') AS outbound_no, ISNULL(d.deliveryRemarks, '') AS outbound_remark, ISNULL(d.applyNo, '') AS requisition_no, ISNULL(d.numberType, '') AS number_type, ISNULL(d.sendNo, '') AS delivery_no, CAST(ISNULL(d.inCount, 0) AS decimal(18,2)) AS received_quantity, CAST(COALESCE(d.priceBAll, ISNULL(d.inCount, 0) * ISNULL(d.priceB, 0), 0) AS decimal(18,2)) AS reconciliation_amount, CAST(ISNULL(freight_info.transportCost, 0) AS decimal(18,2)) AS freight, CAST(ISNULL(d.price, 0) AS decimal(18,2)) AS edge_band_unit_price, CAST(COALESCE(d.priceAll, ISNULL(d.inCount, 0) * ISNULL(d.price, 0), 0) AS decimal(18,2)) AS payable_amount, CAST(ISNULL(d.priceB, 0) AS decimal(18,2)) AS furniture_unit_price, CAST(COALESCE(d.priceBAll, ISNULL(d.inCount, 0) * ISNULL(d.priceB, 0), 0) AS decimal(18,2)) AS furniture_amount, CAST(ISNULL(d.priceB, 0) - ISNULL(d.price, 0) AS decimal(18,2)) AS price_difference, CAST( COALESCE(d.priceBAll, ISNULL(d.inCount, 0) * ISNULL(d.priceB, 0), 0) - COALESCE(d.priceAll, ISNULL(d.inCount, 0) * ISNULL(d.price, 0), 0) AS decimal(18,2) ) AS profit, ROW_NUMBER() OVER (ORDER BY d.inDate DESC, d.id DESC) AS row_no, COUNT(*) OVER () AS total_count FROM [dbo].[finance_edgeBandDeductio] d OUTER APPLY ( SELECT TOP 1 ad.transportCost FROM [dbo].[pm_edgeBandApplyDetail] ad WHERE ad.applyNo = d.applyNo AND (ad.name = d.name OR ad.proNumber LIKE CONCAT(d.number, '%')) ORDER BY CASE WHEN ad.name = d.name THEN 0 ELSE 1 END, ad.Id DESC ) freight_info WHERE {$whereSql} ) SELECT inbound_date, production_code, raw_name, outbound_quantity, outbound_supplier, arrival_supplier, batch_date, outbound_no, outbound_remark, requisition_no, number_type, delivery_no, received_quantity, reconciliation_amount, freight, edge_band_unit_price, payable_amount, furniture_unit_price, furniture_amount, price_difference, profit, total_count FROM source_rows WHERE row_no BETWEEN ? AND ? ORDER BY row_no"; $rows = $this->query()->select($sql, array_merge($bindings, [$offset + 1, $offset + $limit])); foreach ($rows as &$row) { $row['unit'] = '米'; $row['return_flag'] = (float) ($row['outbound_quantity'] ?? 0) < 0 ? '退货' : '正常出库'; } return $this->pageResult($rows); } /** @return array{data:array>,total:int} */ public function payables(array $filters, int $page, int $limit): array { $where = [ "EXISTS ( SELECT 1 FROM [dbo].[pm_averageUnitPrice] edge_price WHERE edge_price.number LIKE 'FBT%' AND edge_price.supplier = p.supplier )", ]; $bindings = []; if (($filters['period'] ?? '') !== '') { $where[] = 'p.Month = ?'; $bindings[] = $filters['period']; } if (($filters['supplier'] ?? '') !== '') { $where[] = 'p.supplier LIKE ? ESCAPE \'\\\''; $bindings[] = $this->contains($filters['supplier']); } $whereSql = implode(' AND ', $where); $page = max($page, 1); $limit = min(max($limit, 1), 100); $offset = ($page - 1) * $limit; $sql = "WITH source_rows AS ( SELECT p.supplier, CAST(SUM(ISNULL(p.bginMonthPay, 0)) AS decimal(18,2)) AS month_start_unpaid, CAST(SUM(ISNULL(p.loan, 0)) AS decimal(18,2)) AS goods_amount, CAST(SUM(ISNULL(p.ExpFieght, 0)) AS decimal(18,2)) AS prepaid_freight, CAST(SUM(ISNULL(p.Totalindemnity, 0)) AS decimal(18,2)) AS compensation, CAST(SUM(ISNULL(p.supplySup, 0)) AS decimal(18,2)) AS supplier_refund, CAST(SUM(ISNULL(p.ShouldPay, 0)) AS decimal(18,2)) AS payable_amount, CAST(SUM(ISNULL(p.factPay, 0)) AS decimal(18,2)) AS paid_amount, CAST(SUM(ISNULL(p.cashierbypaid, 0)) AS decimal(18,2)) AS actual_payment, CAST(SUM(ISNULL(p.toPrivate, 0)) AS decimal(18,2)) AS private_payment, CAST(SUM(ISNULL(p.toCorporate, 0)) AS decimal(18,2)) AS corporate_payment, MAX(ISNULL(p.remarks, '')) AS remark, CAST(SUM(SUM(ISNULL(p.bginMonthPay, 0))) OVER () AS decimal(18,2)) AS summary_month_start_unpaid, CAST(SUM(SUM(ISNULL(p.loan, 0))) OVER () AS decimal(18,2)) AS summary_goods_amount, CAST(SUM(SUM(ISNULL(p.ExpFieght, 0))) OVER () AS decimal(18,2)) AS summary_prepaid_freight, CAST(SUM(SUM(ISNULL(p.Totalindemnity, 0))) OVER () AS decimal(18,2)) AS summary_compensation, CAST(SUM(SUM(ISNULL(p.supplySup, 0))) OVER () AS decimal(18,2)) AS summary_supplier_refund, CAST(SUM(SUM(ISNULL(p.ShouldPay, 0))) OVER () AS decimal(18,2)) AS summary_payable_amount, CAST(SUM(SUM(ISNULL(p.factPay, 0))) OVER () AS decimal(18,2)) AS summary_paid_amount, CAST(SUM(SUM(ISNULL(p.cashierbypaid, 0))) OVER () AS decimal(18,2)) AS summary_actual_payment, CAST(SUM(SUM(ISNULL(p.toPrivate, 0))) OVER () AS decimal(18,2)) AS summary_private_payment, CAST(SUM(SUM(ISNULL(p.toCorporate, 0))) OVER () AS decimal(18,2)) AS summary_corporate_payment, ROW_NUMBER() OVER (ORDER BY p.supplier) AS row_no, COUNT(*) OVER () AS total_count FROM [dbo].[fys_supplierPaymentSummary] p WHERE {$whereSql} GROUP BY p.supplier ) SELECT supplier, month_start_unpaid, goods_amount, prepaid_freight, compensation, supplier_refund, payable_amount, paid_amount, actual_payment, private_payment, corporate_payment, remark, summary_month_start_unpaid, summary_goods_amount, summary_prepaid_freight, summary_compensation, summary_supplier_refund, summary_payable_amount, summary_paid_amount, summary_actual_payment, summary_private_payment, summary_corporate_payment, total_count FROM source_rows WHERE row_no BETWEEN ? AND ? ORDER BY row_no"; $rows = $this->query()->select($sql, array_merge($bindings, [$offset + 1, $offset + $limit])); return $this->payablesPageResult($rows); } private function query(): UpstreamReadOnlyQuery { return $this->query ??= $this->queries->forSource(self::SOURCE); } private function contains(string $value): string { return '%' . str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], trim($value)) . '%'; } /** @param array> $rows */ private function pageResult(array $rows): array { $total = (int) ($rows[0]['total_count'] ?? 0); foreach ($rows as &$row) { unset($row['total_count']); } return ['data' => $rows, 'total' => $total]; } /** @param array> $rows */ private function payablesPageResult(array $rows): array { $summaryKeys = [ 'month_start_unpaid', 'goods_amount', 'prepaid_freight', 'compensation', 'supplier_refund', 'payable_amount', 'paid_amount', 'actual_payment', 'private_payment', 'corporate_payment', ]; $totals = array_fill_keys($summaryKeys, 0.0); if ($rows !== []) { foreach ($summaryKeys as $key) { $totals[$key] = (float) ($rows[0]['summary_' . $key] ?? 0); } } foreach ($rows as &$row) { foreach ($summaryKeys as $key) { unset($row['summary_' . $key]); } } return array_merge($this->pageResult($rows), ['totals' => $totals]); } }