419 lines
12 KiB
PHP
419 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Modules\EcommerceFinance\Http\Controllers\Api;
|
|
|
|
use App\Abstracts\Http\ApiController;
|
|
use Closure;
|
|
use Modules\EcommerceFinance\Repositories\SupplierPayableRepository;
|
|
use Modules\EcommerceFinance\Services\JianSunQueryCache;
|
|
use Modules\EcommerceFinance\Services\SupplierPayableOverrideStore;
|
|
|
|
/**
|
|
* 供应商应付 - 子功能页面 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;
|
|
|
|
private JianSunQueryCache $cache;
|
|
|
|
public function __construct(SupplierPayableRepository $repo, JianSunQueryCache $cache, private readonly SupplierPayableOverrideStore $overrides)
|
|
{
|
|
$this->repo = $repo;
|
|
$this->cache = $cache;
|
|
}
|
|
|
|
// ============================================================
|
|
// 退货对账
|
|
// ============================================================
|
|
public function returnReconciliationsIndex()
|
|
{
|
|
$filters = $this->filters('return');
|
|
|
|
return $this->listResponse(
|
|
'return-reconciliations',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->returnReconciliations($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function returnReconciliationsSummary()
|
|
{
|
|
$filters = $this->filters('return');
|
|
|
|
return $this->summaryResponse(
|
|
'return-reconciliations',
|
|
$filters,
|
|
fn () => $this->repo->returnReconciliationSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function returnReconciliationsOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'return-reconciliations',
|
|
fn () => $this->repo->filterOptionsForReturn()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 发票扣款
|
|
// ============================================================
|
|
public function invoiceDeductionsIndex()
|
|
{
|
|
$filters = $this->filters('invoice');
|
|
|
|
return $this->listResponse(
|
|
'invoice-deductions',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->invoiceDeductions($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function invoiceDeductionsSummary()
|
|
{
|
|
$filters = $this->filters('invoice');
|
|
|
|
return $this->summaryResponse(
|
|
'invoice-deductions',
|
|
$filters,
|
|
fn () => $this->repo->invoiceDeductionSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function invoiceDeductionsOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'invoice-deductions',
|
|
fn () => $this->repo->filterOptionsForInvoice()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 赔偿明细
|
|
// ============================================================
|
|
public function compensationDetailsIndex()
|
|
{
|
|
$filters = $this->filters('compensation');
|
|
|
|
return $this->listResponse(
|
|
'compensation-details',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->compensationDetails($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function compensationDetailsSummary()
|
|
{
|
|
$filters = $this->filters('compensation');
|
|
|
|
return $this->summaryResponse(
|
|
'compensation-details',
|
|
$filters,
|
|
fn () => $this->repo->compensationDetailSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function compensationDetailsOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'compensation-details',
|
|
fn () => $this->repo->filterOptionsForCompensation()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 借支明细
|
|
// ============================================================
|
|
public function advanceDetailsIndex()
|
|
{
|
|
$filters = $this->filters('advance');
|
|
|
|
return $this->listResponse(
|
|
'advance-details',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->advanceDetails($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function advanceDetailsSummary()
|
|
{
|
|
$filters = $this->filters('advance');
|
|
|
|
return $this->summaryResponse(
|
|
'advance-details',
|
|
$filters,
|
|
fn () => $this->repo->advanceDetailSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function advanceDetailsOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'advance-details',
|
|
fn () => $this->repo->filterOptionsForAdvance()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 送货未定价
|
|
// ============================================================
|
|
public function deliveryUnpricedIndex()
|
|
{
|
|
$filters = $this->filters('delivery-unpriced');
|
|
|
|
return $this->listResponse(
|
|
'delivery-unpriced',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->deliveryUnpriced($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function deliveryUnpricedSummary()
|
|
{
|
|
$filters = $this->filters('delivery-unpriced');
|
|
|
|
return $this->summaryResponse(
|
|
'delivery-unpriced',
|
|
$filters,
|
|
fn () => $this->repo->deliveryUnpricedSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function deliveryUnpricedOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'delivery-unpriced',
|
|
fn () => $this->repo->filterOptionsForDeliveryUnpriced()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 退货未定价
|
|
// ============================================================
|
|
public function returnUnpricedIndex()
|
|
{
|
|
$filters = $this->filters('return-unpriced');
|
|
|
|
return $this->listResponse(
|
|
'return-unpriced',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->returnUnpriced($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function returnUnpricedSummary()
|
|
{
|
|
$filters = $this->filters('return-unpriced');
|
|
|
|
return $this->summaryResponse(
|
|
'return-unpriced',
|
|
$filters,
|
|
fn () => $this->repo->returnUnpricedSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function returnUnpricedOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'return-unpriced',
|
|
fn () => $this->repo->filterOptionsForReturnUnpriced()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 样品扣款
|
|
// ============================================================
|
|
public function sampleDeductionsIndex()
|
|
{
|
|
$filters = $this->filters('sample');
|
|
|
|
return $this->listResponse(
|
|
'sample-deductions',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->sampleDeductions($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function sampleDeductionsSummary()
|
|
{
|
|
$filters = $this->filters('sample');
|
|
|
|
return $this->summaryResponse(
|
|
'sample-deductions',
|
|
$filters,
|
|
fn () => $this->repo->sampleDeductionSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function sampleDeductionsOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'sample-deductions',
|
|
fn () => $this->repo->filterOptionsForSample()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 其他扣款补款
|
|
// ============================================================
|
|
public function otherAdjustmentsIndex()
|
|
{
|
|
$filters = $this->filters('other-adjustments');
|
|
|
|
return $this->listResponse(
|
|
'other-adjustments',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->otherAdjustments($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function otherAdjustmentsSummary()
|
|
{
|
|
$filters = $this->filters('other-adjustments');
|
|
|
|
return $this->summaryResponse(
|
|
'other-adjustments',
|
|
$filters,
|
|
fn () => $this->repo->otherAdjustmentsSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function otherAdjustmentsOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'other-adjustments',
|
|
fn () => $this->repo->filterOptionsForOtherAdjustments()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 代发快递
|
|
// ============================================================
|
|
public function dropshippingExpressIndex()
|
|
{
|
|
$filters = $this->filters('dropshipping-express');
|
|
|
|
return $this->listResponse(
|
|
'dropshipping-express',
|
|
$filters,
|
|
fn (int $page, int $limit) => $this->repo->dropshippingExpress($filters, $page, $limit)
|
|
);
|
|
}
|
|
|
|
public function dropshippingExpressSummary()
|
|
{
|
|
$filters = $this->filters('dropshipping-express');
|
|
|
|
return $this->summaryResponse(
|
|
'dropshipping-express',
|
|
$filters,
|
|
fn () => $this->repo->dropshippingExpressSummary($filters)
|
|
);
|
|
}
|
|
|
|
public function dropshippingExpressOptions()
|
|
{
|
|
return $this->optionsResponse(
|
|
'dropshipping-express',
|
|
fn () => $this->repo->filterOptionsForDropshippingExpress()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// Helpers
|
|
// ============================================================
|
|
private function listResponse(string $scope, array $filters, Closure $resolver)
|
|
{
|
|
$page = $this->page();
|
|
$limit = $this->limit();
|
|
$cacheParameters = ['filters' => $filters, 'page' => $page, 'limit' => $limit];
|
|
if ($scope === 'other-adjustments') {
|
|
$cacheParameters['format_version'] = 2;
|
|
}
|
|
$result = $this->cache->remember(
|
|
$scope . '.list',
|
|
$cacheParameters,
|
|
fn () => $resolver($page, $limit)
|
|
);
|
|
|
|
$result['data'] = $this->overrides->decorate($scope, $result['data'] ?? [], (int) (company_id() ?: 1));
|
|
|
|
return $this->snapshotResponse([
|
|
'data' => $result['data'],
|
|
'total' => $result['total'],
|
|
'page' => $page,
|
|
'per_page' => $limit,
|
|
'last_page' => (int) ceil(max($result['total'], 0) / $limit),
|
|
]);
|
|
}
|
|
|
|
private function summaryResponse(string $scope, array $filters, Closure $resolver)
|
|
{
|
|
return $this->snapshotResponse($this->cache->remember(
|
|
$scope . '.summary',
|
|
['filters' => $filters],
|
|
$resolver
|
|
));
|
|
}
|
|
|
|
private function optionsResponse(string $scope, Closure $resolver)
|
|
{
|
|
return $this->snapshotResponse($this->cache->remember(
|
|
$scope . '.options',
|
|
[],
|
|
$resolver
|
|
));
|
|
}
|
|
|
|
private function snapshotResponse(array $payload)
|
|
{
|
|
$response = response()->json($payload);
|
|
|
|
foreach ($this->cache->responseHeaders() as $name => $value) {
|
|
$response->headers->set($name, $value);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|