fix: add ledger refund uniqueness guard

This commit is contained in:
QiuSW
2026-07-02 16:59:02 +08:00
parent be97a35360
commit 4e8c1b45a4
7 changed files with 93 additions and 8 deletions
@@ -0,0 +1,19 @@
# Generated by Django 5.2.15 on 2026-07-02 08:37
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('billing', '0002_exchangerate_pricingrule'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddConstraint(
model_name='pointsledger',
constraint=models.UniqueConstraint(fields=('ref_call', 'change_type'), name='unique_ledger_change_type_per_call'),
),
]
+4
View File
@@ -192,6 +192,10 @@ class PointsLedger(models.Model):
condition=~Q(points_delta=0),
name="points_ledger_points_delta_non_zero",
),
models.UniqueConstraint(
fields=("ref_call", "change_type"),
name="unique_ledger_change_type_per_call",
),
]
indexes = [
models.Index(fields=("user", "created_at")),
+35
View File
@@ -143,6 +143,41 @@ class BillingCoreModelTests(TestCase):
balance_after=-1,
)
def test_points_ledger_allows_consume_and_refund_but_rejects_duplicate_refund(self):
call = CallRecord.objects.create(
user=self.user,
operation_type=CallRecord.OperationType.TITLE,
alias="title-standard",
model_used="gpt-5.5",
points_cost=2,
status=CallRecord.Status.FAILED,
)
PointsLedger.objects.create(
user=self.user,
change_type=PointsLedger.ChangeType.CONSUME,
points_delta=-2,
balance_after=98,
ref_call=call,
)
PointsLedger.objects.create(
user=self.user,
change_type=PointsLedger.ChangeType.REFUND,
points_delta=2,
balance_after=100,
ref_call=call,
)
with self.assertRaises(IntegrityError):
with transaction.atomic():
PointsLedger.objects.create(
user=self.user,
change_type=PointsLedger.ChangeType.REFUND,
points_delta=2,
balance_after=102,
ref_call=call,
)
def test_billing_models_are_registered_in_admin(self):
self.assertIn(UserWallet, admin.site._registry)
self.assertIn(ApiKey, admin.site._registry)