Към съдържанието

Организации

Управлявайте организациите във вашия акаунт в ChatHub. Организациите служат като контейнери за оператори и чат операции.

Преглед

Организации в ChatHub:

  • Группират операторите по отдел, екип или функция
  • Изолират чат операциите между различни бизнес единици
  • Управление на разрешенията на организационно ниво
  • Проследяване на показатели за измервания на успеха (metrics) по организация

Списък с организации

Извлечете всички организации, достъпни с вашия токен на компания (company token).

Крайна точка (Endpoint)

GET /api/company/organization

Заявка

curl -X GET https://chatapi.smsbat.com/api/company/organization \
  -H "Authorization: Bearer {company-token}" \
  -H "Accept: text/plain"

Заглавки (Headers)

Хедър Стойност Задължителен Описание
Authorization Bearer Да Company token
Accept text/plain Да Формат на отговора

Отговор

[
  {
    "id": 6,
    "name": "Customer Support"
  },
  {
    "id": 24,
    "name": "Sales Team"
  },
  {
    "id": 42,
    "name": "Technical Support"
  }
]

Полета в отговора

Поле Тип Описание
id integer Уникален идентификатор на организацията
name string Име на организацията за показване

Организационна структура

Всяка организация съдържа:

  • Оператори: Агенти за чат, назначени към организацията
  • Чат сесии: Активни и исторически чат разговори
  • Уиджети: Вградени чат приставки за тази организация
  • Настройки: Специфична за организацията конфигурация

Случаи на употреба

Многоотделна компания

Компания: ACME Corp
├── Организация: Продажби (id: 10)
│   ├── Оператор: Иван (Агент Продажби)
│   └── Оператор: Сара (Мениджър Продажби)
├── Организация: Поддръжка (id: 20)
│   ├── Оператор: Майк (Агент Поддръжка)
│   └── Оператор: Лиза (Водещ Поддръжка)
└── Организация: Техническа (id: 30)
    └── Оператор: Алекс (Технически експерт)

Бизнес с много марки (Brands)

Компания: Retail Group
├── Организация: Бранд A (id: 101)
│   └── Widget: branda.com
├── Организация: Бранд B (id: 102)
│   └── Widget: brandb.com
└── Организация: Бранд C (id: 103)
    └── Widget: brandc.com

Примери за внедряване

Python

import requests

def get_organizations(company_token):
    """Вземете списък с всички организации"""
    response = requests.get(
        'https://chatapi.smsbat.com/api/company/organization',
        headers={
            'Authorization': f'Bearer {company_token}',
            'Accept': 'text/plain'
        }
    )
    response.raise_for_status()
    return response.json()

def find_organization_by_name(company_token, name):
    """Намерете организация по име"""
    organizations = get_organizations(company_token)

    for org in organizations:
        if org['name'].lower() == name.lower():
            return org

    return None

def get_organization_by_id(company_token, org_id):
    """Вземете конкретна организация по ID"""
    organizations = get_organizations(company_token)

    for org in organizations:
        if org['id'] == org_id:
            return org

    return None

# Употреба
token = "your-company-token"

# Вземете всички организации
orgs = get_organizations(token)
print(f"Намерени {len(orgs)} организации")

# Намерете конкретна организация
support_org = find_organization_by_name(token, "Support")
if support_org:
    print(f"ID на организация Support: {support_org['id']}")

# Вземете по ID
org = get_organization_by_id(token, 24)
print(f"Организация: {org['name']}")

JavaScript (Node.js)

const axios = require('axios');

class OrganizationManager {
  constructor(companyToken) {
    this.companyToken = companyToken;
    this.baseUrl = 'https://chatapi.smsbat.com';
  }

  async getOrganizations() {
    const response = await axios.get(
      `${this.baseUrl}/api/company/organization`,
      {
        headers: {
          'Authorization': `Bearer ${this.companyToken}`,
          'Accept': 'text/plain'
        }
      }
    );

    return response.data;
  }

  async findByName(name) {
    const organizations = await this.getOrganizations();

    return organizations.find(org =>
      org.name.toLowerCase() === name.toLowerCase()
    );
  }

  async findById(id) {
    const organizations = await this.getOrganizations();
    return organizations.find(org => org.id === id);
  }

  async listByIds(ids) {
    const organizations = await this.getOrganizations();
    return organizations.filter(org => ids.includes(org.id));
  }
}

// Употреба
const manager = new OrganizationManager('your-company-token');

async function manageOrganizations() {
  // Вземете всички организации
  const orgs = await manager.getOrganizations();
  console.log(`Намерени ${orgs.length} организации`);

  // Намерете по име
  const support = await manager.findByName('Support');
  console.log('Support org:', support);

  // Намерете по ID
  const org = await manager.findById(24);
  console.log('Организация:', org);

  // Вземете множество организации
  const selectedOrgs = await manager.listByIds([10, 20, 30]);
  console.log('Избрани организации:', selectedOrgs);
}

manageOrganizations();

PHP

<?php

class OrganizationManager {
    private $companyToken;
    private $baseUrl = 'https://chatapi.smsbat.com';

    public function __construct($companyToken) {
        $this->companyToken = $companyToken;
    }

    public function getOrganizations() {
        $ch = curl_init($this->baseUrl . '/api/company/organization');

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->companyToken,
            'Accept: text/plain'
        ]);

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }

    public function findByName($name) {
        $organizations = $this->getOrganizations();

        foreach ($organizations as $org) {
            if (strcasecmp($org['name'], $name) === 0) {
                return $org;
            }
        }

        return null;
    }

    public function findById($id) {
        $organizations = $this->getOrganizations();

        foreach ($organizations as $org) {
            if ($org['id'] === $id) {
                return $org;
            }
        }

        return null;
    }
}

// Употреба
$manager = new OrganizationManager('your-company-token');

// Вземете всички организации
$orgs = $manager->getOrganizations();
echo "Намерени " . count($orgs) . " организации\n";

// Намерете по име
$support = $manager->findByName('Support');
if ($support) {
    echo "ID на организация Support: " . $support['id'] . "\n";
}

// Намерете по ID
$org = $manager->findById(24);
if ($org) {
    echo "Организация: " . $org['name'] . "\n";
}

Работа с организации

Списък на всички организации

const organizations = await getOrganizations(companyToken);

organizations.forEach(org => {
  console.log(`${org.id}: ${org.name}`);
});

Изход:

6: Customer Support
24: Sales Team
42: Technical Support

Филтриране на организации

// Вземете организации, отговарящи на критерии
const supportOrgs = organizations.filter(org =>
  org.name.toLowerCase().includes('support')
);

// Вземете организации по ID
const specificOrgs = organizations.filter(org =>
  [10, 20, 30].includes(org.id)
);

Съпоставяне (Mapping) на организации

// Създайте съпоставяне от ID към име
const orgMap = organizations.reduce((map, org) => {
  map[org.id] = org.name;
  return map;
}, {});

console.log(orgMap[24]); // "Sales Team"

Модели за интеграция (Patterns)

ПГ за избор на организация

async function renderOrganizationSelect(companyToken) {
  const organizations = await getOrganizations(companyToken);

  const select = document.createElement('select');
  select.id = 'organization-select';

  organizations.forEach(org => {
    const option = document.createElement('option');
    option.value = org.id;
    option.textContent = org.name;
    select.appendChild(option);
  });

  return select;
}

Маршрутизиране на чатове по организация

async function routeChatToOrganization(chatRequest) {
  const organizations = await getOrganizations(companyToken);

  // Маршрутизиране въз основа на бизнес логика
  let targetOrg;

  if (chatRequest.department === 'sales') {
    targetOrg = organizations.find(org =>
      org.name.toLowerCase().includes('sales')
    );
  } else if (chatRequest.department === 'support') {
    targetOrg = organizations.find(org =>
      org.name.toLowerCase().includes('support')
    );
  }

  return targetOrg?.id;
}

Показатели (Metrics) на организацията

class OrganizationMetrics {
  async getMetrics(companyToken, orgId) {
    // Вземете оператори за организация
    const operators = await getOperators(companyToken, orgId);

    // Вземете статистика за чата (пример)
    return {
      organizationId: orgId,
      operatorCount: operators.length,
      activeOperators: operators.filter(op => op.isActive).length,
      // Добавете още показатели (metrics) при необходимост
    };
  }

  async getAllMetrics(companyToken) {
    const organizations = await getOrganizations(companyToken);

    const metrics = await Promise.all(
      organizations.map(org =>
        this.getMetrics(companyToken, org.id)
      )
    );

    return metrics;
  }
}

Добри практики

Кеширане

Кеширайте списъка с организации, за да намалите API заявките:

class CachedOrganizationManager {
  constructor(companyToken, cacheTTL = 300000) { // 5 минути
    this.companyToken = companyToken;
    this.cacheTTL = cacheTTL;
    this.cache = null;
    this.cacheTime = 0;
  }

  async getOrganizations(forceRefresh = false) {
    const now = Date.now();

    if (!forceRefresh &&
        this.cache &&
        now - this.cacheTime < this.cacheTTL) {
      return this.cache;
    }

    this.cache = await fetchOrganizations(this.companyToken);
    this.cacheTime = now;

    return this.cache;
  }

  clearCache() {
    this.cache = null;
    this.cacheTime = 0;
  }
}

Обработка на грешки

async function getOrganizationsWithRetry(companyToken, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await getOrganizations(companyToken);
    } catch (error) {
      if (error.response?.status === 401) {
        throw new Error('Невалиден или изтекъл company token');
      }

      if (i === retries - 1) throw error;

      // Изчакайте преди повторен опит
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, i) * 1000)
      );
    }
  }
}

Валидиране

function validateOrganizationId(organizations, orgId) {
  const org = organizations.find(o => o.id === orgId);

  if (!org) {
    throw new Error(`Организация ${orgId} не е намерена`);
  }

  return org;
}

// Употреба
const organizations = await getOrganizations(companyToken);
const org = validateOrganizationId(organizations, requestedOrgId);

Отстраняване на проблеми

Празен списък с организации

  • Уверете се, че company token е валиден
  • Проверете дали токенът има достъп до организацията
  • Уверете се, че организациите съществуват в акаунта

Организацията не е намерена

  • Уверете се, че ID на организацията е правилно
  • Проверете дали организацията не е била изтрита
  • Обновете списъка с организации

401 Unauthorized (Неупълномощен достъп)

  • Уверете се, че company token е валиден и не е изтекъл
  • Поискайте нов company token, ако е необходимо
  • Проверете дали форматът на токена е правилен

Следващи стъпки