קיבלתם רכב עם שריטה בפגוש אבל לא מילאתם את דו"ח המסירה. להוכיח שהנזק לא שלכם הוא בלתי אפשרי. או שאימות הנהג אורך שבוע, ולקוחות עוזבים למתחרים. פתרנו משימות אלה עבור 20+ פרויקטים במשך שנים רבות של ניסיון. המהנדסים שלנו בנו ארכיטקטורה שמתרחבת לאלפי מכוניות. הכל מתחיל במודל הנתונים—הוא קובע כמה גמישה ואמינה תהיה הפלטפורמה. לפי J.D. Power, 60% מהמשתמשים נוטשים פלטפורמות ללא אימות, ובדיקה מקוונת מפחיתה מחלוקות נזק ב-40%. חיסכון בעלויות תפעול מגיע ל-30% באמצעות אוטומציה.
איך עובד מודל הנתונים להשכרת רכב?
כל רכב הוא יחידה ספציפית עם מספר שלדה (VIN), מספר רישוי, היסטוריית ביטוח ובדיקות. ההזמנה מקושרת לרכב אמיתי, לא למחלקה מופשטת. זה מבטל הזמנות כפולות. עבור נתונים גיאוגרפיים אנו משתמשים בPostGIS—הוא מהיר פי 100 לשאילתות מרחביות מאשר אינדקסים רגילים.
CREATE TABLE vehicles (
id BIGSERIAL PRIMARY KEY,
owner_id BIGINT NOT NULL REFERENCES users(id),
make VARCHAR(50) NOT NULL, -- Toyota
model VARCHAR(50) NOT NULL, -- Camry
year SMALLINT NOT NULL,
plate_number VARCHAR(20) UNIQUE NOT NULL,
vin VARCHAR(17) UNIQUE NOT NULL,
transmission VARCHAR(10) NOT NULL, -- auto, manual
fuel_type VARCHAR(15) NOT NULL, -- petrol, diesel, electric, hybrid
seats SMALLINT NOT NULL DEFAULT 5,
mileage_km INT NOT NULL DEFAULT 0,
location GEOGRAPHY(POINT, 4326),
insurance_expiry DATE NOT NULL,
inspection_expiry DATE NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'available'
);
CREATE TABLE rental_bookings (
id BIGSERIAL PRIMARY KEY,
vehicle_id BIGINT NOT NULL REFERENCES vehicles(id),
renter_id BIGINT NOT NULL REFERENCES users(id),
pickup_datetime TIMESTAMPTZ NOT NULL,
return_datetime TIMESTAMPTZ NOT NULL,
pickup_location GEOGRAPHY(POINT, 4326),
return_location GEOGRAPHY(POINT, 4326),
status VARCHAR(20) NOT NULL DEFAULT 'pending',
total_amount NUMERIC(10,2) NOT NULL,
security_deposit NUMERIC(10,2) NOT NULL,
fuel_policy VARCHAR(20) NOT NULL -- 'full_to_full', 'prepaid'
);סכימה זו מאפשרת בניית שאילתות מורכבות: מציאת כל הרכבים הפנויים ליד המשתמש, בדיקת חפיפות הזמנות, חישוב עלות עם עונתיות. אנו משתמשים בטרנזקציות ונעילות ברמת שורה כדי לבטל תנאי מרוץ במהלך ההזמנה.
למה אימות נהג הוא קריטי לפלטפורמה?
פלטפורמה ללא אימות נושאת באחריות משפטית למעשי השוכרים. אנו משלבים Stripe Identity או Jumio: בדיקת מסמך, סלפי, זיהוי תוקף רישיון. כל זה אורך 30 שניות ללא מעורבות מפעיל. זה מפחית הזמנות הונאה ב-60%.
- יזום — יצירת VerificationSession דרך Stripe API.
- אימות — המשתמש מעלה מסמך וסלפי.
- עיבוד — webhook מעדכן את סטטוס המשתמש.
- מוכן — הנהג יכול להזמין.
class DriverVerificationService {
public function initiateVerification(User $user): string {
// Stripe Identity
$session = $this->stripe->identity->verificationSessions->create([
'type' => 'document',
'options' => [
'document' => [
'allowed_types' => ['driving_license'],
'require_id_number' => true,
'require_live_capture' => true,
'require_matching_selfie' => true,
],
],
'metadata' => ['user_id' => $user->id],
]);
$user->update([
'stripe_verification_session_id' => $session->id,
'verification_status' => 'pending',
]);
return $session->url;
}
public function handleWebhook(array $payload): void {
$session = $payload['data']['object'];
$user = User::where(
'stripe_verification_session_id',
$session['id']
)->firstOrFail();
match ($session['status']) {
'verified' => $user->update([
'verification_status' => 'verified',
'verified_at' => now(),
'license_expiry' => $session['last_verification_report']['document']['expiration_date'] ?? null,
]),
'requires_input' => $user->update(['verification_status' => 'failed']),
default => null,
};
}
} איך עובד תמחור גמיש?
אנו תומכים בתעריפים שעתיים, יומיים ומשולבים. מקדם עונתי מוחל אוטומטית בהתאם למחלקת הרכב ולתאריך. להשכרות ארוכות טווח — הנחות עד 20%. המחשבון משווה מיידית את כל האפשרויות ומציג את המחיר הטוב ביותר. עלות השכרה ממוצעת מופחתת ב-15% באמצעות תמחור דינמי.
| משך | תעריף | הנחה |
|---|---|---|
| 1-6 שעות | שעתי | — |
| 1-6 ימים | יומי | — |
| 7-13 ימים | יומי | 10% |
| 14-29 ימים | יומי | 15% |
| 30+ ימים | יומי | 20% |
class PricingCalculator {
public function calculate( Vehicle $vehicle, Carbon $pickup, Carbon $return ): PricingResult {
$hours = $pickup->diffInHours($return);
$days = $pickup->diffInDays($return);
// Если меньше суток — считаем почасово
if ($hours <= 24 && $vehicle->hourly_rate) {
$base = $vehicle->hourly_rate * $hours;
} else {
// Посуточно + доплата за неполные сутки
$fullDays = floor($hours / 24);
$remainHours = $hours % 24;
$base = $vehicle->daily_rate * $fullDays;
if ($remainHours > 0) {
// Если остаток > половины суток — считать как сутки
$base += $remainHours > 12 ? $vehicle->daily_rate : $vehicle->hourly_rate * $remainHours;
}
}
// Сезонный коэффициент
$multiplier = $this->getSeasonMultiplier($pickup, $vehicle->vehicle_class);
// Скидка за длительную аренду
$discount = match(true) {
$days >= 30 => 0.20,
$days >= 14 => 0.15,
$days >= 7 => 0.10,
default => 0.0,
};
$subtotal = $base * $multiplier * (1 - $discount);
$deposit = $vehicle->deposit_amount;
$fee = $subtotal * $this->platformFeeRate;
return new PricingResult(
base: $base,
multiplier: $multiplier,
discount: $discount,
subtotal: $subtotal,
platform_fee: $fee,
security_deposit: $deposit,
total: $subtotal + $fee,
);
}
} איך מובטחת בדיקת תמונות?
לפני המסירה ואחרי ההחזרה, דו"ח דיגיטלי חובה: תרשים רכב עם קואורדינטות נזק, תמונות, קריאות מד מרחק, רמת דלק. חתימת שני הצדדים דרך canvas (signature_pad.js). הדו"ח נשמר ב-S3 והופך למסמך בעל משמעות משפטית.
דוגמה לשדה נזק מותאם אישית
```json { "title": "שריטה בפגוש", "coordinates": [55.7558, 37.6176], "photos": ["https://s3.example.com/act/123.jpg"] } ```למה מעקב GPS הוא חובה לציים?
לציים של 20+ רכבים, מעקב חי דרך MQTT — קואורדינטות כל 10 שניות. MQTT יעיל פי 10 מ-HTTP polling מבחינת זמן השהייה ותעבורה. גיאופנסינג: אם הרכב יוצא מהאזור המותר, הבעלים מקבל התראה. זה מפחית סיכוני גניבה והונאה ב-40%.
// Обработчик MQTT-сообщений от трекеров
class VehicleTelematicsHandler
{
public function handle(string $topic, string $payload): void
{
// topic: vehicles/{plate}/location
preg_match('/vehicles\/(.+)\/location/', $topic, $matches);
$plate = $matches[1];
$data = json_decode($payload, true);
DB::transaction(function () use ($plate, $data) {
$vehicle = Vehicle::where('plate_number', $plate)->firstOrFail();
$vehicle->update([
'location' => DB::raw(
"ST_MakePoint({$data['lng']}, {$data['lat']})"
),
'mileage_km' => $data['odometer'] ?? $vehicle->mileage_km,
'last_seen_at' => now(),
]);
// Геозонирование — проверка выхода за пределы разрешённой зоны
if (isset($vehicle->activeRental)) {
$this->checkGeofence($vehicle, $data);
}
});
}
} איך מטפלים בפיקדונות ביטחון?
הפיקדון מוחזק על הכרטיס בעת ההזמנה דרך Stripe PaymentIntents עם CREATE TABLE vehicles ( id BIGSERIAL PRIMARY KEY, owner_id BIGINT NOT NULL REFERENCES users(id), make VARCHAR(50) NOT NULL, -- Toyota model VARCHAR(50) NOT NULL, -- Camry year SMALLINT NOT NULL, plate_number VARCHAR(20) UNIQUE NOT NULL, vin VARCHAR(17) UNIQUE NOT NULL, transmission VARCHAR(10) NOT NULL, -- auto, manual fuel_type VARCHAR(15) NOT NULL, -- petrol, diesel, electric, hybrid seats SMALLINT NOT NULL DEFAULT 5, mileage_km INT NOT NULL DEFAULT 0, location GEOGRAPHY(POINT, 4326), insurance_expiry DATE NOT NULL, inspection_expiry DATE NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'available' ); CREATE TABLE rental_bookings ( id BIGSERIAL PRIMARY KEY, vehicle_id BIGINT NOT NULL REFERENCES vehicles(id), renter_id BIGINT NOT NULL REFERENCES users(id), pickup_datetime TIMESTAMPTZ NOT NULL, return_datetime TIMESTAMPTZ NOT NULL, pickup_location GEOGRAPHY(POINT, 4326), return_location GEOGRAPHY(POINT, 4326), status VARCHAR(20) NOT NULL DEFAULT 'pending', total_amount NUMERIC(10,2) NOT NULL, security_deposit NUMERIC(10,2) NOT NULL, fuel_policy VARCHAR(20) NOT NULL -- 'full_to_full', 'prepaid' ); . בהחזרה ללא נזק, העיכוב משוחרר. במקרה של נזק, רק סכום הנזק נגבה. אנו מבטיחים: אף דולר לא יוצא ללא אישור.
// Создание hold (authorization hold) без списания
$paymentIntent = $stripe->paymentIntents->create([
'amount' => $booking->security_deposit_cents,
'currency' => 'eur',
'capture_method' => 'manual',
'confirm' => false,
'description' => "Security deposit for booking #{$booking->id}",
]);
// Если повреждений нет — отменяем hold
$stripe->paymentIntents->cancel($paymentIntent->id);
// Если есть повреждения — захватываем нужную сумму
$stripe->paymentIntents->capture($paymentIntent->id, [
'amount_to_capture' => $damageAmount,
]);
שלבי העבודה
אנו פועלים לפי תהליך שקוף כך שתשלטו בכל שלב:
- ניתוח — לימוד הצי שלכם, שוק היעד, דרישות חוקיות.
- עיצוב — יצירת ERD, סכימת API, אב טיפוס ממשק.
- פיתוח — כתיבת קוד, הגדרת CI/CD, ביצוע סקירת קוד.
- בדיקות — בדיקות עומס, בדיקות אבטחה, UAT.
- השקה וניטור — פריסה לייצור, הגדרת התראות.
רכיבי הפתרון
| רכיב | פרטים |
|---|---|
| Backend (API) | Laravel / Django + PostgreSQL + Redis |
| Frontend | React / Next.js (SSR) עם עיצוב mobile-first |
| אימות | Stripe Identity / Jumio + עיבוד webhook |
| תשלומים | Stripe (עיכוב/גבייה, הנחות, עונתיות) |
| מעקב GPS | שרת MQTT + גיאופנסינג (אופציונלי) |
| דו"ח מסירה | תמונות + חתימות canvas → S3 |
| תיעוד | סכימת Swagger, README, תיאור פריסה |
| תמיכה | חודש ניטור חינם לאחר ההשקה |
לוח זמנים לפיתוח
- MVP (קטלוג, הזמנה, אימות, לוח בקרה לבעלים): 8–10 שבועות.
-
- בדיקות, GPS, תמחור גמיש, פיקדונות: 4–5 שבועות נוספים.
העלות מחושבת באופן אישי — תלויה במורכבות האינטגרציה ובגודל הצי. בממוצע, הפלטפורמה מחזירה את עצמה תוך 3–6 חודשים באמצעות אוטומציה.
צרו קשר להערכת פרויקט — נכין ארכיטקטורה והערכת עלות תוך יומיים. קבלו ייעוץ על ארכיטקטורת הפלטפורמה ולוחות זמנים. אנו עובדים עם פרויקטים בכל היקף — מסטארטאפים ועד ציים גדולים.







