Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
{
"permissions": {
"allow": [
"Skill(taches-cc-resources:create-plans)"
"Skill(taches-cc-resources:create-plans)",
"Skill(run-prompt)",
"Bash(dotnet build:*)",
"Bash(where:*)",
"Bash(dir \"C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\*\\\\MSBuild\\\\Current\\\\Bin\\\\MSBuild.exe\")",
"Bash(dir \"C:\\\\Program Files \\(x86\\)\\\\Microsoft Visual Studio\\\\2022\\\\*\\\\MSBuild\\\\Current\\\\Bin\\\\MSBuild.exe\")",
"Bash(dir \"C:\\\\Program Files\\\\Microsoft Visual Studio\" /b)",
"Bash(dir \"C:\\\\Program Files \\(x86\\)\\\\Microsoft Visual Studio\" /b)",
"Bash(dir:*)",
"Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"C:\\\\Users\\\\bpowers\\\\source\\\\repos\\\\Lab-Patient-Accounting\\\\LabBilling Library\\\\LabBilling Core.csproj\" -p:Platform=x64 -verbosity:minimal)",
"Bash(dotnet test:*)",
"Bash(dotnet vstest:*)",
"Bash(findstr:*)",
"WebFetch(domain:github.com)",
"WebSearch"
]
}
}
804 changes: 804 additions & 0 deletions Analysis/sql-plan-cache-pollution-analysis.md

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions Lab PA WinForms UI/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"profiles": {
"Lab Billing WinForms UI": {
"commandName": "Project",
"commandLineArgs": "/TEST"
"commandName": "Project"
}
}
}
72 changes: 39 additions & 33 deletions LabBilling Library/Repositories/AccountSearchRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace LabBilling.Core.DataAccess;

Expand Down Expand Up @@ -79,10 +80,10 @@ public IList<AccountSearch> GetBySearch((string propertyName, operation oper, st
op = "=";
break;
}
if (op == "in")
if (op == "in" || op == "not in")
{
command.Where($"{propName} {op} ({searchText})");

var values = searchText.Split(',').Select(s => s.Trim().Trim('\'')).ToArray();
command.Where($"{propName} {op} (@0)", values);
}
else
{
Expand Down Expand Up @@ -184,8 +185,16 @@ public IEnumerable<AccountSearch> GetBySearchAsync((string propertyName, operati
op = "=";
break;
}
command.Where($"{propName} {op} @0",
new SqlParameter() { SqlDbType = GetType(propType), Value = searchText });
if (op == "in" || op == "not in")
{
var values = searchText.Split(',').Select(s => s.Trim().Trim('\'')).ToArray();
command.Where($"{propName} {op} (@0)", values);
}
else
{
command.Where($"{propName} {op} @0",
new SqlParameter() { SqlDbType = GetType(propType), Value = searchText });
}
}
command.OrderBy(GetRealColumn(typeof(AccountSearch), nameof(AccountSearch.Name)));
var results = Context.Fetch<AccountSearch>(command);
Expand Down Expand Up @@ -217,43 +226,40 @@ public IEnumerable<AccountSearch> GetBySearch(string lastNameSearchText, string

try
{
//string nameSearch = "";
//if (!(lastNameSearchText == "" && firstNameSearchText == ""))
// nameSearch = string.Format("{0}%,{1}%", lastNameSearchText, firstNameSearchText);

var command = PetaPoco.Sql.Builder
.Where("deleted = 0 ");

if (!String.IsNullOrEmpty(lastNameSearchText))
command.Where($"{GetRealColumn(nameof(AccountSearch.LastName))} like @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = lastNameSearchText + "%" });
command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.LastName))} like @1)",
string.IsNullOrEmpty(lastNameSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = lastNameSearchText + "%" },
string.IsNullOrEmpty(lastNameSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = lastNameSearchText + "%" });

if (!string.IsNullOrEmpty(firstNameSearchText))
command.Where($"{GetRealColumn(nameof(AccountSearch.FirstName))} like @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = firstNameSearchText + "%" });
command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.FirstName))} like @1)",
string.IsNullOrEmpty(firstNameSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = firstNameSearchText + "%" },
string.IsNullOrEmpty(firstNameSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = firstNameSearchText + "%" });

if (!string.IsNullOrEmpty(accountSearchText))
command.Where($"{GetRealColumn(nameof(AccountSearch.Account))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = accountSearchText });
command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.Account))} = @1)",
string.IsNullOrEmpty(accountSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = accountSearchText },
string.IsNullOrEmpty(accountSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = accountSearchText });

if (!string.IsNullOrEmpty(mrnSearchText))
command.Where($"{GetRealColumn(nameof(AccountSearch.MRN))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = mrnSearchText });
command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.MRN))} = @1)",
string.IsNullOrEmpty(mrnSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = mrnSearchText },
string.IsNullOrEmpty(mrnSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = mrnSearchText });

if (!string.IsNullOrEmpty(sexSearch))
command.Where($"{GetRealColumn(nameof(AccountSearch.Sex))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = sexSearch });
command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.Sex))} = @1)",
string.IsNullOrEmpty(sexSearch) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = sexSearch },
string.IsNullOrEmpty(sexSearch) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = sexSearch });

if (!string.IsNullOrEmpty(ssnSearchText))
command.Where($"{GetRealColumn(nameof(AccountSearch.SSN))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = ssnSearchText });
command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.SSN))} = @1)",
string.IsNullOrEmpty(ssnSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = ssnSearchText },
string.IsNullOrEmpty(ssnSearchText) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = ssnSearchText });

if (!string.IsNullOrEmpty(dobSearch))
{
_ = DateTime.TryParse(dobSearch, out DateTime dobDt);
command.Where($"{GetRealColumn(nameof(AccountSearch.DateOfBirth))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = dobDt });
}
DateTime? dobDt = null;
if (!string.IsNullOrEmpty(dobSearch) && DateTime.TryParse(dobSearch, out DateTime parsed))
dobDt = parsed;

command.Where($"(@0 IS NULL OR {GetRealColumn(nameof(AccountSearch.DateOfBirth))} = @1)",
dobDt.HasValue ? (object)new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = dobDt.Value } : DBNull.Value,
dobDt.HasValue ? (object)new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = dobDt.Value } : DBNull.Value);

command.OrderBy($"{GetRealColumn(nameof(AccountSearch.ServiceDate))} desc");

Expand Down
6 changes: 5 additions & 1 deletion LabBilling Library/Repositories/AuditReportRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ public AuditReportRepository(IAppEnvironment environment, IDatabase context) : b

public List<string> GetMenus()
{
var list = Context.Fetch<string>($"SELECT DISTINCT {GetRealColumn(nameof(AuditReport.Button))} FROM {TableName}");
var sql = PetaPoco.Sql.Builder
.Select($"DISTINCT {GetRealColumn(nameof(AuditReport.Button))}")
.From(TableName);

var list = Context.Fetch<string>(sql);

return list;
}
Expand Down
20 changes: 8 additions & 12 deletions LabBilling Library/Repositories/ChrgRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,17 @@ public List<Chrg> GetByAccount(string account, bool showCredited = true, bool in
var sql = PetaPoco.Sql.Builder
.Where("account = @0", new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = account });

if (asOfDate != null)
{
sql.Where($"{_tableName}.{GetRealColumn(nameof(Chrg.UpdatedDate))} > @0",
new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = asOfDate });
}
sql.Where($"(@0 IS NULL OR {_tableName}.{GetRealColumn(nameof(Chrg.UpdatedDate))} > @0)", asOfDate);

if (!showCredited)
sql.Where($"{GetRealColumn(nameof(Chrg.IsCredited))} = 0");
sql.Where($"(@0 = 1 OR {GetRealColumn(nameof(Chrg.IsCredited))} = 0)",
new SqlParameter() { SqlDbType = SqlDbType.Bit, Value = showCredited });

if (!includeInvoiced)
sql.Where($"{GetRealColumn(nameof(Chrg.Invoice))} is null or {GetRealColumn(nameof(Chrg.Invoice))} = ''");
sql.Where($"(@0 = 1 OR {GetRealColumn(nameof(Chrg.Invoice))} is null OR {GetRealColumn(nameof(Chrg.Invoice))} = '')",
new SqlParameter() { SqlDbType = SqlDbType.Bit, Value = includeInvoiced });

if (excludeCBill)
sql.Where($"{GetRealColumn(nameof(Chrg.CDMCode))} <> @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = AppEnvironment.ApplicationParameters.ClientInvoiceCdm });
sql.Where($"(@0 = 0 OR {GetRealColumn(nameof(Chrg.CDMCode))} <> @1)",
new SqlParameter() { SqlDbType = SqlDbType.Bit, Value = excludeCBill },
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = AppEnvironment.ApplicationParameters.ClientInvoiceCdm });

sql.OrderBy($"{_tableName}.{GetRealColumn(nameof(Chrg.ChrgId))}");

Expand Down
13 changes: 9 additions & 4 deletions LabBilling Library/Repositories/ClientRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,15 @@ public List<UnbilledAccounts> GetUnbilledAccounts(DateTime thruDate, IProgress<i
.From(chrgTableName)
.InnerJoin(accTableName)
.On($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.AccountNo))} = {accTableName}.{GetRealColumn(typeof(Account), nameof(Account.AccountNo))}")
.Where($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.Status))} not in ('CBILL','N/A')")
.Where($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.Invoice))} is null or {chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.Invoice))} = ''")
.Where($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.FinancialType))} = 'C'")
.Where($"{accTableName}.{GetRealColumn(typeof(Account), nameof(Account.Status))} not like '%HOLD%'")
.Where($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.Status))} not in (@0, @1)",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "CBILL" },
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "N/A" })
.Where($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.Invoice))} is null or {chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.Invoice))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "" })
.Where($"{chrgTableName}.{GetRealColumn(typeof(Chrg), nameof(Chrg.FinancialType))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "C" })
.Where($"{accTableName}.{GetRealColumn(typeof(Account), nameof(Account.Status))} not like @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "%HOLD%" })
.Where($"{accTableName}.{GetRealColumn(typeof(Account), nameof(Account.TransactionDate))} <= @0 ",
new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = thruDate })
.GroupBy(new[]
Expand Down
6 changes: 3 additions & 3 deletions LabBilling Library/Repositories/InsCompanyRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public List<InsCompany> GetAll(bool excludeDeleted)
Log.Instance.Debug($"Entering");

var sql = Sql.Builder;
if(excludeDeleted)
sql.Where($"{GetRealColumn(nameof(InsCompany.IsDeleted))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.Bit, Value = false } );
sql.Where($"(@0 = 0 OR {GetRealColumn(nameof(InsCompany.IsDeleted))} = @1)",
new SqlParameter() { SqlDbType = SqlDbType.Bit, Value = excludeDeleted },
new SqlParameter() { SqlDbType = SqlDbType.Bit, Value = false });

var queryResult = Context.Fetch<InsCompany>(sql);

Expand Down
27 changes: 12 additions & 15 deletions LabBilling Library/Repositories/InvoiceHistoryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,19 @@ public IEnumerable<InvoiceHistory> GetWithSort(string clientMnem = null, DateTim
.From(_tableName)
.LeftJoin("client").On($"{_tableName}.cl_mnem = client.cli_mnem");

if(clientMnem != null)
{
sql.Where($"cl_mnem = @0", new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = clientMnem });
}
sql.Where($"(@0 IS NULL OR cl_mnem = @1)",
string.IsNullOrEmpty(clientMnem) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = clientMnem },
string.IsNullOrEmpty(clientMnem) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = clientMnem });

if (fromDate != null || throughDate != null)
{
if (fromDate != null && throughDate != null)
sql.Where($"{_tableName}.mod_date between @0 and @1",
new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = fromDate},
new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = throughDate});
}
if(!string.IsNullOrEmpty(invoice))
{
sql.Where($"{GetRealColumn(nameof(InvoiceHistory.InvoiceNo))} = @0", new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = invoice });
}
sql.Where($"(@0 IS NULL OR @1 IS NULL OR {_tableName}.mod_date between @2 and @3)",
fromDate.HasValue ? (object)new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = fromDate.Value } : DBNull.Value,
throughDate.HasValue ? (object)new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = throughDate.Value } : DBNull.Value,
fromDate.HasValue ? (object)new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = fromDate.Value } : DBNull.Value,
throughDate.HasValue ? (object)new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = throughDate.Value } : DBNull.Value);

sql.Where($"(@0 IS NULL OR {GetRealColumn(nameof(InvoiceHistory.InvoiceNo))} = @1)",
string.IsNullOrEmpty(invoice) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = invoice },
string.IsNullOrEmpty(invoice) ? (object)DBNull.Value : new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = invoice });
sql.OrderBy($"{_tableName}.mod_date DESC");
Log.Instance.Debug(sql);
return Context.Fetch<InvoiceHistory>(sql);
Expand Down
5 changes: 5 additions & 0 deletions LabBilling Library/Repositories/LogRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public LogRepository(string connectionString)
Log.Instance.Trace("Entering");
_tableInfo = GetTableInfo(typeof(Logs));
_tableName = _tableInfo.TableName;
// LogRepository connects to a separate NLog logging database (not the main LabBilling database).
// It intentionally uses SqlServerMsDataDatabaseProvider instead of CustomSqlMsDatabaseProvider
// because the CustomSqlMsDatabaseProvider workaround for SQL Error 334 is only needed for
// the main application tables. MyMapper is also not required since Logs columns map directly
// without custom attribute resolution.
dbConnection = new PetaPoco.Database(connectionString, new SqlServerMsDataDatabaseProvider());
Log.Instance.Debug(dbConnection.ConnectionString);
}
Expand Down
11 changes: 6 additions & 5 deletions LabBilling Library/Repositories/MappingRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public IList<string> GetReturnTypeList()
{
Log.Instance.Debug($"Entering");

string sql = null;
sql = $"select DISTINCT {GetRealColumn(nameof(Mapping.SystemType))} from {_tableName}";
var sql = PetaPoco.Sql.Builder
.Select($"DISTINCT {GetRealColumn(nameof(Mapping.SystemType))}")
.From(_tableName);

var queryResult = Context.Fetch<string>(sql);

Expand All @@ -31,13 +32,13 @@ public IList<string> GetSendingSystemList()
{
Log.Instance.Debug($"Entering");

string sql = null;
sql = $"select DISTINCT {GetRealColumn(nameof(Mapping.InterfaceName))} from {_tableName}";
var sql = PetaPoco.Sql.Builder
.Select($"DISTINCT {GetRealColumn(nameof(Mapping.InterfaceName))}")
.From(_tableName);

var queryResult = Context.Fetch<string>(sql);

return queryResult;

}

public IEnumerable<Mapping> GetMappings(string codeSet, string sendingSystem)
Expand Down
6 changes: 4 additions & 2 deletions LabBilling Library/Repositories/MessagesInboundRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public List<MessageQueueCount> GetQueueCounts()
var sql = Sql.Builder
.Select($"left({GetRealColumn(nameof(MessageInbound.MessageType))}, 3) as 'MessageType', count(*) as 'QueueCount'")
.From(_tableName)
.Where($"{GetRealColumn(nameof(MessageInbound.ProcessFlag))} = 'N'")
.Where($"{GetRealColumn(nameof(MessageInbound.ProcessFlag))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "N" })
.GroupBy($"left({GetRealColumn(nameof(MessageInbound.MessageType))}, 3)")
.OrderBy($"left({GetRealColumn(nameof(MessageInbound.MessageType))}, 3)");

Expand All @@ -36,7 +37,8 @@ public List<MessageInbound> GetUnprocessedMessages()
Log.Instance.Trace($"Entering");

var command = PetaPoco.Sql.Builder;
command.Where($"{GetRealColumn(nameof(MessageInbound.ProcessFlag))} = 'N'");
command.Where($"{GetRealColumn(nameof(MessageInbound.ProcessFlag))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.VarChar, Value = "N" });
command.OrderBy($"{GetRealColumn(nameof(MessageInbound.MessageDate))}");

var records = Context.Fetch<MessageInbound>(command);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ public List<PatientStatement> GetByBatch(string batch)

sql.Where($"{GetRealColumn(nameof(PatientStatement.BatchId))} = @0",
new SqlParameter() { SqlDbType = System.Data.SqlDbType.VarChar, Value = batch});
sql.Where($"{GetRealColumn(nameof(PatientStatement.StatementSubmittedDateTime))} is null or {GetRealColumn(nameof(PatientStatement.StatementSubmittedDateTime))} = '01/01/1900'");
sql.Where($"{GetRealColumn(nameof(PatientStatement.StatementSubmittedDateTime))} is null or " +
$"{GetRealColumn(nameof(PatientStatement.StatementSubmittedDateTime))} = @0",
new SqlParameter() { SqlDbType = SqlDbType.DateTime, Value = new DateTime(1900, 1, 1) });

var results = Context.Fetch<PatientStatement>(sql);

Expand Down
Loading
Loading