first commit
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\logic\finance;
|
||||
|
||||
use app\common\logic\BaseLogic;
|
||||
use app\common\model\dept\Dept;
|
||||
use app\common\model\finance\AccountCost;
|
||||
use app\common\service\qywx\MediaChannelService;
|
||||
|
||||
class AccountCostLogic extends BaseLogic
|
||||
{
|
||||
public static function add(array $params, int $adminId, string $adminName): bool
|
||||
{
|
||||
try {
|
||||
$costDate = (string) $params['cost_date'];
|
||||
$mediaChannelCode = trim((string) ($params['media_channel_code'] ?? ''));
|
||||
$mediaChannelName = MediaChannelService::getNameByCode($mediaChannelCode);
|
||||
$supportsDeptBinding = AccountCost::supportsDeptBinding();
|
||||
$deptId = $supportsDeptBinding ? (int) ($params['dept_id'] ?? 0) : 0;
|
||||
$deptName = $supportsDeptBinding ? self::resolveDeptName($deptId) : '';
|
||||
|
||||
if ($supportsDeptBinding && $deptName === '') {
|
||||
self::setError('请选择绑定部门');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$existsQuery = AccountCost::where('cost_date', $costDate)
|
||||
->where('media_channel_code', $mediaChannelCode);
|
||||
if ($supportsDeptBinding) {
|
||||
$existsQuery->where('dept_id', $deptId);
|
||||
}
|
||||
|
||||
if ($existsQuery->count() > 0) {
|
||||
self::setError($supportsDeptBinding
|
||||
? '该日期下所选渠道和部门的账户消耗已存在,请直接编辑'
|
||||
: '该日期下所选渠道的账户消耗已存在,请直接编辑');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'cost_date' => $costDate,
|
||||
'media_channel_code' => $mediaChannelCode,
|
||||
'media_channel_name' => $mediaChannelName,
|
||||
'amount' => round((float) $params['amount'], 2),
|
||||
'remark' => (string) ($params['remark'] ?? ''),
|
||||
'creator_id' => $adminId,
|
||||
'creator_name' => $adminName,
|
||||
'updater_id' => $adminId,
|
||||
'updater_name' => $adminName,
|
||||
];
|
||||
if ($supportsDeptBinding) {
|
||||
$payload['dept_id'] = $deptId;
|
||||
$payload['dept_name'] = $deptName;
|
||||
}
|
||||
|
||||
AccountCost::create($payload);
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
self::setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function edit(array $params, int $adminId, string $adminName): bool
|
||||
{
|
||||
try {
|
||||
$model = AccountCost::find($params['id']);
|
||||
if (!$model) {
|
||||
self::setError('记录不存在');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$mediaChannelCode = trim((string) ($params['media_channel_code'] ?? ''));
|
||||
$mediaChannelName = MediaChannelService::getNameByCode($mediaChannelCode);
|
||||
|
||||
$supportsDeptBinding = AccountCost::supportsDeptBinding();
|
||||
$deptId = $supportsDeptBinding ? (int) ($params['dept_id'] ?? 0) : 0;
|
||||
$deptName = $supportsDeptBinding ? self::resolveDeptName($deptId) : '';
|
||||
if ($supportsDeptBinding && $deptName === '') {
|
||||
self::setError('请选择绑定部门');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($supportsDeptBinding) {
|
||||
if (AccountCost::where('id', '<>', (int) $params['id'])
|
||||
->where('cost_date', (string) $model->cost_date)
|
||||
->where('media_channel_code', $mediaChannelCode)
|
||||
->where('dept_id', $deptId)
|
||||
->count() > 0) {
|
||||
self::setError('该日期下所选渠道和部门的账户消耗已存在,请直接编辑');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$model->media_channel_code = $mediaChannelCode;
|
||||
$model->media_channel_name = $mediaChannelName;
|
||||
if ($supportsDeptBinding) {
|
||||
$model->dept_id = $deptId;
|
||||
$model->dept_name = $deptName;
|
||||
}
|
||||
$model->amount = round((float) $params['amount'], 2);
|
||||
$model->remark = (string) ($params['remark'] ?? '');
|
||||
$model->updater_id = $adminId;
|
||||
$model->updater_name = $adminName;
|
||||
$model->save();
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
self::setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function detail(int $id): array
|
||||
{
|
||||
return AccountCost::findOrEmpty($id)->toArray();
|
||||
}
|
||||
|
||||
public static function delete(int $id): bool
|
||||
{
|
||||
try {
|
||||
$model = AccountCost::find($id);
|
||||
if (!$model) {
|
||||
self::setError('记录不存在');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$model->delete();
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
self::setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static function resolveDeptName(int $deptId): string
|
||||
{
|
||||
if ($deptId <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$dept = Dept::find($deptId);
|
||||
if (!$dept) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) ($dept->name ?? '');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\logic\finance;
|
||||
|
||||
use app\adminapi\logic\dept\DeptLogic;
|
||||
use app\common\logic\BaseLogic;
|
||||
use app\common\model\dept\Dept;
|
||||
use app\common\model\finance\DeptPerformanceTarget;
|
||||
use app\common\service\DataScope\DataScopeService;
|
||||
use think\facade\Db;
|
||||
|
||||
class DeptPerformanceTargetLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 指定月份:保留部门树层级 + 合并当月已有目标
|
||||
*
|
||||
* @return array{year_month: string, rows: array<int, array<string, mixed>>, total_target: float, data_scope_limited: bool}
|
||||
*/
|
||||
public static function monthMatrix(string $yearMonth, int $adminId = 0, array $adminInfo = []): array
|
||||
{
|
||||
$tree = DeptLogic::getAllData();
|
||||
$allowed = DataScopeService::getAllowedDeptIdSet($adminId, $adminInfo);
|
||||
$scoped = $allowed !== null;
|
||||
if ($scoped) {
|
||||
$tree = self::filterDeptTreeAllowedForest(is_array($tree) ? $tree : [], $allowed);
|
||||
}
|
||||
|
||||
$rowsDb = DeptPerformanceTarget::where('year_month', $yearMonth)
|
||||
->select()
|
||||
->toArray();
|
||||
$targets = [];
|
||||
foreach ($rowsDb as $r) {
|
||||
$targets[(int) ($r['dept_id'] ?? 0)] = $r;
|
||||
}
|
||||
|
||||
$rows = self::attachTargetsToTree(is_array($tree) ? $tree : [], $targets);
|
||||
$total = self::sumTargetsInTree($rows);
|
||||
|
||||
return [
|
||||
'year_month' => $yearMonth,
|
||||
'rows' => $rows,
|
||||
'total_target' => round($total, 2),
|
||||
'data_scope_limited' => $scoped,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array{dept_id?:int|float|string, target_amount?:int|float|string, remark?:string}> $items
|
||||
*/
|
||||
public static function batchSave(string $yearMonth, array $items, int $adminId, array $adminInfo, string $adminName): bool
|
||||
{
|
||||
$allowed = DataScopeService::getAllowedDeptIdSet($adminId, $adminInfo);
|
||||
|
||||
try {
|
||||
Db::transaction(function () use ($yearMonth, $items, $adminId, $adminName, $allowed): void {
|
||||
foreach ($items as $item) {
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
$deptId = (int) ($item['dept_id'] ?? 0);
|
||||
if ($deptId <= 0) {
|
||||
continue;
|
||||
}
|
||||
// 仅处理 data scope 内的 dept_id(界面树与 monthMatrix 一致,不再含纯展示用父级)
|
||||
if ($allowed !== null && !isset($allowed[$deptId])) {
|
||||
continue;
|
||||
}
|
||||
$dept = Dept::where('id', $deptId)->whereNull('delete_time')->find();
|
||||
if (!$dept) {
|
||||
continue;
|
||||
}
|
||||
$deptName = trim((string) ($dept->name ?? ''));
|
||||
$amt = round((float) ($item['target_amount'] ?? 0), 2);
|
||||
$remark = mb_substr(trim((string) ($item['remark'] ?? '')), 0, 255);
|
||||
|
||||
if ($amt <= 0) {
|
||||
DeptPerformanceTarget::where('dept_id', $deptId)
|
||||
->where('year_month', $yearMonth)
|
||||
->delete();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$row = DeptPerformanceTarget::where('dept_id', $deptId)
|
||||
->where('year_month', $yearMonth)
|
||||
->find();
|
||||
if ($row) {
|
||||
$row->dept_name = $deptName;
|
||||
$row->target_amount = $amt;
|
||||
$row->remark = $remark;
|
||||
$row->updater_id = $adminId;
|
||||
$row->updater_name = $adminName;
|
||||
$row->save();
|
||||
} else {
|
||||
DeptPerformanceTarget::create([
|
||||
'dept_id' => $deptId,
|
||||
'dept_name' => $deptName,
|
||||
'year_month' => $yearMonth,
|
||||
'target_amount' => $amt,
|
||||
'remark' => $remark,
|
||||
'creator_id' => $adminId,
|
||||
'creator_name' => $adminName,
|
||||
'updater_id' => $adminId,
|
||||
'updater_name' => $adminName,
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
self::setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $nodes DeptLogic::getAllData 子树
|
||||
* @param array<int, array<string, mixed>> $targets keyed by dept_id
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private static function attachTargetsToTree(array $nodes, array $targets, string $prefix = ''): array
|
||||
{
|
||||
$out = [];
|
||||
foreach ($nodes as $n) {
|
||||
if (!is_array($n)) {
|
||||
continue;
|
||||
}
|
||||
$id = (int) ($n['id'] ?? 0);
|
||||
$name = trim((string) ($n['name'] ?? ''));
|
||||
if ($id <= 0) {
|
||||
continue;
|
||||
}
|
||||
$path = $prefix === '' ? $name : $prefix . ' / ' . $name;
|
||||
$t = $targets[$id] ?? null;
|
||||
$amt = $t ? round((float) $t['target_amount'], 2) : 0.0;
|
||||
$node = [
|
||||
'dept_id' => $id,
|
||||
'dept_name' => $name,
|
||||
'dept_path' => $path,
|
||||
'target_id' => $t ? (int) $t['id'] : 0,
|
||||
'target_amount' => $amt,
|
||||
'remark' => $t ? (string) ($t['remark'] ?? '') : '',
|
||||
];
|
||||
$rawChildren = $n['children'] ?? [];
|
||||
$childList = is_array($rawChildren) && $rawChildren !== []
|
||||
? self::attachTargetsToTree($rawChildren, $targets, $path)
|
||||
: [];
|
||||
if ($childList !== []) {
|
||||
$node['children'] = $childList;
|
||||
}
|
||||
$out[] = $node;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $nodes
|
||||
*/
|
||||
private static function sumTargetsInTree(array $nodes): float
|
||||
{
|
||||
$s = 0.0;
|
||||
foreach ($nodes as $n) {
|
||||
$s += (float) ($n['target_amount'] ?? 0);
|
||||
$ch = $n['children'] ?? [];
|
||||
if (is_array($ch) && $ch !== []) {
|
||||
$s += self::sumTargetsInTree($ch);
|
||||
}
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 本部门及以下:仅展示 allowed 内节点;无权父级不渲染,从子树中接续(不露出公司/上级中心)。
|
||||
*
|
||||
* @param array<int, array<string, mixed>> $nodes
|
||||
* @param array<int, true> $allowedMap
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private static function filterDeptTreeAllowedForest(array $nodes, array $allowedMap): array
|
||||
{
|
||||
if ($allowedMap === []) {
|
||||
return [];
|
||||
}
|
||||
$out = [];
|
||||
foreach ($nodes as $n) {
|
||||
if (!is_array($n)) {
|
||||
continue;
|
||||
}
|
||||
$id = (int) ($n['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
continue;
|
||||
}
|
||||
$rawChildren = $n['children'] ?? [];
|
||||
$kids = is_array($rawChildren) ? $rawChildren : [];
|
||||
|
||||
if (isset($allowedMap[$id])) {
|
||||
$childList = [];
|
||||
foreach ($kids as $c) {
|
||||
if (!is_array($c)) {
|
||||
continue;
|
||||
}
|
||||
foreach (self::filterDeptTreeAllowedForest([$c], $allowedMap) as $item) {
|
||||
$childList[] = $item;
|
||||
}
|
||||
}
|
||||
$node = $n;
|
||||
if ($childList !== []) {
|
||||
$node['children'] = $childList;
|
||||
} else {
|
||||
unset($node['children']);
|
||||
}
|
||||
$out[] = $node;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($kids as $c) {
|
||||
if (!is_array($c)) {
|
||||
continue;
|
||||
}
|
||||
foreach (self::filterDeptTreeAllowedForest([$c], $allowedMap) as $item) {
|
||||
$out[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | likeadmin快速开发前后端分离管理后台(PHP版)
|
||||
// +----------------------------------------------------------------------
|
||||
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
|
||||
// | 开源版本可自由商用,可去除界面版权logo
|
||||
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
|
||||
// | github下载:https://github.com/likeshop-github/likeadmin
|
||||
// | 访问官网:https://www.likeadmin.cn
|
||||
// | likeadmin团队 版权所有 拥有最终解释权
|
||||
// +----------------------------------------------------------------------
|
||||
// | author: likeadminTeam
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\adminapi\logic\finance;
|
||||
|
||||
|
||||
use app\common\enum\RefundEnum;
|
||||
use app\common\logic\BaseLogic;
|
||||
use app\common\model\refund\RefundLog;
|
||||
use app\common\model\refund\RefundRecord;
|
||||
|
||||
|
||||
/**
|
||||
* 退款
|
||||
* Class RefundLogic
|
||||
* @package app\adminapi\logic\finance
|
||||
*/
|
||||
class RefundLogic extends BaseLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* @notes 退款统计
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author 段誉
|
||||
* @date 2023/3/3 12:09
|
||||
*/
|
||||
public static function stat()
|
||||
{
|
||||
$records = RefundRecord::select()->toArray();
|
||||
|
||||
$total = 0;
|
||||
$ing = 0;
|
||||
$success = 0;
|
||||
$error = 0;
|
||||
|
||||
foreach ($records as $record) {
|
||||
$total += $record['order_amount'];
|
||||
switch ($record['refund_status']) {
|
||||
case RefundEnum::REFUND_ING:
|
||||
$ing += $record['order_amount'];
|
||||
break;
|
||||
case RefundEnum::REFUND_SUCCESS:
|
||||
$success += $record['order_amount'];
|
||||
break;
|
||||
case RefundEnum::REFUND_ERROR:
|
||||
$error += $record['order_amount'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'total' => round($total, 2),
|
||||
'ing' => round($ing, 2),
|
||||
'success' => round($success, 2),
|
||||
'error' => round($error, 2),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @notes 退款日志
|
||||
* @param $recordId
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author 段誉
|
||||
* @date 2023/3/3 14:25
|
||||
*/
|
||||
public static function refundLog($recordId)
|
||||
{
|
||||
return (new RefundLog())
|
||||
->order(['id' => 'desc'])
|
||||
->where('record_id', $recordId)
|
||||
->hidden(['refund_msg'])
|
||||
->append(['handler', 'refund_status_text'])
|
||||
->select()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user