售后金额
This commit is contained in:
@@ -19,7 +19,7 @@ class BillExportTest extends ProcurementTestCase
|
||||
{
|
||||
private static int $billSeq = 0;
|
||||
|
||||
/** 造一张账单(默认配送费 10、筐 2×5 + 托盘 1×20 = 附加 30、总额 140,未支付) */
|
||||
/** 造一张账单(默认配送费 10、筐 2×5 + 托盘 1×20 = 附加 30、售后 0、总额 140,未支付) */
|
||||
private function makeBill(StoreModel $store, array $attributes = []): BillModel
|
||||
{
|
||||
$seq = ++self::$billSeq;
|
||||
@@ -36,6 +36,7 @@ class BillExportTest extends ProcurementTestCase
|
||||
'box_price' => '5.00',
|
||||
'tray_price' => '20.00',
|
||||
'added_amount' => '30.00',
|
||||
'after_sale' => '0.00',
|
||||
'total_amount' => '140.00',
|
||||
'status' => BillModel::STATUS_UNPAID,
|
||||
], $attributes));
|
||||
@@ -70,7 +71,7 @@ class BillExportTest extends ProcurementTestCase
|
||||
$productB = ProductModel::factory()->create(['category_id' => $root->id]);
|
||||
|
||||
$bill1 = $this->makeBill($store);
|
||||
$bill2 = $this->makeBill($store);
|
||||
$bill2 = $this->makeBill($store, ['after_sale' => '-8.00']);
|
||||
// 同一商品跨账单:10×2.00 + 6×3.00 → 数量 16、金额 38.00、加权单价 2.37
|
||||
$this->makeItem($bill1, $productA, 10, '2.00');
|
||||
$this->makeItem($bill2, $productA, 6, '3.00');
|
||||
@@ -84,8 +85,8 @@ class BillExportTest extends ProcurementTestCase
|
||||
'门店账单_' . now()->format('Ymd_His') . '.xlsx',
|
||||
static function (BillExport $export) use ($productA, $productB): bool {
|
||||
$rows = $export->collection()->values();
|
||||
// 标题1 + 范围2 + 空行1 + 列头1 + 明细2 + 合计4 = 11 行
|
||||
if ($rows->count() !== 11) {
|
||||
// 标题1 + 范围2 + 空行1 + 列头1 + 明细2 + 合计5 = 12 行
|
||||
if ($rows->count() !== 12) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ class BillExportTest extends ProcurementTestCase
|
||||
}
|
||||
|
||||
$summary = $rows->slice(7)->values();
|
||||
// 合计:数量 20、商品金额 58.00;配送费 20.00;附加 60.00(筐 4 / 托盘 2);总金额 138.00
|
||||
// 合计:数量 20、商品金额 58.00;配送费 20.00;附加 60.00(筐 4 / 托盘 2);售后 -8.00;总金额 130.00
|
||||
if ((int) $summary[0][5] !== 20 || (float) $summary[0][7] !== 58.0) {
|
||||
return false;
|
||||
}
|
||||
@@ -114,8 +115,11 @@ class BillExportTest extends ProcurementTestCase
|
||||
if (! str_contains((string) $summary[2][0], '筐 4 个 / 周转托盘 2 个') || (float) $summary[2][7] !== 60.0) {
|
||||
return false;
|
||||
}
|
||||
if (! str_contains((string) $summary[3][0], '售后金额合计') || (float) $summary[3][7] !== -8.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (float) $summary[3][7] === 138.0;
|
||||
return (float) $summary[4][7] === 130.0;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -156,15 +160,15 @@ class BillExportTest extends ProcurementTestCase
|
||||
}
|
||||
|
||||
$summary = $rows->slice(6)->values();
|
||||
// 商品金额合计 20.00(仅蔬菜);配送费 10.00 / 附加 30.00 全额;总金额 60.00
|
||||
// 商品金额合计 20.00(仅蔬菜);配送费 10.00 / 附加 30.00 / 售后 0.00 全额;总金额 60.00
|
||||
if ((float) $summary[0][7] !== 20.0) {
|
||||
return false;
|
||||
}
|
||||
if ((float) $summary[1][7] !== 10.0 || (float) $summary[2][7] !== 30.0) {
|
||||
if ((float) $summary[1][7] !== 10.0 || (float) $summary[2][7] !== 30.0 || (float) $summary[3][7] !== 0.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (float) $summary[3][7] === 60.0;
|
||||
return (float) $summary[4][7] === 60.0;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -242,7 +246,7 @@ class BillExportTest extends ProcurementTestCase
|
||||
static function (BillExport $export): bool {
|
||||
$rows = $export->collection()->values();
|
||||
// 明细仅本店账单的 1 行(他店账单未混入)
|
||||
return $rows->count() === 10;
|
||||
return $rows->count() === 11;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class BillPaymentTest extends ProcurementTestCase
|
||||
], $attributes));
|
||||
}
|
||||
|
||||
/** 生成账单:按门店保存售后说明与备注(可选,不参与金额计算) */
|
||||
/** 生成账单:按门店保存售后金额(可正负,计入总金额)与备注(仅存档不参与计算) */
|
||||
public function test_generate_bill_saves_after_sale_and_remark(): void
|
||||
{
|
||||
$level = CustomerLevelModel::factory()->create();
|
||||
@@ -97,17 +97,17 @@ class BillPaymentTest extends ProcurementTestCase
|
||||
'delivery_fee' => 0,
|
||||
'box_num' => 0,
|
||||
'tray_num' => 0,
|
||||
'after_sale' => '白菜烂叶 2 斤已协商',
|
||||
'remark' => '下次配送顺带回收筐',
|
||||
'after_sale' => -5.5,
|
||||
'remark' => '白菜烂叶 2 斤已协商',
|
||||
]],
|
||||
])->assertJsonPath('success', true);
|
||||
|
||||
$bill = BillModel::where('store_id', $store->id)->first();
|
||||
$this->assertSame('白菜烂叶 2 斤已协商', $bill->after_sale);
|
||||
$this->assertSame('下次配送顺带回收筐', $bill->remark);
|
||||
$this->assertSame('20.00', (string) $bill->total_amount, '售后/备注不影响金额');
|
||||
$this->assertSame('-5.50', (string) $bill->after_sale);
|
||||
$this->assertSame('白菜烂叶 2 斤已协商', $bill->remark);
|
||||
$this->assertSame('14.50', (string) $bill->total_amount, '总金额 = 商品 20.00 + 售后金额 -5.50');
|
||||
|
||||
// 不传售后/备注时默认空字符串
|
||||
// 不传售后金额时按 0 计入,备注默认空字符串
|
||||
$store2 = StoreModel::factory()->create(['level_id' => $level->id]);
|
||||
$this->actingAsMiniStore($store2);
|
||||
$this->postJson('/mini/order', ['items' => [['product_id' => $product->id, 'quantity' => 1]]])
|
||||
@@ -125,8 +125,65 @@ class BillPaymentTest extends ProcurementTestCase
|
||||
])->assertJsonPath('success', true);
|
||||
|
||||
$bill2 = BillModel::where('store_id', $store2->id)->first();
|
||||
$this->assertSame('', (string) $bill2->after_sale);
|
||||
$this->assertSame('0.00', (string) $bill2->after_sale);
|
||||
$this->assertSame('', (string) $bill2->remark);
|
||||
$this->assertSame('5.00', (string) $bill2->total_amount, '未传售后金额不影响总金额');
|
||||
}
|
||||
|
||||
/** 生成账单:售后金额为正数时加收计入总金额 */
|
||||
public function test_generate_bill_positive_after_sale_added_to_total(): void
|
||||
{
|
||||
[$store, , $bill] = $this->makeBillViaChain();
|
||||
$this->assertSame('20.00', (string) $bill->total_amount, '基线:无售后金额时总额=商品金额');
|
||||
|
||||
// 重新走一条链:售后金额 +8.00,配送费 2.00 → 总额 20 + 2 + 8 = 30.00
|
||||
$level = CustomerLevelModel::factory()->create();
|
||||
$store2 = StoreModel::factory()->create(['level_id' => $level->id]);
|
||||
$product = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON, 'cost_price' => '5.00']);
|
||||
|
||||
$this->actingAsMiniStore($store2);
|
||||
$this->postJson('/mini/order', ['items' => [['product_id' => $product->id, 'quantity' => 4]]])
|
||||
->assertJsonPath('success', true);
|
||||
$order2 = StoreOrderModel::where('store_id', $store2->id)->first();
|
||||
|
||||
$this->actingAsSysUser();
|
||||
$this->putJson("/order/store/{$order2->id}/status", ['status' => StoreOrderModel::STATUS_SUMMARIZED]);
|
||||
$this->postJson('/purchase/order/generate', ['purchase_date' => now()->toDateString()])
|
||||
->assertJsonPath('success', true);
|
||||
$purchase2 = PurchaseOrderModel::latest('id')->first();
|
||||
$this->putJson("/purchase/order/{$purchase2->id}/finish")->assertJsonPath('success', true);
|
||||
$this->postJson("/purchase/order/{$purchase2->id}/bill", [
|
||||
'stores' => [[
|
||||
'store_id' => $store2->id,
|
||||
'delivery_fee' => 2,
|
||||
'box_num' => 0,
|
||||
'tray_num' => 0,
|
||||
'after_sale' => 8,
|
||||
]],
|
||||
])->assertJsonPath('success', true);
|
||||
|
||||
$bill2 = BillModel::where('store_id', $store2->id)->first();
|
||||
$this->assertSame('8.00', (string) $bill2->after_sale);
|
||||
$this->assertSame('30.00', (string) $bill2->total_amount, '总金额 = 商品 20.00 + 配送费 2.00 + 售后金额 8.00');
|
||||
}
|
||||
|
||||
/** 生成账单:售后金额非数值 → 拒绝 */
|
||||
public function test_generate_bill_rejects_non_numeric_after_sale(): void
|
||||
{
|
||||
$level = CustomerLevelModel::factory()->create();
|
||||
$store = StoreModel::factory()->create(['level_id' => $level->id]);
|
||||
$this->actingAsSysUser();
|
||||
$purchase = PurchaseOrderModel::factory()->create(['status' => PurchaseOrderModel::STATUS_COMPLETED]);
|
||||
|
||||
$this->postJson("/purchase/order/{$purchase->id}/bill", [
|
||||
'stores' => [[
|
||||
'store_id' => $store->id,
|
||||
'delivery_fee' => 0,
|
||||
'box_num' => 0,
|
||||
'tray_num' => 0,
|
||||
'after_sale' => '白菜烂叶 2 斤已协商',
|
||||
]],
|
||||
])->assertJsonPath('success', false);
|
||||
}
|
||||
|
||||
/** 订单状态随业务链自动推进:接单→采购中→配送中→(生成账单)已完成 */
|
||||
|
||||
@@ -156,7 +156,7 @@ class MiniBillTest extends ProcurementTestCase
|
||||
'uploader_id' => 1,
|
||||
]);
|
||||
|
||||
$bill = $this->makeBill($store);
|
||||
$bill = $this->makeBill($store, ['after_sale' => '-3.00']);
|
||||
$product = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON]);
|
||||
$order = StoreOrderModel::factory()->create([
|
||||
'store_id' => $store->id,
|
||||
@@ -182,6 +182,7 @@ class MiniBillTest extends ProcurementTestCase
|
||||
$data = $this->getJson("/mini/bill/{$bill->id}")->assertOk()->json('data');
|
||||
|
||||
$this->assertSame($bill->bill_no, $data['bill']['bill_no']);
|
||||
$this->assertSame('-3.00', $data['bill']['after_sale'], '售后金额输出给门店(计入总金额构成)');
|
||||
$this->assertSame('待支付', $data['bill']['pay_state_name']);
|
||||
$this->assertSame('2026-08-10', $data['bill']['settlement_date'], '回款周期 0 天,出账当天应结算');
|
||||
$this->assertSame($bill->purchase->purchase_no, $data['bill']['purchase']['purchase_no']);
|
||||
|
||||
Reference in New Issue
Block a user