mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Merge pull request #1128 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
This commit is contained in:
@@ -59,26 +59,57 @@ export class CargoTypesRepository implements ICargoTypesRepository {
|
||||
}
|
||||
|
||||
async create(data: Partial<CargoType>): Promise<CargoType> {
|
||||
const entity = this.repo.create(data);
|
||||
return this.repo.save(entity);
|
||||
const { wagonTypes, ...columns } = data;
|
||||
const entity = this.repo.create(columns);
|
||||
const saved = await this.repo.save(entity);
|
||||
if (wagonTypes?.length) {
|
||||
await this.syncWagonTypes(saved.id, wagonTypes.map((wt) => wt.id), []);
|
||||
}
|
||||
return (await this.findById(saved.id)) ?? saved;
|
||||
}
|
||||
|
||||
async update(id: string, data: Partial<CargoType>): Promise<CargoType | null> {
|
||||
// Relation lists can't ride a column UPDATE — sync them via entity save.
|
||||
const { wagonTypes, ...columns } = data;
|
||||
if (Object.keys(columns).length) {
|
||||
await this.repo.update(id, columns as never);
|
||||
}
|
||||
if (wagonTypes) {
|
||||
const entity = await this.repo.findOne({ where: { id } });
|
||||
if (entity) {
|
||||
entity.wagonTypes = wagonTypes;
|
||||
await this.repo.save(entity);
|
||||
const current = await this.repo.findOne({
|
||||
where: { id },
|
||||
relations: { wagonTypes: true },
|
||||
});
|
||||
if (current) {
|
||||
await this.syncWagonTypes(
|
||||
id,
|
||||
wagonTypes.map((wt) => wt.id),
|
||||
(current.wagonTypes ?? []).map((wt) => wt.id),
|
||||
);
|
||||
}
|
||||
}
|
||||
return this.findById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Diffs the wagon-type links through the relation query builder rather than
|
||||
* an entity save: junction-row inserts from save() broadcast afterInsert with
|
||||
* no entity attached, which the @tria-plc/auditlog subscriber (deployed
|
||||
* builds) dereferences and crashes the request on.
|
||||
*/
|
||||
private async syncWagonTypes(
|
||||
id: string,
|
||||
nextIds: string[],
|
||||
currentIds: string[],
|
||||
): Promise<void> {
|
||||
const toAdd = nextIds.filter((x) => !currentIds.includes(x));
|
||||
const toRemove = currentIds.filter((x) => !nextIds.includes(x));
|
||||
if (!toAdd.length && !toRemove.length) return;
|
||||
await this.repo
|
||||
.createQueryBuilder()
|
||||
.relation(CargoType, 'wagonTypes')
|
||||
.of(id)
|
||||
.addAndRemove(toAdd, toRemove);
|
||||
}
|
||||
|
||||
async softDelete(id: string): Promise<void> {
|
||||
await this.repo.softDelete(id);
|
||||
}
|
||||
|
||||
@@ -126,6 +126,15 @@ const FleetRecordActions = ({
|
||||
{removeLabel}
|
||||
</MenuItem>
|
||||
) : null}
|
||||
{onPurge ? (
|
||||
<MenuItem
|
||||
color="red"
|
||||
onClick={() => onPurge(record)}
|
||||
leftSection={<ShieldAlert size={14} strokeWidth={2} />}
|
||||
>
|
||||
Delete permanently
|
||||
</MenuItem>
|
||||
) : null}
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
@@ -191,13 +191,12 @@ export class CbeBillService {
|
||||
return mapPaymentFailure(dto, "Payment is being processed.");
|
||||
}
|
||||
if (prior.failureClass === "BUSINESS") {
|
||||
// Final — retrying cannot change the answer. Replay what we told CBE last time.
|
||||
return (
|
||||
(prior.responsePayload as unknown as CbePaymentResponseDto) ??
|
||||
mapPaymentFailure(
|
||||
dto,
|
||||
prior.responseDescription ?? "Payment already failed.",
|
||||
)
|
||||
// Final — retrying cannot change the answer. Same End_To_End_Txn_Id was already
|
||||
// resolved (possibly against a different Bill_Id/amount); say so instead of
|
||||
// echoing the original reason, which no longer describes this request.
|
||||
return mapPaymentFailure(
|
||||
dto,
|
||||
`End_To_End_Txn_Id ${dto.End_To_End_Txn_Id} was already processed and failed: ${prior.responseDescription ?? "unknown reason"}.`,
|
||||
);
|
||||
}
|
||||
// FAILED + TRANSIENT: allowed retry — fall through and re-run the settlement.
|
||||
|
||||
Reference in New Issue
Block a user