财务报表相关审核流程

main
Jing Li 2024-04-04 16:58:10 +08:00
parent eedcb0bbb8
commit cf972448a3
14 changed files with 239 additions and 55 deletions

View File

@ -4,7 +4,9 @@ namespace App\Admin\Controllers\Finance;
use App\Admin\Controllers\AdminController;
use App\Admin\Services\Finance\LedgerService;
use App\Enums\CheckStatus;
use App\Models\Ledger;
use App\Traits\HasCheckActions;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Slowlyo\OwlAdmin\Admin;
@ -17,6 +19,8 @@ use Slowlyo\OwlAdmin\Renderers\Page;
*/
class LedgerController extends AdminController
{
use HasCheckActions;
protected string $serviceName = LedgerService::class;
public function show($id)
@ -24,7 +28,7 @@ class LedgerController extends AdminController
if ($this->actionOfGetData()) {
/** @var \App\Models\Ledger */
$ledger = Ledger::findOrFail($id);
$ledger->load(['store', 'items.type']);
$ledger->load(['store', 'items.type', 'workflow']);
return $this->response()->success(
array_merge($ledger->toArray(), [
@ -49,51 +53,26 @@ class LedgerController extends AdminController
return $this->response()->success($page);
}
/**
* 修改总账金额
*/
public function updateLedgerAmount($id, Request $request)
{
$validator = Validator::make(
data: $request->all(),
rules: [
'ledger_amount' => ['bail', 'required', 'numeric'],
],
attributes: [
'ledger_amount' => __('finance.ledger.ledger_amount'),
],
);
admin_abort_if($validator->fails(), $validator->errors()->first());
/** @var Ledger */
$ledger = Ledger::findOrFail($id);
$ledger->forceFill([
'ledger_amount' => $request->input('ledger_amount'),
])->save();
return $this->response()->success(null, '修改成功');
}
public function list(): Page
{
$crud = $this->baseCRUD()
->tableLayout('fixed')
->headerToolbar([
...$this->baseHeaderToolBar(),
])
->bulkActions([])
->filter($this->baseFilter()->body([
amis()->GroupControl()->mode('horizontal')->body([
amis()->DateRangeControl('date_range', __('finance.ledger.date'))
->valueFormat('YYYY-MM-DD'),
amis()->SelectControl('store_id', __('finance.ledger.store'))
->source(admin_url('api/stores'))
->labelField('title')
->valueField('id')
->clearable()
->columnRatio(4),
amis()->DateRangeControl('date_range', __('finance.ledger.date'))
->valueFormat('YYYY-MM-DD')
->columnRatio(4),
->clearable(),
amis()->SelectControl()->name('check_status')->label(__('workflow_log.check_status'))
->multiple()
->options(CheckStatus::options())
->clearable(),
]),
]))
->columns([
@ -110,10 +89,25 @@ class LedgerController extends AdminController
amis()->TableColumn()->name('actual_commission')->label(__('finance.ledger.actual_commission')),
amis()->TableColumn()->name('expected_income')->label(__('finance.ledger.expected_income')),
amis()->TableColumn()->name('actual_income')->label(__('finance.ledger.actual_income')),
amis()->TableColumn()->name('created_at')->label(__('finance.ledger.created_at')),
amis()->TableColumn('workflow.check_status', __('workflow_log.check_status'))->set('type', 'mapping')->map(CheckStatus::labelMap()),
// amis()->TableColumn()->name('created_at')->label(__('finance.ledger.created_at')),
$this->rowActions([
$this->applyAction()
->api(
amis()->BaseApi()
->url(admin_url('api/workflow/apply'))
->method('post')
->data(['id' => '${workflow.id}'])
),
$this->cancelAction(),
$this->rowEditLedgerAmountButton()
->visible(Admin::user()->can('admin.finance.ledgers.update_ledger_amount')),
$this->rowEditActualCommissionButton()
->visible(Admin::user()->can('admin.finance.ledgers.update_actual_commission'))
->visibleOn('${OR(workflow.check_status == '.CheckStatus::None->value.', workflow.check_status == '.CheckStatus::Cancel->value.', workflow.check_status == '.CheckStatus::Fail->value.')}'),
$this->rowEditActualIncomeButton()
->visible(Admin::user()->can('admin.finance.ledgers.update_actual_income'))
->visibleOn('${OR(workflow.check_status == '.CheckStatus::None->value.', workflow.check_status == '.CheckStatus::Cancel->value.', workflow.check_status == '.CheckStatus::Fail->value.')}'),
$this->rowShowButton()
->visible(Admin::user()->can('admin.finance.ledgers.view')),
]),
@ -143,7 +137,16 @@ class LedgerController extends AdminController
public function detail(): Form
{
return $this->baseDetail()->title()->body([
$detailId = 'ledger-detail';
$serviceId = 'ledger-workflow-service';
return $this->baseDetail()->id($detailId)->title('')->onEvent([
'inited' => [
'actions' => [
['actionType' => 'reload', 'componentId' => $serviceId],
],
],
])->body([
amis()->Property()->items([
['label' => __('finance.ledger.date'), 'content' => '${date}'],
['label' => __('finance.ledger.store'), 'content' => '${store.title}'],
@ -157,16 +160,66 @@ class LedgerController extends AdminController
['label' => __('finance.ledger.actual_commission'), 'content' => '${actual_commission}'],
['label' => __('finance.ledger.expected_income'), 'content' => '${expected_income}'],
['label' => __('finance.ledger.actual_income'), 'content' => '${actual_income}'],
[
'label' => '上报数据',
'content' => amis()->Property()->source('${items_property}'),
'span' => 3
],
['label' => '上报数据', 'content' => amis()->Property()->source('${items_property}'), 'span' => 3],
['label' => __('finance.ledger.photos'), 'content' => amis()->Images()->enlargeAble()->source('${photos}')->enlargeWithGallary(), 'span' => 3],
['label' => __('workflow_log.check_status'), 'content' => amis()->Mapping()->name('workflow.check_status')->map(CheckStatus::labelMap())],
['label' => __('workflow_log.checked_at'), 'content' => '${workflow.checked_at}'],
['label' => __('workflow_log.remarks'), 'content' => '${workflow.check_remarks}'],
]),
amis()->Divider(),
$this->baseWorkflowLogService($detailId)->id($serviceId),
]);
}
/**
* 修改总账金额
*/
public function updateLedgerAmount($id, Request $request)
{
$validator = Validator::make(
data: $request->all(),
rules: [
'ledger_amount' => ['bail', 'required', 'numeric'],
],
attributes: [
'ledger_amount' => __('finance.ledger.ledger_amount'),
],
);
admin_abort_if($validator->fails(), $validator->errors()->first());
/** @var Ledger */
$ledger = Ledger::findOrFail($id);
$ledger->forceFill([
'ledger_amount' => $request->input('ledger_amount'),
])->save();
return $this->response()->success(null, '保存成功');
}
/**
* 修改实际佣金
*/
public function updateActualCommission($id, Request $request)
{
$this->service->update($id, $request->only(['actual_commission']));
return $this->response()->success(null, '保存成功');
}
/**
* 修改实际收益
*/
public function updateActualIncome($id, Request $request)
{
$this->service->update($id, $request->only(['actual_income']));
return $this->response()->success(null, '保存成功');
}
/**
* 编辑总账金额按钮
*/
protected function rowEditLedgerAmountButton(): DrawerAction
{
return amis()->DrawerAction()
@ -188,4 +241,54 @@ class LedgerController extends AdminController
])->size('lg')
);
}
/**
* 编辑实际佣金按钮
*/
protected function rowEditActualCommissionButton(): DrawerAction
{
return amis()->DrawerAction()
->icon('fa-regular fa-pen-to-square')
->label(__('finance.ledger.actual_commission'))
->level('link')
->drawer(
amis()->Drawer()->title(__('finance.ledger.actual_commission'))->body([
amis()->Form()->title('')
->api('post:'.admin_url('finance/ledgers/${id}/actual-commission'))
->body([
amis()->NumberControl()
->name('actual_commission')
->label(__('finance.ledger.actual_commission'))
->precision(2)
->showSteps(false)
->required(),
]),
])->size('lg')
);
}
/**
* 编辑实际收益按钮
*/
protected function rowEditActualIncomeButton(): DrawerAction
{
return amis()->DrawerAction()
->icon('fa-regular fa-pen-to-square')
->label(__('finance.ledger.actual_income'))
->level('link')
->drawer(
amis()->Drawer()->title(__('finance.ledger.actual_income'))->body([
amis()->Form()->title('')
->api('post:'.admin_url('finance/ledgers/${id}/actual-income'))
->body([
amis()->NumberControl()
->name('actual_income')
->label(__('finance.ledger.actual_income'))
->precision(2)
->showSteps(false)
->required(),
]),
])->size('lg')
);
}
}

View File

@ -4,6 +4,8 @@ namespace App\Admin\Controllers\Finance;
use App\Admin\Controllers\AdminController;
use App\Admin\Services\Finance\ReimbursementService;
use App\Enums\CheckStatus;
use App\Traits\HasCheckActions;
use Slowlyo\OwlAdmin\Admin;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\Page;
@ -13,6 +15,8 @@ use Slowlyo\OwlAdmin\Renderers\Page;
*/
class ReimbursementController extends AdminController
{
use HasCheckActions;
protected string $serviceName = ReimbursementService::class;
public function list(): Page
@ -31,10 +35,17 @@ class ReimbursementController extends AdminController
->source(admin_url('api/keywords/tree-list?parent_key=reimbursement_type'))
->labelField('name')
->valueField('key'),
amis()->SelectControl()->name('check_status')->label(__('workflow_log.check_status'))
->multiple()
->options(CheckStatus::options())
->clearable(),
]),
amis()->GroupControl()->mode('horizontal')->body([
amis()->InputDatetimeRange()
->name('created_at')
->label(__('finance.reimbursement.created_at'))
->format('YYYY-MM-DD HH:mm:ss'),
->format('YYYY-MM-DD HH:mm:ss')
->columnRatio(4),
]),
]))
->columns([
@ -43,9 +54,12 @@ class ReimbursementController extends AdminController
amis()->TableColumn()->name('expense')->label(__('finance.reimbursement.expense')),
amis()->TableColumn()->name('reason')->label(__('finance.reimbursement.reason')),
amis()->TableColumn()->name('type.name')->label(__('finance.reimbursement.type')),
amis()->TableColumn('workflow.check_status', __('workflow_log.check_status'))->set('type', 'mapping')->map(CheckStatus::labelMap()),
amis()->TableColumn()->name('created_at')->label(__('finance.reimbursement.created_at')),
$this->rowActions([
$this->rowShowButton()->visible(Admin::user()->can('admin.finance.reimbursements.view')),
$this->applyAction(),
$this->cancelAction(),
$this->rowShowButton()->visible(Admin::user()->can('admin.finance.reimbursements.view')),
]),
]);
@ -54,7 +68,16 @@ class ReimbursementController extends AdminController
public function detail(): Form
{
return $this->baseDetail()->title()->body([
$detailId = 'reimbursement-detail';
$serviceId = 'reimbursement-workflow-service';
return $this->baseDetail()->id($detailId)->title('')->onEvent([
'inited' => [
'actions' => [
['actionType' => 'reload', 'componentId' => $serviceId],
],
],
])->body([
amis()->Property()->items([
['label' => __('finance.reimbursement.employee'), 'content' => '${employee.name}'],
['label' => __('finance.reimbursement.expense'), 'content' => '${expense}'],
@ -62,7 +85,12 @@ class ReimbursementController extends AdminController
['label' => __('finance.reimbursement.type'), 'content' => '${type.name}'],
['label' => __('finance.reimbursement.created_at'), 'content' => '${created_at}'],
['label' => __('finance.reimbursement.photos'), 'content' => amis()->Images()->enlargeAble()->source('${photos}')->enlargeWithGallary(), 'span' => 3],
['label' => __('workflow_log.check_status'), 'content' => amis()->Mapping()->name('workflow.check_status')->map(CheckStatus::labelMap())],
['label' => __('workflow_log.checked_at'), 'content' => '${workflow.checked_at}'],
['label' => __('workflow_log.remarks'), 'content' => '${workflow.check_remarks}'],
]),
amis()->Divider(),
$this->baseWorkflowLogService($detailId)->id($serviceId),
]);
}
}

View File

@ -33,14 +33,16 @@ class StoreMasterCommissionController extends AdminController
amis()->MonthControl()
->name('month')
->label(__('finance.store_master_commission.month'))
->valueFormat('YYYY-MM')
->columnRatio(3),
->valueFormat('YYYY-MM'),
amis()->SelectControl('store_id', __('finance.ledger.store'))
->source(admin_url('api/stores'))
->labelField('title')
->valueField('id')
->clearable()
->columnRatio(3),
->clearable(),
amis()->SelectControl()->name('check_status')->label(__('workflow_log.check_status'))
->multiple()
->options(CheckStatus::options())
->clearable(),
]),
]))
->columns([

View File

@ -36,4 +36,11 @@ class LedgerFilter extends ModelFilter
->when($cityCode, fn ($query) => $query->where('region->cityCode', $cityCode));
});
}
public function checkStatus($checkStatus)
{
$this->related('workflow', function ($query) use ($checkStatus) {
$query->whereIn('check_status', explode(',', $checkStatus));
});
}
}

View File

@ -21,8 +21,10 @@ class ReimbursementFilter extends ModelFilter
$this->whereBetween('created_at', explode(',', $createdAt));
}
public function status($status)
public function checkStatus($checkStatus)
{
$this->whereIn('reimbursement_status', explode(',', $status));
$this->related('workflow', function ($query) use ($checkStatus) {
$query->whereIn('check_status', explode(',', $checkStatus));
});
}
}

View File

@ -16,8 +16,10 @@ class StoreMasterCommissionFilter extends ModelFilter
$this->where('store_id', $id);
}
public function status($status)
public function checkStatus($checkStatus)
{
$this->whereIn('approval_status', explode(',', $status));
$this->related('workflow', function ($query) use ($checkStatus) {
$query->whereIn('check_status', explode(',', $checkStatus));
});
}
}

View File

@ -4,7 +4,9 @@ namespace App\Admin\Services\Finance;
use App\Admin\Filters\LedgerFilter;
use App\Admin\Services\BaseService;
use App\Enums\CheckStatus;
use App\Models\Ledger;
use Illuminate\Support\Facades\Validator;
class LedgerService extends BaseService
{
@ -12,7 +14,37 @@ class LedgerService extends BaseService
protected string $modelFilterName = LedgerFilter::class;
protected array $withRelationships = ['store'];
protected array $withRelationships = ['store', 'workflow'];
public function update($primaryKey, $data): bool
{
Validator::validate(
data: $data,
rules: [
'actual_commission' => ['filled', 'numeric'],
'actual_income' => ['filled', 'numeric'],
],
attributes: [
'actual_commission' => __('finance.ledger.actual_commission'),
'actual_income' => __('finance.ledger.actual_income'),
],
);
$model = $this->query()->whereKey($primaryKey)->firstOrFail();
switch ($model->workflow->check_status) {
case CheckStatus::Processing:
admin_abort('不能修改审核中的上报数据');
break;
case CheckStatus::Success:
admin_abort('不能修改审核通过的报数据');
break;
}
$model->update($data);
return true;
}
public function sortColumn()
{

View File

@ -12,7 +12,7 @@ class ReimbursementService extends BaseService
protected string $modelFilterName = ReimbursementFilter::class;
protected array $withRelationships = ['employee', 'type'];
protected array $withRelationships = ['employee', 'type', 'workflow'];
public function sortColumn()
{

View File

@ -124,6 +124,8 @@ Route::group([
// 上报数据
$router->resource('ledgers', LedgerController::class);
$router->post('ledgers/{ledger}/ledger-amount', [LedgerController::class, 'updateLedgerAmount'])->name('ledgers.update_ledger_amount');
$router->post('ledgers/{ledger}/actual-commission', [LedgerController::class, 'updateActualCommission'])->name('ledgers.update_actual_commission');
$router->post('ledgers/{ledger}/actual-income', [LedgerController::class, 'updateActualIncome'])->name('ledgers.update_actual_income');
// 佣金收入
$router->get('commission-incomes', [CommissionIncomeController::class, 'index'])->name('commission_incomes.index');
// 收支报销

View File

@ -3,6 +3,7 @@
namespace App\Models;
use App\Enums\LedgerStatus;
use App\Traits\HasCheckable;
use App\Traits\HasDateTimeFormatter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Casts\Attribute;
@ -13,7 +14,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
class Ledger extends Model
{
use Filterable, HasDateTimeFormatter, HasFactory;
use Filterable, HasDateTimeFormatter, HasFactory, HasCheckable;
protected $appends = ['ledger_difference'];

View File

@ -2,6 +2,7 @@
namespace App\Models;
use App\Traits\HasCheckable;
use App\Traits\HasDateTimeFormatter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Casts\Attribute;
@ -11,7 +12,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Reimbursement extends Model
{
use Filterable, HasDateTimeFormatter, HasFactory;
use Filterable, HasDateTimeFormatter, HasFactory, HasCheckable;
protected $fillable = [
'employee_id',

View File

@ -35,6 +35,7 @@ class AppServiceProvider extends ServiceProvider
\App\Models\HolidayApply::class,
\App\Models\OvertimeApply::class,
\App\Models\OfficalBusiness::class,
\App\Models\Ledger::class,
\App\Models\Reimbursement::class,
\App\Models\StoreMasterCommission::class,
])->mapWithKeys(fn ($model) => [(new $model)->getTable() => $model])->all()

View File

@ -195,6 +195,8 @@ class AdminPermissionSeeder extends Seeder
'uri' => '/finance/ledgers',
'resource' => ['list', 'update', 'view'],
'children' => [
'update_actual_commission' => '编辑实际佣金',
'update_actual_income' => '编辑实际收益',
'update_ledger_amount' => '编辑总账金额',
],
],

View File

@ -22,6 +22,7 @@ class WorkflowSeeder extends Seeder
['key' => 'holiday_apply', 'name' => '请假申请', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
['key' => 'overtime_apply', 'name' => '加班申请', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
['key' => 'offical_business', 'name' => '出差报备', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
['key' => 'ledger', 'name' => '上报数据', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
['key' => 'reimbursement', 'name' => '收支报销', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
['key' => 'store_master_commission', 'name' => '店长提成', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
]);