Spaces:
Sleeping
Sleeping
File size: 6,046 Bytes
13240d3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | using BakeryErp.Infrastructure.Database;
namespace BakeryErp.Infrastructure.Repositories;
public sealed class OcrDocumentRepository
{
private readonly DatabaseOptions _options;
public OcrDocumentRepository(DatabaseOptions options)
{
_options = options;
}
public IReadOnlyList<LocalOcrDocument> List()
{
return LocalDataStoreFile.Load(_options)
.OcrDocuments
.OrderByDescending(static document => document.CreatedAt)
.ToList();
}
public LocalOcrDocument? Find(Guid id)
{
return LocalDataStoreFile.Load(_options)
.OcrDocuments
.FirstOrDefault(document => document.Id == id);
}
public OcrReport GetReport()
{
var documents = LocalDataStoreFile.Load(_options).OcrDocuments;
return new OcrReport(
documents.Count,
documents.Count(static document => document.Status == LocalOcrStatus.Uploaded),
documents.Count(static document => document.Status == LocalOcrStatus.Recognized),
documents.Count(static document => document.Status == LocalOcrStatus.MappingRequired),
documents.Count(static document => document.Status == LocalOcrStatus.Confirmed),
documents.Count(static document => document.Status == LocalOcrStatus.ConvertedToReceipt),
documents.Count(static document => document.Status == LocalOcrStatus.Failed),
documents.Sum(static document => document.TotalAmount ?? 0));
}
public SaveOcrDocumentResult Save(LocalOcrDocument document)
{
var store = LocalDataStoreFile.Load(_options);
var documentNumber = document.DocumentNumber.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(documentNumber))
{
return SaveOcrDocumentResult.ValidationError("單據編號為必填。");
}
var duplicatedNumber = store.OcrDocuments.Any(existing =>
existing.Id != document.Id &&
string.Equals(existing.DocumentNumber, documentNumber, StringComparison.OrdinalIgnoreCase));
if (duplicatedNumber)
{
return SaveOcrDocumentResult.ValidationError("單據編號已存在,請改用其他編號。");
}
var existingDocument = store.OcrDocuments.FirstOrDefault(existing => existing.Id == document.Id);
if (existingDocument is null)
{
document.Id = document.Id == Guid.Empty ? Guid.NewGuid() : document.Id;
document.DocumentNumber = documentNumber;
document.FileName = BlankToEmpty(document.FileName);
document.SupplierName = BlankToNull(document.SupplierName);
document.RawText = BlankToNull(document.RawText);
document.RecognizedItems = BlankToNull(document.RecognizedItems);
document.ReviewNote = BlankToNull(document.ReviewNote);
document.CreatedAt = DateTime.UtcNow;
store.OcrDocuments.Add(document);
}
else
{
existingDocument.DocumentNumber = documentNumber;
existingDocument.FileName = BlankToEmpty(document.FileName);
existingDocument.SupplierName = BlankToNull(document.SupplierName);
existingDocument.DocumentDate = document.DocumentDate;
existingDocument.Status = document.Status;
existingDocument.TotalAmount = document.TotalAmount;
existingDocument.RawText = BlankToNull(document.RawText);
existingDocument.RecognizedItems = BlankToNull(document.RecognizedItems);
existingDocument.ReviewNote = BlankToNull(document.ReviewNote);
existingDocument.UpdatedAt = DateTime.UtcNow;
}
LocalDataStoreFile.Save(_options, store);
return SaveOcrDocumentResult.Success();
}
public void Review(Guid id, bool approved)
{
var store = LocalDataStoreFile.Load(_options);
var document = store.OcrDocuments.FirstOrDefault(existing => existing.Id == id);
if (document is null)
{
return;
}
document.Status = approved ? LocalOcrStatus.Confirmed : LocalOcrStatus.MappingRequired;
document.ReviewedAt = DateTime.UtcNow;
document.UpdatedAt = DateTime.UtcNow;
LocalDataStoreFile.Save(_options, store);
}
public void ConvertToReceipt(Guid id)
{
var store = LocalDataStoreFile.Load(_options);
var document = store.OcrDocuments.FirstOrDefault(existing => existing.Id == id);
if (document is null)
{
return;
}
document.Status = LocalOcrStatus.ConvertedToReceipt;
document.UpdatedAt = DateTime.UtcNow;
LocalDataStoreFile.Save(_options, store);
}
public static string GetStatusName(LocalOcrStatus status)
{
return status switch
{
LocalOcrStatus.Uploaded => "已上傳",
LocalOcrStatus.Recognized => "已辨識",
LocalOcrStatus.MappingRequired => "待對應",
LocalOcrStatus.Confirmed => "已確認",
LocalOcrStatus.ConvertedToReceipt => "已轉進貨",
LocalOcrStatus.Failed => "失敗",
_ => status.ToString()
};
}
private static string BlankToEmpty(string? value)
{
return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim();
}
private static string? BlankToNull(string? value)
{
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
}
public sealed record OcrReport(
int TotalCount,
int UploadedCount,
int RecognizedCount,
int MappingRequiredCount,
int ConfirmedCount,
int ConvertedToReceiptCount,
int FailedCount,
decimal TotalAmount);
public sealed record SaveOcrDocumentResult(bool IsSuccess, string? ErrorMessage)
{
public static SaveOcrDocumentResult Success() => new(true, null);
public static SaveOcrDocumentResult ValidationError(string message) => new(false, message);
}
|