feat: Gemini AI (doc OCR + face match) + role-assignment endpoints

- GeminiService (integrations/gemini, @Global): extractDocument (OCR fields) + faceMatch; graceful if no GEMINI_API_KEY
- documents: face-match now real via Gemini; POST /admin/documents/:id/ocr extracts fields for CS auto-fill
- roles: PATCH /admin/users/:id/role (admin) + POST /platform/users/role (bootstrap via x-platform-secret)
- config: gemini + platform.secret; .env.example entries

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 20:01:26 +03:00
co-authored by Claude Opus 4.8
parent 04200db438
commit 6234e66471
1541 changed files with 267713 additions and 16 deletions
@@ -0,0 +1,21 @@
class MonthlyDataModel {
final int year;
final int month;
final int day;
final int ridesCount;
MonthlyDataModel({
required this.year,
required this.month,
required this.day,
required this.ridesCount,
});
factory MonthlyDataModel.fromJson(Map<String, dynamic> json) =>
MonthlyDataModel(
year: json['year'] as int,
month: json['month'] as int,
day: json['day'] as int,
ridesCount: json['rides_count'] as int,
);
}
@@ -0,0 +1,79 @@
class Passenger {
String id;
String phone;
String email;
String gender;
String status;
String birthdate;
String site;
String firstName;
String lastName;
String sosPhone;
String education;
String employmentType;
String maritalStatus;
String createdAt;
String updatedAt;
int countPassenger;
int countFeedback;
double ratingPassenger;
int countDriverRate;
int countPassengerCancel;
double passengerAverageRating;
int countPassengerRate;
int countPassengerRide;
Passenger({
required this.id,
required this.phone,
required this.email,
required this.gender,
required this.status,
required this.birthdate,
required this.site,
required this.firstName,
required this.lastName,
required this.sosPhone,
required this.education,
required this.employmentType,
required this.maritalStatus,
required this.createdAt,
required this.updatedAt,
required this.countPassenger,
required this.countFeedback,
required this.ratingPassenger,
required this.countDriverRate,
required this.countPassengerCancel,
required this.passengerAverageRating,
required this.countPassengerRate,
required this.countPassengerRide,
});
factory Passenger.fromJson(Map<String, dynamic> json) {
return Passenger(
id: json['id'],
phone: json['phone'],
email: json['email'],
gender: json['gender'],
status: json['status'],
birthdate: json['birthdate'],
site: json['site'],
firstName: json['first_name'],
lastName: json['last_name'],
sosPhone: json['sosPhone'],
education: json['education'],
employmentType: json['employmentType'],
maritalStatus: json['maritalStatus'],
createdAt: json['created_at'],
updatedAt: json['updated_at'],
countPassenger: json['countPassenger'],
countFeedback: json['countFeedback'],
ratingPassenger: json['ratingPassenger'].toDouble(),
countDriverRate: json['countDriverRate'],
countPassengerCancel: json['countPassengerCancel'],
passengerAverageRating: json['passengerAverageRating'].toDouble(),
countPassengerRate: json['countPassengerRate'],
countPassengerRide: json['countPassengerRide'],
);
}
}