WuYongJie e9ef4a9eef feat: 新增送货未定价/退货未定价/其他扣款补款/代发快递 4个子页面 + 嵌套子菜单
新增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
2026-07-21 19:17:06 +08:00

305 lines
10 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Http\Controllers\Api;
use App\Abstracts\Http\ApiController;
use Modules\EcommerceFinance\Repositories\SupplierPayableRepository;
/**
* 供应商应付 - 子功能页面 API
*
* 为 5 个子页面提供数据接口:
* 退货对账 : /return-reconciliations + /return-reconciliations/summary + /return-reconciliations/options
* 发票扣款 : /invoice-deductions + /invoice-deductions/summary + /invoice-deductions/options
* 赔偿明细 : /compensation-details + /compensation-details/summary + /compensation-details/options
* 借支明细 : /advance-details + /advance-details/summary + /advance-details/options
* 样品扣款 : /sample-deductions + /sample-deductions/summary + /sample-deductions/options
*/
class SupplierPayables extends ApiController
{
private SupplierPayableRepository $repo;
public function __construct()
{
$this->repo = new SupplierPayableRepository();
}
// ============================================================
// 退货对账
// ============================================================
public function returnReconciliationsIndex()
{
$filters = $this->filters('return');
$result = $this->repo->returnReconciliations($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function returnReconciliationsSummary()
{
return response()->json($this->repo->returnReconciliationSummary($this->filters('return')));
}
public function returnReconciliationsOptions()
{
return response()->json($this->repo->filterOptionsForReturn());
}
// ============================================================
// 发票扣款
// ============================================================
public function invoiceDeductionsIndex()
{
$filters = $this->filters('invoice');
$result = $this->repo->invoiceDeductions($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function invoiceDeductionsSummary()
{
return response()->json($this->repo->invoiceDeductionSummary($this->filters('invoice')));
}
public function invoiceDeductionsOptions()
{
return response()->json($this->repo->filterOptionsForInvoice());
}
// ============================================================
// 赔偿明细
// ============================================================
public function compensationDetailsIndex()
{
$filters = $this->filters('compensation');
$result = $this->repo->compensationDetails($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function compensationDetailsSummary()
{
return response()->json($this->repo->compensationDetailSummary($this->filters('compensation')));
}
public function compensationDetailsOptions()
{
return response()->json($this->repo->filterOptionsForCompensation());
}
// ============================================================
// 借支明细
// ============================================================
public function advanceDetailsIndex()
{
$filters = $this->filters('advance');
$result = $this->repo->advanceDetails($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function advanceDetailsSummary()
{
return response()->json($this->repo->advanceDetailSummary($this->filters('advance')));
}
public function advanceDetailsOptions()
{
return response()->json($this->repo->filterOptionsForAdvance());
}
// ============================================================
// 送货未定价
// ============================================================
public function deliveryUnpricedIndex()
{
$filters = $this->filters('delivery-unpriced');
$result = $this->repo->deliveryUnpriced($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function deliveryUnpricedSummary()
{
return response()->json($this->repo->deliveryUnpricedSummary($this->filters('delivery-unpriced')));
}
public function deliveryUnpricedOptions()
{
return response()->json($this->repo->filterOptionsForDeliveryUnpriced());
}
// ============================================================
// 退货未定价
// ============================================================
public function returnUnpricedIndex()
{
$filters = $this->filters('return-unpriced');
$result = $this->repo->returnUnpriced($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function returnUnpricedSummary()
{
return response()->json($this->repo->returnUnpricedSummary($this->filters('return-unpriced')));
}
public function returnUnpricedOptions()
{
return response()->json($this->repo->filterOptionsForReturnUnpriced());
}
// ============================================================
// 样品扣款
// ============================================================
public function sampleDeductionsIndex()
{
$filters = $this->filters('sample');
$result = $this->repo->sampleDeductions($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function sampleDeductionsSummary()
{
return response()->json($this->repo->sampleDeductionSummary($this->filters('sample')));
}
public function sampleDeductionsOptions()
{
return response()->json($this->repo->filterOptionsForSample());
}
// ============================================================
// 其他扣款补款
// ============================================================
public function otherAdjustmentsIndex()
{
$filters = $this->filters('other-adjustments');
$result = $this->repo->otherAdjustments($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function otherAdjustmentsSummary()
{
return response()->json($this->repo->otherAdjustmentsSummary($this->filters('other-adjustments')));
}
public function otherAdjustmentsOptions()
{
return response()->json($this->repo->filterOptionsForOtherAdjustments());
}
// ============================================================
// 代发快递
// ============================================================
public function dropshippingExpressIndex()
{
$filters = $this->filters('dropshipping-express');
$result = $this->repo->dropshippingExpress($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function dropshippingExpressSummary()
{
return response()->json($this->repo->dropshippingExpressSummary($this->filters('dropshipping-express')));
}
public function dropshippingExpressOptions()
{
return response()->json($this->repo->filterOptionsForDropshippingExpress());
}
// ============================================================
// Helpers
// ============================================================
private function filters(string $type): array
{
$filters = [];
// 通用文本字段
$text = ['supplier', 'warehouse', 'sku_id', 'express_no', 'creator', 'department', 'purchase', 'barcode', 'express_name'];
foreach ($text as $field) {
if ($val = request($field)) {
$filters[$field] = trim($val);
}
}
// 日期
foreach (['date_from', 'date_to', 'month_from', 'month_to'] as $field) {
if ($val = request($field)) {
$filters[$field] = $val;
}
}
return $filters;
}
private function page(): int
{
return max((int) request('page', 1), 1);
}
private function limit(): int
{
return min(max((int) request('limit', 25), 1), 100);
}
}