mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 01:18:18 +00:00
enhance contract document rendering with detailed cargo information
- Updated ContractDocumentViewModelBuilder to include cargoTypeName, containerType, and cargoSummary in the schedule. - Modified contract dynamic template tests to validate the new cargo fields. - Enhanced contract renderer service tests to reflect changes in cargo data structure. - Updated contract view model interface to include new cargo-related fields. - Improved dynamic template rendering to display cargo type and container type. - Refactored exchange settings controller and service to streamline error handling and feed status management. - Introduced article HTML conversion functions to support Quill editor integration for structured article editing. - Added tests for article HTML conversion to ensure correct round-trip processing of clauses and bullets.
This commit is contained in:
@@ -10,6 +10,18 @@ import { ExchangeSetting } from "./entities/exchange-setting.entity";
|
||||
*/
|
||||
const SEED_FALLBACK_RATE = 162.4165;
|
||||
|
||||
/** Health of the CBE feed, as surfaced to the backoffice. */
|
||||
export interface ExchangeFeedStatus {
|
||||
/** Rate most recently observed, whatever its source. */
|
||||
rate: number | null;
|
||||
/** `live` means CBE answered; `stored`/`default` mean it is failing. */
|
||||
source: "live" | "stored" | null;
|
||||
/** ISO timestamp of the last successful fetch. */
|
||||
lastSuccessAt: string | null;
|
||||
/** Message from the most recent failure, cleared on success. */
|
||||
lastError: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owns the single `exchange_settings` row: the USD→ETB fallback used when the
|
||||
* CBE endpoint is unreachable.
|
||||
@@ -22,11 +34,30 @@ const SEED_FALLBACK_RATE = 162.4165;
|
||||
export class ExchangeSettingsService {
|
||||
private readonly logger = new Logger(ExchangeSettingsService.name);
|
||||
|
||||
/**
|
||||
* Feed health, recorded from the exchange provider's callbacks rather than
|
||||
* read off an injected `ExchangeService`. The provider is registered several
|
||||
* times (bookings, contracts, warehouses), so no single instance sees every
|
||||
* fetch — and injecting one here would be circular, since those
|
||||
* registrations inject *this* service.
|
||||
*/
|
||||
private feed: ExchangeFeedStatus = {
|
||||
rate: null,
|
||||
source: null,
|
||||
lastSuccessAt: null,
|
||||
lastError: null,
|
||||
};
|
||||
|
||||
constructor(
|
||||
@InjectRepository(ExchangeSetting)
|
||||
private readonly repository: Repository<ExchangeSetting>,
|
||||
) {}
|
||||
|
||||
/** Health of the CBE feed as last observed by any provider instance. */
|
||||
getFeedStatus(): ExchangeFeedStatus {
|
||||
return { ...this.feed };
|
||||
}
|
||||
|
||||
/** The settings row, created at the seed rate on first access. */
|
||||
async get(): Promise<ExchangeSetting> {
|
||||
const existing = await this.repository.findOne({ where: {} });
|
||||
@@ -47,15 +78,22 @@ export class ExchangeSettingsService {
|
||||
* than propagating a database error into a pricing call.
|
||||
*/
|
||||
async loadFallbackRate(): Promise<number | null> {
|
||||
// Only reached when the live fetch failed, so this call is itself the
|
||||
// signal that the feed is down.
|
||||
try {
|
||||
const { fallbackRate } = await this.get();
|
||||
return Number.isFinite(fallbackRate) && fallbackRate > 0
|
||||
? fallbackRate
|
||||
: null;
|
||||
const usable = Number.isFinite(fallbackRate) && fallbackRate > 0;
|
||||
this.feed = {
|
||||
...this.feed,
|
||||
rate: usable ? fallbackRate : this.feed.rate,
|
||||
source: "stored",
|
||||
lastError: this.feed.lastError ?? "CBE endpoint unreachable",
|
||||
};
|
||||
return usable ? fallbackRate : null;
|
||||
} catch (err) {
|
||||
this.logger.warn(
|
||||
`Could not read stored exchange fallback: ${(err as Error).message}`,
|
||||
);
|
||||
const message = (err as Error).message;
|
||||
this.feed = { ...this.feed, source: "stored", lastError: message };
|
||||
this.logger.warn(`Could not read stored exchange fallback: ${message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -66,6 +104,14 @@ export class ExchangeSettingsService {
|
||||
* down, so a working CBE feed takes precedence again.
|
||||
*/
|
||||
async saveFallbackRate(rate: number): Promise<void> {
|
||||
// Only called after a successful fetch, so the feed is confirmed healthy.
|
||||
this.feed = {
|
||||
rate,
|
||||
source: "live",
|
||||
lastSuccessAt: new Date().toISOString(),
|
||||
lastError: null,
|
||||
};
|
||||
|
||||
const current = await this.get();
|
||||
await this.repository.update(current.id, {
|
||||
fallbackRate: rate,
|
||||
|
||||
Reference in New Issue
Block a user