feat(economy): purchase_items primitive + entitlement import seeding
purchase_items: generic atomic debit + mint of several items (fail-closed) for open-on-buy Store packs (Store BUY returns items immediately) + POST /economy/purchase-items route. Import: add optional entitlements[] to ProfileImportRequest, seeding unconsumed packs rows in the same transaction (so a source's unopened packs become Core entitlements); idempotency via the existing import fingerprint. Tests: 2 purchase_items unit + endpoint + entitlement-seed import. Core matrix 45 lib + 116 integration + 9 import green; clippy clean.
This commit is contained in:
@@ -2776,3 +2776,25 @@ async fn test_economy_insufficient_funds_fail_closed() {
|
||||
.iter()
|
||||
.any(|e| e["definition_id"] == "pack-x"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_economy_purchase_items_debits_and_mints_all() {
|
||||
let app = build_test_app().await;
|
||||
auth(&app, "econ-e").await;
|
||||
let (st, buy) = json_post(
|
||||
&app,
|
||||
"/economy/purchase-items",
|
||||
serde_json::json!({
|
||||
"cost": 800,
|
||||
"items": [
|
||||
{"item_id": "bx-1", "card_id": "d-1"},
|
||||
{"item_id": "bx-2", "card_id": "d-2"}
|
||||
]
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(st, StatusCode::OK);
|
||||
assert_eq!(buy["balance"], 4200);
|
||||
let (_, bal) = json_get(&app, "/economy/balance").await;
|
||||
assert_eq!(bal["balance"], 4200);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user