bfocus 0.2.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: bfocus
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: SDK oficial em Python da API pública do bFocus: clientes, produtos, release notes, base de conhecimento e agentes de IA.
5
5
  Project-URL: Homepage, https://bfocus.com.br
6
6
  Project-URL: Repository, https://github.com/bernisoftware/bfocus-python
@@ -196,7 +196,11 @@ bf.people.upsert("erp-1042", "app-77", access=True) # devolve o acesso
196
196
 
197
197
  - **Nunca duplica**: se o e-mail (ou o telefone) já pertence a uma pessoa que chegou por e-mail
198
198
  ou por outro sistema, ela é **adotada** e ganha o seu `external_id`.
199
- - A mesma pessoa informada com **outro cliente** é transferida para ele.
199
+ - A mesma pessoa informada com **outro cliente** NÃO é transferida: ela é **ligada** também a
200
+ esse cliente e a resposta volta com `linked=True`. O cadastro é único e a mesma pessoa circula
201
+ por vários clientes e vários produtos.
202
+ - **O acesso é do vínculo.** `delete` (e `access=False`) tira o acesso dela NESTE cliente, não nos
203
+ outros: `unlinked=True` na resposta quer dizer que ela segue ativa em algum outro.
200
204
  - `delete` **retira o acesso** (devolve a pessoa com `access=False`); ela continua no histórico
201
205
  de chamados e conversas. Um `upsert` com `access=True` devolve o acesso.
202
206
  - Como nos outros upserts, só o que você passa muda; `name` é obrigatório ao criar.
@@ -169,7 +169,11 @@ bf.people.upsert("erp-1042", "app-77", access=True) # devolve o acesso
169
169
 
170
170
  - **Nunca duplica**: se o e-mail (ou o telefone) já pertence a uma pessoa que chegou por e-mail
171
171
  ou por outro sistema, ela é **adotada** e ganha o seu `external_id`.
172
- - A mesma pessoa informada com **outro cliente** é transferida para ele.
172
+ - A mesma pessoa informada com **outro cliente** NÃO é transferida: ela é **ligada** também a
173
+ esse cliente e a resposta volta com `linked=True`. O cadastro é único e a mesma pessoa circula
174
+ por vários clientes e vários produtos.
175
+ - **O acesso é do vínculo.** `delete` (e `access=False`) tira o acesso dela NESTE cliente, não nos
176
+ outros: `unlinked=True` na resposta quer dizer que ela segue ativa em algum outro.
173
177
  - `delete` **retira o acesso** (devolve a pessoa com `access=False`); ela continua no histórico
174
178
  de chamados e conversas. Um `upsert` com `access=True` devolve o acesso.
175
179
  - Como nos outros upserts, só o que você passa muda; `name` é obrigatório ao criar.
@@ -52,6 +52,7 @@ from .types import (
52
52
  Person,
53
53
  PersonBatchItem,
54
54
  PersonIdentifiers,
55
+ PersonRevokeResult,
55
56
  PersonUpsertResult,
56
57
  Product,
57
58
  ProductRef,
@@ -654,7 +655,8 @@ class People(_Resource):
654
655
  ``PUT /customers/{customer_external_id}/people/{person_external_id}``. O ``status``
655
656
  do retorno diz ``"created"``, ``"updated"`` ou ``"unchanged"``. Se o e-mail (ou o
656
657
  telefone) já pertence a uma pessoa que chegou por outro caminho, ela é **adotada**
657
- (nunca duplicada); a mesma pessoa informada com outro cliente é transferida.
658
+ (nunca duplicada); a mesma pessoa informada com outro cliente é LIGADA a ele também
659
+ (cadastro único em N clientes) e ``linked`` volta ``True``.
658
660
 
659
661
  Args:
660
662
  name: Obrigatório ao criar.
@@ -711,12 +713,13 @@ class People(_Resource):
711
713
  *,
712
714
  idempotency_key: Optional[str] = None,
713
715
  timeout: Optional[float] = None,
714
- ) -> Person:
715
- """Retira o acesso da pessoa (devolve a pessoa com ``access=False``).
716
+ ) -> PersonRevokeResult:
717
+ """Retira o acesso da pessoa NESTE cliente (devolve a pessoa com ``access=False``).
716
718
 
717
719
  ``DELETE /customers/{customer_external_id}/people/{person_external_id}``. A pessoa
718
720
  continua no histórico (chamados, conversas); :meth:`upsert` com ``access=True``
719
- devolve o acesso.
721
+ devolve o acesso. O acesso é DO VÍNCULO: se ela também é de outros clientes, continua
722
+ ativa neles e a resposta volta com ``unlinked=True``.
720
723
  """
721
724
  cext = path_segment(customer_external_id, "customer_external_id")
722
725
  pid = path_segment(person_external_id, "person_external_id")
@@ -724,7 +727,7 @@ class People(_Resource):
724
727
  "DELETE", f"/customers/{cext}/people/{pid}",
725
728
  idempotency_key=idempotency_key, timeout=timeout,
726
729
  )
727
- return cast(Person, data)
730
+ return cast(PersonRevokeResult, data)
728
731
 
729
732
  def batch(
730
733
  self,
@@ -1,3 +1,3 @@
1
1
  """Versão da SDK. O ``scripts/release-sdks.sh`` bumpa esta linha e o ``pyproject.toml``."""
2
2
 
3
- __version__ = "0.2.1"
3
+ __version__ = "0.2.2"
@@ -36,6 +36,7 @@ __all__ = [
36
36
  "AgentPreview",
37
37
  "Deleted",
38
38
  "Person",
39
+ "PersonRevokeResult",
39
40
  "PersonUpsertResult",
40
41
  "Identifier",
41
42
  "CustomerWithIdentifiers",
@@ -228,6 +229,12 @@ class Customer(TypedDict):
228
229
  notes: Optional[str]
229
230
  custom_fields: List[CustomField]
230
231
  is_active: bool
232
+ #: Logotipo do cliente, como a equipe subiu no bFocus (``None`` = sem logotipo).
233
+ logo_url: Optional[str]
234
+ #: E-mails adicionais do cliente (o principal é ``email``).
235
+ extra_emails: List[str]
236
+ #: Telefones adicionais do cliente (o principal é ``phone``).
237
+ extra_phones: List[str]
231
238
  created_at: Optional[str]
232
239
  updated_at: Optional[str]
233
240
 
@@ -385,12 +392,30 @@ class Person(TypedDict):
385
392
  is_primary: bool
386
393
  customer_external_id: str
387
394
  custom_fields: List[CustomField]
395
+ #: Identificadores EXTRAS desta pessoa: os outros ids pelos quais ela também é encontrada.
396
+ #: É por aqui que você descobre que o id do SEU sistema virou apelido de outra ficha.
397
+ identifiers: List["Identifier"]
388
398
 
389
399
 
390
400
  class PersonUpsertResult(Person):
391
- """Retorno de ``people.upsert``: a pessoa + ``status``."""
401
+ """Retorno de ``people.upsert``: a pessoa + ``status`` + ``linked``."""
392
402
 
393
403
  status: Literal["created", "updated", "unchanged"]
404
+ #: ``True`` = a pessoa JÁ EXISTIA em outro cliente e este envio a ligou também a este.
405
+ #: O cadastro é único e ela circula pelos dois; nada foi transferido nem duplicado.
406
+ linked: bool
407
+ #: Preenchido quando o id que você enviou é um APELIDO: este é o principal do cadastro.
408
+ merged_into: Optional[str]
409
+
410
+
411
+ class PersonRevokeResult(Person):
412
+ """Retorno de ``people.delete``: a pessoa + se ela apenas SAIU deste cliente.
413
+
414
+ ``unlinked=True`` = ela continua com acesso, porque também é de outros clientes; o acesso é
415
+ do vínculo. ``False`` = era só deste cliente e foi desligada, como sempre.
416
+ """
417
+
418
+ unlinked: bool
394
419
 
395
420
 
396
421
  class Identifier(TypedDict):
@@ -424,6 +449,8 @@ class BatchItemResult(TypedDict):
424
449
  status: Literal["created", "updated", "unchanged", "error"]
425
450
  external_id: Optional[str]
426
451
  merged_into: Optional[str]
452
+ #: A pessoa já existia em outro cliente e este item a ligou também a este (cadastro único).
453
+ linked: bool
427
454
  error: Optional[str]
428
455
  code: Optional[int]
429
456
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bfocus"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "SDK oficial em Python da API pública do bFocus: clientes, produtos, release notes, base de conhecimento e agentes de IA."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -69,6 +69,9 @@
69
69
  }
70
70
  ],
71
71
  "is_active": true,
72
+ "logo_url": null,
73
+ "extra_emails": [],
74
+ "extra_phones": [],
72
75
  "created_at": "2026-09-13T12:00:00+00:00",
73
76
  "updated_at": "2026-09-13T12:00:00+00:00"
74
77
  },
@@ -97,6 +100,9 @@
97
100
  }
98
101
  ],
99
102
  "is_active": true,
103
+ "logo_url": null,
104
+ "extra_emails": [],
105
+ "extra_phones": [],
100
106
  "created_at": "2026-09-13T12:00:00+00:00",
101
107
  "updated_at": "2026-09-13T12:00:00+00:00"
102
108
  }
@@ -144,6 +150,9 @@
144
150
  }
145
151
  ],
146
152
  "is_active": true,
153
+ "logo_url": null,
154
+ "extra_emails": [],
155
+ "extra_phones": [],
147
156
  "created_at": "2026-09-13T12:00:00+00:00",
148
157
  "updated_at": "2026-09-13T12:00:00+00:00"
149
158
  },
@@ -172,6 +181,9 @@
172
181
  }
173
182
  ],
174
183
  "is_active": true,
184
+ "logo_url": null,
185
+ "extra_emails": [],
186
+ "extra_phones": [],
175
187
  "created_at": "2026-09-13T12:00:00+00:00",
176
188
  "updated_at": "2026-09-13T12:00:00+00:00"
177
189
  }
@@ -216,6 +228,9 @@
216
228
  }
217
229
  ],
218
230
  "is_active": true,
231
+ "logo_url": null,
232
+ "extra_emails": [],
233
+ "extra_phones": [],
219
234
  "created_at": "2026-09-13T12:00:00+00:00",
220
235
  "updated_at": "2026-09-13T12:00:00+00:00"
221
236
  },
@@ -244,6 +259,9 @@
244
259
  }
245
260
  ],
246
261
  "is_active": true,
262
+ "logo_url": null,
263
+ "extra_emails": [],
264
+ "extra_phones": [],
247
265
  "created_at": "2026-09-13T12:00:00+00:00",
248
266
  "updated_at": "2026-09-13T12:00:00+00:00"
249
267
  }
@@ -327,6 +345,9 @@
327
345
  "notes": null,
328
346
  "custom_fields": [],
329
347
  "is_active": true,
348
+ "logo_url": null,
349
+ "extra_emails": [],
350
+ "extra_phones": [],
330
351
  "created_at": "2026-09-13T12:00:00+00:00",
331
352
  "updated_at": "2026-09-13T12:00:00+00:00"
332
353
  }
@@ -356,6 +377,9 @@
356
377
  "notes": null,
357
378
  "custom_fields": [],
358
379
  "is_active": true,
380
+ "logo_url": null,
381
+ "extra_emails": [],
382
+ "extra_phones": [],
359
383
  "created_at": "2026-09-13T12:00:00+00:00",
360
384
  "updated_at": "2026-09-13T12:00:00+00:00"
361
385
  }
@@ -410,6 +434,9 @@
410
434
  }
411
435
  ],
412
436
  "is_active": true,
437
+ "logo_url": null,
438
+ "extra_emails": [],
439
+ "extra_phones": [],
413
440
  "created_at": "2026-09-13T12:00:00+00:00",
414
441
  "updated_at": "2026-09-13T12:00:00+00:00"
415
442
  }
@@ -452,6 +479,9 @@
452
479
  "notes": null,
453
480
  "custom_fields": [],
454
481
  "is_active": true,
482
+ "logo_url": null,
483
+ "extra_emails": [],
484
+ "extra_phones": [],
455
485
  "created_at": "2026-09-13T12:00:00+00:00",
456
486
  "updated_at": "2026-09-13T12:00:00+00:00"
457
487
  }
@@ -488,6 +518,9 @@
488
518
  }
489
519
  ],
490
520
  "is_active": true,
521
+ "logo_url": null,
522
+ "extra_emails": [],
523
+ "extra_phones": [],
491
524
  "created_at": "2026-09-13T12:00:00+00:00",
492
525
  "updated_at": "2026-09-13T12:00:00+00:00"
493
526
  },
@@ -502,6 +535,9 @@
502
535
  "notes": null,
503
536
  "custom_fields": [],
504
537
  "is_active": true,
538
+ "logo_url": null,
539
+ "extra_emails": [],
540
+ "extra_phones": [],
505
541
  "created_at": "2026-09-13T12:00:00+00:00",
506
542
  "updated_at": "2026-09-13T12:00:00+00:00"
507
543
  }
@@ -1029,6 +1065,9 @@
1029
1065
  "visibility": "interno"
1030
1066
  }
1031
1067
  ],
1068
+ "identifiers": [],
1069
+ "linked": false,
1070
+ "merged_into": null,
1032
1071
  "status": "created"
1033
1072
  },
1034
1073
  "message": "Executado com sucesso"
@@ -1054,6 +1093,9 @@
1054
1093
  "visibility": "interno"
1055
1094
  }
1056
1095
  ],
1096
+ "identifiers": [],
1097
+ "linked": false,
1098
+ "merged_into": null,
1057
1099
  "status": "created"
1058
1100
  }
1059
1101
  }
@@ -1109,6 +1151,9 @@
1109
1151
  "visibility": "interno"
1110
1152
  }
1111
1153
  ],
1154
+ "identifiers": [],
1155
+ "linked": false,
1156
+ "merged_into": null,
1112
1157
  "status": "updated"
1113
1158
  },
1114
1159
  "message": "Executado com sucesso"
@@ -1134,6 +1179,9 @@
1134
1179
  "visibility": "interno"
1135
1180
  }
1136
1181
  ],
1182
+ "identifiers": [],
1183
+ "linked": false,
1184
+ "merged_into": null,
1137
1185
  "status": "updated"
1138
1186
  }
1139
1187
  }
@@ -1221,7 +1269,8 @@
1221
1269
  "value": "4471",
1222
1270
  "visibility": "interno"
1223
1271
  }
1224
- ]
1272
+ ],
1273
+ "identifiers": []
1225
1274
  },
1226
1275
  {
1227
1276
  "external_id": null,
@@ -1232,7 +1281,8 @@
1232
1281
  "access": false,
1233
1282
  "is_primary": false,
1234
1283
  "customer_external_id": "ERP 1042",
1235
- "custom_fields": []
1284
+ "custom_fields": [],
1285
+ "identifiers": []
1236
1286
  }
1237
1287
  ],
1238
1288
  "message": "Executado com sucesso"
@@ -1258,7 +1308,8 @@
1258
1308
  "value": "4471",
1259
1309
  "visibility": "interno"
1260
1310
  }
1261
- ]
1311
+ ],
1312
+ "identifiers": []
1262
1313
  },
1263
1314
  {
1264
1315
  "external_id": null,
@@ -1269,7 +1320,8 @@
1269
1320
  "access": false,
1270
1321
  "is_primary": false,
1271
1322
  "customer_external_id": "ERP 1042",
1272
- "custom_fields": []
1323
+ "custom_fields": [],
1324
+ "identifiers": []
1273
1325
  }
1274
1326
  ]
1275
1327
  }
@@ -1311,7 +1363,9 @@
1311
1363
  "value": "4471",
1312
1364
  "visibility": "interno"
1313
1365
  }
1314
- ]
1366
+ ],
1367
+ "identifiers": [],
1368
+ "unlinked": false
1315
1369
  },
1316
1370
  "message": "Acesso retirado"
1317
1371
  }
@@ -1335,7 +1389,9 @@
1335
1389
  "value": "4471",
1336
1390
  "visibility": "interno"
1337
1391
  }
1338
- ]
1392
+ ],
1393
+ "identifiers": [],
1394
+ "unlinked": false
1339
1395
  }
1340
1396
  }
1341
1397
  },
@@ -1427,6 +1483,7 @@
1427
1483
  "status": "updated",
1428
1484
  "external_id": "ERP 1042",
1429
1485
  "merged_into": null,
1486
+ "linked": false,
1430
1487
  "error": null,
1431
1488
  "code": null
1432
1489
  },
@@ -1435,6 +1492,7 @@
1435
1492
  "status": "error",
1436
1493
  "external_id": "ERP 1044",
1437
1494
  "merged_into": null,
1495
+ "linked": false,
1438
1496
  "error": "NAME_REQUIRED",
1439
1497
  "code": 422
1440
1498
  }
@@ -1459,6 +1517,7 @@
1459
1517
  "status": "updated",
1460
1518
  "external_id": "ERP 1042",
1461
1519
  "merged_into": null,
1520
+ "linked": false,
1462
1521
  "error": null,
1463
1522
  "code": null
1464
1523
  },
@@ -1467,6 +1526,7 @@
1467
1526
  "status": "error",
1468
1527
  "external_id": "ERP 1044",
1469
1528
  "merged_into": null,
1529
+ "linked": false,
1470
1530
  "error": "NAME_REQUIRED",
1471
1531
  "code": 422
1472
1532
  }
@@ -1558,6 +1618,7 @@
1558
1618
  "status": "created",
1559
1619
  "external_id": "app-77",
1560
1620
  "merged_into": null,
1621
+ "linked": false,
1561
1622
  "error": null,
1562
1623
  "code": null
1563
1624
  },
@@ -1566,6 +1627,7 @@
1566
1627
  "status": "error",
1567
1628
  "external_id": "app-78",
1568
1629
  "merged_into": null,
1630
+ "linked": false,
1569
1631
  "error": "CUSTOMER_NOT_FOUND",
1570
1632
  "code": 404
1571
1633
  }
@@ -1590,6 +1652,7 @@
1590
1652
  "status": "created",
1591
1653
  "external_id": "app-77",
1592
1654
  "merged_into": null,
1655
+ "linked": false,
1593
1656
  "error": null,
1594
1657
  "code": null
1595
1658
  },
@@ -1598,6 +1661,7 @@
1598
1661
  "status": "error",
1599
1662
  "external_id": "app-78",
1600
1663
  "merged_into": null,
1664
+ "linked": false,
1601
1665
  "error": "CUSTOMER_NOT_FOUND",
1602
1666
  "code": 404
1603
1667
  }
@@ -1673,6 +1737,9 @@
1673
1737
  }
1674
1738
  ],
1675
1739
  "is_active": true,
1740
+ "logo_url": null,
1741
+ "extra_emails": [],
1742
+ "extra_phones": [],
1676
1743
  "created_at": "2026-09-13T12:00:00+00:00",
1677
1744
  "updated_at": "2026-09-13T12:00:00+00:00",
1678
1745
  "identifiers": [
@@ -1708,6 +1775,9 @@
1708
1775
  }
1709
1776
  ],
1710
1777
  "is_active": true,
1778
+ "logo_url": null,
1779
+ "extra_emails": [],
1780
+ "extra_phones": [],
1711
1781
  "created_at": "2026-09-13T12:00:00+00:00",
1712
1782
  "updated_at": "2026-09-13T12:00:00+00:00",
1713
1783
  "identifiers": [
@@ -1806,6 +1876,9 @@
1806
1876
  }
1807
1877
  ],
1808
1878
  "is_active": true,
1879
+ "logo_url": null,
1880
+ "extra_emails": [],
1881
+ "extra_phones": [],
1809
1882
  "created_at": "2026-09-13T12:00:00+00:00",
1810
1883
  "updated_at": "2026-09-13T12:00:00+00:00",
1811
1884
  "identifiers": []
@@ -1835,6 +1908,9 @@
1835
1908
  }
1836
1909
  ],
1837
1910
  "is_active": true,
1911
+ "logo_url": null,
1912
+ "extra_emails": [],
1913
+ "extra_phones": [],
1838
1914
  "created_at": "2026-09-13T12:00:00+00:00",
1839
1915
  "updated_at": "2026-09-13T12:00:00+00:00",
1840
1916
  "identifiers": []
@@ -3596,6 +3672,9 @@
3596
3672
  }
3597
3673
  ],
3598
3674
  "is_active": true,
3675
+ "logo_url": null,
3676
+ "extra_emails": [],
3677
+ "extra_phones": [],
3599
3678
  "created_at": "2026-09-13T12:00:00+00:00",
3600
3679
  "updated_at": "2026-09-13T12:00:00+00:00"
3601
3680
  },
@@ -3624,6 +3703,9 @@
3624
3703
  }
3625
3704
  ],
3626
3705
  "is_active": true,
3706
+ "logo_url": null,
3707
+ "extra_emails": [],
3708
+ "extra_phones": [],
3627
3709
  "created_at": "2026-09-13T12:00:00+00:00",
3628
3710
  "updated_at": "2026-09-13T12:00:00+00:00"
3629
3711
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes