megaplan-sdk 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {megaplan_sdk-0.2.0/src/megaplan_sdk.egg-info → megaplan_sdk-0.2.2}/PKG-INFO +200 -20
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/README.md +199 -19
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/pyproject.toml +1 -1
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/__init__.py +9 -2
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/client.py +4 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/constants.py +1 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/http_client.py +6 -1
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/__init__.py +6 -0
- megaplan_sdk-0.2.2/src/megaplan_sdk/models/base.py +27 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/comment.py +1 -1
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/common.py +39 -6
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/contractor.py +1 -1
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/deal.py +36 -10
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/department.py +1 -1
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/employee.py +1 -1
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/filter.py +2 -2
- megaplan_sdk-0.2.2/src/megaplan_sdk/models/group.py +40 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/milestone.py +1 -1
- megaplan_sdk-0.2.2/src/megaplan_sdk/models/participant.py +74 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/project.py +2 -2
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/models/task.py +2 -2
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/base.py +52 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/contractors.py +46 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/deals.py +74 -19
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/projects.py +180 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/tasks.py +166 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2/src/megaplan_sdk.egg-info}/PKG-INFO +200 -20
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk.egg-info/SOURCES.txt +2 -0
- megaplan_sdk-0.2.0/src/megaplan_sdk/models/base.py +0 -16
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/LICENSE +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/setup.cfg +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/auth.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/cache.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/exceptions.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/filter_builder.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/helpers.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/logging_config.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/__init__.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/auth.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/comments.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/departments.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/employees.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/filters.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/resources/full_details.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk/types.py +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk.egg-info/dependency_links.txt +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk.egg-info/requires.txt +0 -0
- {megaplan_sdk-0.2.0 → megaplan_sdk-0.2.2}/src/megaplan_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: megaplan-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Professional Python SDK for Megaplan API v3
|
|
5
5
|
Author-email: Maxim Borzov <max@borzov.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -74,6 +74,7 @@ Dynamic: license-file
|
|
|
74
74
|
- [Автоматическая подгрузка связанных сущностей](#автоматическая-подгрузка-связанных-сущностей)
|
|
75
75
|
- [Работа с фильтрами](#работа-с-фильтрами)
|
|
76
76
|
- [Настройка HTTP-клиента](#настройка-http-клиента)
|
|
77
|
+
- [Работа через прокси](#работа-через-прокси)
|
|
77
78
|
- [Ручное управление токенами](#ручное-управление-токенами)
|
|
78
79
|
|
|
79
80
|
### Справочная информация
|
|
@@ -313,7 +314,7 @@ entity = await client.{resource}.update(
|
|
|
313
314
|
```python
|
|
314
315
|
task = await client.tasks.update(task_id=42, task_data={"status": "completed"})
|
|
315
316
|
project = await client.projects.update(project_id=5, project_data={"name": "Новое название"})
|
|
316
|
-
deal = await client.deals.update(deal_id=200, deal_data={"
|
|
317
|
+
deal = await client.deals.update(deal_id=200, deal_data={"price": {"currency": "RUB", "value": 60000}})
|
|
317
318
|
```
|
|
318
319
|
|
|
319
320
|
#### Удаление (`delete`)
|
|
@@ -516,8 +517,8 @@ tasks = await client.tasks.list(filter=filter_obj)
|
|
|
516
517
|
- `tags: list[BaseEntity]` - Теги
|
|
517
518
|
- `attaches: list[BaseEntity]` - Вложения (файлы)
|
|
518
519
|
- `todos: list[BaseEntity]` - Подзадачи-чеклисты
|
|
519
|
-
- `
|
|
520
|
-
- `
|
|
520
|
+
- `time_created: str` - Дата создания (API поле `timeCreated`)
|
|
521
|
+
- `time_updated: str` - Дата обновления (API поле `timeUpdated`)
|
|
521
522
|
|
|
522
523
|
### Упрощенные методы создания
|
|
523
524
|
|
|
@@ -570,6 +571,53 @@ actual_subtasks = await client.tasks.get_actual_sub_tasks(
|
|
|
570
571
|
# Возвращает: list[Task] - список актуальных подзадач
|
|
571
572
|
```
|
|
572
573
|
|
|
574
|
+
### Получение доступных родителей
|
|
575
|
+
|
|
576
|
+
Методы для получения доступных надзадач и надпроектов (для выбора родителя при создании или перемещении задачи):
|
|
577
|
+
|
|
578
|
+
```python
|
|
579
|
+
# Глобальный поиск доступных родителей для новой задачи
|
|
580
|
+
# Возвращает список Task и Project объектов
|
|
581
|
+
parents = await client.tasks.get_available_parents(
|
|
582
|
+
is_template=False, # bool: Фильтр по шаблонам
|
|
583
|
+
limit=10, # int: Количество элементов
|
|
584
|
+
)
|
|
585
|
+
for parent in parents:
|
|
586
|
+
print(f"{type(parent).__name__}: {parent.name}") # "Task: ..." или "Project: ..."
|
|
587
|
+
|
|
588
|
+
# Доступные родители для существующей задачи
|
|
589
|
+
# Исключает саму задачу и её потомков
|
|
590
|
+
parents = await client.tasks.get_available_parents_for(
|
|
591
|
+
task_id=123,
|
|
592
|
+
is_template=False,
|
|
593
|
+
limit=10,
|
|
594
|
+
)
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
**Примечание:** Методы возвращают смешанный список объектов `Task` и `Project`, так как задача может быть вложена как в другую задачу, так и в проект.
|
|
598
|
+
|
|
599
|
+
### Получение всех участников задачи
|
|
600
|
+
|
|
601
|
+
Метод `get_all_participants()` возвращает полный список участников задачи (ответственный, соисполнители, аудиторы, владелец) в одном запросе:
|
|
602
|
+
|
|
603
|
+
```python
|
|
604
|
+
participants = await client.tasks.get_all_participants(
|
|
605
|
+
task_id=123,
|
|
606
|
+
limit=None, # int: Количество элементов
|
|
607
|
+
# ... стандартные параметры пагинации
|
|
608
|
+
)
|
|
609
|
+
# Возвращает: list[Employee | ContractorHuman | Group]
|
|
610
|
+
|
|
611
|
+
for participant in participants:
|
|
612
|
+
if hasattr(participant, 'display_name'):
|
|
613
|
+
print(participant.display_name())
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
**Типы участников:**
|
|
617
|
+
- `Employee` — сотрудник организации
|
|
618
|
+
- `ContractorHuman` — контрагент-физлицо
|
|
619
|
+
- `Group` — группа участников (например, отдел)
|
|
620
|
+
|
|
573
621
|
### Получение задач на уровне дерева
|
|
574
622
|
|
|
575
623
|
```python
|
|
@@ -727,8 +775,8 @@ milestone = await client.projects.add_milestone(
|
|
|
727
775
|
- `tags: list[BaseEntity]` - Теги
|
|
728
776
|
- `attaches: list[BaseEntity]` - Вложения
|
|
729
777
|
- `todos: list[BaseEntity]` - Подзадачи-чеклисты
|
|
730
|
-
- `
|
|
731
|
-
- `
|
|
778
|
+
- `time_created: str` - Дата создания (API поле `timeCreated`)
|
|
779
|
+
- `time_updated: str` - Дата обновления (API поле `timeUpdated`)
|
|
732
780
|
|
|
733
781
|
### Упрощенные методы создания
|
|
734
782
|
|
|
@@ -790,6 +838,45 @@ actual_issues = await client.projects.get_actual_issues(
|
|
|
790
838
|
# Возвращает: list[Task] - список актуальных задач проекта
|
|
791
839
|
```
|
|
792
840
|
|
|
841
|
+
### Получение доступных родителей
|
|
842
|
+
|
|
843
|
+
Методы для получения доступных родительских проектов (для выбора родителя при создании или перемещении проекта):
|
|
844
|
+
|
|
845
|
+
```python
|
|
846
|
+
# Глобальный поиск доступных родительских проектов
|
|
847
|
+
parents = await client.projects.get_available_parents(
|
|
848
|
+
is_template=False, # bool: Фильтр по шаблонам
|
|
849
|
+
limit=10, # int: Количество элементов
|
|
850
|
+
)
|
|
851
|
+
for parent in parents:
|
|
852
|
+
print(f"Project: {parent.name}")
|
|
853
|
+
|
|
854
|
+
# Доступные родители для существующего проекта
|
|
855
|
+
# Исключает сам проект и его потомков
|
|
856
|
+
parents = await client.projects.get_available_parents_for(
|
|
857
|
+
project_id=456,
|
|
858
|
+
is_template=False,
|
|
859
|
+
limit=10,
|
|
860
|
+
)
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
**Примечание:** В отличие от задач, проекты могут быть вложены только в другие проекты, поэтому возвращается список объектов `Project`.
|
|
864
|
+
|
|
865
|
+
### Получение всех участников проекта
|
|
866
|
+
|
|
867
|
+
Метод `get_all_participants()` возвращает полный список участников проекта в одном запросе:
|
|
868
|
+
|
|
869
|
+
```python
|
|
870
|
+
participants = await client.projects.get_all_participants(
|
|
871
|
+
project_id=123,
|
|
872
|
+
limit=None, # int: Количество элементов
|
|
873
|
+
)
|
|
874
|
+
# Возвращает: list[Employee | ContractorHuman | Group]
|
|
875
|
+
|
|
876
|
+
for participant in participants:
|
|
877
|
+
print(f"{type(participant).__name__}: {participant.display_name()}")
|
|
878
|
+
```
|
|
879
|
+
|
|
793
880
|
### Получение полной информации о проекте
|
|
794
881
|
|
|
795
882
|
Метод `get_full_details()` для проектов поддерживает следующие специфичные параметры:
|
|
@@ -880,18 +967,26 @@ deals = await client.deals.list(filter=filter_obj)
|
|
|
880
967
|
### Поля модели Deal
|
|
881
968
|
- `id: int` - Идентификатор сделки
|
|
882
969
|
- `name: str` - Название сделки
|
|
970
|
+
- `number: str` - Номер сделки
|
|
971
|
+
- `short_description: str` - Краткое описание
|
|
883
972
|
- `program: BaseEntity` - Программа (схема сделки)
|
|
884
973
|
- `state: ProgramState` - Текущий статус в программе
|
|
885
974
|
- `contractor: BaseEntity` - Контрагент (ContractorCompany/ContractorHuman)
|
|
886
|
-
- `
|
|
887
|
-
- `
|
|
975
|
+
- `manager: BaseEntity` - Ответственный (Employee, API поле `manager`)
|
|
976
|
+
- `price: Money` - Сумма сделки (объект с полями `currency`, `value`)
|
|
977
|
+
- `cost: Money` - Стоимость
|
|
978
|
+
- `debt: Money` - Долг
|
|
979
|
+
- `result: str` - Результат (`"positive"`, `"negative"`, `null`)
|
|
888
980
|
- `currency: BaseEntity` - Валюта
|
|
889
981
|
- `deadline: str` - Срок
|
|
890
|
-
- `description: str` - Описание
|
|
982
|
+
- `description: str` - Описание (только в `deals.get()`, не в списке)
|
|
891
983
|
- `tags: list[BaseEntity]` - Теги
|
|
892
984
|
- `attaches: list[BaseEntity]` - Вложения
|
|
893
|
-
- `
|
|
894
|
-
- `
|
|
985
|
+
- `time_created: str` - Дата создания (API поле `timeCreated`)
|
|
986
|
+
- `time_updated: str` - Дата обновления (API поле `timeUpdated`)
|
|
987
|
+
- `state_time_updated: str` - Дата последнего изменения статуса
|
|
988
|
+
|
|
989
|
+
> **Примечание:** Поля `description`, `deadline` и пользовательские поля доступны только при запросе отдельной сделки через `deals.get(id)`, но не в списке.
|
|
895
990
|
|
|
896
991
|
**Важно:** При создании сделки обязательно указывать поле `program` (программа/схема сделки).
|
|
897
992
|
|
|
@@ -917,6 +1012,23 @@ deal = await client.deals.apply_trigger(
|
|
|
917
1012
|
# Возвращает: Deal - обновленная сделка
|
|
918
1013
|
```
|
|
919
1014
|
|
|
1015
|
+
### Получение всех участников сделки
|
|
1016
|
+
|
|
1017
|
+
Метод `get_all_participants()` возвращает полный список участников сделки:
|
|
1018
|
+
|
|
1019
|
+
```python
|
|
1020
|
+
participants = await client.deals.get_all_participants(
|
|
1021
|
+
deal_id=200,
|
|
1022
|
+
limit=None, # int: Количество элементов
|
|
1023
|
+
)
|
|
1024
|
+
# Возвращает: list[Employee]
|
|
1025
|
+
|
|
1026
|
+
for employee in participants:
|
|
1027
|
+
print(employee.display_name())
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
**Примечание:** В отличие от задач и проектов, сделки возвращают только сотрудников (`Employee`).
|
|
1031
|
+
|
|
920
1032
|
### Получение аудиторов сделки
|
|
921
1033
|
|
|
922
1034
|
```python
|
|
@@ -959,7 +1071,7 @@ details = await client.deals.get_full_details(
|
|
|
959
1071
|
include_history=True, # Загрузить историю изменений
|
|
960
1072
|
include_status_history=True, # Загрузить историю статусов
|
|
961
1073
|
include_auditors=True, # Загрузить список аудиторов
|
|
962
|
-
|
|
1074
|
+
include_manager_details=True, # Загрузить полные данные ответственного
|
|
963
1075
|
include_contractor_details=True, # Загрузить полные данные контрагента
|
|
964
1076
|
include_related_tasks=True, # Загрузить связанные задачи
|
|
965
1077
|
comments_limit=50, # Лимит комментариев (опционально)
|
|
@@ -973,7 +1085,7 @@ details = await client.deals.get_full_details(
|
|
|
973
1085
|
- `history: list[dict] | None` - История изменений
|
|
974
1086
|
- `status_history: list[dict] | None` - История статусов
|
|
975
1087
|
- `auditors: list[dict] | None` - Аудиторы
|
|
976
|
-
- `
|
|
1088
|
+
- `manager_details: Employee | None` - Полные данные ответственного
|
|
977
1089
|
- `contractor_details: Contractor | None` - Полные данные контрагента
|
|
978
1090
|
- `related_tasks: list[Task] | None` - Связанные задачи
|
|
979
1091
|
|
|
@@ -1174,14 +1286,14 @@ for task_full in tasks_full:
|
|
|
1174
1286
|
### Использование expand в сделках
|
|
1175
1287
|
|
|
1176
1288
|
```python
|
|
1177
|
-
deals_full = await client.deals.list(limit=10, expand=["
|
|
1289
|
+
deals_full = await client.deals.list(limit=10, expand=["manager", "contractor"])
|
|
1178
1290
|
|
|
1179
1291
|
for deal_full in deals_full:
|
|
1180
1292
|
deal = deal_full.deal
|
|
1181
1293
|
print(f"Сделка: {deal.name}")
|
|
1182
1294
|
|
|
1183
|
-
if deal_full.
|
|
1184
|
-
print(f"Ответственный: {deal_full.
|
|
1295
|
+
if deal_full.manager_details:
|
|
1296
|
+
print(f"Ответственный: {deal_full.manager_details.display_name()}")
|
|
1185
1297
|
|
|
1186
1298
|
if deal_full.contractor_details:
|
|
1187
1299
|
print(f"Контрагент: {deal_full.contractor_details.display_name()}")
|
|
@@ -1192,7 +1304,7 @@ for deal_full in deals_full:
|
|
|
1192
1304
|
```
|
|
1193
1305
|
|
|
1194
1306
|
**Поддерживаемые поля для expand в сделках:**
|
|
1195
|
-
- `
|
|
1307
|
+
- `manager` - ответственный сотрудник
|
|
1196
1308
|
- `contractor` - контрагент
|
|
1197
1309
|
|
|
1198
1310
|
### Использование expand в проектах
|
|
@@ -1402,6 +1514,48 @@ client = MegaplanClient(
|
|
|
1402
1514
|
)
|
|
1403
1515
|
```
|
|
1404
1516
|
|
|
1517
|
+
### Работа через прокси
|
|
1518
|
+
|
|
1519
|
+
SDK поддерживает работу через HTTP/HTTPS/SOCKS5 прокси-серверы. Это полезно для корпоративных сетей, где все запросы должны проходить через прокси.
|
|
1520
|
+
|
|
1521
|
+
```python
|
|
1522
|
+
# HTTP прокси с аутентификацией
|
|
1523
|
+
async with MegaplanClient(
|
|
1524
|
+
base_url="https://my.megaplan.ru",
|
|
1525
|
+
username="user@example.com",
|
|
1526
|
+
password="password",
|
|
1527
|
+
proxy="http://login:pass@proxy.corp.local:8080",
|
|
1528
|
+
) as client:
|
|
1529
|
+
tasks = await client.tasks.list()
|
|
1530
|
+
|
|
1531
|
+
# HTTP прокси без аутентификации
|
|
1532
|
+
client = MegaplanClient(
|
|
1533
|
+
base_url="https://my.megaplan.ru",
|
|
1534
|
+
access_token="token",
|
|
1535
|
+
proxy="http://proxy.corp.local:8080",
|
|
1536
|
+
)
|
|
1537
|
+
|
|
1538
|
+
# HTTPS прокси
|
|
1539
|
+
client = MegaplanClient(
|
|
1540
|
+
base_url="https://my.megaplan.ru",
|
|
1541
|
+
access_token="token",
|
|
1542
|
+
proxy="https://proxy.corp.local:8080",
|
|
1543
|
+
)
|
|
1544
|
+
|
|
1545
|
+
# SOCKS5 прокси (требует httpx[socks])
|
|
1546
|
+
client = MegaplanClient(
|
|
1547
|
+
base_url="https://my.megaplan.ru",
|
|
1548
|
+
access_token="token",
|
|
1549
|
+
proxy="socks5://user:pass@proxy.corp.local:1080",
|
|
1550
|
+
)
|
|
1551
|
+
```
|
|
1552
|
+
|
|
1553
|
+
**Поддерживаемые форматы прокси:**
|
|
1554
|
+
- `http://proxy:port` - HTTP прокси без аутентификации
|
|
1555
|
+
- `http://user:password@proxy:port` - HTTP прокси с аутентификацией
|
|
1556
|
+
- `https://proxy:port` - HTTPS прокси
|
|
1557
|
+
- `socks5://user:password@proxy:port` - SOCKS5 прокси (требует `pip install httpx[socks]`)
|
|
1558
|
+
|
|
1405
1559
|
### Ручное управление токенами
|
|
1406
1560
|
|
|
1407
1561
|
```python
|
|
@@ -1440,13 +1594,39 @@ API возвращает ошибку 500 при попытке получить
|
|
|
1440
1594
|
# comments = await client.contractors.get_comments(contractor_id=123)
|
|
1441
1595
|
|
|
1442
1596
|
# Вместо этого используйте комментарии в сделках контрагента
|
|
1443
|
-
deals = await client.
|
|
1444
|
-
base_on={"contentType": "Contractor", "id": 123}
|
|
1445
|
-
)
|
|
1597
|
+
deals = await client.contractors.get_deals(contractor_id=123)
|
|
1446
1598
|
for deal in deals:
|
|
1447
1599
|
comments = await client.deals.get_comments(deal.id)
|
|
1448
1600
|
```
|
|
1449
1601
|
|
|
1602
|
+
### Получение сделок контрагента
|
|
1603
|
+
|
|
1604
|
+
SDK предоставляет удобный метод `get_deals()` для получения сделок контрагента:
|
|
1605
|
+
|
|
1606
|
+
```python
|
|
1607
|
+
# Получить все сделки контрагента
|
|
1608
|
+
deals = await client.contractors.get_deals(
|
|
1609
|
+
contractor_id=123,
|
|
1610
|
+
limit=50 # Опционально
|
|
1611
|
+
)
|
|
1612
|
+
|
|
1613
|
+
for deal in deals:
|
|
1614
|
+
print(f"[{deal.id}] {deal.name}")
|
|
1615
|
+
if deal.state:
|
|
1616
|
+
print(f" Статус: {deal.state}")
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
Это удобнее, чем использование `FilterBuilder`:
|
|
1620
|
+
|
|
1621
|
+
```python
|
|
1622
|
+
# Альтернатива через FilterBuilder (более сложный способ)
|
|
1623
|
+
from megaplan_sdk import TradeFilterBuilder
|
|
1624
|
+
filter_obj = TradeFilterBuilder().field("contractor").equals(
|
|
1625
|
+
{"contentType": "Contractor", "id": 123}
|
|
1626
|
+
).build()
|
|
1627
|
+
deals = await client.deals.list(filter=filter_obj)
|
|
1628
|
+
```
|
|
1629
|
+
|
|
1450
1630
|
### Поиск сотрудников
|
|
1451
1631
|
|
|
1452
1632
|
Поиск сотрудников по имени или телефону может работать некорректно и возвращать 0 результатов. Для надежного поиска используйте точный email:
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
- [Автоматическая подгрузка связанных сущностей](#автоматическая-подгрузка-связанных-сущностей)
|
|
43
43
|
- [Работа с фильтрами](#работа-с-фильтрами)
|
|
44
44
|
- [Настройка HTTP-клиента](#настройка-http-клиента)
|
|
45
|
+
- [Работа через прокси](#работа-через-прокси)
|
|
45
46
|
- [Ручное управление токенами](#ручное-управление-токенами)
|
|
46
47
|
|
|
47
48
|
### Справочная информация
|
|
@@ -281,7 +282,7 @@ entity = await client.{resource}.update(
|
|
|
281
282
|
```python
|
|
282
283
|
task = await client.tasks.update(task_id=42, task_data={"status": "completed"})
|
|
283
284
|
project = await client.projects.update(project_id=5, project_data={"name": "Новое название"})
|
|
284
|
-
deal = await client.deals.update(deal_id=200, deal_data={"
|
|
285
|
+
deal = await client.deals.update(deal_id=200, deal_data={"price": {"currency": "RUB", "value": 60000}})
|
|
285
286
|
```
|
|
286
287
|
|
|
287
288
|
#### Удаление (`delete`)
|
|
@@ -484,8 +485,8 @@ tasks = await client.tasks.list(filter=filter_obj)
|
|
|
484
485
|
- `tags: list[BaseEntity]` - Теги
|
|
485
486
|
- `attaches: list[BaseEntity]` - Вложения (файлы)
|
|
486
487
|
- `todos: list[BaseEntity]` - Подзадачи-чеклисты
|
|
487
|
-
- `
|
|
488
|
-
- `
|
|
488
|
+
- `time_created: str` - Дата создания (API поле `timeCreated`)
|
|
489
|
+
- `time_updated: str` - Дата обновления (API поле `timeUpdated`)
|
|
489
490
|
|
|
490
491
|
### Упрощенные методы создания
|
|
491
492
|
|
|
@@ -538,6 +539,53 @@ actual_subtasks = await client.tasks.get_actual_sub_tasks(
|
|
|
538
539
|
# Возвращает: list[Task] - список актуальных подзадач
|
|
539
540
|
```
|
|
540
541
|
|
|
542
|
+
### Получение доступных родителей
|
|
543
|
+
|
|
544
|
+
Методы для получения доступных надзадач и надпроектов (для выбора родителя при создании или перемещении задачи):
|
|
545
|
+
|
|
546
|
+
```python
|
|
547
|
+
# Глобальный поиск доступных родителей для новой задачи
|
|
548
|
+
# Возвращает список Task и Project объектов
|
|
549
|
+
parents = await client.tasks.get_available_parents(
|
|
550
|
+
is_template=False, # bool: Фильтр по шаблонам
|
|
551
|
+
limit=10, # int: Количество элементов
|
|
552
|
+
)
|
|
553
|
+
for parent in parents:
|
|
554
|
+
print(f"{type(parent).__name__}: {parent.name}") # "Task: ..." или "Project: ..."
|
|
555
|
+
|
|
556
|
+
# Доступные родители для существующей задачи
|
|
557
|
+
# Исключает саму задачу и её потомков
|
|
558
|
+
parents = await client.tasks.get_available_parents_for(
|
|
559
|
+
task_id=123,
|
|
560
|
+
is_template=False,
|
|
561
|
+
limit=10,
|
|
562
|
+
)
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**Примечание:** Методы возвращают смешанный список объектов `Task` и `Project`, так как задача может быть вложена как в другую задачу, так и в проект.
|
|
566
|
+
|
|
567
|
+
### Получение всех участников задачи
|
|
568
|
+
|
|
569
|
+
Метод `get_all_participants()` возвращает полный список участников задачи (ответственный, соисполнители, аудиторы, владелец) в одном запросе:
|
|
570
|
+
|
|
571
|
+
```python
|
|
572
|
+
participants = await client.tasks.get_all_participants(
|
|
573
|
+
task_id=123,
|
|
574
|
+
limit=None, # int: Количество элементов
|
|
575
|
+
# ... стандартные параметры пагинации
|
|
576
|
+
)
|
|
577
|
+
# Возвращает: list[Employee | ContractorHuman | Group]
|
|
578
|
+
|
|
579
|
+
for participant in participants:
|
|
580
|
+
if hasattr(participant, 'display_name'):
|
|
581
|
+
print(participant.display_name())
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**Типы участников:**
|
|
585
|
+
- `Employee` — сотрудник организации
|
|
586
|
+
- `ContractorHuman` — контрагент-физлицо
|
|
587
|
+
- `Group` — группа участников (например, отдел)
|
|
588
|
+
|
|
541
589
|
### Получение задач на уровне дерева
|
|
542
590
|
|
|
543
591
|
```python
|
|
@@ -695,8 +743,8 @@ milestone = await client.projects.add_milestone(
|
|
|
695
743
|
- `tags: list[BaseEntity]` - Теги
|
|
696
744
|
- `attaches: list[BaseEntity]` - Вложения
|
|
697
745
|
- `todos: list[BaseEntity]` - Подзадачи-чеклисты
|
|
698
|
-
- `
|
|
699
|
-
- `
|
|
746
|
+
- `time_created: str` - Дата создания (API поле `timeCreated`)
|
|
747
|
+
- `time_updated: str` - Дата обновления (API поле `timeUpdated`)
|
|
700
748
|
|
|
701
749
|
### Упрощенные методы создания
|
|
702
750
|
|
|
@@ -758,6 +806,45 @@ actual_issues = await client.projects.get_actual_issues(
|
|
|
758
806
|
# Возвращает: list[Task] - список актуальных задач проекта
|
|
759
807
|
```
|
|
760
808
|
|
|
809
|
+
### Получение доступных родителей
|
|
810
|
+
|
|
811
|
+
Методы для получения доступных родительских проектов (для выбора родителя при создании или перемещении проекта):
|
|
812
|
+
|
|
813
|
+
```python
|
|
814
|
+
# Глобальный поиск доступных родительских проектов
|
|
815
|
+
parents = await client.projects.get_available_parents(
|
|
816
|
+
is_template=False, # bool: Фильтр по шаблонам
|
|
817
|
+
limit=10, # int: Количество элементов
|
|
818
|
+
)
|
|
819
|
+
for parent in parents:
|
|
820
|
+
print(f"Project: {parent.name}")
|
|
821
|
+
|
|
822
|
+
# Доступные родители для существующего проекта
|
|
823
|
+
# Исключает сам проект и его потомков
|
|
824
|
+
parents = await client.projects.get_available_parents_for(
|
|
825
|
+
project_id=456,
|
|
826
|
+
is_template=False,
|
|
827
|
+
limit=10,
|
|
828
|
+
)
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Примечание:** В отличие от задач, проекты могут быть вложены только в другие проекты, поэтому возвращается список объектов `Project`.
|
|
832
|
+
|
|
833
|
+
### Получение всех участников проекта
|
|
834
|
+
|
|
835
|
+
Метод `get_all_participants()` возвращает полный список участников проекта в одном запросе:
|
|
836
|
+
|
|
837
|
+
```python
|
|
838
|
+
participants = await client.projects.get_all_participants(
|
|
839
|
+
project_id=123,
|
|
840
|
+
limit=None, # int: Количество элементов
|
|
841
|
+
)
|
|
842
|
+
# Возвращает: list[Employee | ContractorHuman | Group]
|
|
843
|
+
|
|
844
|
+
for participant in participants:
|
|
845
|
+
print(f"{type(participant).__name__}: {participant.display_name()}")
|
|
846
|
+
```
|
|
847
|
+
|
|
761
848
|
### Получение полной информации о проекте
|
|
762
849
|
|
|
763
850
|
Метод `get_full_details()` для проектов поддерживает следующие специфичные параметры:
|
|
@@ -848,18 +935,26 @@ deals = await client.deals.list(filter=filter_obj)
|
|
|
848
935
|
### Поля модели Deal
|
|
849
936
|
- `id: int` - Идентификатор сделки
|
|
850
937
|
- `name: str` - Название сделки
|
|
938
|
+
- `number: str` - Номер сделки
|
|
939
|
+
- `short_description: str` - Краткое описание
|
|
851
940
|
- `program: BaseEntity` - Программа (схема сделки)
|
|
852
941
|
- `state: ProgramState` - Текущий статус в программе
|
|
853
942
|
- `contractor: BaseEntity` - Контрагент (ContractorCompany/ContractorHuman)
|
|
854
|
-
- `
|
|
855
|
-
- `
|
|
943
|
+
- `manager: BaseEntity` - Ответственный (Employee, API поле `manager`)
|
|
944
|
+
- `price: Money` - Сумма сделки (объект с полями `currency`, `value`)
|
|
945
|
+
- `cost: Money` - Стоимость
|
|
946
|
+
- `debt: Money` - Долг
|
|
947
|
+
- `result: str` - Результат (`"positive"`, `"negative"`, `null`)
|
|
856
948
|
- `currency: BaseEntity` - Валюта
|
|
857
949
|
- `deadline: str` - Срок
|
|
858
|
-
- `description: str` - Описание
|
|
950
|
+
- `description: str` - Описание (только в `deals.get()`, не в списке)
|
|
859
951
|
- `tags: list[BaseEntity]` - Теги
|
|
860
952
|
- `attaches: list[BaseEntity]` - Вложения
|
|
861
|
-
- `
|
|
862
|
-
- `
|
|
953
|
+
- `time_created: str` - Дата создания (API поле `timeCreated`)
|
|
954
|
+
- `time_updated: str` - Дата обновления (API поле `timeUpdated`)
|
|
955
|
+
- `state_time_updated: str` - Дата последнего изменения статуса
|
|
956
|
+
|
|
957
|
+
> **Примечание:** Поля `description`, `deadline` и пользовательские поля доступны только при запросе отдельной сделки через `deals.get(id)`, но не в списке.
|
|
863
958
|
|
|
864
959
|
**Важно:** При создании сделки обязательно указывать поле `program` (программа/схема сделки).
|
|
865
960
|
|
|
@@ -885,6 +980,23 @@ deal = await client.deals.apply_trigger(
|
|
|
885
980
|
# Возвращает: Deal - обновленная сделка
|
|
886
981
|
```
|
|
887
982
|
|
|
983
|
+
### Получение всех участников сделки
|
|
984
|
+
|
|
985
|
+
Метод `get_all_participants()` возвращает полный список участников сделки:
|
|
986
|
+
|
|
987
|
+
```python
|
|
988
|
+
participants = await client.deals.get_all_participants(
|
|
989
|
+
deal_id=200,
|
|
990
|
+
limit=None, # int: Количество элементов
|
|
991
|
+
)
|
|
992
|
+
# Возвращает: list[Employee]
|
|
993
|
+
|
|
994
|
+
for employee in participants:
|
|
995
|
+
print(employee.display_name())
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
**Примечание:** В отличие от задач и проектов, сделки возвращают только сотрудников (`Employee`).
|
|
999
|
+
|
|
888
1000
|
### Получение аудиторов сделки
|
|
889
1001
|
|
|
890
1002
|
```python
|
|
@@ -927,7 +1039,7 @@ details = await client.deals.get_full_details(
|
|
|
927
1039
|
include_history=True, # Загрузить историю изменений
|
|
928
1040
|
include_status_history=True, # Загрузить историю статусов
|
|
929
1041
|
include_auditors=True, # Загрузить список аудиторов
|
|
930
|
-
|
|
1042
|
+
include_manager_details=True, # Загрузить полные данные ответственного
|
|
931
1043
|
include_contractor_details=True, # Загрузить полные данные контрагента
|
|
932
1044
|
include_related_tasks=True, # Загрузить связанные задачи
|
|
933
1045
|
comments_limit=50, # Лимит комментариев (опционально)
|
|
@@ -941,7 +1053,7 @@ details = await client.deals.get_full_details(
|
|
|
941
1053
|
- `history: list[dict] | None` - История изменений
|
|
942
1054
|
- `status_history: list[dict] | None` - История статусов
|
|
943
1055
|
- `auditors: list[dict] | None` - Аудиторы
|
|
944
|
-
- `
|
|
1056
|
+
- `manager_details: Employee | None` - Полные данные ответственного
|
|
945
1057
|
- `contractor_details: Contractor | None` - Полные данные контрагента
|
|
946
1058
|
- `related_tasks: list[Task] | None` - Связанные задачи
|
|
947
1059
|
|
|
@@ -1142,14 +1254,14 @@ for task_full in tasks_full:
|
|
|
1142
1254
|
### Использование expand в сделках
|
|
1143
1255
|
|
|
1144
1256
|
```python
|
|
1145
|
-
deals_full = await client.deals.list(limit=10, expand=["
|
|
1257
|
+
deals_full = await client.deals.list(limit=10, expand=["manager", "contractor"])
|
|
1146
1258
|
|
|
1147
1259
|
for deal_full in deals_full:
|
|
1148
1260
|
deal = deal_full.deal
|
|
1149
1261
|
print(f"Сделка: {deal.name}")
|
|
1150
1262
|
|
|
1151
|
-
if deal_full.
|
|
1152
|
-
print(f"Ответственный: {deal_full.
|
|
1263
|
+
if deal_full.manager_details:
|
|
1264
|
+
print(f"Ответственный: {deal_full.manager_details.display_name()}")
|
|
1153
1265
|
|
|
1154
1266
|
if deal_full.contractor_details:
|
|
1155
1267
|
print(f"Контрагент: {deal_full.contractor_details.display_name()}")
|
|
@@ -1160,7 +1272,7 @@ for deal_full in deals_full:
|
|
|
1160
1272
|
```
|
|
1161
1273
|
|
|
1162
1274
|
**Поддерживаемые поля для expand в сделках:**
|
|
1163
|
-
- `
|
|
1275
|
+
- `manager` - ответственный сотрудник
|
|
1164
1276
|
- `contractor` - контрагент
|
|
1165
1277
|
|
|
1166
1278
|
### Использование expand в проектах
|
|
@@ -1370,6 +1482,48 @@ client = MegaplanClient(
|
|
|
1370
1482
|
)
|
|
1371
1483
|
```
|
|
1372
1484
|
|
|
1485
|
+
### Работа через прокси
|
|
1486
|
+
|
|
1487
|
+
SDK поддерживает работу через HTTP/HTTPS/SOCKS5 прокси-серверы. Это полезно для корпоративных сетей, где все запросы должны проходить через прокси.
|
|
1488
|
+
|
|
1489
|
+
```python
|
|
1490
|
+
# HTTP прокси с аутентификацией
|
|
1491
|
+
async with MegaplanClient(
|
|
1492
|
+
base_url="https://my.megaplan.ru",
|
|
1493
|
+
username="user@example.com",
|
|
1494
|
+
password="password",
|
|
1495
|
+
proxy="http://login:pass@proxy.corp.local:8080",
|
|
1496
|
+
) as client:
|
|
1497
|
+
tasks = await client.tasks.list()
|
|
1498
|
+
|
|
1499
|
+
# HTTP прокси без аутентификации
|
|
1500
|
+
client = MegaplanClient(
|
|
1501
|
+
base_url="https://my.megaplan.ru",
|
|
1502
|
+
access_token="token",
|
|
1503
|
+
proxy="http://proxy.corp.local:8080",
|
|
1504
|
+
)
|
|
1505
|
+
|
|
1506
|
+
# HTTPS прокси
|
|
1507
|
+
client = MegaplanClient(
|
|
1508
|
+
base_url="https://my.megaplan.ru",
|
|
1509
|
+
access_token="token",
|
|
1510
|
+
proxy="https://proxy.corp.local:8080",
|
|
1511
|
+
)
|
|
1512
|
+
|
|
1513
|
+
# SOCKS5 прокси (требует httpx[socks])
|
|
1514
|
+
client = MegaplanClient(
|
|
1515
|
+
base_url="https://my.megaplan.ru",
|
|
1516
|
+
access_token="token",
|
|
1517
|
+
proxy="socks5://user:pass@proxy.corp.local:1080",
|
|
1518
|
+
)
|
|
1519
|
+
```
|
|
1520
|
+
|
|
1521
|
+
**Поддерживаемые форматы прокси:**
|
|
1522
|
+
- `http://proxy:port` - HTTP прокси без аутентификации
|
|
1523
|
+
- `http://user:password@proxy:port` - HTTP прокси с аутентификацией
|
|
1524
|
+
- `https://proxy:port` - HTTPS прокси
|
|
1525
|
+
- `socks5://user:password@proxy:port` - SOCKS5 прокси (требует `pip install httpx[socks]`)
|
|
1526
|
+
|
|
1373
1527
|
### Ручное управление токенами
|
|
1374
1528
|
|
|
1375
1529
|
```python
|
|
@@ -1408,13 +1562,39 @@ API возвращает ошибку 500 при попытке получить
|
|
|
1408
1562
|
# comments = await client.contractors.get_comments(contractor_id=123)
|
|
1409
1563
|
|
|
1410
1564
|
# Вместо этого используйте комментарии в сделках контрагента
|
|
1411
|
-
deals = await client.
|
|
1412
|
-
base_on={"contentType": "Contractor", "id": 123}
|
|
1413
|
-
)
|
|
1565
|
+
deals = await client.contractors.get_deals(contractor_id=123)
|
|
1414
1566
|
for deal in deals:
|
|
1415
1567
|
comments = await client.deals.get_comments(deal.id)
|
|
1416
1568
|
```
|
|
1417
1569
|
|
|
1570
|
+
### Получение сделок контрагента
|
|
1571
|
+
|
|
1572
|
+
SDK предоставляет удобный метод `get_deals()` для получения сделок контрагента:
|
|
1573
|
+
|
|
1574
|
+
```python
|
|
1575
|
+
# Получить все сделки контрагента
|
|
1576
|
+
deals = await client.contractors.get_deals(
|
|
1577
|
+
contractor_id=123,
|
|
1578
|
+
limit=50 # Опционально
|
|
1579
|
+
)
|
|
1580
|
+
|
|
1581
|
+
for deal in deals:
|
|
1582
|
+
print(f"[{deal.id}] {deal.name}")
|
|
1583
|
+
if deal.state:
|
|
1584
|
+
print(f" Статус: {deal.state}")
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
Это удобнее, чем использование `FilterBuilder`:
|
|
1588
|
+
|
|
1589
|
+
```python
|
|
1590
|
+
# Альтернатива через FilterBuilder (более сложный способ)
|
|
1591
|
+
from megaplan_sdk import TradeFilterBuilder
|
|
1592
|
+
filter_obj = TradeFilterBuilder().field("contractor").equals(
|
|
1593
|
+
{"contentType": "Contractor", "id": 123}
|
|
1594
|
+
).build()
|
|
1595
|
+
deals = await client.deals.list(filter=filter_obj)
|
|
1596
|
+
```
|
|
1597
|
+
|
|
1418
1598
|
### Поиск сотрудников
|
|
1419
1599
|
|
|
1420
1600
|
Поиск сотрудников по имени или телефону может работать некорректно и возвращать 0 результатов. Для надежного поиска используйте точный email:
|