CaiWuXiTong/app/Http/Controllers/StoreReceivables/StoreZhongcaiReconciliations.php
15061959991 308e7eb479 feat: 店铺应收账款 - 种菜应收对账页面(21字段)
- 新增种菜应收对账完整CRUD:21字段对账数据表
- 字段:日期、种菜订单编号、财务售价/运费/佣金/空包费/打款金额、
  京喜差价、扣款、正确店铺、负责人、创建人、所属利润中心、
  负责平台、ID、店铺、财务备注、支付宝订单、账单项目、
  收入金额、差异数据
- 表单分4组:基本信息、财务数据、店铺与人员、收款与差异
- 修改Business\Pages支持无tabs页面加载内容
- 路由:zhongcai-reconciliations 路由组
2026-07-21 19:20:55 +08:00

201 lines
7.8 KiB
PHP

<?php
namespace App\Http\Controllers\StoreReceivables;
use App\Abstracts\Http\Controller;
use App\Http\Requests\StoreReceivables\StoreZhongcaiReconciliation as Request;
use App\Models\StoreReceivables\StoreZhongcaiReconciliation;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request as HttpRequest;
class StoreZhongcaiReconciliations extends Controller
{
private const CSV_HEADERS = [
'日期', '种菜订单编号', '财务售价', '财务运费', '财务佣金', '京喜差价',
'扣款', '财务空包费', '财务打款金额', '正确店铺', '负责人', '创建人',
'所属利润中心', '负责平台', 'ID', '店铺', '财务备注', '支付宝订单',
'账单项目', '收入金额', '差异数据',
];
public function __construct()
{
$this->middleware('permission:read-banking-accounts')->only('index');
$this->middleware('permission:create-banking-accounts')->only('create', 'store', 'import', 'template');
$this->middleware('permission:update-banking-accounts')->only('edit', 'update', 'export');
$this->middleware('permission:delete-banking-accounts')->only('destroy');
}
public function index()
{
return view('store_receivables.zhongcai_reconciliations.index', [
'records' => StoreZhongcaiReconciliation::orderBy('bill_date', 'desc')
->orderBy('id', 'desc')
->paginate(setting('default.list_limit', 25)),
]);
}
public function create()
{
return view('store_receivables.zhongcai_reconciliations.form', [
'record' => new StoreZhongcaiReconciliation([
'company_id' => company_id(),
'bill_date' => now()->toDateString(),
]),
]);
}
public function template()
{
return response()->streamDownload(function () {
$csv = fopen('php://output', 'w');
fputs($csv, chr(0xEF) . chr(0xBB) . chr(0xBF));
fputcsv($csv, self::CSV_HEADERS);
fclose($csv);
}, 'zhongcai_reconciliation_template.csv', [
'Content-Type' => 'text/csv; charset=UTF-8',
]);
}
public function export(HttpRequest $request)
{
$ids = $request->validate([
'ids' => ['nullable', 'array', 'max:5000'],
'ids.*' => ['integer'],
])['ids'] ?? [];
$query = StoreZhongcaiReconciliation::oldest('id');
if (!empty($ids)) {
$query->whereKey($ids);
}
$records = $query->get();
return response()->streamDownload(function () use ($records) {
$csv = fopen('php://output', 'w');
fputs($csv, chr(0xEF) . chr(0xBB) . chr(0xBF));
fputcsv($csv, self::CSV_HEADERS);
foreach ($records as $r) {
fputcsv($csv, [
$r->bill_date->toDateString(),
$r->planting_order_no,
$r->finance_selling_price,
$r->finance_freight,
$r->finance_commission,
$r->jingxi_price_diff,
$r->deduction,
$r->finance_empty_package_fee,
$r->finance_payment_amount,
$r->correct_store,
$r->person_in_charge,
$r->creator,
$r->profit_center,
$r->responsible_platform,
$r->external_id,
$r->store,
$r->finance_notes,
$r->alipay_order,
$r->bill_item,
$r->income_amount,
$r->difference_data,
]);
}
fclose($csv);
}, 'zhongcai_reconciliation_export.csv', [
'Content-Type' => 'text/csv; charset=UTF-8',
]);
}
public function import(HttpRequest $request): RedirectResponse
{
$validated = $request->validate([
'import' => ['required', 'file', 'mimes:xlsx,xls,csv', 'max:5120'],
], [
'import.required' => trans('store_zhongcai_reconciliations.import_required'),
'import.mimes' => trans('store_zhongcai_reconciliations.import_file_type'),
'import.max' => trans('store_zhongcai_reconciliations.import_file_size'),
]);
$handle = fopen($validated['import']->getRealPath(), 'r');
$bom = fread($handle, 3);
if ($bom !== chr(0xEF) . chr(0xBB) . chr(0xBF)) {
rewind($handle);
}
fgetcsv($handle); // skip header
$count = 0;
$companyId = company_id();
$userId = user()->id;
while (($row = fgetcsv($handle)) !== false) {
if (empty($row[0]) && empty($row[1])) {
continue;
}
StoreZhongcaiReconciliation::create([
'company_id' => $companyId,
'bill_date' => $row[0] ?? now()->toDateString(),
'planting_order_no' => $row[1] ?? '',
'finance_selling_price' => (float) ($row[2] ?? 0),
'finance_freight' => (float) ($row[3] ?? 0),
'finance_commission' => (float) ($row[4] ?? 0),
'jingxi_price_diff' => (float) ($row[5] ?? 0),
'deduction' => (float) ($row[6] ?? 0),
'finance_empty_package_fee' => (float) ($row[7] ?? 0),
'finance_payment_amount' => (float) ($row[8] ?? 0),
'correct_store' => $row[9] ?? null,
'person_in_charge' => $row[10] ?? null,
'creator' => $row[11] ?? null,
'profit_center' => $row[12] ?? null,
'responsible_platform' => $row[13] ?? null,
'external_id' => $row[14] ?? null,
'store' => $row[15] ?? null,
'finance_notes' => $row[16] ?? null,
'alipay_order' => $row[17] ?? null,
'bill_item' => $row[18] ?? null,
'income_amount' => (float) ($row[19] ?? 0),
'difference_data' => $row[20] ?? null,
'created_from' => 'core::ui',
'created_by' => $userId,
]);
$count++;
}
fclose($handle);
flash(trans('store_zhongcai_reconciliations.import_success', ['count' => $count]))->success();
return redirect()->route('zhongcai-reconciliations.index');
}
public function store(Request $request): RedirectResponse
{
StoreZhongcaiReconciliation::create(array_merge($request->validated(), [
'company_id' => company_id(),
'created_from' => 'core::ui',
'created_by' => user()->id,
]));
flash(trans('messages.success.created', ['type' => trans('store_zhongcai_reconciliations.title')]))->success();
return redirect()->route('zhongcai-reconciliations.index');
}
public function edit(StoreZhongcaiReconciliation $zhongcaiReconciliation)
{
return view('store_receivables.zhongcai_reconciliations.form', [
'record' => $zhongcaiReconciliation,
]);
}
public function update(Request $request, StoreZhongcaiReconciliation $zhongcaiReconciliation): RedirectResponse
{
$zhongcaiReconciliation->update($request->validated());
flash(trans('messages.success.updated', ['type' => trans('store_zhongcai_reconciliations.title')]))->success();
return redirect()->route('zhongcai-reconciliations.index');
}
public function destroy(StoreZhongcaiReconciliation $zhongcaiReconciliation): RedirectResponse
{
$zhongcaiReconciliation->delete();
flash(trans('messages.success.deleted', ['type' => trans('store_zhongcai_reconciliations.title')]))->success();
return redirect()->route('zhongcai-reconciliations.index');
}
}