90 lines
4.4 KiB
C#
90 lines
4.4 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using PowderCoating.Core.Entities;
|
|
|
|
namespace PowderCoating.Infrastructure.Services;
|
|
|
|
public partial class SeedDataService
|
|
{
|
|
/// <summary>
|
|
/// Seeds platform-level release notes (changelog entries) that are displayed to all
|
|
/// tenants in the What's New / Release Notes section. Safe to call repeatedly —
|
|
/// each version string is checked individually and skipped if it already exists,
|
|
/// so new entries can be added to the list over time without re-inserting old ones.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Unlike other seed methods, this one does NOT use <c>IgnoreQueryFilters()</c> because
|
|
/// release notes are global platform records with no <c>CompanyId</c> tenant filter, so
|
|
/// the default query already sees all rows.
|
|
/// </para>
|
|
/// <para>
|
|
/// The idempotency check is per-version (not a blanket "any rows exist?" guard) so that
|
|
/// future versions can be appended to the <c>notes</c> list and seeded incrementally.
|
|
/// </para>
|
|
/// <para>
|
|
/// This method is <c>public</c> because it is callable from the Platform Management →
|
|
/// Seed Data UI independently of company-scoped operations.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <returns>Number of new release note entries inserted, or 0 if all versions already exist.</returns>
|
|
public async Task<int> SeedReleaseNotesAsync()
|
|
{
|
|
var existingVersions = (await _context.ReleaseNotes
|
|
.Select(r => r.Version)
|
|
.ToListAsync())
|
|
.ToHashSet();
|
|
|
|
var notes = new List<ReleaseNote>
|
|
{
|
|
new()
|
|
{
|
|
Version = "2.1.0",
|
|
Title = "AI Accounting Suite, Cash Flow Forecast & Anomaly Detection",
|
|
Tag = "Feature",
|
|
IsPublished = true,
|
|
ReleasedAt = new DateTime(2026, 4, 4, 0, 0, 0, DateTimeKind.Utc),
|
|
CreatedAt = DateTime.UtcNow,
|
|
Body = """
|
|
## What's New
|
|
|
|
### AI Accounting Features
|
|
Four new AI-powered tools to save time and catch problems:
|
|
|
|
- **Receipt Scanning** — Upload a photo or PDF receipt when creating a bill. AI extracts the vendor, date, invoice number, total, and line items, and attaches the file automatically.
|
|
- **Smart Account Categorisation** — As you type each bill line item description, the system silently suggests the best expense account. No button to click — it fills in as you work.
|
|
- **AR Follow-up Email Drafts** — On the AR Aging report, click *Draft Reminder* next to any overdue customer. AI writes a professional collections email with tone that scales from gentle (≤30 days) to serious (60+ days).
|
|
- **Plain-English Financial Summary** — In Full Analytics, click *Generate AI Summary* for a short, readable paragraph explaining what your numbers mean this period.
|
|
|
|
### Cash Flow Forecast *(New Report)*
|
|
- Projects your 30, 60, and 90-day cash position
|
|
- Factors in open AR invoices (with each customer's historical average days-to-pay), outstanding bills, and your active job pipeline
|
|
- Displays an overall outlook — Strong, Moderate, Tight, or Concerning — with plain-English insights per period
|
|
|
|
### Anomaly Detection *(New Report)*
|
|
- Scans your last 90 days of bills for duplicate entries, unusual amounts, and expense accounts running above their historical average
|
|
- Flags ranked by severity: Critical, Warning, Info
|
|
- Each flag includes a plain-English description and a recommended action
|
|
|
|
### Bills / Expenses Unified List
|
|
- Bills and Expenses are now combined under **Bills / Expenses** in the navigation
|
|
- Single *New* split-button to create either type
|
|
- Type filter to view all entries, bills only, or expenses only
|
|
|
|
### Other Improvements
|
|
- Bills now save as **Open** by default — Record Payment is available immediately without a status change
|
|
- New **I Already Paid This** toggle on the bill create form — records the bill and payment in one step
|
|
- PDF receipts are now accepted everywhere image receipts were previously supported
|
|
- Reports landing page reorganised into two clear sections: Charts & Dashboards, and Detailed Reports
|
|
"""
|
|
},
|
|
};
|
|
|
|
var toAdd = notes.Where(n => !existingVersions.Contains(n.Version)).ToList();
|
|
if (toAdd.Count == 0) return 0;
|
|
|
|
_context.ReleaseNotes.AddRange(toAdd);
|
|
await _context.SaveChangesAsync();
|
|
return toAdd.Count;
|
|
}
|
|
}
|