arc/docs/REPAIR_SHOP_COMPLETE_DOCUMENTATION.md
2026-04-14 19:34:55 +03:30

18 KiB
Executable file
Raw Permalink Blame History

📚 مستندات کامل افزونه مدیریت تعمیرگاه

فهرست مطالب

  1. معرفی
  2. معماری سیستم
  3. دیتابیس
  4. API Documentation
  5. یکپارچگی‌ها
  6. جریان کاری
  7. امنیت و دسترسی‌ها
  8. خطاها و عیب‌یابی

معرفی

افزونه مدیریت تعمیرگاه یک سیستم جامع برای مدیریت فرآیند تعمیرات از دریافت کالا تا تحویل نهایی است.

ویژگی‌های کلیدی

  • ✅ دریافت و ثبت کالای تعمیری
  • ✅ مدیریت تعمیرکاران و حق‌الزحمه
  • ✅ کارتابل تعمیرات (10 وضعیت)
  • ✅ یکپارچگی با سیستم گارانتی
  • ✅ حواله خروج خودکار قطعات
  • ✅ صدور فاکتور و ثبت حسابداری
  • ✅ تاریخچه کامل تعمیرات

معماری سیستم

لایه‌های سیستم

┌─────────────────────────────────┐
│      API Layer (FastAPI)        │
│  /api/v1/repair-shop/*          │
└─────────────────────────────────┘
              ↓
┌─────────────────────────────────┐
│     Service Layer               │
│  - repair_shop_service          │
│  - repair_shop_operations       │
│  - repair_shop_accounting       │
└─────────────────────────────────┘
              ↓
┌─────────────────────────────────┐
│     Repository Layer            │
│  - RepairOrderRepository        │
│  - RepairTechnicianRepository   │
│  - etc.                         │
└─────────────────────────────────┘
              ↓
┌─────────────────────────────────┐
│     Database Layer (MySQL)      │
│  7 جدول اصلی                    │
└─────────────────────────────────┘

یکپارچگی با سیستم‌های دیگر

┌──────────────────────────┐
│   Repair Shop System     │
└──────────────────────────┘
         ↓ ↑
    ┌────────────┬─────────────┬─────────────┬──────────────┐
    ↓            ↓             ↓             ↓              ↓
┌────────┐  ┌──────────┐  ┌──────────┐  ┌─────────┐  ┌──────────┐
│Products│  │Warehouse │  │Accounting│  │Warranty │  │  Storage │
└────────┘  └──────────┘  └──────────┘  └─────────┘  └──────────┘

دیتابیس

ERD (Entity Relationship Diagram)

┌─────────────────────┐
│ repair_shop_settings│
│ - business_id (PK)  │
│ - receipt_format    │
│ - auto_send_sms     │
└─────────────────────┘

┌──────────────────────┐        ┌─────────────────────┐
│ repair_technicians   │        │   repair_orders     │
│ - id (PK)            │◄───────│ - id (PK)           │
│ - business_id        │        │ - code (UNIQUE)     │
│ - person_id (FK)     │        │ - customer_id (FK)  │
│ - commission_type    │        │ - technician_id (FK)│
│ - commission_value   │        │ - status            │
└──────────────────────┘        │ - final_cost        │
                                └─────────────────────┘
                                         ↓ 1:N
                        ┌────────────────┴────────────────┐
                        ↓                                 ↓
            ┌──────────────────────┐      ┌─────────────────────────┐
            │ repair_order_parts   │      │ repair_order_statuses   │
            │ - id (PK)            │      │ - id (PK)               │
            │ - repair_order_id(FK)│      │ - repair_order_id (FK)  │
            │ - product_id (FK)    │      │ - status                │
            │ - quantity           │      │ - created_at            │
            │ - unit_price         │      │ - sms_sent              │
            └──────────────────────┘      └─────────────────────────┘

جدول repair_orders (جدول اصلی)

ستون نوع توضیحات
id INT شناسه یکتا
code VARCHAR(50) کد یکتا (مثل REC-2025-0001)
business_id INT کسب‌وکار
customer_person_id INT مشتری از جدول persons
product_name VARCHAR(255) نام کالا
warranty_code_id INT NULL کد گارانتی (اختیاری)
status VARCHAR(50) وضعیت فعلی
assigned_technician_id INT NULL تعمیرکار
final_cost DECIMAL(18,2) هزینه نهایی
parts_cost DECIMAL(18,2) هزینه قطعات
labor_cost DECIMAL(18,2) دستمزد
technician_commission DECIMAL(18,2) حق‌الزحمه
received_at DATETIME تاریخ دریافت
completed_at DATETIME NULL تاریخ تکمیل
delivered_at DATETIME NULL تاریخ تحویل

وضعیت‌های مجاز (Status)

وضعیت توضیح
received دریافت شده
assigned اختصاص داده شده
in_progress در حال تعمیر
waiting_parts منتظر قطعات
testing در حال تست
completed_fixed تعمیر موفق
completed_unfixable غیرقابل تعمیر
ready_for_pickup آماده تحویل
delivered تحویل داده شده
cancelled لغو شده

API Documentation

Authentication

تمام API ها نیاز به Bearer Token دارند:

Authorization: Bearer sk_your_api_key

Base URL

/api/v1/repair-shop

Endpoints

1. Settings

GET /businesses/{business_id}/settings

دریافت تنظیمات تعمیرگاه

Response:

{
  "id": 1,
  "business_id": 1,
  "receipt_code_format": "sequential",
  "receipt_code_prefix": "REC",
  "auto_send_sms_on_receive": true,
  "sms_templates": {...}
}
PUT /businesses/{business_id}/settings

به‌روزرسانی تنظیمات

Request Body:

{
  "auto_send_sms_on_receive": true,
  "receipt_code_prefix": "REC"
}

2. Technicians

POST /businesses/{business_id}/technicians

ایجاد تعمیرکار جدید

Request Body:

{
  "person_id": 123,
  "commission_type": "percentage",
  "commission_value": 30,
  "is_active": true
}

Commission Types:

  • fixed: مبلغ فیکس (مثلاً 200,000 تومان)
  • percentage: درصد از دستمزد (مثلاً 30%)
  • case_by_case: موردی (دستی وارد می‌شود)

3. Repair Orders

POST /businesses/{business_id}/orders

ایجاد سفارش تعمیر جدید

Request Body:

{
  "customer_person_id": 123,
  "product_name": "لپتاپ ایسوس",
  "product_serial": "ABC123",
  "warranty_code_id": 456,
  "problem_description": "روشن نمی‌شود",
  "estimated_cost": 1500000
}

Response:

{
  "id": 1,
  "code": "REC-2025-0001",
  "status": "received",
  "customer_name": "علی احمدی",
  "product_name": "لپتاپ ایسوس",
  "received_at": "2025-02-05T10:30:00",
  ...
}
GET /businesses/{business_id}/orders?status=in_progress

لیست سفارشات با فیلتر

Query Parameters:

  • status: فیلتر بر اساس وضعیت
  • customer_person_id: فیلتر بر اساس مشتری
  • assigned_technician_id: فیلتر بر اساس تعمیرکار
  • search: جستجو در کد، نام کالا، سریال
  • offset: شروع از (pagination)
  • limit: تعداد نتایج

4. Operations

POST /businesses/{business_id}/orders/{order_id}/assign-technician

اختصاص تعمیرکار

Request Body:

{
  "technician_id": 1
}
POST /businesses/{business_id}/orders/{order_id}/update-status

تغییر وضعیت

Request Body:

{
  "status": "in_progress",
  "notes": "شروع تعمیر",
  "send_notification": true
}
POST /businesses/{business_id}/orders/{order_id}/add-parts

افزودن قطعات

Request Body:

{
  "parts": [
    {
      "product_id": 10,
      "quantity": 1,
      "unit_price": 500000,
      "warehouse_id": 1
    },
    {
      "product_id": 11,
      "quantity": 2,
      "warehouse_id": 1
    }
  ]
}

نکته: سیستم به صورت خودکار:

  1. موجودی را بررسی می‌کند
  2. حواله خروج پیش‌نویس ایجاد می‌کند
  3. هزینه قطعات را محاسبه می‌کند
POST /businesses/{business_id}/orders/{order_id}/calculate-costs

محاسبه هزینه‌ها

Request Body:

{
  "labor_cost": 1000000
}

Response:

{
  "parts_cost": 500000,
  "labor_cost": 1000000,
  "technician_commission": 300000,
  "final_cost": 1500000
}
POST /businesses/{business_id}/orders/{order_id}/complete

اتمام تعمیر

Request Body:

{
  "is_fixed": true,
  "notes": "تعمیر با موفقیت انجام شد"
}

نکته: در این مرحله:

  1. حواله خروج پست می‌شود
  2. وضعیت به completed_fixed یا completed_unfixable تغییر می‌کند
  3. موجودی از انبار کسر می‌شود
POST /businesses/{business_id}/orders/{order_id}/deliver

تحویل کالا

Request Body:

{
  "notes": "تحویل به مشتری"
}

5. Accounting

POST /businesses/{business_id}/orders/{order_id}/create-invoice

صدور فاکتور تعمیر

Response:

{
  "document": {
    "id": 123,
    "code": "INV-2025-001",
    "document_type": "invoice_sales",
    ...
  },
  "accounting_summary": {
    "labor_cost": 1000000,
    "parts_cost": 500000,
    "final_cost": 1500000
  }
}

اسناد حسابداری ثبت شده:

حساب دریافتنی (10401)   بدهکار: 1,500,000
درآمد فروش (50001)        بستانکار: 1,000,000 (خدمات)
درآمد فروش (50001)        بستانکار: 500,000 (قطعات)
بهای تمام شده (40001)    بدهکار: 300,000
موجودی کالا (10102)       بستانکار: 300,000

یکپارچگی‌ها

1. Marketplace Plugin System

# بررسی فعال بودن
from app.core.repair_shop_plugin_dependency import check_repair_shop_plugin_active

is_active = check_repair_shop_plugin_active(db, business_id)

2. Permission System

دسترسی‌های مورد نیاز:

  • repair_shop.read: مشاهده
  • repair_shop.write: ثبت و ویرایش
  • repair_shop.delete: حذف
  • repair_shop.manage: مدیریت تنظیمات

3. Warehouse Integration

# هنگام افزودن قطعات
from app.services.warehouse_service import get_product_stock

stock = get_product_stock(db, business_id, product_id, warehouse_id)
if stock < quantity:
    raise ApiError("INSUFFICIENT_STOCK", ...)

4. Accounting Integration

from app.services.invoice_service import create_invoice

# صدور فاکتور
invoice = create_invoice(db, business_id, user_id, invoice_payload)

جریان کاری

سناریوی کامل: تعمیر لپتاپ

1️⃣ دریافت کالا
   POST /orders
   {
     "customer_person_id": 1,
     "product_name": "لپتاپ",
     "problem_description": "روشن نمی‌شود"
   }
   
2️⃣ اختصاص تعمیرکار
   POST /orders/1/assign-technician
   {"technician_id": 1}
   
3️⃣ شروع تعمیر
   POST /orders/1/update-status
   {"status": "in_progress"}
   
4️⃣ افزودن قطعات
   POST /orders/1/add-parts
   {
     "parts": [{"product_id": 10, "quantity": 1, "warehouse_id": 1}]
   }
   → حواله خروج پیش‌نویس ایجاد می‌شود
   
5️⃣ محاسبه هزینه
   POST /orders/1/calculate-costs
   {"labor_cost": 1000000}
   → حق‌الزحمه تعمیرکار محاسبه می‌شود
   
6️⃣ اتمام تعمیر
   POST /orders/1/complete
   {"is_fixed": true}
   → حواله خروج پست می‌شود
   → موجودی کسر می‌شود
   
7️⃣ صدور فاکتور
   POST /orders/1/create-invoice
   → فاکتور فروش ایجاد می‌شود
   → اسناد حسابداری ثبت می‌شوند
   
8️⃣ تحویل
   POST /orders/1/deliver

امنیت و دسترسی‌ها

نقش‌های پیشنهادی

1. مدیر تعمیرگاه

{
  "repair_shop": {
    "read": true,
    "write": true,
    "delete": true,
    "manage": true
  }
}

2. تعمیرکار

{
  "repair_shop": {
    "read": true,
    "write": true
  }
}

3. کارشناس پذیرش

{
  "repair_shop": {
    "read": true,
    "write": true
  },
  "people": {
    "read": true,
    "write": true
  }
}

خطاها و عیب‌یابی

خطاهای رایج

1. PLUGIN_NOT_ACTIVE

{
  "error_code": "PLUGIN_NOT_ACTIVE",
  "message": "افزونه مدیریت تعمیرگاه فعال نیست"
}

حل: افزونه را از marketplace خریداری یا trial کنید.

2. INSUFFICIENT_STOCK

{
  "error_code": "INSUFFICIENT_STOCK",
  "message": "موجودی کافی نیست",
  "extra_data": {
    "product_id": 10,
    "current_stock": 5,
    "requested": 10
  }
}

حل: موجودی را افزایش دهید یا تعداد را کاهش دهید.

3. INVOICE_ALREADY_EXISTS

{
  "error_code": "INVOICE_ALREADY_EXISTS",
  "message": "فاکتور قبلاً ایجاد شده است"
}

حل: هر سفارش فقط یک فاکتور دارد.

4. NO_ACTIVE_STORAGE_PLAN

{
  "error_code": "NO_ACTIVE_STORAGE_PLAN",
  "message": "پکیج ذخیره‌سازی فعالی وجود ندارد"
}

حل: برای آپلود تصاویر، پلن ذخیره‌سازی فعال کنید.

Logging

تمام عملیات مهم لاگ می‌شوند:

import logging
logger = logging.getLogger(__name__)

logger.info(f"سفارش تعمیر {order.code} ایجاد شد")
logger.warning(f"موجودی کافی نیست: {product_id}")
logger.error(f"خطا در ایجاد فاکتور: {e}")

نکات عملیاتی

1. Performance

  • استفاده از Index ها برای جستجوی سریع
  • Pagination برای لیست‌ها
  • Lazy Loading برای relationships

2. Scalability

  • جداسازی concerns (Service, Repository, API)
  • استفاده از Queue برای پیامک/ایمیل
  • Cache برای تنظیمات

3. Best Practices

  • Validation در Pydantic models
  • Transaction management در service layer
  • Error handling مناسب
  • Logging جامع

مثال‌های کاربردی

مثال 1: دریافت آمار تعمیرات

from sqlalchemy import func

# تعداد تعمیرات موفق
successful_repairs = db.query(func.count(RepairOrder.id)).filter(
    RepairOrder.business_id == business_id,
    RepairOrder.status == "completed_fixed"
).scalar()

# میانگین زمان تعمیر
avg_duration = db.query(
    func.avg(
        func.timestampdiff(
            sa.text('HOUR'),
            RepairOrder.received_at,
            RepairOrder.completed_at
        )
    )
).filter(
    RepairOrder.business_id == business_id,
    RepairOrder.completed_at.isnot(None)
).scalar()

مثال 2: گزارش عملکرد تعمیرکار

from sqlalchemy import func, case

technician_report = db.query(
    RepairTechnician.id,
    Person.name,
    func.count(RepairOrder.id).label('total_repairs'),
    func.sum(
        case(
            (RepairOrder.status == 'completed_fixed', 1),
            else_=0
        )
    ).label('successful_repairs'),
    func.sum(RepairOrder.technician_commission).label('total_commission')
).join(
    Person, RepairTechnician.person_id == Person.id
).outerjoin(
    RepairOrder, RepairOrder.assigned_technician_id == RepairTechnician.id
).filter(
    RepairTechnician.business_id == business_id
).group_by(
    RepairTechnician.id, Person.name
).all()

تاریخ: 2025-02-05
نسخه: 1.0.0
نویسنده: AI Assistant