< Summary

Information
Class: ShopGuard.Core.Database.OrderRepository
Assembly: ShopGuard.Core
File(s): /home/runner/work/ShopGuard/ShopGuard/ShopGuard/ShopGuard.Core/Database/OrderRepository.cs
Line coverage
100%
Covered lines: 54
Uncovered lines: 0
Coverable lines: 54
Total lines: 95
Line coverage: 100%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
EnsureSchema()100%11100%
InsertOrder(...)100%11100%
UpdateStatus(...)100%22100%
GetByOrderNumber(...)100%11100%
CountByCustomer(...)100%11100%
DeleteByCustomer(...)100%11100%
Open()100%11100%

File(s)

/home/runner/work/ShopGuard/ShopGuard/ShopGuard/ShopGuard.Core/Database/OrderRepository.cs

#LineLine coverage
 1using Dapper;
 2using Microsoft.Data.Sqlite;
 3
 4namespace ShopGuard.Core.Database;
 5
 6/// <summary>
 7/// Dapper-based access to the order validation database (SQLite locally and in CI;
 8/// the SQL is kept ANSI-compatible so it also runs against SQL Server).
 9/// </summary>
 710public sealed class OrderRepository(string connectionString)
 11{
 12    /// <summary>Creates the Orders table when it does not exist yet.</summary>
 13    public void EnsureSchema()
 14    {
 715        using var connection = Open();
 716        connection.Execute(
 717            """
 718            CREATE TABLE IF NOT EXISTS Orders (
 719                Id            INTEGER PRIMARY KEY AUTOINCREMENT,
 720                OrderNumber   TEXT NOT NULL UNIQUE,
 721                CustomerEmail TEXT NOT NULL,
 722                Total         NUMERIC NOT NULL,
 723                Status        TEXT NOT NULL,
 724                CreatedAtUtc  TEXT NOT NULL
 725            )
 726            """);
 1427    }
 28
 29    /// <summary>Inserts a new order with status <see cref="OrderStatus.Pending"/>.</summary>
 30    public void InsertOrder(string orderNumber, string customerEmail, decimal total)
 31    {
 932        using var connection = Open();
 933        connection.Execute(
 934            """
 935            INSERT INTO Orders (OrderNumber, CustomerEmail, Total, Status, CreatedAtUtc)
 936            VALUES (@orderNumber, @customerEmail, @total, @status, @createdAtUtc)
 937            """,
 938            new
 939            {
 940                orderNumber,
 941                customerEmail,
 942                total,
 943                status = OrderStatus.Pending,
 944                createdAtUtc = DateTime.UtcNow.ToString("O"),
 945            });
 1646    }
 47
 48    /// <summary>Updates the status of an existing order.</summary>
 49    public void UpdateStatus(string orderNumber, string newStatus)
 50    {
 251        using var connection = Open();
 252        var affected = connection.Execute(
 253            "UPDATE Orders SET Status = @newStatus WHERE OrderNumber = @orderNumber",
 254            new { newStatus, orderNumber });
 55
 256        if (affected == 0)
 57        {
 158            throw new InvalidOperationException($"Order '{orderNumber}' not found.");
 59        }
 260    }
 61
 62    /// <summary>Reads a single order by its business key, or null when absent.</summary>
 63    public Order? GetByOrderNumber(string orderNumber)
 64    {
 365        using var connection = Open();
 366        return connection.QuerySingleOrDefault<Order>(
 367            "SELECT Id, OrderNumber, CustomerEmail, Total, Status, CreatedAtUtc FROM Orders WHERE OrderNumber = @orderNu
 368            new { orderNumber });
 369    }
 70
 71    /// <summary>Counts orders for a customer; used for test data isolation checks.</summary>
 72    public int CountByCustomer(string customerEmail)
 73    {
 274        using var connection = Open();
 275        return connection.ExecuteScalar<int>(
 276            "SELECT COUNT(*) FROM Orders WHERE CustomerEmail = @customerEmail",
 277            new { customerEmail });
 278    }
 79
 80    /// <summary>Removes all orders of a customer; used to clean up scenario data.</summary>
 81    public void DeleteByCustomer(string customerEmail)
 82    {
 183        using var connection = Open();
 184        connection.Execute(
 185            "DELETE FROM Orders WHERE CustomerEmail = @customerEmail",
 186            new { customerEmail });
 287    }
 88
 89    private SqliteConnection Open()
 90    {
 2491        var connection = new SqliteConnection(connectionString);
 2492        connection.Open();
 2493        return connection;
 94    }
 95}