新增4个子功能页面: - 送货未定价 (delivery-unpriced): pm_unOrderDetails, 265452行 - 退货未定价 (return-unpriced): finance_purchaseReturn WHERE priceB=0, 35928行 - 其他扣款补款 (other-adjustments): fys_supplierPaymentSummary WHERE other!=0, 460行 - 代发快递 (dropshipping-express): fys_express_courier_settlement, 765行 嵌套子菜单改造: - 未定价明细下新增children嵌套结构(送货未定价+退货未定价) - ShowInAdmin监听器支持page级dropdown嵌套 - Business\Pages控制器支持父级page跳转到第一个子页面 - SidebarPermissions支持children权限key
878 lines
34 KiB
PHP
878 lines
34 KiB
PHP
<?php
|
||
|
||
namespace Modules\EcommerceFinance\Repositories;
|
||
|
||
use Modules\EcommerceFinance\Services\JianSunConnection;
|
||
use PDO;
|
||
|
||
/**
|
||
* 供应商应付 - 子功能页面数据仓库
|
||
*
|
||
* 封装 5 个子页面的数据访问逻辑:
|
||
* - returnReconciliations() 退货对账
|
||
* - invoiceDeductions() 发票扣款
|
||
* - compensationDetails() 赔偿明细(UNION 纸板 + 压板)
|
||
* - advanceDetails() 借支明细
|
||
* - sampleDeductions() 样品扣款
|
||
*
|
||
* 所有方法返回统一结构: ['data' => array<int,array>, 'total' => int]
|
||
*/
|
||
class SupplierPayableRepository
|
||
{
|
||
private PDO $db;
|
||
|
||
public function __construct()
|
||
{
|
||
$this->db = JianSunConnection::get();
|
||
}
|
||
|
||
/**
|
||
* 通用工具:带筛选 + 分页的查询
|
||
*/
|
||
private function runQuery(string $sql, array $params, int $page, int $pageSize, int $countThreshold = 5000): array
|
||
{
|
||
$offset = ($page - 1) * $pageSize;
|
||
|
||
// 1. 总数(先查总数,超阈值再用近似)
|
||
$countSql = 'SELECT COUNT(*) AS cnt FROM (' . $sql . ') AS sub';
|
||
$total = 0;
|
||
try {
|
||
$stmt = $this->db->prepare($countSql);
|
||
$stmt->execute($params);
|
||
$total = (int) $stmt->fetchColumn();
|
||
} catch (\Throwable $e) {
|
||
// 极端情况:表太大查不到总数时退回到 -1
|
||
$total = -1;
|
||
}
|
||
|
||
// 2. 分页数据(用 TOP + OFFSET/FETCH 不可行,统一使用 ROW_NUMBER() OVER 包装)
|
||
$pagedSql = 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rn FROM (' . $sql . ') AS src) AS t WHERE rn BETWEEN ? AND ?';
|
||
$paramsWithRange = array_merge($params, [$offset + 1, $offset + $pageSize]);
|
||
|
||
$stmt = $this->db->prepare($pagedSql);
|
||
$stmt->execute($paramsWithRange);
|
||
|
||
return [
|
||
'data' => $stmt->fetchAll(),
|
||
'total' => $total,
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 计算分页的 SELECT TOP N(无 COUNT),加速大表查询
|
||
*/
|
||
private function runQueryFast(string $sql, array $params, int $page, int $pageSize, int $total = -1): array
|
||
{
|
||
$offset = ($page - 1) * $pageSize;
|
||
$pagedSql = 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rn FROM (' . $sql . ') AS src) AS t WHERE rn BETWEEN ? AND ?';
|
||
$paramsWithRange = array_merge($params, [$offset + 1, $offset + $pageSize]);
|
||
$stmt = $this->db->prepare($pagedSql);
|
||
$stmt->execute($paramsWithRange);
|
||
|
||
return [
|
||
'data' => $stmt->fetchAll(),
|
||
'total' => $total,
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 1. 退货对账 — finance_purchaseReturn (36791行)
|
||
// ============================================================
|
||
public function returnReconciliations(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplierName LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['warehouse'])) {
|
||
$where[] = 'warehouseName LIKE ?';
|
||
$params[] = '%' . $filters['warehouse'] . '%';
|
||
}
|
||
if (!empty($filters['sku_id'])) {
|
||
$where[] = 'sku_id LIKE ?';
|
||
$params[] = '%' . $filters['sku_id'] . '%';
|
||
}
|
||
if (!empty($filters['express_no'])) {
|
||
$where[] = 'expressNo LIKE ?';
|
||
$params[] = '%' . $filters['express_no'] . '%';
|
||
}
|
||
if (!empty($filters['date_from'])) {
|
||
$where[] = 'date >= ?';
|
||
$params[] = $filters['date_from'];
|
||
}
|
||
if (!empty($filters['date_to'])) {
|
||
$where[] = 'date <= ?';
|
||
$params[] = $filters['date_to'];
|
||
}
|
||
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
CONVERT(varchar(10), date, 120) AS send_time,
|
||
supplierName AS supplier,
|
||
sku_id AS barcode,
|
||
name AS sku_name,
|
||
CAST(qty AS decimal(18,2)) AS qty,
|
||
CAST(price AS decimal(18,2)) AS unit_price,
|
||
CAST(price * qty AS decimal(18,2)) AS amount,
|
||
CAST(priceB AS decimal(18,2)) AS guess_unit_price,
|
||
CAST(priceB * qty AS decimal(18,2)) AS guess_amount,
|
||
remark,
|
||
io_id AS wms_pick_no,
|
||
warehouseName AS warehouse,
|
||
expressNo AS express_no,
|
||
expressName AS express_name,
|
||
CONVERT(varchar(10), io_date, 120) AS io_date,
|
||
labels,
|
||
creator_name AS creator,
|
||
'' AS title,
|
||
'' AS supplier_barcode,
|
||
'' AS original_barcode,
|
||
'' AS reconciler
|
||
FROM finance_purchaseReturn
|
||
$whereSql";
|
||
|
||
$result = $this->runQuery($sql, $params, $page, $pageSize);
|
||
|
||
return [
|
||
'data' => $result['data'],
|
||
'total' => $result['total'],
|
||
];
|
||
}
|
||
|
||
public function returnReconciliationSummary(array $filters): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplierName LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['date_from'])) {
|
||
$where[] = 'date >= ?';
|
||
$params[] = $filters['date_from'];
|
||
}
|
||
if (!empty($filters['date_to'])) {
|
||
$where[] = 'date <= ?';
|
||
$params[] = $filters['date_to'];
|
||
}
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
ISNULL(SUM(price * qty), 0) AS total_amount,
|
||
ISNULL(SUM(priceB * qty), 0) AS total_guess_amount,
|
||
COUNT(*) AS total_count
|
||
FROM finance_purchaseReturn $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalGuessAmount' => (float) $row['total_guess_amount'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 2. 发票扣款 — finance_invoiceDeduction (195行)
|
||
// ============================================================
|
||
public function invoiceDeductions(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['month_from'])) {
|
||
$where[] = 'month >= ?';
|
||
$params[] = $filters['month_from'];
|
||
}
|
||
if (!empty($filters['month_to'])) {
|
||
$where[] = 'month <= ?';
|
||
$params[] = $filters['month_to'];
|
||
}
|
||
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
CONVERT(varchar(7), month, 120) AS month_str,
|
||
'' AS category,
|
||
supplier AS payee,
|
||
supplier AS receiver,
|
||
'' AS board_factory,
|
||
CAST(0 AS decimal(18,2)) AS subsidy_fee,
|
||
remark,
|
||
CAST(price AS decimal(18,2)) AS price,
|
||
remark AS detail,
|
||
'' AS note,
|
||
personCharge AS person_charge,
|
||
CONVERT(varchar(19), createTime, 120) AS create_time,
|
||
creator
|
||
FROM finance_invoiceDeduction
|
||
$whereSql";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function invoiceDeductionSummary(array $filters): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT ISNULL(SUM(price), 0) AS total_price, COUNT(*) AS total_count FROM finance_invoiceDeduction $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalPrice' => (float) $row['total_price'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 3. 赔偿明细 — fys_paper_factory + fys_pressing_factory UNION
|
||
// ============================================================
|
||
public function compensationDetails(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['month_from'])) {
|
||
$where[] = 'month >= ?';
|
||
$params[] = $filters['month_from'];
|
||
}
|
||
if (!empty($filters['month_to'])) {
|
||
$where[] = 'month <= ?';
|
||
$params[] = $filters['month_to'];
|
||
}
|
||
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
month,
|
||
supplier,
|
||
CAST(compensation_amount AS decimal(18,2)) AS amount,
|
||
reason,
|
||
'' AS remark,
|
||
creator,
|
||
CONVERT(varchar(19), create_time, 120) AS create_time,
|
||
'纸板厂' AS factory_type
|
||
FROM (
|
||
SELECT
|
||
month,
|
||
factory_subject_name AS supplier,
|
||
compensation_amount,
|
||
reason,
|
||
creator,
|
||
create_time
|
||
FROM fys_paper_factory_compensation_detail
|
||
UNION ALL
|
||
SELECT
|
||
month,
|
||
factory_subject_name AS supplier,
|
||
compensation_amount,
|
||
reason,
|
||
creator,
|
||
create_time
|
||
FROM fys_pressing_factory_compensation_detail
|
||
) AS t
|
||
$whereSql
|
||
ORDER BY month DESC, create_time DESC";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function compensationDetailSummary(array $filters): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
ISNULL(SUM(compensation_amount), 0) AS total_amount,
|
||
COUNT(*) AS total_count
|
||
FROM (
|
||
SELECT compensation_amount, factory_subject_name AS supplier FROM fys_paper_factory_compensation_detail
|
||
UNION ALL
|
||
SELECT compensation_amount, factory_subject_name AS supplier FROM fys_pressing_factory_compensation_detail
|
||
) AS t
|
||
$whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 4. 借支明细 — finance_advanceLoans (4行, 字段不足,部分列显示-)
|
||
// ============================================================
|
||
public function advanceDetails(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['month_from'])) {
|
||
$where[] = 'month >= ?';
|
||
$params[] = $filters['month_from'];
|
||
}
|
||
if (!empty($filters['month_to'])) {
|
||
$where[] = 'month <= ?';
|
||
$params[] = $filters['month_to'];
|
||
}
|
||
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
supplier,
|
||
'' AS contract_name,
|
||
CAST(price AS decimal(18,2)) AS advance_amount,
|
||
CAST(0 AS decimal(18,2)) AS actual_pay,
|
||
CAST(0 AS decimal(18,2)) AS month_deduct,
|
||
CAST(0 AS decimal(18,2)) AS should_deduct,
|
||
'' AS deduct_start_month,
|
||
'' AS deduct_end_month,
|
||
0 AS remain_periods,
|
||
CONVERT(varchar(7), month, 120) AS month_str,
|
||
'' AS loan_term,
|
||
remark,
|
||
'' AS is_paid,
|
||
CONVERT(varchar(7), month, 120) AS pay_month,
|
||
'' AS serial_no,
|
||
'' AS loan_agreement,
|
||
personCharge AS person_charge,
|
||
'' AS receipt_0,
|
||
'' AS receipt_1,
|
||
'' AS receipt_2,
|
||
CONVERT(varchar(19), createTime, 120) AS create_time,
|
||
creator
|
||
FROM finance_advanceLoans
|
||
$whereSql
|
||
ORDER BY month DESC, createTime DESC";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function advanceDetailSummary(array $filters): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT ISNULL(SUM(price), 0) AS total_amount, COUNT(*) AS total_count FROM finance_advanceLoans $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 5. 样品扣款 — finance_sampleDeduction (12行)
|
||
// ============================================================
|
||
public function sampleDeductions(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['department'])) {
|
||
$where[] = 'department LIKE ?';
|
||
$params[] = '%' . $filters['department'] . '%';
|
||
}
|
||
if (!empty($filters['creator'])) {
|
||
$where[] = 'creator LIKE ?';
|
||
$params[] = '%' . $filters['creator'] . '%';
|
||
}
|
||
if (!empty($filters['sku_id'])) {
|
||
$where[] = 'sku_id LIKE ?';
|
||
$params[] = '%' . $filters['sku_id'] . '%';
|
||
}
|
||
if (!empty($filters['date_from'])) {
|
||
$where[] = 'finishTime >= ?';
|
||
$params[] = $filters['date_from'];
|
||
}
|
||
if (!empty($filters['date_to'])) {
|
||
$where[] = 'finishTime <= ?';
|
||
$params[] = $filters['date_to'];
|
||
}
|
||
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
CONVERT(varchar(10), finishTime, 120) AS finish_time,
|
||
department,
|
||
creator,
|
||
sku_id,
|
||
skuName,
|
||
CAST(num AS decimal(18,2)) AS num,
|
||
supplier,
|
||
purchase,
|
||
productCode,
|
||
CAST(shippingFee AS decimal(18,2)) AS shipping_fee,
|
||
CAST(costPrice AS decimal(18,2)) AS cost_price,
|
||
CAST(totalAmount AS decimal(18,2)) AS total_amount,
|
||
CAST(estimatedPrice AS decimal(18,2)) AS estimated_price,
|
||
CAST(estimatedPriceAll AS decimal(18,2)) AS estimated_price_all,
|
||
'' AS remark,
|
||
businessId,
|
||
CONVERT(varchar(19), updateAt, 120) AS update_time
|
||
FROM finance_sampleDeduction
|
||
$whereSql
|
||
ORDER BY finishTime DESC";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function sampleDeductionSummary(array $filters): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
ISNULL(SUM(totalAmount), 0) AS total_amount,
|
||
ISNULL(SUM(estimatedPriceAll), 0) AS total_estimate,
|
||
COUNT(*) AS total_count
|
||
FROM finance_sampleDeduction $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalEstimate' => (float) $row['total_estimate'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 6. 送货未定价 — pm_unOrderDetails (265452行)
|
||
// ============================================================
|
||
public function deliveryUnpriced(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['warehouse'])) {
|
||
$where[] = 'warehouse LIKE ?';
|
||
$params[] = '%' . $filters['warehouse'] . '%';
|
||
}
|
||
if (!empty($filters['purchase'])) {
|
||
$where[] = 'purchase LIKE ?';
|
||
$params[] = '%' . $filters['purchase'] . '%';
|
||
}
|
||
if (!empty($filters['barcode'])) {
|
||
$where[] = 'barCode LIKE ?';
|
||
$params[] = '%' . $filters['barcode'] . '%';
|
||
}
|
||
if (!empty($filters['express_no'])) {
|
||
$where[] = 'expressNo LIKE ?';
|
||
$params[] = '%' . $filters['express_no'] . '%';
|
||
}
|
||
if (!empty($filters['date_from'])) {
|
||
$where[] = 'date >= ?';
|
||
$params[] = $filters['date_from'];
|
||
}
|
||
if (!empty($filters['date_to'])) {
|
||
$where[] = 'date <= ?';
|
||
$params[] = $filters['date_to'];
|
||
}
|
||
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT
|
||
Id AS id,
|
||
CONVERT(varchar(10), date, 120) AS date,
|
||
purchase,
|
||
warehouse,
|
||
supplier,
|
||
transactionNo,
|
||
distributionNo,
|
||
expressNo,
|
||
sku,
|
||
barCode,
|
||
skuName,
|
||
CONVERT(varchar(19), distributionDate, 120) AS distribution_date,
|
||
CONVERT(varchar(10), shipDate, 120) AS ship_date,
|
||
expressName
|
||
FROM pm_unOrderDetails
|
||
$whereSql
|
||
ORDER BY date DESC, Id DESC";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function deliveryUnpricedSummary(array $filters): array
|
||
{
|
||
$where = [];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||
|
||
$sql = "SELECT COUNT(*) AS total_count FROM pm_unOrderDetails $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 7. 退货未定价 — finance_purchaseReturn WHERE priceB = 0 (35928行)
|
||
// ============================================================
|
||
public function returnUnpriced(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = ['(priceB = 0 OR priceB IS NULL)'];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplierName LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['warehouse'])) {
|
||
$where[] = 'warehouseName LIKE ?';
|
||
$params[] = '%' . $filters['warehouse'] . '%';
|
||
}
|
||
if (!empty($filters['sku_id'])) {
|
||
$where[] = 'sku_id LIKE ?';
|
||
$params[] = '%' . $filters['sku_id'] . '%';
|
||
}
|
||
if (!empty($filters['express_no'])) {
|
||
$where[] = 'expressNo LIKE ?';
|
||
$params[] = '%' . $filters['express_no'] . '%';
|
||
}
|
||
if (!empty($filters['date_from'])) {
|
||
$where[] = 'date >= ?';
|
||
$params[] = $filters['date_from'];
|
||
}
|
||
if (!empty($filters['date_to'])) {
|
||
$where[] = 'date <= ?';
|
||
$params[] = $filters['date_to'];
|
||
}
|
||
|
||
$whereSql = 'WHERE ' . implode(' AND ', $where);
|
||
|
||
$sql = "SELECT
|
||
CONVERT(varchar(10), date, 120) AS send_time,
|
||
supplierName AS supplier,
|
||
sku_id AS barcode,
|
||
name AS sku_name,
|
||
CAST(qty AS decimal(18,2)) AS qty,
|
||
CAST(price AS decimal(18,2)) AS unit_price,
|
||
CAST(price * qty AS decimal(18,2)) AS amount,
|
||
CAST(ISNULL(priceB, 0) AS decimal(18,2)) AS guess_unit_price,
|
||
CAST(ISNULL(priceB, 0) * qty AS decimal(18,2)) AS guess_amount,
|
||
remark,
|
||
io_id AS wms_pick_no,
|
||
warehouseName AS warehouse,
|
||
expressNo AS express_no,
|
||
expressName AS express_name,
|
||
CONVERT(varchar(10), io_date, 120) AS io_date,
|
||
labels,
|
||
creator_name AS creator
|
||
FROM finance_purchaseReturn
|
||
$whereSql
|
||
ORDER BY date DESC";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function returnUnpricedSummary(array $filters): array
|
||
{
|
||
$where = ['(priceB = 0 OR priceB IS NULL)'];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplierName LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = 'WHERE ' . implode(' AND ', $where);
|
||
|
||
$sql = "SELECT
|
||
ISNULL(SUM(price * qty), 0) AS total_amount,
|
||
COUNT(*) AS total_count
|
||
FROM finance_purchaseReturn $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 筛选器选项
|
||
// ============================================================
|
||
public function filterOptionsForReturn(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplierName FROM finance_purchaseReturn WHERE supplierName IS NOT NULL ORDER BY supplierName');
|
||
$warehouses = $this->fetchDistinct('SELECT DISTINCT warehouseName FROM finance_purchaseReturn WHERE warehouseName IS NOT NULL ORDER BY warehouseName');
|
||
|
||
return compact('suppliers', 'warehouses');
|
||
}
|
||
|
||
public function filterOptionsForInvoice(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplier FROM finance_invoiceDeduction WHERE supplier IS NOT NULL ORDER BY supplier');
|
||
|
||
return ['suppliers' => $suppliers];
|
||
}
|
||
|
||
public function filterOptionsForCompensation(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct("SELECT DISTINCT supplier FROM (
|
||
SELECT factory_subject_name AS supplier FROM fys_paper_factory_compensation_detail WHERE factory_subject_name IS NOT NULL
|
||
UNION
|
||
SELECT factory_subject_name AS supplier FROM fys_pressing_factory_compensation_detail WHERE factory_subject_name IS NOT NULL
|
||
) AS t ORDER BY supplier");
|
||
|
||
return ['suppliers' => $suppliers];
|
||
}
|
||
|
||
public function filterOptionsForAdvance(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplier FROM finance_advanceLoans WHERE supplier IS NOT NULL ORDER BY supplier');
|
||
|
||
return ['suppliers' => $suppliers];
|
||
}
|
||
|
||
public function filterOptionsForDeliveryUnpriced(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplier FROM pm_unOrderDetails WHERE supplier IS NOT NULL ORDER BY supplier');
|
||
$warehouses = $this->fetchDistinct('SELECT DISTINCT warehouse FROM pm_unOrderDetails WHERE warehouse IS NOT NULL ORDER BY warehouse');
|
||
$purchases = $this->fetchDistinct('SELECT DISTINCT purchase FROM pm_unOrderDetails WHERE purchase IS NOT NULL ORDER BY purchase');
|
||
|
||
return compact('suppliers', 'warehouses', 'purchases');
|
||
}
|
||
|
||
public function filterOptionsForReturnUnpriced(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct("SELECT DISTINCT supplierName FROM finance_purchaseReturn WHERE (priceB = 0 OR priceB IS NULL) AND supplierName IS NOT NULL ORDER BY supplierName");
|
||
$warehouses = $this->fetchDistinct("SELECT DISTINCT warehouseName FROM finance_purchaseReturn WHERE (priceB = 0 OR priceB IS NULL) AND warehouseName IS NOT NULL ORDER BY warehouseName");
|
||
|
||
return compact('suppliers', 'warehouses');
|
||
}
|
||
|
||
public function filterOptionsForSample(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplier FROM finance_sampleDeduction WHERE supplier IS NOT NULL ORDER BY supplier');
|
||
$departments = $this->fetchDistinct('SELECT DISTINCT department FROM finance_sampleDeduction WHERE department IS NOT NULL ORDER BY department');
|
||
$creators = $this->fetchDistinct('SELECT DISTINCT creator FROM finance_sampleDeduction WHERE creator IS NOT NULL ORDER BY creator');
|
||
|
||
return compact('suppliers', 'departments', 'creators');
|
||
}
|
||
|
||
private function fetchDistinct(string $sql): array
|
||
{
|
||
$rows = $this->db->query($sql)->fetchAll(PDO::FETCH_COLUMN);
|
||
return array_values(array_filter($rows, fn ($v) => $v !== null && $v !== ''));
|
||
}
|
||
|
||
// ============================================================
|
||
// 8. 其他扣款补款 — fys_supplierPaymentSummary WHERE other != 0 (460行)
|
||
// ============================================================
|
||
public function otherAdjustments(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = ['(other IS NOT NULL AND other != 0)'];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['month_from'])) {
|
||
$where[] = 'Month >= ?';
|
||
$params[] = $filters['month_from'];
|
||
}
|
||
if (!empty($filters['month_to'])) {
|
||
$where[] = 'Month <= ?';
|
||
$params[] = $filters['month_to'];
|
||
}
|
||
|
||
$whereSql = 'WHERE ' . implode(' AND ', $where);
|
||
|
||
$sql = "SELECT
|
||
'其他扣款补款' AS project,
|
||
Month AS month_str,
|
||
supplier,
|
||
CAST(other AS decimal(18,2)) AS supplement_amount,
|
||
reason AS supplement_reason,
|
||
remarks AS remark,
|
||
mark AS remark2,
|
||
checker AS person_charge
|
||
FROM fys_supplierPaymentSummary
|
||
$whereSql
|
||
ORDER BY Month DESC, supplier";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function otherAdjustmentsSummary(array $filters): array
|
||
{
|
||
$where = ['(other IS NOT NULL AND other != 0)'];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'supplier LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = 'WHERE ' . implode(' AND ', $where);
|
||
|
||
$sql = "SELECT
|
||
ISNULL(SUM(other), 0) AS total_amount,
|
||
COUNT(*) AS total_count
|
||
FROM fys_supplierPaymentSummary $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
// ============================================================
|
||
// 9. 代发快递 — fys_express_courier_settlement (940行)
|
||
// ============================================================
|
||
public function dropshippingExpress(array $filters, int $page, int $pageSize): array
|
||
{
|
||
$where = ['(is_delete = 0 OR is_delete IS NULL)'];
|
||
$params = [];
|
||
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'courier_company_name LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
if (!empty($filters['express_name'])) {
|
||
$where[] = 'expressname LIKE ?';
|
||
$params[] = '%' . $filters['express_name'] . '%';
|
||
}
|
||
if (!empty($filters['month_from'])) {
|
||
$where[] = 'month >= ?';
|
||
$params[] = $filters['month_from'];
|
||
}
|
||
if (!empty($filters['month_to'])) {
|
||
$where[] = 'month <= ?';
|
||
$params[] = $filters['month_to'];
|
||
}
|
||
|
||
$whereSql = 'WHERE ' . implode(' AND ', $where);
|
||
|
||
$sql = "SELECT
|
||
reconciliation_person,
|
||
month AS month_str,
|
||
courier_company_name AS supplier,
|
||
CAST(ISNULL(waybill, 0) AS decimal(18,2)) AS express_freight,
|
||
CAST(ISNULL(courier_provided_amount, 0) AS decimal(18,2)) AS express_account,
|
||
CAST(ISNULL(replenish_courier, 0) AS decimal(18,2)) AS replenish_freight,
|
||
CAST(ISNULL(confirmed_amount, 0) AS decimal(18,2)) AS replenish_account,
|
||
CAST(ISNULL(reconciliation_difference, 0) AS decimal(18,2)) AS return_fee,
|
||
CAST(ISNULL(compensation_amount, 0) AS decimal(18,2)) AS intercept_fee,
|
||
CAST(ISNULL(other_replenishment, 0) AS decimal(18,2)) AS change_address_fee,
|
||
CAST(ISNULL(corporate_payment_amount, 0) AS decimal(18,2)) AS turnover_fee,
|
||
CAST(ISNULL(personal_payment_amount, 0) AS decimal(18,2)) AS overlong_fee,
|
||
CAST(ISNULL(payable_amount, 0) AS decimal(18,2)) AS total_freight,
|
||
status AS remark,
|
||
expressname AS express_name,
|
||
file_status AS remark2,
|
||
creator,
|
||
CONVERT(varchar(19), create_time, 120) AS create_time
|
||
FROM fys_express_courier_settlement
|
||
$whereSql
|
||
ORDER BY month DESC, expressname";
|
||
|
||
return $this->runQuery($sql, $params, $page, $pageSize);
|
||
}
|
||
|
||
public function dropshippingExpressSummary(array $filters): array
|
||
{
|
||
$where = ['(is_delete = 0 OR is_delete IS NULL)'];
|
||
$params = [];
|
||
if (!empty($filters['supplier'])) {
|
||
$where[] = 'courier_company_name LIKE ?';
|
||
$params[] = '%' . $filters['supplier'] . '%';
|
||
}
|
||
$whereSql = 'WHERE ' . implode(' AND ', $where);
|
||
|
||
$sql = "SELECT
|
||
ISNULL(SUM(payable_amount), 0) AS total_amount,
|
||
COUNT(*) AS total_count
|
||
FROM fys_express_courier_settlement $whereSql";
|
||
$stmt = $this->db->prepare($sql);
|
||
$stmt->execute($params);
|
||
$row = $stmt->fetch();
|
||
|
||
return [
|
||
'totalAmount' => (float) $row['total_amount'],
|
||
'totalCount' => (int) $row['total_count'],
|
||
];
|
||
}
|
||
|
||
public function filterOptionsForOtherAdjustments(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct("SELECT DISTINCT supplier FROM fys_supplierPaymentSummary WHERE (other IS NOT NULL AND other != 0) AND supplier IS NOT NULL ORDER BY supplier");
|
||
|
||
return ['suppliers' => $suppliers];
|
||
}
|
||
|
||
public function filterOptionsForDropshippingExpress(): array
|
||
{
|
||
$suppliers = $this->fetchDistinct("SELECT DISTINCT courier_company_name FROM fys_express_courier_settlement WHERE (is_delete = 0 OR is_delete IS NULL) AND courier_company_name IS NOT NULL ORDER BY courier_company_name");
|
||
$expressNames = $this->fetchDistinct("SELECT DISTINCT expressname FROM fys_express_courier_settlement WHERE (is_delete = 0 OR is_delete IS NULL) AND expressname IS NOT NULL ORDER BY expressname");
|
||
|
||
return compact('suppliers', 'expressNames');
|
||
}
|
||
}
|