added new view in contracts customer and contracts
This commit is contained in:
@@ -5,7 +5,16 @@ import { ApiResponse, AuthRequest } from '../types/index.js';
|
||||
|
||||
export async function getContracts(req: AuthRequest, res: Response): Promise<void> {
|
||||
try {
|
||||
const { customerId, type, status, search, page, limit } = req.query;
|
||||
const { customerId, type, status, search, page, limit, tree } = req.query;
|
||||
|
||||
// Baumstruktur für Kundenansicht
|
||||
if (tree === 'true' && customerId) {
|
||||
const treeData = await contractService.getContractTreeForCustomer(
|
||||
parseInt(customerId as string)
|
||||
);
|
||||
res.json({ success: true, data: treeData } as ApiResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
// Für Kundenportal-Benutzer: nur eigene + vertretene Kunden-Verträge anzeigen
|
||||
let customerIds: number[] | undefined;
|
||||
|
||||
@@ -77,7 +77,7 @@ export async function getAllContracts(filters: ContractFilters) {
|
||||
where,
|
||||
skip,
|
||||
take,
|
||||
orderBy: [{ startDate: 'desc' }, { createdAt: 'desc' }],
|
||||
orderBy: [{ createdAt: 'desc' }],
|
||||
include: {
|
||||
customer: {
|
||||
select: {
|
||||
@@ -778,3 +778,96 @@ export async function getSipCredentials(phoneNumberId: number): Promise<{ passwo
|
||||
return { password: null };
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== VERTRAGSBAUM FÜR KUNDENANSICHT ====================
|
||||
|
||||
export interface ContractTreeNode {
|
||||
contract: {
|
||||
id: number;
|
||||
contractNumber: string;
|
||||
type: ContractType;
|
||||
status: ContractStatus;
|
||||
startDate: Date | null;
|
||||
endDate: Date | null;
|
||||
providerName: string | null;
|
||||
tariffName: string | null;
|
||||
previousContractId: number | null;
|
||||
provider?: { id: number; name: string } | null;
|
||||
tariff?: { id: number; name: string } | null;
|
||||
contractCategory?: { id: number; name: string } | null;
|
||||
};
|
||||
predecessors: ContractTreeNode[];
|
||||
hasHistory: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verträge eines Kunden als Baumstruktur abrufen.
|
||||
* Wurzelknoten = Verträge ohne Nachfolger (aktuellste Verträge)
|
||||
* Vorgänger werden rekursiv eingebettet.
|
||||
*/
|
||||
export async function getContractTreeForCustomer(customerId: number): Promise<ContractTreeNode[]> {
|
||||
// Alle Verträge des Kunden laden (außer DEACTIVATED)
|
||||
const allContracts = await prisma.contract.findMany({
|
||||
where: {
|
||||
customerId,
|
||||
status: { not: ContractStatus.DEACTIVATED },
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
contractNumber: true,
|
||||
type: true,
|
||||
status: true,
|
||||
startDate: true,
|
||||
endDate: true,
|
||||
providerName: true,
|
||||
tariffName: true,
|
||||
previousContractId: true,
|
||||
provider: { select: { id: true, name: true } },
|
||||
tariff: { select: { id: true, name: true } },
|
||||
contractCategory: { select: { id: true, name: true } },
|
||||
},
|
||||
orderBy: [{ startDate: 'desc' }, { createdAt: 'desc' }],
|
||||
});
|
||||
|
||||
// Map für schnellen Zugriff: contractId -> contract
|
||||
const contractMap = new Map(allContracts.map(c => [c.id, c]));
|
||||
|
||||
// Set der IDs die als Vorgänger referenziert werden
|
||||
const predecessorIds = new Set(
|
||||
allContracts
|
||||
.filter(c => c.previousContractId !== null)
|
||||
.map(c => c.previousContractId!)
|
||||
);
|
||||
|
||||
// Wurzelverträge = Verträge die keinen Nachfolger haben
|
||||
// (werden von keinem anderen Vertrag als previousContractId referenziert)
|
||||
const rootContracts = allContracts.filter(c => !predecessorIds.has(c.id));
|
||||
|
||||
// Rekursive Funktion um Vorgängerkette aufzubauen
|
||||
function buildPredecessorChain(contractId: number | null): ContractTreeNode[] {
|
||||
if (contractId === null) return [];
|
||||
|
||||
const contract = contractMap.get(contractId);
|
||||
if (!contract) return [];
|
||||
|
||||
const predecessors = buildPredecessorChain(contract.previousContractId);
|
||||
|
||||
return [{
|
||||
contract,
|
||||
predecessors,
|
||||
hasHistory: predecessors.length > 0,
|
||||
}];
|
||||
}
|
||||
|
||||
// Baumstruktur für jeden Wurzelvertrag aufbauen
|
||||
const tree: ContractTreeNode[] = rootContracts.map(contract => {
|
||||
const predecessors = buildPredecessorChain(contract.previousContractId);
|
||||
return {
|
||||
contract,
|
||||
predecessors,
|
||||
hasHistory: predecessors.length > 0,
|
||||
};
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user