采购单优化

This commit is contained in:
liu
2026-08-12 14:38:20 +08:00
parent ce1f36b5b4
commit dadfdc1511
30 changed files with 1059 additions and 1441 deletions
+16 -51
View File
@@ -7,17 +7,19 @@ use App\Models\ProductModel;
use App\Models\ProductPriceModel;
use App\Models\PurchaseOrderModel;
use App\Models\StoreModel;
use App\Models\StoreOrderItemModel;
use App\Models\StoreOrderModel;
use App\Models\UserModel;
/**
* C1 订单汇总生成采购单:多门店聚合、订单状态回写、无订单/重复生成防护
* C1 订单汇总生成采购单:订单/明细归集回写、头部汇总、无订单/重复生成防护
* (采购单无独立明细表,明细直接溯源订货明细 store_order_item.purchase_id
*/
class PurchaseGenerateTest extends ProcurementTestCase
{
/**
* 造当日已接单订单:门店A 两单各 3 件 + 门店B 一单 4 件(同一商品),下单后统一接单
* 商品设两个等级价 5.00 / 4.00,估算单价应取最低 4.00
* 门店等级价 5.00(另设低等级价 4.00 不影响本店下单价)
*/
private function seedAcceptedOrders(): ProductModel
{
@@ -41,8 +43,8 @@ class PurchaseGenerateTest extends ProcurementTestCase
return $product;
}
/** 多门店多订单按商品聚合,估算单价取最低等级价 */
public function test_generate_aggregates_orders_by_product(): void
/** 头部汇总取订货明细合计:total_quantity = Σ数量,estimate_amount = Σ订货金额 */
public function test_generate_aggregates_order_items_into_header(): void
{
$this->seedAcceptedOrders();
$admin = $this->actingAsSysUser();
@@ -58,15 +60,12 @@ class PurchaseGenerateTest extends ProcurementTestCase
$this->assertSame($admin->id, $purchase->operator_id);
$this->assertSame(PurchaseOrderModel::STATUS_PENDING, $purchase->status);
$this->assertCount(1, $purchase->items, '单一商品应聚合为一行');
$item = $purchase->items->first();
$this->assertSame('10.00', (string) $item->quantity, '3+3+4');
$this->assertSame('4.00', (string) $item->price, '估算单价取最低等级价');
$this->assertSame('40.00', (string) $item->amount, '10 × 4.00');
$this->assertSame('40.00', (string) $purchase->estimate_amount);
$this->assertSame('10.00', (string) $purchase->total_quantity, '3+3+4');
$this->assertSame('50.00', (string) $purchase->estimate_amount, '10 件 × 等级价 5.00');
$this->assertSame('0.00', (string) $purchase->actual_amount);
}
/** 源订单状态回写为采购中,并关联 purchase_id */
/** 源订单状态回写为采购中,订单与订货明细均回写 purchase_id */
public function test_generate_writes_back_order_status(): void
{
$this->seedAcceptedOrders();
@@ -79,6 +78,12 @@ class PurchaseGenerateTest extends ProcurementTestCase
$this->assertSame(0, StoreOrderModel::where('status', StoreOrderModel::STATUS_SUMMARIZED)->count());
$this->assertSame(3, StoreOrderModel::where('status', StoreOrderModel::STATUS_DELIVERING)->count());
$this->assertSame(3, StoreOrderModel::where('purchase_id', $purchase->id)->count());
$this->assertSame(
3,
StoreOrderItemModel::where('purchase_id', $purchase->id)->count(),
'订货明细应全部回写 purchase_id(采购明细溯源依据)'
);
$this->assertSame(0, StoreOrderItemModel::where('purchase_id', 0)->count());
}
/** 仅有待接单订单时不可生成(待接单不再被归集)→ 报错 */
@@ -140,44 +145,4 @@ class PurchaseGenerateTest extends ProcurementTestCase
$this->assertSame(1, PurchaseOrderModel::count(), '第二次生成应被拒绝,不产生新采购单');
}
/** 估算单价取「最低实际价」:固定价与百分比计价混合时按换算后值比较 */
public function test_generate_uses_min_actual_price_across_types(): void
{
$level = CustomerLevelModel::factory()->create();
$levelFixed = CustomerLevelModel::factory()->create();
$store = StoreModel::factory()->create(['level_id' => $level->id]);
$product = ProductModel::factory()->create([
'status' => ProductModel::STATUS_ON,
'cost_price' => 10,
]);
// 百分比行:10 × (1+40%) = 14.00;固定价行 5.00 → 估算应取 5.00
ProductPriceModel::factory()->create([
'product_id' => $product->id,
'level_id' => $level->id,
'price_type' => ProductPriceModel::PRICE_TYPE_PERCENT,
'percent' => 40,
'price' => 14.00,
]);
ProductPriceModel::factory()->create([
'product_id' => $product->id,
'level_id' => $levelFixed->id,
'price' => 5.00,
]);
$this->actingAsMiniUser(UserModel::factory()->forStore($store->id)->create());
$this->postJson('/mini/order', ['items' => [['product_id' => $product->id, 'quantity' => 3]]])
->assertJsonPath('success', true);
// 接单后生成
StoreOrderModel::query()->update(['status' => StoreOrderModel::STATUS_SUMMARIZED]);
$this->actingAsSysUser();
$this->postJson('/purchase/order/generate', ['purchase_date' => now()->toDateString()])
->assertJsonPath('success', true);
$item = PurchaseOrderModel::first()->items->first();
$this->assertSame('5.00', (string) $item->price, '估算单价应取换算后的最低实际价');
$this->assertSame('15.00', (string) $item->amount, '3 × 5.00');
}
}