create(); $store = StoreModel::factory()->create(['level_id' => $level->id]); $product = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON]); ProductPriceModel::factory()->create([ 'product_id' => $product->id, 'level_id' => $level->id, 'price' => '5.00', ]); $user = UserModel::factory()->forStore($store->id)->create(); $this->actingAsMiniUser($user); $this->postJson('/mini/order', ['items' => [['product_id' => $product->id, 'quantity' => 4]]]) ->assertJsonPath('success', true); $order = StoreOrderModel::where('store_id', $store->id)->first(); $this->actingAsSysUser(); // 接单 $this->putJson("/order/store/{$order->id}/status", ['status' => StoreOrderModel::STATUS_SUMMARIZED]) ->assertJsonPath('success', true); // 生成采购单 → 采购中 $this->postJson('/purchase/order/generate', ['purchase_date' => now()->toDateString()]) ->assertJsonPath('success', true); $purchase = PurchaseOrderModel::first(); // 完成采购单 → 配送中 $this->putJson("/purchase/order/{$purchase->id}/finish")->assertJsonPath('success', true); // 生成账单 → 已完成 $this->postJson("/purchase/order/{$purchase->id}/bill", [ 'stores' => [['store_id' => $store->id, 'delivery_fee' => 0, 'box_num' => 0, 'tray_num' => 0]], ])->assertJsonPath('success', true); return [$store, $order->fresh(), BillModel::where('store_id', $store->id)->first()]; } /** 造一张指定商品金额的未支付账单(总额=商品金额) */ private function makeBill(StoreModel $store, string $productAmount, array $attributes = []): BillModel { return BillModel::create(array_merge([ 'bill_no' => 'ZD' . random_int(100000000000, 999999999999), 'purchase_id' => PurchaseOrderModel::factory()->create()->id, 'store_id' => $store->id, 'bill_date' => '2026-08-10', 'product_amount' => $productAmount, 'delivery_fee' => '0.00', 'box_num' => 0, 'tray_num' => 0, 'box_price' => '0.00', 'tray_price' => '0.00', 'added_amount' => '0.00', 'total_amount' => $productAmount, 'status' => BillModel::STATUS_UNPAID, ], $attributes)); } /** 订单状态随业务链自动推进:接单→采购中→配送中→(生成账单)已完成 */ public function test_order_status_progresses_via_business_chain(): void { $level = CustomerLevelModel::factory()->create(); $store = StoreModel::factory()->create(['level_id' => $level->id]); $product = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON]); ProductPriceModel::factory()->create(['product_id' => $product->id, 'level_id' => $level->id, 'price' => '5.00']); $user = UserModel::factory()->forStore($store->id)->create(); $this->actingAsMiniUser($user); $this->postJson('/mini/order', ['items' => [['product_id' => $product->id, 'quantity' => 4]]]) ->assertJsonPath('success', true); $order = StoreOrderModel::where('store_id', $store->id)->first(); $this->assertSame(StoreOrderModel::STATUS_PENDING, $order->status); $this->actingAsSysUser(); // 接单 → 已接单 $this->putJson("/order/store/{$order->id}/status", ['status' => StoreOrderModel::STATUS_SUMMARIZED]) ->assertJsonPath('success', true); $this->assertSame(StoreOrderModel::STATUS_SUMMARIZED, $order->fresh()->status); // 生成采购单 → 采购中 $this->postJson('/purchase/order/generate', ['purchase_date' => now()->toDateString()]) ->assertJsonPath('success', true); $purchase = PurchaseOrderModel::first(); $order->refresh(); $this->assertSame(StoreOrderModel::STATUS_DELIVERING, $order->status); $this->assertSame($purchase->id, $order->purchase_id); // 完成采购单 → 配送中 $this->putJson("/purchase/order/{$purchase->id}/finish")->assertJsonPath('success', true); $this->assertSame(StoreOrderModel::STATUS_DISTRIBUTION, $order->fresh()->status); // 生成账单 → 已完成 + 回写 bill_id $this->postJson("/purchase/order/{$purchase->id}/bill", [ 'stores' => [['store_id' => $store->id, 'delivery_fee' => 0, 'box_num' => 0, 'tray_num' => 0]], ])->assertJsonPath('success', true); $order->refresh(); $bill = BillModel::where('store_id', $store->id)->first(); $this->assertNotNull($bill); $this->assertSame(StoreOrderModel::STATUS_COMPLETED, $order->status); $this->assertSame($bill->id, $order->bill_id); $this->assertSame('20.00', (string) $bill->product_amount, '5.00 × 4'); } /** 后台手动确认收款:累加门店总采购金额(只统计商品金额),重复收款拒绝不重复累加 */ public function test_manual_pay_accumulates_store_total_purchase_amount(): void { [$store, , $bill] = $this->makeBillViaChain(); $this->actingAsSysUser(); $this->putJson("/recon/bill/{$bill->id}/pay", ['pay_remark' => '线下现金']) ->assertJsonPath('success', true); $store->refresh(); $this->assertSame('20.00', (string) $store->total_purchase_amount, '只累加商品金额 20.00'); // 第二笔账单收款后继续累加 $bill2 = $this->makeBill($store, '100.00'); $this->putJson("/recon/bill/{$bill2->id}/pay")->assertJsonPath('success', true); $this->assertSame('120.00', (string) $store->fresh()->total_purchase_amount); // 重复收款拒绝,金额不重复累加 $this->putJson("/recon/bill/{$bill->id}/pay")->assertJsonPath('success', false); $this->assertSame('120.00', (string) $store->fresh()->total_purchase_amount); } /** 支付审核通过:关联账单置已支付并累加门店总采购金额 */ public function test_payment_audit_pass_accumulates_store_total_purchase_amount(): void { $store = StoreModel::factory()->create(); $user = UserModel::factory()->forStore($store->id)->create(); $payment = PaymentModel::create([ 'payment_no' => 'ZF202608140001', 'store_id' => $store->id, 'user_id' => $user->id, 'amount' => '150.00', 'pay_method' => PaymentModel::METHOD_BANK, 'voucher_ids' => '', 'status' => PaymentModel::STATUS_PENDING, ]); $bill1 = $this->makeBill($store, '100.00', ['payment_id' => $payment->id]); $bill2 = $this->makeBill($store, '50.00', ['payment_id' => $payment->id]); $this->actingAsSysUser(); $this->putJson("/recon/payment/{$payment->id}/audit", ['result' => 'pass']) ->assertJsonPath('success', true); $this->assertSame(BillModel::STATUS_PAID, $bill1->fresh()->status); $this->assertSame(BillModel::STATUS_PAID, $bill2->fresh()->status); $this->assertSame('150.00', (string) $store->fresh()->total_purchase_amount); // 重复审核拒绝,不重复累加 $this->putJson("/recon/payment/{$payment->id}/audit", ['result' => 'pass']) ->assertJsonPath('success', false); $this->assertSame('150.00', (string) $store->fresh()->total_purchase_amount); } /** 审核拒绝:账单释放回待支付,不累加门店总采购金额 */ public function test_payment_audit_reject_does_not_accumulate(): void { $store = StoreModel::factory()->create(); $user = UserModel::factory()->forStore($store->id)->create(); $payment = PaymentModel::create([ 'payment_no' => 'ZF202608140002', 'store_id' => $store->id, 'user_id' => $user->id, 'amount' => '100.00', 'pay_method' => PaymentModel::METHOD_WECHAT, 'voucher_ids' => '', 'status' => PaymentModel::STATUS_PENDING, ]); $bill = $this->makeBill($store, '100.00', ['payment_id' => $payment->id]); $this->actingAsSysUser(); $this->putJson("/recon/payment/{$payment->id}/audit", [ 'result' => 'reject', 'audit_remark' => '凭证不清晰', ])->assertJsonPath('success', true); $bill->refresh(); $this->assertSame(BillModel::STATUS_UNPAID, $bill->status); $this->assertSame(0, $bill->payment_id, '账单释放可重新付款'); $this->assertSame('0.00', (string) $store->fresh()->total_purchase_amount); } }