מסמך תכנון Maintor API
סקירה כללית
Maintor היא מערכת לניהול תחזוקה עבור חברות תעשייתיות. ה-API מספק נקודות קצה (endpoints) לניהול כרטיסי תחזוקה, שיכולים להיות תחזוקה מונעת (מתוכננת) או תחזוקת שבר.
URL בסיס
https://your-api-domain.com/v1
אימות (Authentication)
כל נקודות הקצה דורשות אימות באמצעות ה-middleware identityValidator. ה-API משתמש באימות Firebase עם Google OAuth או אימייל/סיסמה.
כותרות (Headers)
Authorization: Bearer <firebase-token>
Content-Type: application/json
מודלי נתונים (Data Models)
מודל כרטיס (Ticket Model)
מודל הכרטיס המאוחד תומך הן בתחזוקה מונעת והן בתחזוקת שבר:
interface Ticket {
id: string; // מזהה ייחודי
type: 'PLANNED' | 'BREAKDOWN'; // סוג הכרטיס
assetId?: string; // מזהה נכס - חובה לכרטיסי שבר
// מידע בסיסי
title: string; // כותרת הכרטיס
description: string; // תיאור
priority: number; // 1-5 (1=חירום, 5=נמוך)
status: 'OPEN' | 'IN_PROGRESS' | 'COMPLETED' | 'CLOSED' | 'SKIPPED';
// תזמון
scheduled_date?: string; // מתי התחזוקה המתוכננת צריכה לקרות (רק לכרטיסים מתוכננים)
// ציר זמן (משותף לכרטיסים מתוכננים וכרטיסי שבר)
timeline?: {
started?: string; // מתי העבודה/השבר התחילו (ISO datetime)
ended?: string; // מתי העבודה/השבר הסתיימו (ISO datetime)
duration_min?: number; // משך זמן כולל בדקות
downtime_min?: number; // זמן השבתת מכונה בדקות
labor_entries?: Array<{ // מעקב עבודה מפורט
user_id: string; // מזהה משתמש
started: string; // זמן התחלה (ISO datetime)
ended: string; // זמן סיום (ISO datetime)
duration_min: number; // משך העבודה עבור ערך זה (דקות)
}>;
};
// שדות ספציפיים לשבר (רק עבור סוג: "BREAKDOWN")
breakdown?: {
problem_description: string; // מה השתבש - חובה
solution_description?: string; // איך זה תוקן
root_cause?: string; // מקטלוג סיבות שורש
};
// הערות מפעיל (רלוונטי לשני הסוגים)
operator_notes?: string; // הקשר נוסף
// משימות (מתוכנן) או הערות (שבר)
tasks?: Array<{
description: string;
status: 'PENDING' | 'DONE' | 'SKIPPED' | 'FAILED';
}>;
notes?: Array<{
at: string; // ISO datetime
by: string; // user_id
note: string;
}>;
// אנשים
owner_user_id: string; // בעלים (מתכנן/מפקח)
reported_by_user_id: string; // מי דיווח על השבר
assignees: Array<{
user_id: string;
}>;
// ראיות ותיעוד
photos?: Array<{
url: string;
caption?: string;
}>;
attachments?: Array<{
doc_id: string;
title: string;
kind: string;
}>;
// ביקורת (Audit)
created_at: string; // ISO datetime
updated_at: string; // ISO datetime
archived_at?: string; // ISO datetime
}
נקודות קצה של ה-API (API Endpoints)
ניהול חשבון
קבלת החשבון שלי
GET /accounts/myAccount
תגובה (Response):
{
"id": "account_123",
"name": "Acme Corp",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
ניהול כרטיסים
רשימת כרטיסים
GET /accounts/{accountId}/tickets
פרמטרי שאילתה:
type(אופציונלי): סינון לפי סוג כרטיס (planned|breakdown)status(אופציונלי): סינון לפי סטטוס
דוגמה:
GET /accounts/acme/tickets?type=breakdown&status=open
תגובה:
[
{
"id": "tkt_2025_001245",
"type": "breakdown",
"title": "Pump failure on Line 3",
"priority": 1,
"status": "open",
"scheduled_date": "2025-09-14",
"assetId": "asset_pmp_004",
"created_at": "2025-09-14T13:40:00Z"
}
]
יצירת כרטיס
POST /accounts/{accountId}/tickets
גוף הבקשה (Request Body):
{
"ticket": {
"type": "planned",
"title": "500-hour pump service",
"description": "Routine maintenance per schedule",
"priority": 3,
"status": "open",
"scheduled_date": "2025-09-26",
"assetId": "asset_pmp_004",
"owner_user_id": "tu_acme_super1",
"reported_by_user_id": "tu_acme_super1",
"assignees": [
{ "user_id": "tu_acme_alex" }
],
"tasks": [
{
"description": "Inspect coupling & alignment",
"status": "pending"
}
]
}
}
תגובה: 201 Created
{
"id": "tkt_2025_001245",
"type": "planned",
"title": "500-hour pump service",
"status": "open",
"created_at": "2025-09-26T06:55:00Z"
}
קבלת כרטיס
GET /accounts/{accountId}/tickets/{ticketId}
תגובה: 200 OK
{
"id": "tkt_2025_001245",
"type": "planned",
"title": "500-hour pump service",
"description": "Routine maintenance per schedule",
"priority": 3,
"status": "open",
"scheduled_date": "2025-09-26",
"timeline": {
"started": "2025-09-26T07:15:00Z",
"ended": "2025-09-26T08:55:00Z",
"duration_min": 100,
"downtime_min": 30,
"labor_entries": [
{
"user_id": "tu_acme_alex",
"started": "2025-09-26T07:15:00Z",
"ended": "2025-09-26T08:55:00Z",
"duration_min": 100
}
]
},
"tasks": [
{
"description": "Inspect coupling & alignment",
"status": "DONE"
}
],
"assignees": [
{ "user_id": "tu_acme_alex" }
],
"created_at": "2025-09-26T06:55:00Z",
"updated_at": "2025-09-26T09:00:00Z"
}
עדכון כרטיס
PATCH /accounts/{accountId}/tickets/{ticketId}
גוף הבקשה:
{
"status": "in_progress",
"actual_work": {
"started": "2025-09-26T07:15:00Z"
},
"tasks": [
{
"description": "Inspect coupling & alignment",
"status": "done"
}
]
}
תגובה: 200 OK
{
"id": "tkt_2025_001245",
"status": "in_progress",
"actual_work": {
"started": "2025-09-26T07:15:00Z"
},
"updated_at": "2025-09-26T09:30:00Z"
}
מחיקת כרטיס
DELETE /accounts/{accountId}/tickets/{ticketId}
תגובה: 200 OK
{
"success": true
}
תגובות שגיאה (Error Responses)
400 Bad Request
{
"issues": [
{
"path": ["priority"],
"message": "Number must be greater than or equal to 1"
}
]
}
401 Unauthorized (לא מורשה)
"Unauthorized"
מוחזר כאשר האימות נכשל (טוקן לא חוקי או חסר)
403 Forbidden (אסור)
"Forbidden"
מוחזר כאשר למשתמש אין גישה לחשבון
404 Not Found (לא נמצא)
"Ticket not found"
500 Internal Server Error (שגיאת שרת פנימית)
"Error creating ticket"
סולם עדיפויות (Priority Scale)
- 1 = חירום (עדיפות עליונה)
- 2 = גבוהה
- 3 = בינונית
- 4 = נמוכה
- 5 = נמוכה מאוד (העדיפות הנמוכה ביותר)
זרימת סטטוסים (Status Flow)
תחזוקה מתוכננת
draft → open → in_progress → completed → closed
תחזוקת שבר
draft → open → in_progress → awaiting_approval → closed
דוגמאות לשימוש
יצירת כרטיס שבר
const response = await fetch('/v1/accounts/acme/tickets', {
method: 'POST',
headers: {
'Authorization': 'Bearer <firebase-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
ticket: {
type: 'breakdown',
title: 'Pump failure on Line 3',
description: 'Seal leak causing motor overload trip',
priority: 1,
status: 'open',
assetId: 'asset_pmp_004',
breakdown: {
started: '2025-09-14T13:22:00Z',
problem_description: 'Seal leak; pump tripped on motor overload.',
root_cause: 'improper_alignment'
},
owner_user_id: 'tu_acme_super1',
reported_by_user_id: 'usr_op_42',
assignees: [
{ user_id: 'tu_acme_alex' }
]
}
})
});
עדכון סטטוס כרטיס
const response = await fetch('/v1/accounts/acme/tickets/tkt_123', {
method: 'PATCH',
headers: {
'Authorization': 'Bearer <firebase-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
status: 'in_progress',
actual_work: {
started: '2025-09-14T13:45:00Z'
}
})
});
סינון כרטיסים
// קבלת כל כרטיסי השבר
const response = await fetch('/v1/accounts/acme/tickets?type=breakdown');
// קבלת כרטיסים פתוחים בלבד
const response = await fetch('/v1/accounts/acme/tickets?status=open');
// קבלת כרטיסי שבר פתוחים
const response = await fetch('/v1/accounts/acme/tickets?type=breakdown&status=open');
הערות לפיתוח פרונטאנד
- אימות (Authentication): כל הבקשות חייבות לכלול את טוקן ה-Firebase בכותרת ה-Authorization
- כתובות מבוססות חשבון: כל פעולות הכרטיסים דורשות
accountIdבנתיב ה-URL - שדות ספציפיים לסוג: שדות מסוימים כמו
breakdownרלוונטיים רק לכרטיסי שבר - ניהול סטטוסים: לסוגי כרטיסים שונים יש זרימות סטטוס שונות
- סינון: השתמש בפרמטרי שאילתה כדי לסנן כרטיסים לפי סוג וסטטוס
- טיפול בשגיאות: בדוק שגיאות 401/403 כדי לטפל בבעיות אימות/הרשאה
- פורמט תאריכים: כל התאריכים הם בפורמט ISO 8601 (UTC)
- עדיפות: מספרים נמוכים יותר מצביעים על עדיפות גבוהה יותר (1 = חירום)
- שדות תזמון:
- כרטיסים מתוכננים: חייבים להכיל את
scheduled_date(מתי התחזוקה מתוכננת) - כרטיסי שבר: חייבים להכיל את
breakdown.started(מתי השבר התרחש), לא אמורים להכיל אתscheduled_date
- כרטיסים מתוכננים: חייבים להכיל את
- שיוך נכסים (Assets):
- כרטיסי שבר: חייבים להכיל את השדה
assetId(מזהה נכס) - כרטיסים מתוכננים: עשויים להכיל את השדה
assetId(אופציונלי)
- כרטיסי שבר: חייבים להכיל את השדה