177 lines
5.4 KiB
TypeScript
177 lines
5.4 KiB
TypeScript
import { Injectable, inject } from '@angular/core';
|
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
|
import { environment } from '@environments/environment';
|
|
import { Observable, map, catchError, throwError } from 'rxjs';
|
|
|
|
import {
|
|
Transaction,
|
|
TransactionQuery,
|
|
PaginatedTransactions,
|
|
TransactionStats,
|
|
RefundRequest
|
|
} from '../models/transaction';
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class TransactionsService {
|
|
private http = inject(HttpClient);
|
|
private apiUrl = `${environment.localServiceTestApiUrl}/transactions`;
|
|
|
|
// === CRUD OPERATIONS ===
|
|
getTransactions(query: TransactionQuery): Observable<PaginatedTransactions> {
|
|
let params = new HttpParams();
|
|
|
|
// Ajouter tous les paramètres de query
|
|
Object.keys(query).forEach(key => {
|
|
const value = query[key as keyof TransactionQuery];
|
|
if (value !== undefined && value !== null) {
|
|
if (value instanceof Date) {
|
|
params = params.set(key, value.toISOString());
|
|
} else {
|
|
params = params.set(key, value.toString());
|
|
}
|
|
}
|
|
});
|
|
|
|
return this.http.get<PaginatedTransactions>(`${this.apiUrl}`, { params }).pipe(
|
|
catchError(error => {
|
|
console.error('Error loading transactions:', error);
|
|
return throwError(() => error);
|
|
})
|
|
);
|
|
}
|
|
|
|
getTransactionById(id: string): Observable<Transaction> {
|
|
return this.http.get<Transaction>(`${this.apiUrl}/${id}`).pipe(
|
|
catchError(error => {
|
|
console.error('Error loading transaction:', error);
|
|
return throwError(() => error);
|
|
})
|
|
);
|
|
}
|
|
|
|
// === ACTIONS ===
|
|
refundTransaction(refundRequest: RefundRequest): Observable<{ message: string; transaction: Transaction }> {
|
|
return this.http.post<{ message: string; transaction: Transaction }>(
|
|
`${this.apiUrl}/${refundRequest.transactionId}/refund`,
|
|
refundRequest
|
|
);
|
|
}
|
|
|
|
cancelTransaction(transactionId: string): Observable<{ message: string }> {
|
|
return this.http.post<{ message: string }>(
|
|
`${this.apiUrl}/${transactionId}/cancel`,
|
|
{}
|
|
);
|
|
}
|
|
|
|
retryTransaction(transactionId: string): Observable<{ message: string; transaction: Transaction }> {
|
|
return this.http.post<{ message: string; transaction: Transaction }>(
|
|
`${this.apiUrl}/${transactionId}/retry`,
|
|
{}
|
|
);
|
|
}
|
|
|
|
// === STATISTIQUES ===
|
|
getTransactionStats(query?: Partial<TransactionQuery>): Observable<TransactionStats> {
|
|
let params = new HttpParams();
|
|
|
|
if (query) {
|
|
Object.keys(query).forEach(key => {
|
|
const value = query[key as keyof TransactionQuery];
|
|
if (value !== undefined && value !== null) {
|
|
if (value instanceof Date) {
|
|
params = params.set(key, value.toISOString());
|
|
} else {
|
|
params = params.set(key, value.toString());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
return this.http.get<TransactionStats>(`${this.apiUrl}/stats`, { params });
|
|
}
|
|
|
|
// === EXPORT ===
|
|
exportTransactions(exportRequest: any): Observable<{ url: string; filename: string }> {
|
|
return this.http.post<{ url: string; filename: string }>(
|
|
`${this.apiUrl}/export`,
|
|
exportRequest
|
|
);
|
|
}
|
|
|
|
// === MOCK DATA POUR LE DÉVELOPPEMENT ===
|
|
getMockTransactions(): Transaction[] {
|
|
return [
|
|
{
|
|
id: 'tx_001',
|
|
msisdn: '+33612345678',
|
|
operator: 'Orange',
|
|
operatorId: 'orange_fr',
|
|
country: 'FR',
|
|
amount: 4.99,
|
|
currency: 'EUR',
|
|
status: 'SUCCESS',
|
|
productId: 'prod_premium',
|
|
productName: 'Contenu Premium',
|
|
productCategory: 'ENTERTAINMENT',
|
|
transactionDate: new Date('2024-01-15T14:30:00'),
|
|
createdAt: new Date('2024-01-15T14:30:00'),
|
|
updatedAt: new Date('2024-01-15T14:30:00'),
|
|
externalId: 'ext_123456',
|
|
merchantName: 'MediaCorp'
|
|
},
|
|
{
|
|
id: 'tx_002',
|
|
msisdn: '+33798765432',
|
|
operator: 'Free',
|
|
operatorId: 'free_fr',
|
|
country: 'FR',
|
|
amount: 2.99,
|
|
currency: 'EUR',
|
|
status: 'PENDING',
|
|
productId: 'prod_basic',
|
|
productName: 'Abonnement Basique',
|
|
productCategory: 'SUBSCRIPTION',
|
|
transactionDate: new Date('2024-01-15T14:25:00'),
|
|
createdAt: new Date('2024-01-15T14:25:00'),
|
|
updatedAt: new Date('2024-01-15T14:25:00'),
|
|
externalId: 'ext_123457'
|
|
},
|
|
{
|
|
id: 'tx_003',
|
|
msisdn: '+33687654321',
|
|
operator: 'SFR',
|
|
operatorId: 'sfr_fr',
|
|
country: 'FR',
|
|
amount: 9.99,
|
|
currency: 'EUR',
|
|
status: 'FAILED',
|
|
productId: 'prod_pro',
|
|
productName: 'Pack Professionnel',
|
|
productCategory: 'BUSINESS',
|
|
transactionDate: new Date('2024-01-15T14:20:00'),
|
|
createdAt: new Date('2024-01-15T14:20:00'),
|
|
updatedAt: new Date('2024-01-15T14:20:00'),
|
|
errorCode: 'INSUFFICIENT_FUNDS',
|
|
errorMessage: 'Solde insuffisant'
|
|
},
|
|
{
|
|
id: 'tx_004',
|
|
msisdn: '+33611223344',
|
|
operator: 'Bouygues',
|
|
operatorId: 'bouygues_fr',
|
|
country: 'FR',
|
|
amount: 1.99,
|
|
currency: 'EUR',
|
|
status: 'REFUNDED',
|
|
productId: 'prod_mini',
|
|
productName: 'Pack Découverte',
|
|
productCategory: 'GAMING',
|
|
transactionDate: new Date('2024-01-15T14:15:00'),
|
|
createdAt: new Date('2024-01-15T14:15:00'),
|
|
updatedAt: new Date('2024-01-15T16:30:00'),
|
|
merchantName: 'GameStudio'
|
|
}
|
|
];
|
|
}
|
|
} |