246 lines
14 KiB
Markdown
246 lines
14 KiB
Markdown
---
|
||
source_files:
|
||
- Common/DTS.Common.DataModel/Classes/TestMetaData/CustomerDetails.cs
|
||
- Common/DTS.Common.DataModel/Classes/TestMetaData/LabratoryDetails.cs
|
||
- Common/DTS.Common.DataModel/Classes/TestMetaData/TestEngineerDetails.cs
|
||
generated_at: "2026-04-16T03:33:20.750893+00:00"
|
||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
schema_version: 1
|
||
sha256: "9acc3ac2395ce04b"
|
||
---
|
||
|
||
# TestMetaData
|
||
|
||
## Documentation: Test Metadata Domain Models
|
||
|
||
---
|
||
|
||
### 1. Purpose
|
||
|
||
This module provides domain models for managing test-related metadata entities—specifically `CustomerDetails`, `LabratoryDetails`, and `TestEngineerDetails`—within the DataPROWin7 system. Each class wraps a corresponding low-level ISO-compliant data object (`DTS.Common.ISO.*`) and exposes a property-change-aware interface for UI binding and data entry. The module also provides static/list management classes (`*DetailsList`) for CRUD operations (create, read, delete, list) against persisted metadata, with special handling for caching in run-test scenarios (only for `TestEngineerDetails`). Its role is to abstract persistence and change tracking while enabling data binding in WPF UIs.
|
||
|
||
---
|
||
|
||
### 2. Public Interface
|
||
|
||
#### `CustomerDetails` (inherits `BasePropertyChanged`)
|
||
- **`bool IsBlank()`**
|
||
Returns `true` if no property has been set since construction (initial state only).
|
||
- **`string Name { get; set; }`**
|
||
Gets/sets the display name of the customer. Setting triggers `_blank = false` and `OnPropertyChanged("Name")`.
|
||
- **`string CustomerName { get; set; }`**
|
||
Gets/sets the full customer name.
|
||
- **`string CustomerTestRefNumber { get; set; }`**
|
||
Gets/sets the customer’s test reference number.
|
||
- **`string ProjectRefNumber { get; set; }`**
|
||
Gets/sets the associated project reference number.
|
||
- **`string CustomerOrderNumber { get; set; }`**
|
||
Gets/sets the customer order number.
|
||
- **`string CustomerCostUnit { get; set; }`**
|
||
Gets/sets the cost center or unit.
|
||
- **`bool LocalOnly { get; }`**
|
||
Gets the `LocalOnly` flag from the underlying ISO object.
|
||
- **`DateTime LastModified { get; }`**
|
||
Gets the last modification timestamp.
|
||
- **`string LastModifiedBy { get; }`**
|
||
Gets the user who last modified the record.
|
||
- **`int Version { get; }`**
|
||
Gets the version number of the record.
|
||
- **`bool HasBlankName()`**
|
||
Returns `true` if `Name` equals `StringResources.TestTemplate_EmptyListName`.
|
||
- **`CustomerDetails()`**
|
||
Default constructor: initializes `_customerDetails` with a new `DTS.Common.ISO.CustomerDetails`, sets `Name` to `TestTemplate_EmptyListName`, and `_blank = true`.
|
||
- **`CustomerDetails(DTS.Common.ISO.CustomerDetails customerDetails)`**
|
||
Wraps an existing ISO object; sets `_blank = false`.
|
||
- **`DTS.Common.ISO.CustomerDetails GetISOCustomer()`**
|
||
Returns the underlying ISO object.
|
||
- **`override string ToString()`**
|
||
Returns `Name`.
|
||
|
||
#### `CustomerDetailsList`
|
||
- **`static void Delete(CustomerDetails customer)`**
|
||
Calls `customer.GetISOCustomer().Delete(currentUser)`.
|
||
- **`static void Delete(CustomerDetails[] customers)`**
|
||
Deletes each customer in the array.
|
||
- **`static CustomerDetails[] GetAllCustomers()`**
|
||
Fetches all ISO customers via `DTS.Common.ISO.CustomerDetails.GetAllCustomerDetails()`, wraps each in `CustomerDetails`, sorts by `Name` (ordinal), and returns as array.
|
||
- **`static void DeleteAll()`**
|
||
Calls `DTS.Common.ISO.CustomerDetails.DeleteCustomerDetails()`.
|
||
- **`static CustomerDetails GetCustomerDetail(string name)`**
|
||
Returns a wrapped `CustomerDetails` for the given `name`, or `null` if not found or `name` is null/empty.
|
||
|
||
#### `LabratoryDetails` (inherits `BasePropertyChanged`)
|
||
- **`bool IsBlank()`**
|
||
Returns `_isBlank`, initialized `true`, set to `false` on first property mutation.
|
||
- **`string Name { get; set; }`**
|
||
Display name; triggers `_isBlank = false` and `OnPropertyChanged("Name")`.
|
||
- **`string LabratoryName { get; set; }`**
|
||
Laboratory name.
|
||
- **`string LabratoryContactName { get; set; }`**
|
||
Contact person name.
|
||
- **`string LabratoryContactPhone { get; set; }`**
|
||
Contact phone number.
|
||
- **`string LabratoryContactFax { get; set; }`**
|
||
Contact fax number.
|
||
- **`string LabratoryContactEmail { get; set; }`**
|
||
Contact email address.
|
||
- **`string LabratoryTestRefNumber { get; set; }`**
|
||
Laboratory test reference number.
|
||
- **`string LabratoryProjectRefNumber { get; set; }`**
|
||
Laboratory project reference number.
|
||
- **`bool LocalOnly { get; }`**
|
||
Gets `LocalOnly` from underlying ISO object.
|
||
- **`DateTime LastModified { get; }`**
|
||
Gets last modification timestamp.
|
||
- **`string LastModifiedBy { get; }`**
|
||
Gets last modifier username.
|
||
- **`int Version { get; }`**
|
||
Gets record version.
|
||
- **`bool HasBlankName()`**
|
||
Returns `true` if `Name == StringResources.TestTemplate_EmptyListName`.
|
||
- **`LabratoryDetails()`**
|
||
Default constructor: initializes `_lab` with new `DTS.Common.ISO.LabratoryDetails`, sets `Name` to `TestTemplate_EmptyListName`, `_isBlank = true`.
|
||
- **`LabratoryDetails(DTS.Common.ISO.LabratoryDetails lab)`**
|
||
Wraps an existing ISO object; sets `_isBlank = false`.
|
||
- **`DTS.Common.ISO.LabratoryDetails GetIsoLab()`**
|
||
Returns the underlying ISO object.
|
||
- **`override string ToString()`**
|
||
Returns `Name`.
|
||
|
||
#### `LabratoryDetailsList`
|
||
- **`static LabratoryDetails[] GetAllLabs()`**
|
||
Fetches all ISO labs via `DTS.Common.ISO.LabratoryDetails.GetAllLabratoryDetails()`, wraps each, sorts by `Name`, returns array.
|
||
- **`static void DeleteAll()`**
|
||
Calls `DTS.Common.ISO.LabratoryDetails.DeleteLabratoryDetails()`.
|
||
- **`static void Delete(LabratoryDetails lab)`**
|
||
Calls `lab?.GetIsoLab().Delete(currentUser)`.
|
||
- **`static void Delete(LabratoryDetails[] labs)`**
|
||
Deletes each lab in the array.
|
||
- **`static LabratoryDetails GetLab(string name)`**
|
||
Returns a wrapped `LabratoryDetails` for the given `name`, or `null` if not found or `name` is null/empty.
|
||
|
||
#### `TestEngineerDetails` (inherits `BasePropertyChanged`)
|
||
- **`bool IsBlank()`**
|
||
Returns `_blank`, initialized `true`, set to `false` on first mutation.
|
||
- **`string Name { get; set; }`**
|
||
Display name; triggers `_blank = false` and `OnPropertyChanged("Name")`.
|
||
- **`string TestEngineerName { get; set; }`**
|
||
Full test engineer name.
|
||
- **`string TestEngineerPhone { get; set; }`**
|
||
Phone number.
|
||
- **`string TestEngineerFax { get; set; }`**
|
||
Fax number.
|
||
- **`string TestEngineerEmail { get; set; }`**
|
||
Email address.
|
||
- **`bool LocalOnly { get; }`**
|
||
Gets `LocalOnly` from underlying ISO object.
|
||
- **`DateTime LastModified { get; }`**
|
||
Gets last modification timestamp.
|
||
- **`string LastModifiedBy { get; }`**
|
||
Gets last modifier username.
|
||
- **`int Version { get; }`**
|
||
Gets record version.
|
||
- **`bool HasBlankName()`**
|
||
Returns `true` if `Name == StringResources.TestTemplate_EmptyListName`.
|
||
- **`TestEngineerDetails()`**
|
||
Default constructor: initializes `_testEngineerDetails` with new `DTS.Common.ISO.TestEngineerDetails`, sets `Name` to `TestTemplate_EmptyListName`, `_blank = true`.
|
||
- **`TestEngineerDetails(DTS.Common.ISO.TestEngineerDetails testEngineerDetails)`**
|
||
Wraps an existing ISO object; sets `_blank = false`.
|
||
- **`DTS.Common.ISO.TestEngineerDetails GetISOTestEngineer()`**
|
||
Returns the underlying ISO object.
|
||
- **`override string ToString()`**
|
||
Returns `Name`.
|
||
|
||
#### `TestEngineerDetailsList` (inherits `BasePropertyChanged`)
|
||
- **`static TestEngineerDetailsList TestEngineerList { get; }`**
|
||
Singleton instance of `TestEngineerDetailsList`.
|
||
- **`void Delete(TestEngineerDetails testEngineer)`**
|
||
Deletes from ISO store, removes from internal `_testEngineers` dictionary, and raises `OnPropertyChanged("TestEngineers")`.
|
||
- **`void Delete(TestEngineerDetails[] testEngineers)`**
|
||
Deletes each engineer in the array.
|
||
- **`TestEngineerDetails[] TestEngineers { get; }`**
|
||
Returns all engineers sorted by `Name`. Lazily populates from `GetAllTestEngineers()` if `_testEngineers` is null/empty (thread-safe via lock).
|
||
- **`void ReloadAll()`**
|
||
Clears `_testEngineers` and repopulates from `GetAllTestEngineers()`.
|
||
- **`void DeleteAll()`**
|
||
Clears `_testEngineers`, calls `DTS.Common.ISO.TestEngineerDetails.DeleteAllTestEngineerDetails()`.
|
||
- **`TestEngineerDetails GetTestEngineerDetail(string name)`**
|
||
Returns engineer by `Name` from in-memory cache (`TestEngineers`), or `null` if not found or `name` is null/whitespace.
|
||
- **`void AddTestEngineer(TestEngineerDetails testEngineer)`**
|
||
Commits to ISO store, adds/updates in `_testEngineers` dictionary, and raises `OnPropertyChanged("TestEngineers")`.
|
||
- **`static TestEngineerDetails[] GetAllTestEngineers()`**
|
||
Returns all engineers. **Special behavior**: if `RunTestVariables.InRunTest` is `true` and `TestTemplateList.TestTemplatesList.CachedTestEngineerDetails` is populated, returns cached data (converted to ISO objects and wrapped); otherwise fetches from `DTS.Common.ISO.TestEngineerDetails.GetAllTestEngineerDetails()`.
|
||
|
||
---
|
||
|
||
### 3. Invariants
|
||
|
||
- **`_blank` / `_isBlank` state**:
|
||
- For `CustomerDetails` and `TestEngineerDetails`, `_blank` starts `true` and is set to `false` on first property setter invocation.
|
||
- For `LabratoryDetails`, `_isBlank` behaves identically.
|
||
- `IsBlank()` returns this state, but it is *not* reset by any operation (e.g., `DeleteAll()` does not reset it).
|
||
- **`Name` field semantics**:
|
||
- Default constructor sets `Name` to `StringResources.TestTemplate_EmptyListName`.
|
||
- `HasBlankName()` checks for this exact string.
|
||
- `Name` is used as the primary key for lookup (`GetCustomerDetail`, `GetLab`, `GetTestEngineerDetail`, `CompareCustomers`, etc.).
|
||
- **Sorting**:
|
||
- `GetAllCustomers()`, `GetAllLabs()`, and `TestEngineers` getter sort by `Name` using `string.Compare(..., StringComparison.Ordinal)`.
|
||
- **Persistence layer**:
|
||
- All mutations (`set` on properties, `Add*`, `Delete*`) ultimately call methods on `DTS.Common.ISO.*` types (e.g., `Commit`, `Delete`).
|
||
- `Commit` and `Delete` are called with `ApplicationProperties.CurrentUser.UserName`.
|
||
- **Caching for run-test mode**:
|
||
- `TestEngineerDetailsList.GetAllTestEngineers()` uses cached data *only* when `RunTestVariables.InRunTest` is `true` *and* `CachedTestEngineerDetails` is non-null/non-empty.
|
||
- This cache is *not* used by `CustomerDetailsList` or `LabratoryDetailsList`.
|
||
|
||
---
|
||
|
||
### 4. Dependencies
|
||
|
||
#### Internal Dependencies (from source)
|
||
- **`DTS.Common.ISO.*`**
|
||
Core data models: `CustomerDetails`, `LabratoryDetails`, `TestEngineerDetails` (ISO layer).
|
||
- **`DTS.Common.Base.BasePropertyChanged`**
|
||
Base class for `INotifyPropertyChanged` implementation.
|
||
- **`DTS.Common.SharedResource.Strings.StringResources`**
|
||
Used for `TestTemplate_EmptyListName`.
|
||
- **`DTS.Common.Storage.ApplicationProperties`**
|
||
Used to get `CurrentUser.UserName`.
|
||
- **`DTS.Common.Enums.RunTestVariables`**
|
||
Used in `TestEngineerDetailsList.GetAllTestEngineers()` to check `InRunTest`.
|
||
- **`DTS.Common.DataModel.TestTemplateList.TestTemplatesList`**
|
||
Used in `TestEngineerDetailsList.GetAllTestEngineers()` to access `CachedTestEngineerDetails`.
|
||
|
||
#### External Dependencies (inferred)
|
||
- **WPF (`System.Windows`)**
|
||
Used for `ApplicationProperties.CurrentUser` (likely tied to WPF app context).
|
||
- **.NET Core/Standard runtime**
|
||
Standard libraries (`System`, `System.Collections.Generic`, `System.Linq`).
|
||
|
||
#### What depends on this module?
|
||
- UI layers (WPF) binding to `CustomerDetails`, `LabratoryDetails`, `TestEngineerDetails` properties.
|
||
- Any code managing test metadata (e.g., test setup, reporting) via `*DetailsList` static methods.
|
||
- `TestTemplateList.TestTemplatesList` (indirectly via caching dependency).
|
||
|
||
---
|
||
|
||
### 5. Gotchas
|
||
|
||
- **Inconsistent naming**:
|
||
- Class is named `LabratoryDetails` (misspelled "Laboratory") in all files. This is preserved in ISO layer and must be used as-is.
|
||
- **`IsBlank()` behavior is one-way**:
|
||
- Once set to `false`, `_blank`/`_isBlank` is never reset (e.g., by `Delete`, `Clear`, or `ReloadAll`). A deleted record may still report `IsBlank() == false`.
|
||
- **`TestEngineerDetailsList` is a singleton with mutable state**:
|
||
- `_testEngineerList` is static; `TestEngineerList` returns the same instance.
|
||
- `TestEngineers` property caches data in `_testEngineers` dictionary, which is lazily populated and cleared only by `DeleteAll()` or `ReloadAll()`.
|
||
- Concurrent access is partially protected by `lock (_testEngineerLock)` in `TestEngineers` getter and `AddTestEngineer`, but `GetTestEngineerDetail` uses `AsParallel()` on `TestEngineers` without locking—potential race condition if `TestEngineers` is being repopulated.
|
||
- **`GetAllTestEngineers()` has conditional caching logic**:
|
||
- Behavior changes based on `RunTestVariables.InRunTest` and `CachedTestEngineerDetails`. This is not obvious from the class alone and may cause inconsistent data if caching is stale or misconfigured.
|
||
- **`CustomerDetailsList` and `LabratoryDetailsList` lack instance methods**:
|
||
- All operations are `static`. Only `TestEngineerDetailsList` provides instance methods (e.g., `AddTestEngineer`, `Delete(TestEngineerDetails)`), suggesting inconsistent design or incomplete refactoring.
|
||
- **No validation on property setters**:
|
||
- Setting `Name` to `null` or empty is allowed (though `HasBlankName()` checks only for `TestTemplate_EmptyListName`).
|
||
- `GetCustomerDetail`, `GetLab`, `GetTestEngineerDetail` return `null` for `null`/empty/whitespace input, but no validation prevents setting such values on `Name`.
|
||
- **`ToString()` returns `Name`**:
|
||
- If `Name` is `null`, this may cause `NullReferenceException` in UI bindings or `string.Format` calls.
|
||
|
||
None identified beyond the above for `CustomerDetails` and `LabratoryDetails`. |