Files
yingqing/core/backend/apps/ops/tests.py
T
zycandClaude Opus 4.8 0695c36f4c fix(ai): 平台套图改走商品主图参考 image_edit · 模特上身图锁商品+模特双图
- 平台套图(cover)以前纯文生图,不参考真实商品主图 → 出图与商品对不上;
  现以商品主图为参考图1走 image_edit,锁包装一致性,有模特则参考图2=模特
- 新增 build_platform_cover_prompt_refs;model_url 解析对 cover 模式同样生效
- 补回归测试:cover 传商品主图、model 传商品主图+模特图、无主图回落文生图

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:58:39 +08:00

87 lines
3.8 KiB
Python

from decimal import Decimal
from django.test import TestCase
from apps.accounts.models import Team, TeamMember, User
from apps.ai.models import AITask, ModelConfig, ModelProvider
from apps.assets.models import Asset
from apps.billing.models import CreditAccount, CreditLedger
from apps.ops.models import Notification
from apps.ops.views import ensure_team_notifications
from apps.products.models import Product
from apps.projects.models import Project
class BillingNotificationTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(username="owner", password="pass")
self.team = Team.objects.create(name="T", owner=self.user)
TeamMember.objects.create(team=self.team, user=self.user, role=TeamMember.Role.OWNER)
CreditAccount.objects.create(team=self.team, balance="500.0000")
self.provider = ModelProvider.objects.create(name="ops-test-prov", display_name="TSR")
self.model = ModelConfig.objects.create(
provider=self.provider, name="ops-test-image", capability=ModelConfig.Capability.IMAGE
)
self.product = Product.objects.create(team=self.team, created_by=self.user, title="补水面膜")
self.project = Project.objects.create(
team=self.team, name="补水面膜·短视频", product=self.product, created_by=self.user
)
def _charge(self, task_type, amount, balance_after):
task = AITask.objects.create(
team=self.team,
project=self.project,
task_type=task_type,
model_config=self.model,
idempotency_key=f"k-{task_type}-{amount}",
actual_cost=Decimal(amount),
)
CreditLedger.objects.create(
team=self.team,
user=self.user,
project=self.project,
task=task,
ledger_type=CreditLedger.Type.CHARGE,
amount=Decimal(amount),
balance_after=Decimal(balance_after),
reason="AI 任务扣费",
)
return task
def test_charge_becomes_billing_notification_with_real_amount(self):
self._charge("product_image", "0.32", "499.68")
self._charge("video_segment", "18.40", "481.28")
ensure_team_notifications(self.team, self.user)
billing = Notification.objects.filter(team=self.team, notification_type=Notification.Type.BILLING)
# 每笔扣费一条计费消息,且费用不为空、为真实金额
costs = sorted(n.cost_label for n in billing)
self.assertIn("¥0.32", costs)
self.assertIn("¥18.40", costs)
self.assertFalse(billing.filter(cost_label__in=["", "-"]).exists())
self.assertTrue(billing.filter(title__contains="图生成").exists())
self.assertTrue(billing.filter(title__contains="视频生成").exists())
def test_project_notification_shows_aggregated_spend(self):
self._charge("product_image", "0.32", "499.68")
self._charge("video_segment", "18.40", "481.28")
ensure_team_notifications(self.team, self.user)
proj_note = Notification.objects.get(
team=self.team, notification_type=Notification.Type.TASK, title__contains="补水面膜"
)
self.assertEqual(proj_note.cost_label, "¥18.72") # 0.32 + 18.40
def test_existing_dash_cost_is_backfilled(self):
# 早期建的项目通知费用是占位「-」;补上扣费后再跑 ensure 应回填真实金额
ensure_team_notifications(self.team, self.user)
note = Notification.objects.get(team=self.team, title__contains="补水面膜")
self.assertEqual(note.cost_label, "-")
self._charge("product_image", "0.32", "499.68")
ensure_team_notifications(self.team, self.user)
note.refresh_from_db()
self.assertEqual(note.cost_label, "¥0.32")