PhotoFlow Documentation Help

Photoflow Service

Overview

The Photoflow Service is the core service of the PhotoFlow platform, responsible for managing albums, photos, feedback, and the workflow state machine.

Responsibilities

  • Album lifecycle management (CRUD operations)

  • Album state machine execution

  • Photo processing and synchronization

  • Client feedback collection

  • Photo voting and selection

  • Real-time notifications via SignalR

Project Structure

Photoflow/ ├── Photoflow.API/ │ ├── Controllers/ │ │ ├── AlbumController.cs │ │ ├── AlbumTagController.cs │ │ ├── PhotoController.cs │ │ ├── PhotoCommentController.cs │ │ ├── PhotoLikeController.cs │ │ ├── FeedbackController.cs │ │ └── PublicController.cs │ └── Program.cs ├── Photoflow.Application/ │ ├── UseCases/ │ │ ├── Albums/ │ │ ├── AlbumTags/ │ │ ├── Photos/ │ │ └── Feedback/ │ ├── Events/ │ │ ├── Sync/ │ │ └── Handlers/ │ └── Services/ ├── Photoflow.Domain/ │ ├── Entities/ │ │ ├── AlbumEntity.cs │ │ ├── AlbumTagEntity.cs │ │ ├── PhotoProcEntity.cs │ │ ├── PhotoComment.cs │ │ ├── PhotoLikeEntity.cs │ │ └── PublicUrlEntity.cs │ ├── StateMachine/ │ │ └── AlbumStateMachineDefinition.cs │ ├── Common/ │ │ └── Enums/ │ │ ├── States/AlbumState.cs │ │ ├── Triggers/AlbumTrigger.cs │ │ ├── AlbumTagType.cs │ │ └── EnumAlbumTagStatus.cs │ └── Repositories/ └── Photoflow.Infrastructure/ ├── Persistence/ │ ├── PhotoflowDbContext.cs │ └── Repositories/ └── Services/

Domain Entities

AlbumEntity

The root aggregate for album management:

public sealed class AlbumEntity : BaseEntity<Guid>, IMultiTenantEntity, IAggregateRoot { public string Name { get; private set; } public AlbumStatus Status { get; set; } public AlbumState AlbumState { get; set; } public Guid OrgId { get; set; } public Guid ProviderId { get; private set; } // Relationships public ICollection<AlbumTagEntity> AlbumTags { get; set; } public ICollection<PhotoProcEntity> PhotoProcs { get; set; } // Computed properties public int TotalPhotos => GetPhotosFromCurrentStateAlbumTag()?.Count ?? 0; public int SelectedPhotos => GetPhotosFromCurrentStateAlbumTag()?.Count(p => p.Voted) ?? 0; }

AlbumTagEntity

Represents a stage in the album workflow:

public class AlbumTagEntity : BaseEntity<Guid> { public Guid AlbumId { get; private set; } public AlbumTagType Type { get; private set; } public EnumAlbumTagStatus Status { get; private set; } public AlbumTagLink? Link { get; private set; } public Guid ProviderId { get; private set; } public Guid? FolderId { get; private set; } }

PhotoProcEntity

Individual photo within an album tag:

public class PhotoProcEntity : BaseEntity<Guid> { public Guid AlbumTagId { get; private set; } public string FileName { get; private set; } public string ExternalId { get; private set; } public PhotoStatus Status { get; private set; } public bool Voted { get; private set; } public int SortOrder { get; private set; } }

Use Cases

Album Use Cases

Use Case

Description

CreateAlbumUseCase

Create a new album

UpdateAlbumUseCase

Update album details

DeleteAlbumUseCase

Soft delete an album

GetAlbumDetailUseCase

Get album with all related data

GetAlbumsUseCase

List albums with filtering

TriggerAlbumStateUseCase

Execute state machine trigger

GetAlbumTransitionsUseCase

Get available transitions

Photo Use Cases

Use Case

Description

GetPhotosUseCase

List photos in an album tag

VotePhotoUseCase

Mark photo as voted/selected

GetPhotoDetailUseCase

Get photo details

Feedback Use Cases

Use Case

Description

CreateFeedbackUseCase

Add feedback comment to photo

GetFeedbackCountUseCase

Get count of photos with feedback

Event Handlers

Sync Events

Event

Handler

Action

FullSyncStorageEvent

SyncPhotosHandler

Sync photos from Google Drive

StorageFolderSyncProgressEvent

StorageFolderSyncProgressEventHandler

Update sync progress

StorageFolderSyncCompletedEvent

StorageFolderSyncCompletedEventHandler

Complete photo sync

Domain Events

Event

Handler

Action

AlbumStateMachineTriggeredEvent

AlbumStateMachineTriggeredEventHandler

Update album state

PhotoVotedEvent

PhotoVotedEventHandler

Handle photo voting

AlbumTagCreatedEvent

AlbumTagCreatedEventHandler

Send SignalR notification

AlbumTagStatusChangedEvent

AlbumTagStatusChangedEventHandler

Send SignalR notification

API Controllers

AlbumController

# List albums GET /api/v1/albums # Get album detail GET /api/v1/albums/{id} # Create album POST /api/v1/albums # Update album PUT /api/v1/albums/{id} # Delete album DELETE /api/v1/albums/{id} # Get available transitions GET /api/v1/albums/{id}/transitions # Trigger state change PUT /api/v1/albums/{id}/state

AlbumTagController

# List album tags GET /api/v1/albums/{albumId}/tags # Get album tag detail GET /api/v1/albums/{albumId}/tags/{tagId} # Update album tag URL PUT /api/v1/albums/{albumId}/tags/{tagId}/url

PhotoController

# List photos in album tag GET /api/v1/albums/{albumId}/tags/{tagId}/photos # Get photo detail GET /api/v1/albums/{albumId}/photos/{photoId} # Vote photo POST /api/v1/albums/{albumId}/photos/{photoId}/vote

PublicController

Anonymous endpoints for client access:

# Get public album by URL GET /api/v1/public/albums/{publicUrl} # Get public photos GET /api/v1/public/albums/{publicUrl}/photos # Submit feedback POST /api/v1/public/albums/{publicUrl}/feedback

Database Schema

Tables

Table

Description

Albums

Album master data

AlbumTags

Album workflow stages

PhotoProcs

Photo records

PhotoComments

Photo feedback comments

PhotoLikes

Photo likes/votes

PublicUrls

Public access URLs

FailureRecords

Rollback failure tracking

Key Relationships

Albums (1) ─── (N) AlbumTags Albums (1) ─── (N) PhotoProcs AlbumTags (1) ─── (N) PhotoProcs PhotoProcs (1) ─── (N) PhotoComments PhotoProcs (1) ─── (N) PhotoLikes AlbumTags (1) ─── (0..1) PublicUrls

Configuration

appsettings.json

{ "ConnectionStrings": { "DefaultConnection": "Host=localhost;Database=pfl-dev;..." }, "Photoflow": { "SyncBatchSize": 50, "MaxRetryAttempts": 3, "RetryDelaySeconds": 5 } }
Last modified: 25 February 2026