Add the period balance reconciliation page, permissions, financial closing balances, Jushuitan snapshots for Taobao Alipay, Pinduoduo and Douyin, and explicit unavailable states.
482 lines
22 KiB
PHP
482 lines
22 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Modules\EcommerceFinance\Repositories\JushuitanShopBalanceRepository;
|
|
use Modules\EcommerceFinance\Services\JushuitanShopBalanceImporter;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
use Tests\TestCase;
|
|
|
|
class JushuitanShopBalanceRepositoryTest extends TestCase
|
|
{
|
|
/** @var list<string> */
|
|
private array $temporaryFiles = [];
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
DB::connection('business_mirror')->table(JushuitanShopBalanceRepository::TABLE)->delete();
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
foreach ($this->temporaryFiles as $path) {
|
|
if (is_file($path)) {
|
|
unlink($path);
|
|
}
|
|
}
|
|
|
|
parent::tearDown();
|
|
}
|
|
|
|
public function testItImportsTheRequestedJsonDateAndUsesPlatformToDisambiguateStores(): void
|
|
{
|
|
$path = $this->jsonFile([
|
|
'data' => [
|
|
'isSuccess' => true,
|
|
'fldHeads' => [
|
|
['title' => '店铺', 'fld' => 'shop_name'],
|
|
['title' => '支付宝账号', 'fld' => 'platform_shop_id'],
|
|
['title' => '09-11', 'fld' => 'balance_20260911'],
|
|
['title' => '09-10', 'fld' => 'balance_20260910'],
|
|
],
|
|
'dataList' => [
|
|
['shop_name' => '天猫-同名店', 'platform_shop_id' => 'TM-1', 'balance_20260911' => '19,895.01', 'balance_20260910' => 1],
|
|
['shop_name' => '淘宝-同名店', 'platform_shop_id' => 'TB-1', 'balance_20260911' => 425, 'balance_20260910' => 2],
|
|
['shop_name' => '支付宝-唯一店', 'platform_shop_id' => 'ALI-1', 'balance_20260911' => 10334.09, 'balance_20260910' => 3],
|
|
['shop_name' => '拼多多-跨平台店', 'platform_shop_id' => 'PDD-1', 'balance_20260911' => 999, 'balance_20260910' => 4],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$result = app(JushuitanShopBalanceImporter::class)->import($path, '2026-09-11');
|
|
$matches = app(JushuitanShopBalanceRepository::class)->matchesForStores([
|
|
(object) ['id' => 1, 'store_platform' => '天猫', 'shop_name' => '同名店', 'erp_store_name' => 'ERP同名店'],
|
|
(object) ['id' => 2, 'store_platform' => '淘宝', 'shop_name' => '同名店', 'erp_store_name' => 'ERP同名店'],
|
|
(object) ['id' => 3, 'store_platform' => '京东', 'shop_name' => '唯一店', 'erp_store_name' => 'ERP唯一店'],
|
|
(object) ['id' => 4, 'store_platform' => '拼多多', 'shop_name' => '不存在', 'erp_store_name' => 'ERP不存在'],
|
|
(object) ['id' => 5, 'store_platform' => '京东', 'shop_name' => '跨平台店', 'erp_store_name' => 'ERP跨平台店'],
|
|
], '2026-09-11');
|
|
|
|
$this->assertSame('2026-09-11', $result['balance_date']);
|
|
$this->assertSame(4, $result['total']);
|
|
$this->assertSame(4, app(JushuitanShopBalanceRepository::class)->countForDate('2026-09-11'));
|
|
$this->assertSame(19895.01, $matches[1]['balance']);
|
|
$this->assertSame(425.0, $matches[2]['balance']);
|
|
$this->assertSame('unmatched', $matches[3]['status']);
|
|
$this->assertSame('unmatched', $matches[4]['status']);
|
|
$this->assertSame('unmatched', $matches[5]['status']);
|
|
}
|
|
|
|
public function testItKeepsMultipleUnresolvedAccountsAmbiguous(): void
|
|
{
|
|
$path = $this->jsonFile([
|
|
'isSuccess' => true,
|
|
'fldHeads' => [
|
|
['title' => '店铺', 'fld' => 'shop_name'],
|
|
['title' => '支付宝账号', 'fld' => 'platform_shop_id'],
|
|
['title' => '09-11', 'fld' => 'balance'],
|
|
],
|
|
'dataList' => [
|
|
['shop_name' => '天猫-重复店', 'platform_shop_id' => 'A-1', 'balance' => 10],
|
|
['shop_name' => '天猫-重复店', 'platform_shop_id' => 'A-2', 'balance' => 20],
|
|
],
|
|
]);
|
|
|
|
app(JushuitanShopBalanceImporter::class)->import($path, '2026-09-11');
|
|
$matches = app(JushuitanShopBalanceRepository::class)->matchesForStores([
|
|
(object) ['id' => 10, 'store_platform' => '天猫', 'shop_name' => '重复店', 'erp_store_name' => '重复店'],
|
|
], '2026-09-11');
|
|
|
|
$this->assertSame('ambiguous', $matches[10]['status']);
|
|
$this->assertNull($matches[10]['balance']);
|
|
}
|
|
|
|
public function testItInfers1688PlatformWhenTheExportedStoreHasNoPlatformPrefix(): void
|
|
{
|
|
DB::connection('business_mirror')->table(JushuitanShopBalanceRepository::TABLE)->insert([
|
|
'balance_date' => '2026-09-11',
|
|
'source_scope' => 'alipay',
|
|
'source_platform' => null,
|
|
'store_name' => '新佰广1688',
|
|
'normalized_store_name' => JushuitanShopBalanceRepository::normalizeStoreName('新佰广1688'),
|
|
'platform_account_id' => '2088180857774924',
|
|
'balance' => 44501.18,
|
|
'source_row_key' => hash('sha256', '新佰广1688'),
|
|
'source_file_name' => 'fixture.xlsx',
|
|
'source_sha256' => str_repeat('b', 64),
|
|
'imported_at' => now(),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$matches = app(JushuitanShopBalanceRepository::class)->matchesForStores([
|
|
(object) ['id' => 30, 'store_platform' => '阿里巴巴', 'shop_name' => '新佰广1688', 'erp_store_name' => '新佰广1688'],
|
|
], '2026-09-11');
|
|
|
|
$this->assertSame('matched', $matches[30]['status']);
|
|
$this->assertSame(44501.18, $matches[30]['balance']);
|
|
$this->assertSame('1688', JushuitanShopBalanceRepository::sourcePlatform('新佰广1688'));
|
|
$this->assertSame('淘宝', JushuitanShopBalanceRepository::sourcePlatform('淘宝-1688家具店'));
|
|
}
|
|
|
|
public function testItReadsThePreviousYearDateFromAnXlsxExportOnNewYearsDay(): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$spreadsheet->getActiveSheet()->fromArray([
|
|
['店铺', '支付宝账号', '12-31'],
|
|
['天猫-跨年店', 'TM-2026', 88.88],
|
|
]);
|
|
$path = sys_get_temp_dir() . '/jushuitan-shop-balance-' . uniqid('', true) . '.xlsx';
|
|
(new Xlsx($spreadsheet))->save($path);
|
|
$spreadsheet->disconnectWorksheets();
|
|
$this->temporaryFiles[] = $path;
|
|
|
|
$result = app(JushuitanShopBalanceImporter::class)->import($path, '2026-12-31');
|
|
|
|
$this->assertSame('2026-12-31', $result['balance_date']);
|
|
$this->assertSame(1, $result['total']);
|
|
$this->assertSame(88.88, (float) DB::connection('business_mirror')
|
|
->table(JushuitanShopBalanceRepository::TABLE)
|
|
->value('balance'));
|
|
}
|
|
|
|
public function testItImportsPlatformFundBalancesFromTheActualClosingBalanceColumn(): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$spreadsheet->getActiveSheet()->fromArray([
|
|
['平台', '来源', '店铺', '期初余额', '本期收入', '本期支出', '期末余额', '平台实际期末余额', '状态'],
|
|
['拼多多', '拼多多货款账户', '拼多多-多平台测试店', 0, 0, 0, 0, 34499.28, '空'],
|
|
]);
|
|
$path = sys_get_temp_dir() . '/jushuitan-platform-balance-' . uniqid('', true) . '.xlsx';
|
|
(new Xlsx($spreadsheet))->save($path);
|
|
$spreadsheet->disconnectWorksheets();
|
|
$this->temporaryFiles[] = $path;
|
|
|
|
$result = app(JushuitanShopBalanceImporter::class)->import(
|
|
$path,
|
|
'2026-09-11',
|
|
'pinduoduo',
|
|
);
|
|
$matches = app(JushuitanShopBalanceRepository::class)->matchesForStores([
|
|
(object) ['id' => 20, 'store_platform' => '拼多多', 'shop_name' => '多平台测试店', 'erp_store_name' => 'ERP测试店'],
|
|
], '2026-09-11');
|
|
|
|
$this->assertSame(1, $result['total']);
|
|
$this->assertSame(34499.28, $matches[20]['balance']);
|
|
$this->assertSame('拼多多', $matches[20]['source_platform']);
|
|
}
|
|
|
|
public function testItReplacesTheSameDateAndSourceScopeOnRefresh(): void
|
|
{
|
|
$firstPath = $this->jsonFile([
|
|
'isSuccess' => true,
|
|
'fldHeads' => [
|
|
['title' => '店铺', 'fld' => 'shop_name'],
|
|
['title' => '09-12', 'fld' => 'balance'],
|
|
],
|
|
'dataList' => [
|
|
['shop_name' => '拼多多-每日刷新店', 'balance' => 100],
|
|
['shop_name' => '拼多多-应被移除店', 'balance' => 200],
|
|
],
|
|
]);
|
|
$secondPath = $this->jsonFile([
|
|
'isSuccess' => true,
|
|
'fldHeads' => [
|
|
['title' => '店铺', 'fld' => 'shop_name'],
|
|
['title' => '09-12', 'fld' => 'balance'],
|
|
],
|
|
'dataList' => [
|
|
['shop_name' => '拼多多-每日刷新店', 'balance' => 350.25],
|
|
],
|
|
]);
|
|
|
|
app(JushuitanShopBalanceImporter::class)->import($firstPath, '2026-09-12', 'pinduoduo');
|
|
$result = app(JushuitanShopBalanceImporter::class)->import($secondPath, '2026-09-12', 'pinduoduo');
|
|
$rows = DB::connection('business_mirror')
|
|
->table(JushuitanShopBalanceRepository::TABLE)
|
|
->where('balance_date', '2026-09-12')
|
|
->where('source_scope', 'pinduoduo')
|
|
->get(['store_name', 'balance']);
|
|
|
|
$this->assertSame(2, $result['replaced']);
|
|
$this->assertCount(1, $rows);
|
|
$this->assertSame('拼多多-每日刷新店', $rows->first()->store_name);
|
|
$this->assertSame(350.25, (float) $rows->first()->balance);
|
|
}
|
|
|
|
public function testItImportsTheLatestJdWalletBalanceAtTheRequestedCutoff(): void
|
|
{
|
|
$path = $this->xlsxFile([
|
|
['记录编码', '店铺', '账户名称', '费用结算时间', '账户余额'],
|
|
['90000000000000000001', '京东-同名钱包店', '京东账户', '2026-09-13 22:00:00', 10],
|
|
['90000000000000000002', '京东-同名钱包店', '京东账户', '2026-09-14 22:00:00', 20],
|
|
['100000000000000000003', '京东-同名钱包店', '京东账户', '2026-09-14 22:00:00', 25.5],
|
|
['100000000000000000004', '京东-同名钱包店', '京东账户', '2026-09-15 00:00:00', 999],
|
|
['200000000000000000001', '京喜-京喜钱包店', '京喜账户', '2026-09-14 16:00:00', 30.75],
|
|
['300000000000000000001', '京喜小店-制造店', '京喜小店账户', '2026-09-14 17:00:00', 40.25],
|
|
]);
|
|
|
|
$result = app(JushuitanShopBalanceImporter::class)->import(
|
|
$path,
|
|
'2026-09-14',
|
|
'jd-wallet',
|
|
);
|
|
$matches = app(JushuitanShopBalanceRepository::class)->matchesForStores([
|
|
(object) ['id' => 40, 'store_platform' => '京东', 'shop_name' => '同名钱包店', 'erp_store_name' => 'ERP京东店'],
|
|
(object) ['id' => 41, 'store_platform' => '京喜', 'shop_name' => '京喜钱包店', 'erp_store_name' => 'ERP京喜店'],
|
|
(object) ['id' => 42, 'store_platform' => '京喜', 'shop_name' => '制造店', 'erp_store_name' => 'ERP京喜小店'],
|
|
], '2026-09-14');
|
|
|
|
$this->assertSame(3, $result['total']);
|
|
$this->assertSame(25.5, $matches[40]['balance']);
|
|
$this->assertSame('京东', $matches[40]['source_platform']);
|
|
$this->assertSame(30.75, $matches[41]['balance']);
|
|
$this->assertSame('京喜', $matches[41]['source_platform']);
|
|
$this->assertSame(40.25, $matches[42]['balance']);
|
|
$this->assertSame('京喜小店', $matches[42]['source_platform']);
|
|
}
|
|
|
|
public function testJdWalletValidationFailureKeepsThePreviousSnapshot(): void
|
|
{
|
|
$validPath = $this->xlsxFile([
|
|
['记录编码', '店铺', '账户名称', '费用结算时间', '账户余额'],
|
|
['1', '京东-保留旧余额店', '京东账户', '2026-09-14 12:00:00', 88.88],
|
|
]);
|
|
$invalidPath = $this->xlsxFile([
|
|
['记录编码', '店铺', '账户名称', '账户余额'],
|
|
['2', '京东-保留旧余额店', '京东账户', 99.99],
|
|
]);
|
|
|
|
app(JushuitanShopBalanceImporter::class)->import($validPath, '2026-09-14', 'jd-wallet');
|
|
|
|
try {
|
|
app(JushuitanShopBalanceImporter::class)->import($invalidPath, '2026-09-14', 'jd-wallet');
|
|
$this->fail('缺少费用结算时间的京东钱包文件不应被导入。');
|
|
} catch (\InvalidArgumentException $exception) {
|
|
$this->assertStringContainsString('费用结算时间', $exception->getMessage());
|
|
}
|
|
|
|
$row = DB::connection('business_mirror')
|
|
->table(JushuitanShopBalanceRepository::TABLE)
|
|
->where('balance_date', '2026-09-14')
|
|
->where('source_scope', 'jd-wallet')
|
|
->sole();
|
|
|
|
$this->assertSame('京东-保留旧余额店', $row->store_name);
|
|
$this->assertSame(88.88, (float) $row->balance);
|
|
}
|
|
|
|
public function testJdWalletRowsAfterTheCutoffKeepThePreviousSnapshot(): void
|
|
{
|
|
$validPath = $this->xlsxFile([
|
|
['记录编码', '店铺', '费用结算时间', '账户余额'],
|
|
['1', '京东-截止日前店铺', '2026-09-14 23:59:59', 66.66],
|
|
]);
|
|
$futurePath = $this->xlsxFile([
|
|
['记录编码', '店铺', '费用结算时间', '账户余额'],
|
|
['2', '京东-截止日前店铺', '2026-09-15 00:00:00', 77.77],
|
|
]);
|
|
|
|
app(JushuitanShopBalanceImporter::class)->import($validPath, '2026-09-14', 'jd-wallet');
|
|
|
|
try {
|
|
app(JushuitanShopBalanceImporter::class)->import($futurePath, '2026-09-14', 'jd-wallet');
|
|
$this->fail('截止日期后没有可用数据时不应替换旧快照。');
|
|
} catch (\InvalidArgumentException $exception) {
|
|
$this->assertStringContainsString('已保留原有快照', $exception->getMessage());
|
|
}
|
|
|
|
$this->assertSame(66.66, (float) DB::connection('business_mirror')
|
|
->table(JushuitanShopBalanceRepository::TABLE)
|
|
->where('balance_date', '2026-09-14')
|
|
->where('source_scope', 'jd-wallet')
|
|
->value('balance'));
|
|
}
|
|
|
|
public function testItKeepsHistoricalSnapshotsAndSelectsTheLatestBalanceDate(): void
|
|
{
|
|
Carbon::setTestNow('2026-10-20 10:00:00');
|
|
|
|
try {
|
|
$this->insertBalanceSnapshot('2026-09-01', '2026-09-02 10:00:00', '历史店');
|
|
$this->insertBalanceSnapshot('2026-10-18', '2026-10-19 10:00:00', '最新店');
|
|
$this->insertBalanceSnapshot('2026-10-25', '2026-10-25 10:00:00', '未来店');
|
|
|
|
$repository = app(JushuitanShopBalanceRepository::class);
|
|
|
|
$this->assertSame('2026-10-18', $repository->latestBalanceDate());
|
|
$this->assertSame('2026-09-01', $repository->earliestBalanceDate());
|
|
$this->assertSame(['2026-10-18', '2026-09-01'], $repository->availableDates());
|
|
$this->assertSame(1, $repository->countForDate('2026-09-01'));
|
|
$matches = $repository->matchesForStores([
|
|
(object) ['id' => 70, 'store_platform' => '天猫', 'shop_name' => '历史店', 'erp_store_name' => '历史店'],
|
|
], '2026-09-01');
|
|
$this->assertSame('matched', $matches[70]['status']);
|
|
$this->assertSame(100.0, $matches[70]['balance']);
|
|
} finally {
|
|
Carbon::setTestNow();
|
|
}
|
|
}
|
|
|
|
public function testStoreLedgerScopeIsIsolatedFromWithdrawalBalanceMatching(): void
|
|
{
|
|
$this->insertBalanceSnapshot('2026-10-18', '2026-10-19 10:00:00', '隔离测试店', 'daily');
|
|
DB::connection('business_mirror')->table(JushuitanShopBalanceRepository::TABLE)->insert([
|
|
'balance_date' => '2026-10-18',
|
|
'source_scope' => JushuitanShopBalanceRepository::SOURCE_SCOPE_STORE_LEDGER,
|
|
'data_source' => 'store_receiving_bill',
|
|
'source_platform' => '天猫',
|
|
'store_name' => '隔离测试店',
|
|
'normalized_store_name' => JushuitanShopBalanceRepository::normalizeStoreName('隔离测试店'),
|
|
'platform_account_id' => 'ledger-account',
|
|
'balance' => 200,
|
|
'source_row_key' => hash('sha256', 'store-ledger|隔离测试店'),
|
|
'source_file_name' => '财务系统/店铺收款账户账单/淘系支付宝',
|
|
'source_sha256' => str_repeat('d', 64),
|
|
'imported_at' => now(),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$repository = app(JushuitanShopBalanceRepository::class);
|
|
$store = (object) [
|
|
'id' => 80,
|
|
'store_platform' => '天猫',
|
|
'shop_name' => '隔离测试店',
|
|
'erp_store_name' => '隔离测试店',
|
|
];
|
|
|
|
$this->assertSame(1, $repository->countForDate('2026-10-18'));
|
|
$this->assertSame('matched', $repository->matchesForStores([$store], '2026-10-18')[80]['status']);
|
|
$this->assertSame(100.0, $repository->matchesForStores([$store], '2026-10-18')[80]['balance']);
|
|
$this->assertSame(200.0, $repository->matchesForStores(
|
|
[$store],
|
|
'2026-10-18',
|
|
null,
|
|
JushuitanShopBalanceRepository::SOURCE_SCOPE_STORE_LEDGER,
|
|
)[80]['balance']);
|
|
}
|
|
|
|
public function testImportingANewDateKeepsOlderSnapshots(): void
|
|
{
|
|
Carbon::setTestNow('2026-10-20 10:00:00');
|
|
|
|
try {
|
|
$this->insertBalanceSnapshot('2026-09-01', '2026-09-02 12:00:00', '旧导入店', 'daily');
|
|
|
|
$path = $this->jsonFile([
|
|
'isSuccess' => true,
|
|
'fldHeads' => [
|
|
['title' => '店铺', 'fld' => 'shop_name'],
|
|
['title' => '10-19', 'fld' => 'balance'],
|
|
],
|
|
'dataList' => [
|
|
['shop_name' => '拼多多-今日导入店', 'balance' => 123.45],
|
|
],
|
|
]);
|
|
|
|
$result = app(JushuitanShopBalanceImporter::class)->import($path, '2026-10-19', 'daily');
|
|
|
|
$this->assertSame(1, $result['total']);
|
|
$this->assertArrayNotHasKey('pruned', $result);
|
|
$this->assertTrue(DB::connection('business_mirror')
|
|
->table(JushuitanShopBalanceRepository::TABLE)
|
|
->where('store_name', '旧导入店')
|
|
->exists());
|
|
$this->assertSame(1, app(JushuitanShopBalanceRepository::class)->countForDate('2026-09-01'));
|
|
} finally {
|
|
Carbon::setTestNow();
|
|
}
|
|
}
|
|
|
|
public function testItSelectsTheLatestComparisonSnapshotPerConnectedSourceAndIgnoresTheFinancialLedger(): void
|
|
{
|
|
$this->insertBalanceSnapshot('2026-10-20', '2026-10-20 18:00:00', '淘系旧快照店', 'taobao');
|
|
$this->insertBalanceSnapshot('2026-11-10', '2026-11-10 18:00:00', '淘系截止日后店', 'taobao');
|
|
$this->insertBalanceSnapshot('2026-10-30', '2026-10-30 18:00:00', '淘系店铺', 'taobao');
|
|
$this->insertBalanceSnapshot('2026-10-25', '2026-10-25 18:00:00', '拼多多店铺', 'pinduoduo');
|
|
$this->insertBalanceSnapshot('2026-10-24', '2026-10-24 18:00:00', '抖音店铺', 'douyin');
|
|
$this->insertBalanceSnapshot(
|
|
'2026-10-31',
|
|
'2026-10-31 18:00:00',
|
|
'财务系统快照店',
|
|
JushuitanShopBalanceRepository::SOURCE_SCOPE_STORE_LEDGER,
|
|
'store_receiving_bill',
|
|
);
|
|
|
|
$result = app(JushuitanShopBalanceRepository::class)->latestComparisonSnapshots(
|
|
['taobao', 'pinduoduo', 'douyin'],
|
|
'2026-10-31',
|
|
);
|
|
$dates = $result['dates'];
|
|
ksort($dates);
|
|
|
|
$this->assertSame([
|
|
'douyin' => '2026-10-24',
|
|
'pinduoduo' => '2026-10-25',
|
|
'taobao' => '2026-10-30',
|
|
], $dates);
|
|
$this->assertSame(
|
|
['抖音店铺', '拼多多店铺', '淘系店铺'],
|
|
array_values(array_map(static fn (object $row): string => $row->store_name, $result['rows'])),
|
|
);
|
|
$this->assertNotContains(
|
|
'财务系统快照店',
|
|
array_column(array_map(static fn (object $row): array => (array) $row, $result['rows']), 'store_name'),
|
|
);
|
|
}
|
|
|
|
private function insertBalanceSnapshot(
|
|
string $balanceDate,
|
|
string $importedAt,
|
|
string $storeName,
|
|
string $sourceScope = 'all',
|
|
string $dataSource = 'jushuitan',
|
|
): void {
|
|
DB::connection('business_mirror')->table(JushuitanShopBalanceRepository::TABLE)->insert([
|
|
'balance_date' => $balanceDate,
|
|
'source_scope' => $sourceScope,
|
|
'data_source' => $dataSource,
|
|
'source_platform' => '天猫',
|
|
'store_name' => $storeName,
|
|
'normalized_store_name' => JushuitanShopBalanceRepository::normalizeStoreName($storeName),
|
|
'platform_account_id' => 'retention-' . $balanceDate,
|
|
'balance' => 100,
|
|
'source_row_key' => hash('sha256', $balanceDate . '|' . $sourceScope . '|' . $storeName),
|
|
'source_file_name' => 'retention-fixture.json',
|
|
'source_sha256' => str_repeat('c', 64),
|
|
'imported_at' => Carbon::parse($importedAt),
|
|
'created_at' => Carbon::parse($importedAt),
|
|
'updated_at' => Carbon::parse($importedAt),
|
|
]);
|
|
}
|
|
|
|
/** @param array<string,mixed> $payload */
|
|
private function jsonFile(array $payload): string
|
|
{
|
|
$path = sys_get_temp_dir() . '/jushuitan-shop-balance-' . uniqid('', true) . '.json';
|
|
file_put_contents($path, json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
$this->temporaryFiles[] = $path;
|
|
|
|
return $path;
|
|
}
|
|
|
|
/** @param list<list<mixed>> $rows */
|
|
private function xlsxFile(array $rows): string
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$spreadsheet->getActiveSheet()->fromArray($rows);
|
|
$path = sys_get_temp_dir() . '/jushuitan-shop-balance-' . uniqid('', true) . '.xlsx';
|
|
(new Xlsx($spreadsheet))->save($path);
|
|
$spreadsheet->disconnectWorksheets();
|
|
$this->temporaryFiles[] = $path;
|
|
|
|
return $path;
|
|
}
|
|
}
|