Initial import into Gitea

This commit is contained in:
Grae Jones
2026-03-14 13:50:09 -07:00
parent 8e7e03702e
commit 34c1f09e01
154 changed files with 17666 additions and 1548 deletions

View File

@@ -0,0 +1,186 @@
using Registration.Data;
using System.Collections.Concurrent;
using Microsoft.Extensions.Logging;
namespace Registration.Mock;
/// <summary>
/// In-memory mock registration data for development.
/// Persists across requests within a single Function host lifecycle.
/// State resets on cold start (by design — it's mock data).
///
/// Swap to SqlDataService in Program.cs when dbRegistration is ready.
/// </summary>
public class MockDataService : IRegistrationDataService
{
private readonly ConcurrentDictionary<string, Applicant> _store;
private readonly ILogger<MockDataService> _log;
public MockDataService(ILogger<MockDataService> log)
{
_log = log;
_store = new ConcurrentDictionary<string, Applicant>(SeedData());
_log.LogInformation("[Mock] Initialized with {Count} applicants", _store.Count);
}
public Task<RegistrationListResult> GetPendingAsync(CancellationToken ct)
{
var pending = _store.Values
.Where(a => a.Status == "Pending")
.OrderBy(a => a.RegisteredUtc)
.ToList();
return Task.FromResult(new RegistrationListResult
{
Ok = true,
Applicants = pending,
TotalCount = pending.Count
});
}
public Task<Applicant?> GetByIdAsync(string registrationId, CancellationToken ct)
{
_store.TryGetValue(registrationId, out var applicant);
return Task.FromResult(applicant);
}
public Task<RegistrationResult> RegisterAsync(RegisterRequest request, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(request.BusinessName))
return Task.FromResult(new RegistrationResult { Ok = false, Error = "Business name is required" });
// Check for duplicate business name
if (_store.Values.Any(a => string.Equals(a.BusinessName, request.BusinessName, StringComparison.OrdinalIgnoreCase)
&& a.Status != "Rejected"))
return Task.FromResult(new RegistrationResult { Ok = false, Error = "A registration with this name already exists" });
var id = Guid.NewGuid().ToString("D");
var applicant = new Applicant
{
RegistrationId = id,
BusinessName = request.BusinessName!.Trim(),
WebsiteUrl = request.WebsiteUrl,
BusinessCategory = request.BusinessCategory,
BusinessDescription = request.BusinessDescription,
ContactName = request.ContactName,
ContactEmail = request.ContactEmail,
ContactPhone = request.ContactPhone,
EntraSubjectId = request.EntraSubjectId,
Status = "Pending",
PaymentVerified = false,
RegisteredUtc = DateTime.UtcNow
};
_store[id] = applicant;
_log.LogInformation("[Mock] New registration: {Name} ({Id})", applicant.BusinessName, id);
return Task.FromResult(new RegistrationResult { Ok = true, RegistrationId = id });
}
public Task<RegistrationResult> RejectAsync(string registrationId, string? reason, string? rejectedBy, CancellationToken ct)
{
if (!_store.TryGetValue(registrationId, out var applicant))
return Task.FromResult(new RegistrationResult { Ok = false, Error = "Registration not found" });
if (applicant.Status != "Pending")
return Task.FromResult(new RegistrationResult { Ok = false, Error = $"Cannot reject — status is {applicant.Status}" });
applicant.Status = "Rejected";
applicant.RejectionReason = reason;
applicant.ReviewedBy = rejectedBy;
applicant.ReviewedUtc = DateTime.UtcNow;
_log.LogInformation("[Mock] Rejected: {Name} ({Id}) reason={Reason}", applicant.BusinessName, registrationId, reason);
return Task.FromResult(new RegistrationResult { Ok = true, RegistrationId = registrationId });
}
public Task<RegistrationResult> CompleteAsync(string registrationId, string? platformClientId, CancellationToken ct)
{
if (!_store.TryGetValue(registrationId, out var applicant))
return Task.FromResult(new RegistrationResult { Ok = false, Error = "Registration not found" });
if (applicant.Status != "Pending")
return Task.FromResult(new RegistrationResult { Ok = false, Error = $"Cannot complete — status is {applicant.Status}" });
applicant.Status = "Approved";
applicant.PlatformClientId = platformClientId;
applicant.ReviewedUtc = DateTime.UtcNow;
_log.LogInformation("[Mock] Approved: {Name} ({Id}) → platform client {PlatformId}",
applicant.BusinessName, registrationId, platformClientId);
return Task.FromResult(new RegistrationResult { Ok = true, RegistrationId = registrationId });
}
// ── Seed Data ───────────────────────────────────
private static IEnumerable<KeyValuePair<string, Applicant>> SeedData()
{
var applicants = new[]
{
new Applicant
{
RegistrationId = "reg-001",
BusinessName = "Bella's Boutique",
WebsiteUrl = "https://bellasboutique.com",
BusinessCategory = "retail",
BusinessDescription = "Women's fashion and accessories boutique in Orange County. Looking to expand online presence through targeted social and search ads.",
ContactName = "Bella Rodriguez",
ContactEmail = "bella@bellasboutique.com",
ContactPhone = "(714) 555-0142",
EntraSubjectId = "entra-mock-bella-001",
Status = "Pending",
PaymentVerified = true,
RegisteredUtc = DateTime.UtcNow.AddDays(-3)
},
new Applicant
{
RegistrationId = "reg-002",
BusinessName = "Pacific Coast Plumbing",
WebsiteUrl = "https://pacificcoastplumbing.com",
BusinessCategory = "home_services",
BusinessDescription = "Full-service plumbing company serving LA and OC. Need help with Google Local Services ads and Maps visibility.",
ContactName = "Mike Chen",
ContactEmail = "mike@pcplumbing.com",
ContactPhone = "(562) 555-0198",
EntraSubjectId = "entra-mock-mike-002",
Status = "Pending",
PaymentVerified = true,
RegisteredUtc = DateTime.UtcNow.AddDays(-1)
},
new Applicant
{
RegistrationId = "reg-003",
BusinessName = "Sunrise Dental Group",
WebsiteUrl = "https://sunrisedental.care",
BusinessCategory = "healthcare",
BusinessDescription = "Multi-location dental practice. Interested in running awareness campaigns for new patient acquisition across Google and Meta.",
ContactName = "Dr. Sarah Kim",
ContactEmail = "sarah@sunrisedental.care",
ContactPhone = "(949) 555-0267",
EntraSubjectId = "entra-mock-sarah-003",
Status = "Pending",
PaymentVerified = false,
RegisteredUtc = DateTime.UtcNow.AddHours(-6)
},
new Applicant
{
RegistrationId = "reg-004",
BusinessName = "FreshBite Meal Prep",
WebsiteUrl = "https://freshbitemealprep.com",
BusinessCategory = "food_beverage",
BusinessDescription = "Healthy meal prep delivery service. $2k/month budget for Instagram and TikTok ads targeting health-conscious millennials.",
ContactName = "Jordan Williams",
ContactEmail = "jordan@freshbitemealprep.com",
ContactPhone = "(310) 555-0334",
EntraSubjectId = "entra-mock-jordan-004",
Status = "Pending",
PaymentVerified = true,
RegisteredUtc = DateTime.UtcNow.AddHours(-2)
},
};
return applicants.Select(a => new KeyValuePair<string, Applicant>(a.RegistrationId, a));
}
}