财务确认(2026-10-20):种菜损耗是查种菜报销的单有没有真实发出有价值的货—— - 发货数据中交易单号下出现信誉订单虚拟条码或透明挂钩(含条形码 GG 开头)即整单不扣款; - 任务备注/卖家备注含拍A发B/拍A发A 的不扣款,且无论是否匹配到发货都从种菜报销中挑出发运营; - “导出拍A发B(发运营)”直接按「种菜报销」页字段输出;其余真实发货的单按成本价×数量+运费扣款。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VANWYsNUbu2piMtCKymoyd
85 lines
3.2 KiB
PHP
85 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Business;
|
|
|
|
use Illuminate\Routing\Controller;
|
|
use Modules\EcommerceFinance\Services\PlantingLossCalculator;
|
|
use Modules\EcommerceFinance\View\PlantingLossPageData;
|
|
use Modules\EcommerceFinance\View\PlantingReimbursementPageData;
|
|
|
|
/** 种菜数据汇总:种菜报销 / 种菜损耗 导出(与页面同一筛选口径)。 */
|
|
class PlantingWorkOrders extends Controller
|
|
{
|
|
public function exportReimbursements(PlantingReimbursementPageData $data)
|
|
{
|
|
$filters = $data->filters();
|
|
|
|
return $this->csv(
|
|
PlantingReimbursementPageData::TITLE . '-' . $filters['month'],
|
|
$data->exportColumns(),
|
|
static fn () => $data->rows($filters),
|
|
);
|
|
}
|
|
|
|
public function exportLoss(PlantingLossPageData $data)
|
|
{
|
|
$filters = $data->filters();
|
|
$suffix = match ($filters['result']) {
|
|
PlantingLossCalculator::RESULT_EXEMPT => '-不扣款拍A发B',
|
|
PlantingLossCalculator::RESULT_FREE_GOODS => '-不扣款虚拟条码挂钩',
|
|
PlantingLossCalculator::RESULT_UNMATCHED => '-未匹配发货',
|
|
'all' => '-全部',
|
|
default => '-扣款',
|
|
};
|
|
|
|
// 发运营的拍A发B 名单直接按「种菜报销」的字段导出。
|
|
if (request()->query('format') === 'reimbursement') {
|
|
return $this->csv(
|
|
'拍A发B发运营-' . $filters['month'],
|
|
PlantingReimbursementPageData::COLUMNS,
|
|
static fn () => $data->rows($filters),
|
|
);
|
|
}
|
|
|
|
return $this->csv(
|
|
PlantingLossPageData::TITLE . '-' . $filters['month'] . $suffix,
|
|
$data->exportColumns(),
|
|
static fn () => $data->rows($filters),
|
|
);
|
|
}
|
|
|
|
/** @param array<string,string> $columns @param callable():iterable<array<string,mixed>> $rows */
|
|
private function csv(string $name, array $columns, callable $rows)
|
|
{
|
|
$file = tmpfile();
|
|
abort_if($file === false, 500, '无法创建导出文件。');
|
|
|
|
try {
|
|
fwrite($file, "\xEF\xBB\xBF");
|
|
fputcsv($file, array_values($columns));
|
|
foreach ($rows() as $row) {
|
|
$values = [];
|
|
foreach (array_keys($columns) as $key) {
|
|
$values[] = $row[$key] ?? '';
|
|
}
|
|
fputcsv($file, array_map(static function (mixed $value): string {
|
|
$value = (string) $value;
|
|
|
|
// 长数字单号/账号保留文本,避免 Excel 截断;同时阻止公式执行。
|
|
return preg_match('/^[=+\-@\t\r\n]|^\d{12,}$/u', $value) ? "'" . $value : $value;
|
|
}, $values));
|
|
}
|
|
rewind($file);
|
|
} catch (\Throwable $exception) {
|
|
fclose($file);
|
|
report($exception);
|
|
abort(503, '聚工单镜像或发货数据未就绪,未生成不完整的导出文件,请稍后重试。');
|
|
}
|
|
|
|
return response()->streamDownload(static function () use ($file): void {
|
|
fpassthru($file);
|
|
fclose($file);
|
|
}, $name . '-' . now()->format('YmdHis') . '.csv', ['Content-Type' => 'text/csv; charset=UTF-8']);
|
|
}
|
|
}
|