feat: 店铺应收账款 - 种菜应收对账页面(21字段)
- 新增种菜应收对账完整CRUD:21字段对账数据表 - 字段:日期、种菜订单编号、财务售价/运费/佣金/空包费/打款金额、 京喜差价、扣款、正确店铺、负责人、创建人、所属利润中心、 负责平台、ID、店铺、财务备注、支付宝订单、账单项目、 收入金额、差异数据 - 表单分4组:基本信息、财务数据、店铺与人员、收款与差异 - 修改Business\Pages支持无tabs页面加载内容 - 路由:zhongcai-reconciliations 路由组
This commit is contained in:
parent
752f26bf30
commit
308e7eb479
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Business;
|
||||
use App\Models\Banking\MarketingAccountBill;
|
||||
use App\Models\Banking\MarketingTaobaoAlipayBill;
|
||||
use App\Models\Banking\MarketingPinduoduoBill;
|
||||
use App\Models\StoreReceivables\StoreZhongcaiReconciliation;
|
||||
use App\Utilities\SidebarPermissions;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
@ -70,11 +71,14 @@ class Pages extends Controller
|
||||
if ($tabs->isEmpty()) {
|
||||
abort_if($tab !== null, 404);
|
||||
|
||||
$content = $this->resolveContent($page, null);
|
||||
|
||||
return view('business.pages.show', [
|
||||
'section' => $sectionConfig,
|
||||
'page' => $pageConfig,
|
||||
'tabs' => $tabs,
|
||||
'activeTab' => null,
|
||||
'content' => $content,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -100,14 +104,28 @@ class Pages extends Controller
|
||||
/**
|
||||
* 根据页面和标签加载对应的业务内容数据
|
||||
*/
|
||||
protected function resolveContent(string $page, string $tab): ?array
|
||||
protected function resolveContent(string $page, ?string $tab): ?array
|
||||
{
|
||||
return match ($page) {
|
||||
'marketing-account-bills' => $this->contentForMarketingAccountBills($tab),
|
||||
'zhongcai-reconciliation' => $this->contentForZhongcaiReconciliation(),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 种菜应收对账 - 加载对账数据(21字段)
|
||||
*/
|
||||
protected function contentForZhongcaiReconciliation(): ?array
|
||||
{
|
||||
return [
|
||||
'view' => 'store_receivables.zhongcai_reconciliations.partials.embedded-table',
|
||||
'records' => StoreZhongcaiReconciliation::orderBy('bill_date', 'desc')
|
||||
->orderBy('id', 'desc')
|
||||
->paginate(setting('default.list_limit', 25)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 营销账户账单 - 加载指定平台的数据
|
||||
* 淘系支付宝、拼多多使用独立的流水账单表,其他平台使用通用汇总账单表
|
||||
|
||||
@ -0,0 +1,200 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\StoreReceivables;
|
||||
|
||||
use App\Abstracts\Http\FormRequest;
|
||||
|
||||
class StoreZhongcaiReconciliation extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'bill_date' => ['required', 'date'],
|
||||
'planting_order_no' => ['required', 'string', 'max:100'],
|
||||
'finance_selling_price' => ['nullable', 'numeric'],
|
||||
'finance_freight' => ['nullable', 'numeric'],
|
||||
'finance_commission' => ['nullable', 'numeric'],
|
||||
'jingxi_price_diff' => ['nullable', 'numeric'],
|
||||
'deduction' => ['nullable', 'numeric'],
|
||||
'finance_empty_package_fee' => ['nullable', 'numeric'],
|
||||
'finance_payment_amount' => ['nullable', 'numeric'],
|
||||
'correct_store' => ['nullable', 'string', 'max:191'],
|
||||
'person_in_charge' => ['nullable', 'string', 'max:100'],
|
||||
'creator' => ['nullable', 'string', 'max:100'],
|
||||
'profit_center' => ['nullable', 'string', 'max:100'],
|
||||
'responsible_platform' => ['nullable', 'string', 'max:100'],
|
||||
'external_id' => ['nullable', 'string', 'max:100'],
|
||||
'store' => ['nullable', 'string', 'max:191'],
|
||||
'finance_notes' => ['nullable', 'string', 'max:1000'],
|
||||
'alipay_order' => ['nullable', 'string', 'max:100'],
|
||||
'bill_item' => ['nullable', 'string', 'max:100'],
|
||||
'income_amount' => ['nullable', 'numeric'],
|
||||
'difference_data' => ['nullable', 'string', 'max:1000'],
|
||||
];
|
||||
}
|
||||
}
|
||||
50
app/Models/StoreReceivables/StoreZhongcaiReconciliation.php
Normal file
50
app/Models/StoreReceivables/StoreZhongcaiReconciliation.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\StoreReceivables;
|
||||
|
||||
use App\Abstracts\Model;
|
||||
|
||||
class StoreZhongcaiReconciliation extends Model
|
||||
{
|
||||
protected $table = 'store_zhongcai_reconciliations';
|
||||
|
||||
protected $fillable = [
|
||||
'company_id',
|
||||
'bill_date',
|
||||
'planting_order_no',
|
||||
'finance_selling_price',
|
||||
'finance_freight',
|
||||
'finance_commission',
|
||||
'jingxi_price_diff',
|
||||
'deduction',
|
||||
'finance_empty_package_fee',
|
||||
'finance_payment_amount',
|
||||
'correct_store',
|
||||
'person_in_charge',
|
||||
'creator',
|
||||
'profit_center',
|
||||
'responsible_platform',
|
||||
'external_id',
|
||||
'store',
|
||||
'finance_notes',
|
||||
'alipay_order',
|
||||
'bill_item',
|
||||
'income_amount',
|
||||
'difference_data',
|
||||
'created_from',
|
||||
'created_by',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'bill_date' => 'date',
|
||||
'finance_selling_price' => 'double',
|
||||
'finance_freight' => 'double',
|
||||
'finance_commission' => 'double',
|
||||
'jingxi_price_diff' => 'double',
|
||||
'deduction' => 'double',
|
||||
'finance_empty_package_fee' => 'double',
|
||||
'finance_payment_amount' => 'double',
|
||||
'income_amount' => 'double',
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('store_zhongcai_reconciliations', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('company_id');
|
||||
$table->date('bill_date')->comment('日期');
|
||||
$table->string('planting_order_no', 100)->comment('种菜订单编号');
|
||||
$table->decimal('finance_selling_price', 15, 2)->default(0)->comment('财务售价');
|
||||
$table->decimal('finance_freight', 15, 2)->default(0)->comment('财务运费');
|
||||
$table->decimal('finance_commission', 15, 2)->default(0)->comment('财务佣金');
|
||||
$table->decimal('jingxi_price_diff', 15, 2)->default(0)->comment('京喜差价');
|
||||
$table->decimal('deduction', 15, 2)->default(0)->comment('扣款');
|
||||
$table->decimal('finance_empty_package_fee', 15, 2)->default(0)->comment('财务空包费');
|
||||
$table->decimal('finance_payment_amount', 15, 2)->default(0)->comment('财务打款金额');
|
||||
$table->string('correct_store', 191)->nullable()->comment('正确店铺');
|
||||
$table->string('person_in_charge', 100)->nullable()->comment('负责人');
|
||||
$table->string('creator', 100)->nullable()->comment('创建人');
|
||||
$table->string('profit_center', 100)->nullable()->comment('所属利润中心');
|
||||
$table->string('responsible_platform', 100)->nullable()->comment('负责平台');
|
||||
$table->string('external_id', 100)->nullable()->comment('ID');
|
||||
$table->string('store', 191)->nullable()->comment('店铺');
|
||||
$table->text('finance_notes')->nullable()->comment('财务备注');
|
||||
$table->string('alipay_order', 100)->nullable()->comment('支付宝订单');
|
||||
$table->string('bill_item', 100)->nullable()->comment('账单项目');
|
||||
$table->decimal('income_amount', 15, 2)->default(0)->comment('收入金额');
|
||||
$table->text('difference_data')->nullable()->comment('差异数据');
|
||||
$table->string('created_from', 50)->nullable();
|
||||
$table->unsignedInteger('created_by')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index(['company_id', 'bill_date']);
|
||||
$table->index('planting_order_no');
|
||||
$table->index('store');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('store_zhongcai_reconciliations');
|
||||
}
|
||||
};
|
||||
51
resources/lang/zh-CN/store_zhongcai_reconciliations.php
Normal file
51
resources/lang/zh-CN/store_zhongcai_reconciliations.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'title' => '种菜应收对账',
|
||||
|
||||
// 表格列标题(对应Excel表1,21个字段)
|
||||
'bill_date' => '日期',
|
||||
'planting_order_no' => '种菜订单编号',
|
||||
'finance_selling_price' => '财务售价',
|
||||
'finance_freight' => '财务运费',
|
||||
'finance_commission' => '财务佣金',
|
||||
'jingxi_price_diff' => '京喜差价',
|
||||
'deduction' => '扣款',
|
||||
'finance_empty_package_fee' => '财务空包费',
|
||||
'finance_payment_amount' => '财务打款金额',
|
||||
'correct_store' => '正确店铺',
|
||||
'person_in_charge' => '负责人',
|
||||
'creator' => '创建人',
|
||||
'profit_center' => '所属利润中心',
|
||||
'responsible_platform' => '负责平台',
|
||||
'external_id' => 'ID',
|
||||
'store' => '店铺',
|
||||
'finance_notes' => '财务备注',
|
||||
'alipay_order' => '支付宝订单',
|
||||
'bill_item' => '账单项目',
|
||||
'income_amount' => '收入金额',
|
||||
'difference_data' => '差异数据',
|
||||
|
||||
// 操作
|
||||
'add_record' => '新增对账记录',
|
||||
'edit_record' => '编辑对账记录',
|
||||
'bulk_upload' => '批量导入',
|
||||
'bulk_download' => '批量导出',
|
||||
'download_template' => '下载导入模板',
|
||||
'choose_file' => '选择文件',
|
||||
'import_success' => '成功导入 :count 条对账记录',
|
||||
'import_required' => '请选择要导入的文件',
|
||||
'import_file_type' => '仅支持 .xlsx、.xls、.csv 文件',
|
||||
'import_file_size' => '文件大小不能超过 5MB',
|
||||
'select_all' => '全选',
|
||||
'select_record' => '选择记录',
|
||||
'no_records' => '暂无对账数据',
|
||||
|
||||
// 表单分组
|
||||
'section_basic' => '基本信息',
|
||||
'section_finance' => '财务数据(元)',
|
||||
'section_store' => '店铺与人员',
|
||||
'section_payment' => '收款与差异',
|
||||
|
||||
];
|
||||
@ -0,0 +1,157 @@
|
||||
@php $isEdit = $record->exists; @endphp
|
||||
|
||||
<x-layouts.admin>
|
||||
<x-slot name="title">
|
||||
{{ $isEdit ? trans('store_zhongcai_reconciliations.edit_record') : trans('store_zhongcai_reconciliations.add_record') }}
|
||||
- {{ trans('store_zhongcai_reconciliations.title') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<x-form.container>
|
||||
<form method="POST"
|
||||
action="{{ $isEdit ? route('zhongcai-reconciliations.update', $record) : route('zhongcai-reconciliations.store') }}"
|
||||
class="space-y-6">
|
||||
@csrf
|
||||
@if ($isEdit) @method('PATCH') @endif
|
||||
|
||||
{{-- 基本信息 --}}
|
||||
<div class="rounded-lg border border-gray-200 bg-gray-50 px-5 py-4">
|
||||
<h3 class="mb-4 text-sm font-semibold text-gray-700">{{ trans('store_zhongcai_reconciliations.section_basic') }}</h3>
|
||||
<div class="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.bill_date') }} <span class="text-red-500">*</span></label>
|
||||
<input type="date" name="bill_date" value="{{ old('bill_date', $record->bill_date ? $record->bill_date->toDateString() : now()->toDateString()) }}" required
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.planting_order_no') }} <span class="text-red-500">*</span></label>
|
||||
<input name="planting_order_no" value="{{ old('planting_order_no', $record->planting_order_no) }}" required
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 财务数据 --}}
|
||||
<div class="rounded-lg border border-gray-200 bg-white px-5 py-4">
|
||||
<h3 class="mb-4 text-sm font-semibold text-gray-700">{{ trans('store_zhongcai_reconciliations.section_finance') }}</h3>
|
||||
<div class="grid gap-5 sm:grid-cols-3 lg:grid-cols-4">
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.finance_selling_price') }}</label>
|
||||
<input type="number" step="0.01" name="finance_selling_price" value="{{ old('finance_selling_price', $record->finance_selling_price) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.finance_freight') }}</label>
|
||||
<input type="number" step="0.01" name="finance_freight" value="{{ old('finance_freight', $record->finance_freight) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.finance_commission') }}</label>
|
||||
<input type="number" step="0.01" name="finance_commission" value="{{ old('finance_commission', $record->finance_commission) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.jingxi_price_diff') }}</label>
|
||||
<input type="number" step="0.01" name="jingxi_price_diff" value="{{ old('jingxi_price_diff', $record->jingxi_price_diff) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.deduction') }}</label>
|
||||
<input type="number" step="0.01" name="deduction" value="{{ old('deduction', $record->deduction) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.finance_empty_package_fee') }}</label>
|
||||
<input type="number" step="0.01" name="finance_empty_package_fee" value="{{ old('finance_empty_package_fee', $record->finance_empty_package_fee) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.finance_payment_amount') }}</label>
|
||||
<input type="number" step="0.01" name="finance_payment_amount" value="{{ old('finance_payment_amount', $record->finance_payment_amount) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 店铺与人员 --}}
|
||||
<div class="rounded-lg border border-gray-200 bg-white px-5 py-4">
|
||||
<h3 class="mb-4 text-sm font-semibold text-gray-700">{{ trans('store_zhongcai_reconciliations.section_store') }}</h3>
|
||||
<div class="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.correct_store') }}</label>
|
||||
<input name="correct_store" value="{{ old('correct_store', $record->correct_store) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.store') }}</label>
|
||||
<input name="store" value="{{ old('store', $record->store) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.person_in_charge') }}</label>
|
||||
<input name="person_in_charge" value="{{ old('person_in_charge', $record->person_in_charge) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.creator') }}</label>
|
||||
<input name="creator" value="{{ old('creator', $record->creator) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.profit_center') }}</label>
|
||||
<input name="profit_center" value="{{ old('profit_center', $record->profit_center) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.responsible_platform') }}</label>
|
||||
<input name="responsible_platform" value="{{ old('responsible_platform', $record->responsible_platform) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.external_id') }}</label>
|
||||
<input name="external_id" value="{{ old('external_id', $record->external_id) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 收款与差异 --}}
|
||||
<div class="rounded-lg border border-gray-200 bg-white px-5 py-4">
|
||||
<h3 class="mb-4 text-sm font-semibold text-gray-700">{{ trans('store_zhongcai_reconciliations.section_payment') }}</h3>
|
||||
<div class="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.alipay_order') }}</label>
|
||||
<input name="alipay_order" value="{{ old('alipay_order', $record->alipay_order) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.bill_item') }}</label>
|
||||
<input name="bill_item" value="{{ old('bill_item', $record->bill_item) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.income_amount') }}</label>
|
||||
<input type="number" step="0.01" name="income_amount" value="{{ old('income_amount', $record->income_amount) }}"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:border-green focus:ring-green" />
|
||||
</div>
|
||||
<div class="sm:col-span-2 lg:col-span-3">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.finance_notes') }}</label>
|
||||
<textarea name="finance_notes" rows="2"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green">{{ old('finance_notes', $record->finance_notes) }}</textarea>
|
||||
</div>
|
||||
<div class="sm:col-span-2 lg:col-span-3">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600">{{ trans('store_zhongcai_reconciliations.difference_data') }}</label>
|
||||
<textarea name="difference_data" rows="2"
|
||||
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-green focus:ring-green">{{ old('difference_data', $record->difference_data) }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end gap-4">
|
||||
<a href="{{ route('zhongcai-reconciliations.index') }}" class="px-5 py-2 text-gray-600 text-sm">{{ trans('general.cancel') }}</a>
|
||||
<button type="submit" class="rounded-lg bg-green px-6 py-2 text-sm text-white hover:bg-green-700">{{ trans('general.save') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</x-form.container>
|
||||
</x-slot>
|
||||
</x-layouts.admin>
|
||||
@ -0,0 +1,8 @@
|
||||
<x-layouts.admin>
|
||||
<x-slot name="title">
|
||||
{{ trans('store_zhongcai_reconciliations.title') }}
|
||||
</x-slot>
|
||||
<x-slot name="content">
|
||||
@include('store_receivables.zhongcai_reconciliations.partials.embedded-table')
|
||||
</x-slot>
|
||||
</x-layouts.admin>
|
||||
@ -0,0 +1,162 @@
|
||||
<!-- 种菜应收对账 - 嵌入业务页面的21列表格 -->
|
||||
<style>
|
||||
.zhongcai-table-wrapper { overflow-x: auto; border-radius: 0.5rem; border: 1px solid #e5e7eb; }
|
||||
.zhongcai-table { min-width: 100%; white-space: nowrap; font-size: 0.8125rem; }
|
||||
.zhongcai-table thead th { position: sticky; top: 0; background: #f9fafb; text-align: left; color: #6b7280; padding: 0.5rem 0.6rem; border-bottom: 1px solid #e5e7eb; font-weight: 600; }
|
||||
.zhongcai-table tbody td { padding: 0.5rem 0.6rem; border-bottom: 1px solid #f3f4f6; }
|
||||
.zhongcai-table tbody tr:hover { background: #f9fafb; }
|
||||
.amount-cell { text-align: right; font-variant-numeric: tabular-nums; }
|
||||
</style>
|
||||
|
||||
@php $pageIds = $records->pluck('id')->map(fn($id) => (string) $id)->values(); @endphp
|
||||
|
||||
<div class="w-full" x-data="{ selected: [] }">
|
||||
<form id="zhongcai-export-form" method="GET" action="{{ route('zhongcai-reconciliations.export') }}"></form>
|
||||
|
||||
<div class="mb-4 flex flex-wrap items-end justify-between gap-3 border-b border-gray-200 pb-4">
|
||||
@can('create-banking-accounts')
|
||||
<div class="flex flex-wrap items-end gap-3">
|
||||
<a href="{{ route('zhongcai-reconciliations.create') }}"
|
||||
class="inline-flex h-10 items-center gap-2 rounded-lg bg-green px-4 text-sm text-white hover:bg-green-700">
|
||||
<span class="material-icons text-base" aria-hidden="true">add</span>
|
||||
{{ trans('store_zhongcai_reconciliations.add_record') }}
|
||||
</a>
|
||||
<form method="POST" action="{{ route('zhongcai-reconciliations.import') }}"
|
||||
enctype="multipart/form-data" class="flex flex-wrap items-end gap-3">
|
||||
@csrf
|
||||
<div>
|
||||
<label for="zhongcai-import" class="mb-1 block text-xs font-medium text-gray-600">
|
||||
{{ trans('store_zhongcai_reconciliations.choose_file') }}
|
||||
</label>
|
||||
<input id="zhongcai-import" type="file" name="import" accept=".xlsx,.xls,.csv" required
|
||||
class="block max-w-xs text-sm text-gray-600" />
|
||||
</div>
|
||||
<button type="submit"
|
||||
class="inline-flex h-10 items-center gap-2 rounded-lg bg-green px-4 text-sm text-white hover:bg-green-700">
|
||||
<span class="material-icons text-base" aria-hidden="true">upload_file</span>
|
||||
{{ trans('store_zhongcai_reconciliations.bulk_upload') }}
|
||||
</button>
|
||||
</form>
|
||||
<a href="{{ route('zhongcai-reconciliations.template') }}"
|
||||
class="inline-flex h-10 items-center gap-2 rounded-lg border border-gray-300 bg-white px-4 text-sm text-gray-700 hover:bg-gray-50">
|
||||
<span class="material-icons text-base" aria-hidden="true">file_download</span>
|
||||
{{ trans('store_zhongcai_reconciliations.download_template') }}
|
||||
</a>
|
||||
</div>
|
||||
@endcan
|
||||
<div class="flex items-center gap-3">
|
||||
@can('update-banking-accounts')
|
||||
<button type="submit" form="zhongcai-export-form"
|
||||
class="inline-flex h-10 items-center gap-2 rounded-lg border border-gray-300 bg-white px-4 text-sm text-gray-700 hover:bg-gray-50">
|
||||
<span class="material-icons text-base" aria-hidden="true">download</span>
|
||||
{{ trans('store_zhongcai_reconciliations.bulk_download') }}
|
||||
</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($errors->has('import'))
|
||||
<div class="mb-4 border-l-4 border-red-500 bg-red-50 px-4 py-3 text-sm text-red-700">
|
||||
@foreach ($errors->get('import') as $message)
|
||||
<p>{{ $message }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- 21列数据表格 --}}
|
||||
<div class="zhongcai-table-wrapper">
|
||||
<table class="zhongcai-table divide-y divide-gray-200">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-12 text-center">
|
||||
<input type="checkbox" aria-label="{{ trans('store_zhongcai_reconciliations.select_all') }}"
|
||||
@if ($pageIds->isEmpty()) disabled @endif
|
||||
x-on:change="selected = $event.target.checked ? @js($pageIds) : []"
|
||||
x-bind:checked="selected.length === {{ $pageIds->count() }} && selected.length > 0"
|
||||
class="h-4 w-4 rounded border-gray-300 text-green" />
|
||||
</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.bill_date') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.planting_order_no') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.finance_selling_price') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.finance_freight') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.finance_commission') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.jingxi_price_diff') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.deduction') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.finance_empty_package_fee') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.finance_payment_amount') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.correct_store') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.person_in_charge') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.creator') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.profit_center') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.responsible_platform') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.external_id') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.store') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.finance_notes') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.alipay_order') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.bill_item') }}</th>
|
||||
<th class="text-right">{{ trans('store_zhongcai_reconciliations.income_amount') }}</th>
|
||||
<th>{{ trans('store_zhongcai_reconciliations.difference_data') }}</th>
|
||||
<th class="text-right">{{ trans('general.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100 bg-white">
|
||||
@if ($records->isEmpty())
|
||||
<tr>
|
||||
<td colspan="23" class="px-5 py-10 text-center text-gray-400">
|
||||
{{ trans('store_zhongcai_reconciliations.no_records') }}
|
||||
</td>
|
||||
</tr>
|
||||
@else
|
||||
@foreach ($records as $r)
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<input type="checkbox" name="ids[]" value="{{ $r->id }}" form="zhongcai-export-form"
|
||||
x-model="selected" aria-label="{{ trans('store_zhongcai_reconciliations.select_record') }}"
|
||||
class="h-4 w-4 rounded border-gray-300 text-green" />
|
||||
</td>
|
||||
<td>{{ $r->bill_date->format('Y-m-d') }}</td>
|
||||
<td>{{ $r->planting_order_no }}</td>
|
||||
<td class="amount-cell">{{ number_format($r->finance_selling_price, 2) }}</td>
|
||||
<td class="amount-cell">{{ number_format($r->finance_freight, 2) }}</td>
|
||||
<td class="amount-cell">{{ number_format($r->finance_commission, 2) }}</td>
|
||||
<td class="amount-cell">{{ number_format($r->jingxi_price_diff, 2) }}</td>
|
||||
<td class="amount-cell">{{ number_format($r->deduction, 2) }}</td>
|
||||
<td class="amount-cell">{{ number_format($r->finance_empty_package_fee, 2) }}</td>
|
||||
<td class="amount-cell font-semibold">{{ number_format($r->finance_payment_amount, 2) }}</td>
|
||||
<td>{{ $r->correct_store }}</td>
|
||||
<td>{{ $r->person_in_charge }}</td>
|
||||
<td>{{ $r->creator }}</td>
|
||||
<td>{{ $r->profit_center }}</td>
|
||||
<td>{{ $r->responsible_platform }}</td>
|
||||
<td>{{ $r->external_id }}</td>
|
||||
<td>{{ $r->store }}</td>
|
||||
<td class="max-w-xs truncate" title="{{ $r->finance_notes }}">{{ \Illuminate\Support\Str::limit($r->finance_notes, 15) }}</td>
|
||||
<td>{{ $r->alipay_order }}</td>
|
||||
<td>{{ $r->bill_item }}</td>
|
||||
<td class="amount-cell font-semibold">{{ number_format($r->income_amount, 2) }}</td>
|
||||
<td class="max-w-xs truncate" title="{{ $r->difference_data }}">{{ \Illuminate\Support\Str::limit($r->difference_data, 15) }}</td>
|
||||
<td class="text-right whitespace-nowrap">
|
||||
@can('update-banking-accounts')
|
||||
<a href="{{ route('zhongcai-reconciliations.edit', $r) }}"
|
||||
class="text-purple hover:underline mr-3">{{ trans('general.edit') }}</a>
|
||||
@endcan
|
||||
@can('delete-banking-accounts')
|
||||
<form action="{{ route('zhongcai-reconciliations.destroy', $r) }}"
|
||||
method="POST" class="inline"
|
||||
onsubmit="return confirm('{{ trans('general.delete_confirm') }}')">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="text-red-600 hover:underline">{{ trans('general.delete') }}</button>
|
||||
</form>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@unless ($records->isEmpty())
|
||||
<div class="mt-5">{{ $records->links() }}</div>
|
||||
@endunless
|
||||
</div>
|
||||
@ -234,6 +234,18 @@ Route::group(['prefix' => 'banking'], function () {
|
||||
Route::resource('reconciliations', 'Banking\Reconciliations', ['middleware' => ['date.format', 'money', 'dropzone']]);
|
||||
});
|
||||
|
||||
Route::group(['as' => 'zhongcai-reconciliations.', 'prefix' => 'zhongcai-reconciliations'], function () {
|
||||
Route::get('template', 'StoreReceivables\StoreZhongcaiReconciliations@template')->name('template');
|
||||
Route::get('export', 'StoreReceivables\StoreZhongcaiReconciliations@export')->name('export');
|
||||
Route::post('import', 'StoreReceivables\StoreZhongcaiReconciliations@import')->name('import');
|
||||
Route::get('create', 'StoreReceivables\StoreZhongcaiReconciliations@create')->name('create');
|
||||
Route::post('/', 'StoreReceivables\StoreZhongcaiReconciliations@store')->name('store');
|
||||
Route::get('{zhongcaiReconciliation}/edit', 'StoreReceivables\StoreZhongcaiReconciliations@edit')->name('edit');
|
||||
Route::patch('{zhongcaiReconciliation}', 'StoreReceivables\StoreZhongcaiReconciliations@update')->name('update');
|
||||
Route::delete('{zhongcaiReconciliation}', 'StoreReceivables\StoreZhongcaiReconciliations@destroy')->name('destroy');
|
||||
Route::get('/', 'StoreReceivables\StoreZhongcaiReconciliations@index')->name('index');
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'settings'], function () {
|
||||
Route::get('categories/{category}/enable', 'Settings\Categories@enable')->name('categories.enable');
|
||||
Route::get('categories/{category}/disable', 'Settings\Categories@disable')->name('categories.disable');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user