两个「终版」目录(供应商应付(终版)、快递应付(终版))改为独立数据: 保留原有导入、导出、查询、重置、编辑按钮和导入模板,数据初始为空、按表独立存放, 不再借用基础目录的页面与数据。 - 终版目录拥有自己的同名子页面与横向页签 - 新增终版按表数据的独立导入/导出/模板/编辑接口(数据集键 final:<目录>:<页面>) - 供应商终版 13 个页面、快递终版 4 个页面已接入 - 终版导入模板统一增加“月份”列,记录标识列改为选填
129 lines
4.6 KiB
PHP
129 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace Modules\EcommerceFinance\Services;
|
|
|
|
use Closure;
|
|
use Illuminate\Database\ConnectionInterface;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class SupplierPayableOverrideStore
|
|
{
|
|
public function key(string $dataset, array $row): string
|
|
{
|
|
if (isset($row['sourceId']) && $row['sourceId'] !== '') {
|
|
return 'id:' . (string) ($row['recordType'] ?? '') . ':' . (string) $row['sourceId'];
|
|
}
|
|
if (isset($row['id']) && $row['id'] !== '') {
|
|
return 'id:' . (string) $row['id'];
|
|
}
|
|
|
|
$immutable = $row;
|
|
unset($immutable['_action_key'], $immutable['_overridden']);
|
|
|
|
return 'hash:' . hash('sha256', json_encode($immutable, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
}
|
|
|
|
/** @param array<int,array<string,mixed>> $rows */
|
|
public function decorate(string $dataset, array $rows, int $companyId): array
|
|
{
|
|
if ($rows === []) {
|
|
return [];
|
|
}
|
|
|
|
$keys = [];
|
|
foreach ($rows as $row) {
|
|
$keys[] = $this->key($dataset, $row);
|
|
}
|
|
|
|
$overrides = $this->connection()->table('supplier_payable_overrides')
|
|
->where('company_id', $companyId)
|
|
->where('dataset', $dataset)
|
|
->whereIn('record_key', $keys)
|
|
->get()
|
|
->keyBy('record_key');
|
|
|
|
foreach ($rows as $index => &$row) {
|
|
$key = $keys[$index];
|
|
$row['_action_key'] = $key;
|
|
$override = $overrides->get($key);
|
|
if ($override) {
|
|
$values = json_decode((string) $override->values, true) ?: [];
|
|
$row = array_merge($row, $values);
|
|
$row['_overridden'] = true;
|
|
} else {
|
|
$row['_overridden'] = false;
|
|
}
|
|
}
|
|
unset($row);
|
|
|
|
return $rows;
|
|
}
|
|
|
|
/** @return array{created:int,updated:int} */
|
|
public function save(string $dataset, string $recordKey, array $values, int $companyId, ?int $userId, string $source = 'manual'): array
|
|
{
|
|
$connection = $this->connection();
|
|
$existing = $connection->table('supplier_payable_overrides')
|
|
->where(['company_id' => $companyId, 'dataset' => $dataset, 'record_key' => $recordKey])
|
|
->first();
|
|
$before = $existing ? (json_decode((string) $existing->values, true) ?: []) : null;
|
|
$now = now();
|
|
|
|
$connection->transaction(function () use ($connection, $existing, $dataset, $recordKey, $values, $companyId, $userId, $now, $source, $before): void {
|
|
$connection->table('supplier_payable_overrides')->updateOrInsert(
|
|
['company_id' => $companyId, 'dataset' => $dataset, 'record_key' => $recordKey],
|
|
[
|
|
'values' => json_encode($values, JSON_UNESCAPED_UNICODE),
|
|
'updated_by' => $userId,
|
|
'created_by' => $existing->created_by ?? $userId,
|
|
'created_at' => $existing->created_at ?? $now,
|
|
'updated_at' => $now,
|
|
],
|
|
);
|
|
$connection->table('supplier_payable_override_events')->insert([
|
|
'company_id' => $companyId,
|
|
'dataset' => $dataset,
|
|
'record_key' => $recordKey,
|
|
'source' => $source,
|
|
'before_values' => $before === null ? null : json_encode($before, JSON_UNESCAPED_UNICODE),
|
|
'after_values' => json_encode($values, JSON_UNESCAPED_UNICODE),
|
|
'user_id' => $userId,
|
|
'created_at' => $now,
|
|
]);
|
|
});
|
|
|
|
return ['created' => $existing ? 0 : 1, 'updated' => $existing ? 1 : 0];
|
|
}
|
|
|
|
public function transaction(Closure $callback): mixed
|
|
{
|
|
return $this->connection()->transaction($callback);
|
|
}
|
|
|
|
/**
|
|
* 列出某个数据集已经保存的全部记录(「终版」目录的独立数据就是这些行)。
|
|
*
|
|
* @return array<int,array<string,mixed>>
|
|
*/
|
|
public function listRows(string $dataset, int $companyId): array
|
|
{
|
|
return $this->connection()->table('supplier_payable_overrides')
|
|
->where('company_id', $companyId)
|
|
->where('dataset', $dataset)
|
|
->orderBy('id')
|
|
->get()
|
|
->map(static function (object $record): array {
|
|
$values = json_decode((string) $record->values, true) ?: [];
|
|
$values['_action_key'] = (string) $record->record_key;
|
|
|
|
return $values;
|
|
})
|
|
->all();
|
|
}
|
|
|
|
private function connection(): ConnectionInterface
|
|
{
|
|
return DB::connection(config('database.supplier_payable_maintenance_connection'));
|
|
}
|
|
}
|