167 lines
6.9 KiB
PHP
167 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Console;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Tests\Feature\FeatureTestCase;
|
|
|
|
class StoreReceiptProductCostRealtimePriceTest extends FeatureTestCase
|
|
{
|
|
public function test_realtime_prices_prefer_catalog_cost_then_online_daifa_without_changing_historical_cost(): void
|
|
{
|
|
$mirror = DB::connection('business_mirror');
|
|
$schema = Schema::connection('business_mirror');
|
|
$this->createPriceSources($schema);
|
|
|
|
$mirror->table('ops_jst_sku')->insert([
|
|
['sku_id' => 'SKU-CATALOG', 'sku_type' => 'normal', 'cost_price' => 12],
|
|
['sku_id' => 'SKU-PURCHASE', 'sku_type' => 'normal', 'cost_price' => 0],
|
|
]);
|
|
$mirror->table('product_purchase_price_mirror_rows')->insert([
|
|
[
|
|
'item_id' => 1,
|
|
'sku_id' => 'SKU-CATALOG',
|
|
'unit_price' => 20,
|
|
'document_status' => 'Finished',
|
|
'finished_at' => '2026-09-10 10:00:00',
|
|
'created_at' => '2026-09-10 10:00:00',
|
|
'updated_at' => '2026-09-10 10:00:00',
|
|
],
|
|
[
|
|
'item_id' => 2,
|
|
'sku_id' => 'SKU-PURCHASE',
|
|
'unit_price' => 5.5,
|
|
'document_status' => 'Finished',
|
|
'finished_at' => '2026-09-11 10:00:00',
|
|
'created_at' => '2026-09-11 10:00:00',
|
|
'updated_at' => '2026-09-11 10:00:00',
|
|
],
|
|
]);
|
|
$mirror->table('ding_online_daifa_price_mirror')->insert([
|
|
'process_instance_id' => 'PROC-1',
|
|
'detail_index' => 0,
|
|
'product_id' => '9001',
|
|
'ship_qty' => 3,
|
|
'daifa_amount' => 21,
|
|
'workflow_created_at' => '2026-09-12 10:00:00',
|
|
]);
|
|
$mirror->table('ops_jst_sku_map')->insert([
|
|
'shop_i_id' => '9001',
|
|
'sku_id' => 'SKU-DING',
|
|
]);
|
|
$mirror->table('store_receipt_product_cost_rows')->insert([
|
|
$this->row('catalog', 'SKU-CATALOG', 2, 9, 18),
|
|
$this->row('purchase', 'SKU-PURCHASE', 3, 8, 24),
|
|
$this->row('ding', 'SKU-DING', 4, 7, 28),
|
|
$this->row('missing', 'SKU-MISSING', 5, 6, 30),
|
|
]);
|
|
|
|
$this->artisan('store-receipt:product-cost:sync', [
|
|
'month' => '2026-09',
|
|
'--refresh-realtime-prices-only' => true,
|
|
])->assertExitCode(Command::SUCCESS);
|
|
|
|
$rows = $mirror->table('store_receipt_product_cost_rows')
|
|
->orderBy('row_key')
|
|
->get()
|
|
->keyBy('row_key');
|
|
|
|
$this->assertSame(12.0, (float) $rows['catalog']->realtime_unit_price);
|
|
$this->assertSame(24.0, (float) $rows['catalog']->realtime_product_cost);
|
|
$this->assertSame(5.5, (float) $rows['purchase']->realtime_unit_price);
|
|
$this->assertSame(16.5, (float) $rows['purchase']->realtime_product_cost);
|
|
$this->assertSame(7.0, (float) $rows['ding']->realtime_unit_price);
|
|
$this->assertSame(28.0, (float) $rows['ding']->realtime_product_cost);
|
|
$this->assertNull($rows['missing']->realtime_unit_price);
|
|
$this->assertNull($rows['missing']->realtime_product_cost);
|
|
|
|
$historical = [
|
|
'catalog' => [9.0, 18.0],
|
|
'purchase' => [8.0, 24.0],
|
|
'ding' => [7.0, 28.0],
|
|
'missing' => [6.0, 30.0],
|
|
];
|
|
foreach ($rows as $key => $row) {
|
|
$this->assertSame($historical[$key][0], (float) $row->unit_price, $key);
|
|
$this->assertSame($historical[$key][1], (float) $row->product_cost, $key);
|
|
$this->assertSame('保留历史口径', $row->remark, $key);
|
|
}
|
|
|
|
$csv = $this->loginAs()->get(route(
|
|
'business.financial-operations.product-costs.export',
|
|
['month' => '2026-09'],
|
|
))->assertOk()->streamedContent();
|
|
$this->assertStringContainsString('商品单价,商品成本,商品实时价,商品实时成本', $csv);
|
|
$this->assertStringContainsString(',12.00,24.00', $csv);
|
|
}
|
|
|
|
private function createPriceSources($schema): void
|
|
{
|
|
if (! $schema->hasTable('ops_jst_sku')) {
|
|
$schema->create('ops_jst_sku', function (Blueprint $table): void {
|
|
$table->string('sku_id');
|
|
$table->string('sku_type')->nullable();
|
|
$table->decimal('cost_price', 20, 4)->nullable();
|
|
});
|
|
}
|
|
if (! $schema->hasTable('ops_jst_sku_map')) {
|
|
$schema->create('ops_jst_sku_map', function (Blueprint $table): void {
|
|
$table->string('shop_i_id');
|
|
$table->string('sku_id');
|
|
});
|
|
}
|
|
if (! $schema->hasTable('product_purchase_price_mirror_rows')) {
|
|
$schema->create('product_purchase_price_mirror_rows', function (Blueprint $table): void {
|
|
$table->unsignedBigInteger('item_id')->primary();
|
|
$table->string('sku_id')->nullable();
|
|
$table->decimal('unit_price', 20, 4)->nullable();
|
|
$table->string('document_status')->nullable();
|
|
$table->dateTime('finished_at')->nullable();
|
|
$table->dateTime('document_created_at')->nullable();
|
|
$table->dateTime('purchase_updated_at')->nullable();
|
|
$table->timestamps();
|
|
});
|
|
}
|
|
if (! $schema->hasTable('ding_online_daifa_price_mirror')) {
|
|
$schema->create('ding_online_daifa_price_mirror', function (Blueprint $table): void {
|
|
$table->string('process_instance_id');
|
|
$table->unsignedTinyInteger('detail_index')->default(0);
|
|
$table->string('product_id')->nullable();
|
|
$table->unsignedInteger('ship_qty')->nullable();
|
|
$table->decimal('daifa_amount', 14, 2)->nullable();
|
|
$table->string('workflow_created_at')->nullable();
|
|
$table->primary(['process_instance_id', 'detail_index']);
|
|
});
|
|
}
|
|
}
|
|
|
|
/** @return array<string,mixed> */
|
|
private function row(
|
|
string $rowKey,
|
|
string $productCode,
|
|
int $quantity,
|
|
float $historicalUnitPrice,
|
|
float $historicalCost,
|
|
): array {
|
|
return [
|
|
'report_month' => '2026-09-01',
|
|
'row_key' => $rowKey,
|
|
'platform' => '京东账单',
|
|
'occurred_date' => '2026-09-01',
|
|
'store_name' => '测试店铺',
|
|
'online_order_no' => 'ORDER-' . $rowKey,
|
|
'warehouse' => '简尚-崔桥工厂仓',
|
|
'warehouse_short_name' => '崔桥工厂仓',
|
|
'product_code' => $productCode,
|
|
'product_quantity' => $quantity,
|
|
'unit_price' => $historicalUnitPrice,
|
|
'product_cost' => $historicalCost,
|
|
'remark' => '保留历史口径',
|
|
'imported_at' => now(),
|
|
];
|
|
}
|
|
}
|