Skip to content

Categories

Moon ERP provides two category systems: Product Categories for organizing products and services, and Partner Categories for classifying business partners (customers and suppliers). Product categories are hierarchical (tree structure), while partner categories are flat.

Product Categories

Purpose

  • Organize products and services into a hierarchical tree
  • Support unlimited nesting depth via parent-child relationships
  • Enable filtering and reporting by category
  • Provide a tree endpoint for building navigation UI

Entity Attributes

FieldTypeDescription
idintegerPrimary key
company_idintegerForeign key to the company
parent_idinteger?Foreign key to parent category (null for root)
codestringCategory code (e.g., ELEC, FOOD)
namestringCategory name (English)
name_arstringCategory name (Arabic)
levelintegerDepth in the tree (0 for root)
has_childrenbooleanWhether this category has sub-categories
is_activebooleanWhether the category is active
descriptionstring?Description (English)
description_arstring?Description (Arabic)
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp
deleted_atdatetime?Soft-delete timestamp

Relationships

API Endpoints

MethodPathDescription
GET/api/core/product-categoriesList categories (paginated, flat)
GET/api/core/product-categories/treeGet full category tree
POST/api/core/product-categoriesCreate a category
GET/api/core/product-categories/{id}Get a specific category
PUT/api/core/product-categories/{id}Update a category
DELETE/api/core/product-categories/{id}Soft-delete a category

Query Parameters for GET /api/core/product-categories

ParameterTypeDescription
searchstringSearch by code, name, or name_ar
pageintegerPage number for pagination

Request/Response Examples

GET /api/core/product-categories/tree

Retrieve the full category hierarchy as a nested tree.

bash
curl -X GET https://moon-erp.test/api/core/product-categories/tree \
  -H "Accept: application/json" \
  -H "Accept-Language: ar" \
  -H "Authorization: Bearer {token}"
dart
final response = await http.get(
  Uri.parse('https://moon-erp.test/api/core/product-categories/tree'),
  headers: {
    'Accept': 'application/json',
    'Accept-Language': 'ar',
    'Authorization': 'Bearer $token',
  },
);

Response 200 OK

json
{
  "data": [
    {
      "id": 1,
      "code": "ELEC",
      "name": "إلكترونيات",
      "name_en": "Electronics",
      "name_ar": "إلكترونيات",
      "level": 0,
      "has_children": true,
      "is_active": true,
      "children": [
        {
          "id": 2,
          "code": "ELEC-COMP",
          "name": "حواسيب",
          "name_en": "Computers",
          "name_ar": "حواسيب",
          "level": 1,
          "has_children": false,
          "is_active": true,
          "children": []
        },
        {
          "id": 3,
          "code": "ELEC-PHONE",
          "name": "هواتف",
          "name_en": "Phones",
          "name_ar": "هواتف",
          "level": 1,
          "has_children": false,
          "is_active": true,
          "children": []
        }
      ]
    },
    {
      "id": 4,
      "code": "FOOD",
      "name": "مواد غذائية",
      "name_en": "Food Items",
      "name_ar": "مواد غذائية",
      "level": 0,
      "has_children": false,
      "is_active": true,
      "children": []
    }
  ]
}

POST /api/core/product-categories

Create a new category. To create a sub-category, provide the parent_id.

bash
curl -X POST https://moon-erp.test/api/core/product-categories \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {token}" \
  -d '{
    "code": "ELEC-TAB",
    "name": "Tablets",
    "name_ar": "أجهزة لوحية",
    "parent_id": 1,
    "is_active": true
  }'
dart
final response = await http.post(
  Uri.parse('https://moon-erp.test/api/core/product-categories'),
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  },
  body: jsonEncode({
    'code': 'ELEC-TAB',
    'name': 'Tablets',
    'name_ar': 'أجهزة لوحية',
    'parent_id': 1,
    'is_active': true,
  }),
);

Response 201 Created

json
{
  "data": {
    "id": 5,
    "code": "ELEC-TAB",
    "name": "Tablets",
    "name_en": "Tablets",
    "name_ar": "أجهزة لوحية",
    "parent_id": 1,
    "level": 1,
    "has_children": false,
    "is_active": true,
    "description": null,
    "description_ar": null,
    "created_at": "2026-02-16T10:00:00.000000Z",
    "updated_at": "2026-02-16T10:00:00.000000Z"
  }
}

Business Rules

  • Automatic level calculation -- when a parent_id is provided, the level is automatically set to parent.level + 1.
  • has_children flag -- automatically set to true on the parent when a child category is created.
  • Cannot delete with children -- attempting to delete a category that has has_children: true returns a 422 error. Delete child categories first.
  • Company scoping -- categories are scoped to the authenticated user's company.

Partner Categories

Purpose

  • Classify business partners into groups for reporting and filtering
  • Support scope-based categorization (customer-only, supplier-only, or both)

Entity Attributes

FieldTypeDescription
idintegerPrimary key
company_idintegerForeign key to the company
namestringCategory name (English)
name_arstringCategory name (Arabic)
scopeenumApplicability: customer, supplier, both
is_activebooleanWhether the category is active
descriptionstring?Description (English)
description_arstring?Description (Arabic)
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp
deleted_atdatetime?Soft-delete timestamp

API Endpoints

MethodPathDescription
GET/api/core/partner-categoriesList partner categories (paginated)
POST/api/core/partner-categoriesCreate a partner category
GET/api/core/partner-categories/{id}Get a specific partner category
PUT/api/core/partner-categories/{id}Update a partner category
DELETE/api/core/partner-categories/{id}Soft-delete a partner category

Query Parameters for GET /api/core/partner-categories

ParameterTypeDescription
scopestringFilter by scope: customer, supplier, both
pageintegerPage number for pagination

Request/Response Examples

POST /api/core/partner-categories

bash
curl -X POST https://moon-erp.test/api/core/partner-categories \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {token}" \
  -d '{
    "name": "Wholesale Suppliers",
    "name_ar": "موردين بالجملة",
    "scope": "supplier",
    "is_active": true,
    "description": "Large-volume wholesale suppliers",
    "description_ar": "موردين بكميات كبيرة بالجملة"
  }'
dart
final response = await http.post(
  Uri.parse('https://moon-erp.test/api/core/partner-categories'),
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  },
  body: jsonEncode({
    'name': 'Wholesale Suppliers',
    'name_ar': 'موردين بالجملة',
    'scope': 'supplier',
    'is_active': true,
  }),
);

Response 201 Created

json
{
  "data": {
    "id": 1,
    "name": "Wholesale Suppliers",
    "name_en": "Wholesale Suppliers",
    "name_ar": "موردين بالجملة",
    "scope": "supplier",
    "is_active": true,
    "description": "Large-volume wholesale suppliers",
    "description_ar": "موردين بكميات كبيرة بالجملة",
    "created_at": "2026-02-16T10:00:00.000000Z",
    "updated_at": "2026-02-16T10:00:00.000000Z"
  }
}

Business Rules

  • Flat structure -- partner categories have no parent-child hierarchy, unlike product categories.
  • Scope filtering -- the scope field determines whether a category applies to customers, suppliers, or both. Use this to filter categories when displaying them in a customer or supplier form.
  • Company scoping -- categories are scoped to the authenticated user's company.

Moon ERP API Documentation