166 lines
5.7 KiB
PHP
166 lines
5.7 KiB
PHP
<?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 think\facade\Db;
|
|
|
|
class DeptPerformanceTargetLogic extends BaseLogic
|
|
{
|
|
/**
|
|
* 指定月份:保留部门树层级 + 合并当月已有目标
|
|
*
|
|
* @return array{year_month: string, rows: array<int, array<string, mixed>>, total_target: float}
|
|
*/
|
|
public static function monthMatrix(string $yearMonth): array
|
|
{
|
|
$tree = DeptLogic::getAllData();
|
|
|
|
$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),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @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, string $adminName): bool
|
|
{
|
|
try {
|
|
Db::transaction(function () use ($yearMonth, $items, $adminId, $adminName): void {
|
|
foreach ($items as $item) {
|
|
if (!is_array($item)) {
|
|
continue;
|
|
}
|
|
$deptId = (int) ($item['dept_id'] ?? 0);
|
|
if ($deptId <= 0) {
|
|
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;
|
|
}
|
|
}
|