karaoke-gen 0.99.3__py3-none-any.whl → 0.103.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backend/api/routes/admin.py +512 -1
- backend/api/routes/audio_search.py +17 -34
- backend/api/routes/file_upload.py +60 -84
- backend/api/routes/internal.py +6 -0
- backend/api/routes/jobs.py +11 -3
- backend/api/routes/rate_limits.py +428 -0
- backend/api/routes/review.py +13 -6
- backend/api/routes/tenant.py +120 -0
- backend/api/routes/users.py +229 -247
- backend/config.py +16 -0
- backend/exceptions.py +66 -0
- backend/main.py +30 -1
- backend/middleware/__init__.py +7 -1
- backend/middleware/tenant.py +192 -0
- backend/models/job.py +19 -3
- backend/models/tenant.py +208 -0
- backend/models/user.py +18 -0
- backend/services/email_service.py +253 -6
- backend/services/email_validation_service.py +646 -0
- backend/services/firestore_service.py +27 -0
- backend/services/job_defaults_service.py +113 -0
- backend/services/job_manager.py +73 -3
- backend/services/rate_limit_service.py +641 -0
- backend/services/stripe_service.py +61 -35
- backend/services/tenant_service.py +285 -0
- backend/services/user_service.py +85 -7
- backend/tests/conftest.py +7 -1
- backend/tests/emulator/test_made_for_you_integration.py +167 -0
- backend/tests/test_admin_job_files.py +337 -0
- backend/tests/test_admin_job_reset.py +384 -0
- backend/tests/test_admin_job_update.py +326 -0
- backend/tests/test_audio_search.py +12 -8
- backend/tests/test_email_service.py +233 -0
- backend/tests/test_email_validation_service.py +298 -0
- backend/tests/test_file_upload.py +8 -6
- backend/tests/test_impersonation.py +223 -0
- backend/tests/test_job_creation_regression.py +4 -0
- backend/tests/test_job_manager.py +146 -1
- backend/tests/test_made_for_you.py +2088 -0
- backend/tests/test_models.py +139 -0
- backend/tests/test_rate_limit_service.py +396 -0
- backend/tests/test_rate_limits_api.py +392 -0
- backend/tests/test_tenant_api.py +350 -0
- backend/tests/test_tenant_middleware.py +345 -0
- backend/tests/test_tenant_models.py +406 -0
- backend/tests/test_tenant_service.py +418 -0
- backend/workers/video_worker.py +8 -3
- backend/workers/video_worker_orchestrator.py +26 -0
- {karaoke_gen-0.99.3.dist-info → karaoke_gen-0.103.1.dist-info}/METADATA +1 -1
- {karaoke_gen-0.99.3.dist-info → karaoke_gen-0.103.1.dist-info}/RECORD +55 -33
- lyrics_transcriber/frontend/src/api.ts +13 -5
- lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +90 -57
- {karaoke_gen-0.99.3.dist-info → karaoke_gen-0.103.1.dist-info}/WHEEL +0 -0
- {karaoke_gen-0.99.3.dist-info → karaoke_gen-0.103.1.dist-info}/entry_points.txt +0 -0
- {karaoke_gen-0.99.3.dist-info → karaoke_gen-0.103.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -313,9 +313,154 @@ class TestJobFailure:
|
|
|
313
313
|
assert call_args[1]['error_message'] == error_message
|
|
314
314
|
|
|
315
315
|
|
|
316
|
+
class TestMadeForYouFieldMapping:
|
|
317
|
+
"""
|
|
318
|
+
CRITICAL: Test that made-for-you fields are properly copied from JobCreate to Job.
|
|
319
|
+
|
|
320
|
+
These tests verify that JobManager.create_job() properly maps all fields from
|
|
321
|
+
JobCreate to the Job object that gets persisted to Firestore.
|
|
322
|
+
|
|
323
|
+
Bug context (2026-01-09): Production made-for-you orders were created with
|
|
324
|
+
made_for_you=False, customer_email=None, customer_notes=None because
|
|
325
|
+
JobManager.create_job() wasn't copying these fields from JobCreate to Job.
|
|
326
|
+
"""
|
|
327
|
+
|
|
328
|
+
def test_create_job_copies_made_for_you_flag(self, job_manager, mock_firestore_service):
|
|
329
|
+
"""
|
|
330
|
+
CRITICAL: made_for_you flag must be copied from JobCreate to Job.
|
|
331
|
+
|
|
332
|
+
This flag is essential for:
|
|
333
|
+
- Ownership transfer on job completion
|
|
334
|
+
- Email suppression for intermediate states
|
|
335
|
+
- Identifying made-for-you jobs in admin UI
|
|
336
|
+
"""
|
|
337
|
+
job_create = JobCreate(
|
|
338
|
+
artist="Test Artist",
|
|
339
|
+
title="Test Song",
|
|
340
|
+
theme_id="nomad",
|
|
341
|
+
made_for_you=True, # This MUST be copied to the Job
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
job = job_manager.create_job(job_create)
|
|
345
|
+
|
|
346
|
+
# CRITICAL ASSERTION: made_for_you must be True on the created Job
|
|
347
|
+
assert job.made_for_you is True, \
|
|
348
|
+
"made_for_you=True on JobCreate must be copied to Job"
|
|
349
|
+
|
|
350
|
+
# Also verify what was saved to Firestore
|
|
351
|
+
mock_firestore_service.create_job.assert_called_once()
|
|
352
|
+
saved_job = mock_firestore_service.create_job.call_args[0][0]
|
|
353
|
+
assert saved_job.made_for_you is True, \
|
|
354
|
+
"made_for_you=True must be persisted to Firestore"
|
|
355
|
+
|
|
356
|
+
def test_create_job_copies_customer_email(self, job_manager, mock_firestore_service):
|
|
357
|
+
"""
|
|
358
|
+
CRITICAL: customer_email must be copied from JobCreate to Job.
|
|
359
|
+
|
|
360
|
+
This field is essential for:
|
|
361
|
+
- Ownership transfer on job completion (transferring to this email)
|
|
362
|
+
- Sending completion email with download links to customer
|
|
363
|
+
"""
|
|
364
|
+
job_create = JobCreate(
|
|
365
|
+
artist="Test Artist",
|
|
366
|
+
title="Test Song",
|
|
367
|
+
theme_id="nomad",
|
|
368
|
+
made_for_you=True,
|
|
369
|
+
customer_email="customer@example.com", # This MUST be copied to the Job
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
job = job_manager.create_job(job_create)
|
|
373
|
+
|
|
374
|
+
# CRITICAL ASSERTION: customer_email must be copied
|
|
375
|
+
assert job.customer_email == "customer@example.com", \
|
|
376
|
+
"customer_email on JobCreate must be copied to Job"
|
|
377
|
+
|
|
378
|
+
# Also verify what was saved to Firestore
|
|
379
|
+
saved_job = mock_firestore_service.create_job.call_args[0][0]
|
|
380
|
+
assert saved_job.customer_email == "customer@example.com", \
|
|
381
|
+
"customer_email must be persisted to Firestore"
|
|
382
|
+
|
|
383
|
+
def test_create_job_copies_customer_notes(self, job_manager, mock_firestore_service):
|
|
384
|
+
"""
|
|
385
|
+
customer_notes must be copied from JobCreate to Job.
|
|
386
|
+
|
|
387
|
+
Customer notes contain special requests that admin needs to see.
|
|
388
|
+
"""
|
|
389
|
+
job_create = JobCreate(
|
|
390
|
+
artist="Test Artist",
|
|
391
|
+
title="Test Song",
|
|
392
|
+
theme_id="nomad",
|
|
393
|
+
made_for_you=True,
|
|
394
|
+
customer_notes="Please make this perfect for my wedding!",
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
job = job_manager.create_job(job_create)
|
|
398
|
+
|
|
399
|
+
assert job.customer_notes == "Please make this perfect for my wedding!", \
|
|
400
|
+
"customer_notes on JobCreate must be copied to Job"
|
|
401
|
+
|
|
402
|
+
saved_job = mock_firestore_service.create_job.call_args[0][0]
|
|
403
|
+
assert saved_job.customer_notes == "Please make this perfect for my wedding!", \
|
|
404
|
+
"customer_notes must be persisted to Firestore"
|
|
405
|
+
|
|
406
|
+
def test_create_job_full_made_for_you_config(self, job_manager, mock_firestore_service):
|
|
407
|
+
"""
|
|
408
|
+
Test complete made-for-you job creation with all fields.
|
|
409
|
+
|
|
410
|
+
This is the realistic scenario: a made-for-you order creates a job with:
|
|
411
|
+
- made_for_you=True
|
|
412
|
+
- user_email=admin (owner during processing)
|
|
413
|
+
- customer_email=customer (for final delivery)
|
|
414
|
+
- customer_notes=notes (customer's special requests)
|
|
415
|
+
"""
|
|
416
|
+
job_create = JobCreate(
|
|
417
|
+
artist="Avril Lavigne",
|
|
418
|
+
title="Complicated",
|
|
419
|
+
theme_id="nomad",
|
|
420
|
+
made_for_you=True,
|
|
421
|
+
user_email="admin@nomadkaraoke.com",
|
|
422
|
+
customer_email="customer@example.com",
|
|
423
|
+
customer_notes="Anniversary gift!",
|
|
424
|
+
# Distribution settings that should also be applied
|
|
425
|
+
enable_youtube_upload=True,
|
|
426
|
+
dropbox_path="/Production/Ready",
|
|
427
|
+
brand_prefix="NOMAD",
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
job = job_manager.create_job(job_create)
|
|
431
|
+
|
|
432
|
+
# Verify all made-for-you fields
|
|
433
|
+
assert job.made_for_you is True
|
|
434
|
+
assert job.user_email == "admin@nomadkaraoke.com"
|
|
435
|
+
assert job.customer_email == "customer@example.com"
|
|
436
|
+
assert job.customer_notes == "Anniversary gift!"
|
|
437
|
+
|
|
438
|
+
# Verify distribution settings too
|
|
439
|
+
assert job.enable_youtube_upload is True
|
|
440
|
+
assert job.dropbox_path == "/Production/Ready"
|
|
441
|
+
assert job.brand_prefix == "NOMAD"
|
|
442
|
+
|
|
443
|
+
def test_create_job_made_for_you_false_by_default(self, job_manager, mock_firestore_service):
|
|
444
|
+
"""
|
|
445
|
+
Regular jobs should have made_for_you=False by default.
|
|
446
|
+
"""
|
|
447
|
+
job_create = JobCreate(
|
|
448
|
+
artist="Test Artist",
|
|
449
|
+
title="Test Song",
|
|
450
|
+
theme_id="nomad",
|
|
451
|
+
# No made_for_you specified - should default to False
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
job = job_manager.create_job(job_create)
|
|
455
|
+
|
|
456
|
+
assert job.made_for_you is False
|
|
457
|
+
assert job.customer_email is None
|
|
458
|
+
assert job.customer_notes is None
|
|
459
|
+
|
|
460
|
+
|
|
316
461
|
class TestJobDeletion:
|
|
317
462
|
"""Test job deletion logic."""
|
|
318
|
-
|
|
463
|
+
|
|
319
464
|
def test_delete_job(self, job_manager, mock_firestore_service):
|
|
320
465
|
"""Test deleting a job."""
|
|
321
466
|
existing_job = Job(
|