CaiWuXiTong/app/Http/Controllers/Banking/MarketingAccountBills.php
15061959991 1adf627c0d feat: 财务系统二次开发 - 营销账户账单功能
- 基础环境:Docker 部署配置,源码挂载实时同步
- 修复:super_admin 权限补全、登录重定向循环
- 开发:店铺营销账户账单 - 抖音账户(15字段汇总账单)
- 开发:店铺营销账户账单 - 淘系支付宝账户(8字段流水账单)
- 开发:店铺营销账户账单 - 拼多多账户(7字段流水账单)
- 业务页面导航集成:config/business_navigation.php + Business\Pages 控制器
- 各平台独立表结构和视图,互不影响
2026-07-21 18:43:52 +08:00

314 lines
10 KiB
PHP

<?php
namespace App\Http\Controllers\Banking;
use App\Abstracts\Http\Controller;
use App\Http\Requests\Banking\MarketingAccountBill as Request;
use App\Models\Banking\MarketingAccountBill;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request as HttpRequest;
class MarketingAccountBills extends Controller
{
/**
* 支持的营销账户平台列表
*/
public const PLATFORMS = [
'douyin' => 'platform_douyin',
'taobao-alipay' => 'platform_taobao-alipay',
'taobao-wechat' => 'platform_taobao-wechat',
'pinduoduo' => 'platform_pinduoduo',
'jd-wallet' => 'platform_jd-wallet',
'dewu' => 'platform_dewu',
'vipshop' => 'platform_vipshop',
];
public function __construct()
{
$this->middleware('permission:read-banking-accounts')->only('storeIndex', 'platformIndex');
$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 storeIndex()
{
return view('banking.marketing_account_bills.store-index', [
'platforms' => self::PLATFORMS,
]);
}
/**
* 单平台账单列表
*/
public function platformIndex(string $platform)
{
return $this->index($platform);
}
/**
* 创建表单
*/
public function create(string $platform)
{
$platform = $this->resolvePlatform($platform);
return view('banking.marketing_account_bills.form', [
'platform' => $platform,
'account' => new MarketingAccountBill([
'company_id' => company_id(),
'bill_date' => now()->toDateString(),
]),
]);
}
/**
* 下载导入模板
*/
public function template(string $platform)
{
$this->resolvePlatform($platform);
return response()->streamDownload(function () {
$csv = fopen('php://output', 'w');
fputs($csv, chr(0xEF) . chr(0xBB) . chr(0xBF)); // BOM for Excel
fputcsv($csv, [
'店铺名称', '账单日期', '总存入金额', '总转入金额', '总转出金额',
'非赠款消耗金额', '赠款消耗金额', '消返红包消耗金额', '立减红包消耗金额',
'共享钱包消耗金额', '共享赠款消耗金额', '当日资金总金额', '期末总余额',
'赠款余额', '非赠款余额', '备注',
]);
fclose($csv);
}, "marketing_account_bills_{$platform}_template.csv", [
'Content-Type' => 'text/csv; charset=UTF-8',
]);
}
/**
* 批量导出
*/
public function export(HttpRequest $request, string $platform)
{
$this->resolvePlatform($platform);
$ids = $request->validate([
'ids' => ['nullable', 'array', 'max:5000'],
'ids.*' => ['integer'],
])['ids'] ?? [];
$query = MarketingAccountBill::platform($platform)->oldest('id');
if (!empty($ids)) {
$query->whereKey($ids);
}
$bills = $query->get();
return response()->streamDownload(function () use ($bills) {
$csv = fopen('php://output', 'w');
fputs($csv, chr(0xEF) . chr(0xBB) . chr(0xBF));
fputcsv($csv, [
'店铺名称', '账单日期', '总存入金额', '总转入金额', '总转出金额',
'非赠款消耗金额', '赠款消耗金额', '消返红包消耗金额', '立减红包消耗金额',
'共享钱包消耗金额', '共享赠款消耗金额', '当日资金总金额', '期末总余额',
'赠款余额', '非赠款余额', '备注',
]);
foreach ($bills as $bill) {
fputcsv($csv, [
$bill->store_name,
$bill->bill_date->toDateString(),
$bill->total_deposit,
$bill->total_transfer_in,
$bill->total_transfer_out,
$bill->non_grant_consumption,
$bill->grant_consumption,
$bill->rebate_redpack_consumption,
$bill->discount_redpack_consumption,
$bill->shared_wallet_consumption,
$bill->shared_grant_consumption,
$bill->daily_total_amount,
$bill->period_end_balance,
$bill->grant_balance,
$bill->non_grant_balance,
$bill->notes,
]);
}
fclose($csv);
}, 'marketing_account_bills_export.csv', [
'Content-Type' => 'text/csv; charset=UTF-8',
]);
}
/**
* 批量导入
*/
public function import(HttpRequest $request, string $platform): RedirectResponse
{
$this->resolvePlatform($platform);
$validated = $request->validate([
'import' => ['required', 'file', 'mimes:xlsx,xls,csv', 'max:5120'],
], [
'import.required' => trans('marketing_account_bills.import_required'),
'import.mimes' => trans('marketing_account_bills.import_file_type'),
'import.max' => trans('marketing_account_bills.import_file_size'),
]);
$file = $validated['import'];
$handle = fopen($file->getRealPath(), 'r');
// Skip BOM
$bom = fread($handle, 3);
if ($bom !== chr(0xEF) . chr(0xBB) . chr(0xBF)) {
rewind($handle);
}
// Skip header
fgetcsv($handle);
$count = 0;
$companyId = company_id();
$userId = user()->id;
while (($row = fgetcsv($handle)) !== false) {
if (empty($row[0]) && empty($row[1])) {
continue;
}
MarketingAccountBill::create([
'company_id' => $companyId,
'platform' => $platform,
'store_name' => $row[0] ?? '',
'bill_date' => $row[1] ?? now()->toDateString(),
'total_deposit' => (float) ($row[2] ?? 0),
'total_transfer_in' => (float) ($row[3] ?? 0),
'total_transfer_out' => (float) ($row[4] ?? 0),
'non_grant_consumption' => (float) ($row[5] ?? 0),
'grant_consumption' => (float) ($row[6] ?? 0),
'rebate_redpack_consumption' => (float) ($row[7] ?? 0),
'discount_redpack_consumption' => (float) ($row[8] ?? 0),
'shared_wallet_consumption' => (float) ($row[9] ?? 0),
'shared_grant_consumption' => (float) ($row[10] ?? 0),
'daily_total_amount' => (float) ($row[11] ?? 0),
'period_end_balance' => (float) ($row[12] ?? 0),
'grant_balance' => (float) ($row[13] ?? 0),
'non_grant_balance' => (float) ($row[14] ?? 0),
'notes' => $row[15] ?? null,
'created_from' => 'core::ui',
'created_by' => $userId,
]);
$count++;
}
fclose($handle);
flash(trans('marketing_account_bills.import_success', ['count' => $count]))->success();
return redirect()->route('marketing-account-bills.platform.index', $platform);
}
/**
* 存储新账单
*/
public function store(Request $request, string $platform): RedirectResponse
{
$this->resolvePlatform($platform);
$data = $request->validated();
MarketingAccountBill::create(array_merge($data, [
'company_id' => company_id(),
'platform' => $platform,
'created_from' => 'core::ui',
'created_by' => user()->id,
]));
flash(trans('messages.success.created', ['type' => $this->platformTitle($platform)]))->success();
return redirect()->route('marketing-account-bills.platform.index', $platform);
}
/**
* 编辑表单
*/
public function edit(string $platform, MarketingAccountBill $marketingAccountBill)
{
abort_unless($marketingAccountBill->platform === $this->resolvePlatform($platform), 404);
return view('banking.marketing_account_bills.form', [
'platform' => $marketingAccountBill->platform,
'account' => $marketingAccountBill,
]);
}
/**
* 更新账单
*/
public function update(Request $request, string $platform, MarketingAccountBill $marketingAccountBill): RedirectResponse
{
abort_unless($marketingAccountBill->platform === $this->resolvePlatform($platform), 404);
$marketingAccountBill->update($request->validated());
flash(trans('messages.success.updated', ['type' => $this->platformTitle($platform)]))->success();
return redirect()->route('marketing-account-bills.platform.index', $platform);
}
/**
* 删除账单
*/
public function destroy(string $platform, MarketingAccountBill $marketingAccountBill): RedirectResponse
{
abort_unless($marketingAccountBill->platform === $this->resolvePlatform($platform), 404);
$marketingAccountBill->delete();
flash(trans('messages.success.deleted', ['type' => $this->platformTitle($platform)]))->success();
return redirect()->route('marketing-account-bills.platform.index', $platform);
}
/**
* 列表页
*/
private function index(string $platform)
{
$platform = $this->resolvePlatform($platform);
return view('banking.marketing_account_bills.index', [
'platform' => $platform,
'accounts' => MarketingAccountBill::platform($platform)
->orderBy('bill_date', 'desc')
->orderBy('id', 'desc')
->paginate(setting('default.list_limit', 25)),
]);
}
/**
* 校验并返回有效平台标识
*/
private function resolvePlatform(string $platform): string
{
abort_unless(array_key_exists($platform, self::PLATFORMS), 404);
return $platform;
}
/**
* 获取平台中文标题
*/
private function platformTitle(string $platform): string
{
return trans('marketing_account_bills.' . $platform);
}
}