dub 0.34.1__py3-none-any.whl → 0.35.0__py3-none-any.whl

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.
Files changed (93) hide show
  1. dub/_version.py +3 -3
  2. dub/basesdk.py +20 -6
  3. dub/models/components/__init__.py +108 -26
  4. dub/models/components/analyticsbrowsers.py +18 -1
  5. dub/models/components/analyticscities.py +18 -1
  6. dub/models/components/analyticscontinents.py +18 -1
  7. dub/models/components/analyticscount.py +18 -1
  8. dub/models/components/analyticscountries.py +20 -1
  9. dub/models/components/analyticsdevices.py +18 -1
  10. dub/models/components/analyticsos.py +18 -1
  11. dub/models/components/analyticsreferers.py +18 -1
  12. dub/models/components/analyticsrefererurls.py +18 -1
  13. dub/models/components/analyticsregions.py +18 -1
  14. dub/models/components/analyticstimeseries.py +18 -1
  15. dub/models/components/analyticstoplinks.py +16 -26
  16. dub/models/components/analyticstopurls.py +18 -1
  17. dub/models/components/analyticstriggers.py +18 -1
  18. dub/models/components/commissioncreatedevent.py +96 -64
  19. dub/models/components/domainschema.py +31 -50
  20. dub/models/components/folderschema.py +18 -19
  21. dub/models/components/leadcreatedevent.py +151 -134
  22. dub/models/components/linkclickedevent.py +57 -70
  23. dub/models/components/linkschema.py +63 -64
  24. dub/models/components/linkwebhookevent.py +43 -51
  25. dub/models/components/partneranalyticscount.py +18 -1
  26. dub/models/components/partneranalyticstimeseries.py +18 -1
  27. dub/models/components/partneranalyticstoplinks.py +16 -27
  28. dub/models/components/partnerapplicationsubmittedevent.py +42 -75
  29. dub/models/components/partnerenrolledevent.py +477 -83
  30. dub/models/components/salecreatedevent.py +152 -151
  31. dub/models/errors/badrequest.py +18 -1
  32. dub/models/errors/conflict.py +18 -1
  33. dub/models/errors/forbidden.py +18 -1
  34. dub/models/errors/internalservererror.py +18 -1
  35. dub/models/errors/inviteexpired.py +18 -1
  36. dub/models/errors/notfound.py +18 -1
  37. dub/models/errors/ratelimitexceeded.py +18 -1
  38. dub/models/errors/unauthorized.py +18 -1
  39. dub/models/errors/unprocessableentity.py +18 -1
  40. dub/models/operations/__init__.py +230 -19
  41. dub/models/operations/approvebountysubmission.py +71 -45
  42. dub/models/operations/banpartner.py +14 -19
  43. dub/models/operations/bulkcreatelinks.py +86 -87
  44. dub/models/operations/bulkupdatelinks.py +97 -82
  45. dub/models/operations/checkdomainstatus.py +1 -17
  46. dub/models/operations/createdomain.py +33 -34
  47. dub/models/operations/createfolder.py +18 -19
  48. dub/models/operations/createlink.py +86 -87
  49. dub/models/operations/createpartner.py +560 -168
  50. dub/models/operations/createpartnerlink.py +74 -85
  51. dub/models/operations/createreferralsembedtoken.py +99 -87
  52. dub/models/operations/createtag.py +18 -1
  53. dub/models/operations/deactivatepartner.py +65 -0
  54. dub/models/operations/getcustomer.py +106 -105
  55. dub/models/operations/getcustomers.py +123 -105
  56. dub/models/operations/getlinkinfo.py +18 -1
  57. dub/models/operations/getlinks.py +36 -1
  58. dub/models/operations/getlinkscount.py +32 -1
  59. dub/models/operations/getqrcode.py +29 -1
  60. dub/models/operations/gettags.py +20 -1
  61. dub/models/operations/listbountysubmissions.py +63 -26
  62. dub/models/operations/listcommissions.py +129 -64
  63. dub/models/operations/listdomains.py +18 -1
  64. dub/models/operations/listevents.py +414 -389
  65. dub/models/operations/listfolders.py +18 -1
  66. dub/models/operations/listpartners.py +510 -84
  67. dub/models/operations/registerdomain.py +1 -17
  68. dub/models/operations/rejectbountysubmission.py +71 -26
  69. dub/models/operations/retrieveanalytics.py +65 -66
  70. dub/models/operations/retrievelinks.py +30 -19
  71. dub/models/operations/retrievepartneranalytics.py +25 -28
  72. dub/models/operations/tracklead.py +38 -83
  73. dub/models/operations/tracksale.py +52 -95
  74. dub/models/operations/updatecommission.py +126 -64
  75. dub/models/operations/updatecustomer.py +122 -131
  76. dub/models/operations/updatedomain.py +50 -35
  77. dub/models/operations/updatefolder.py +34 -19
  78. dub/models/operations/updatelink.py +101 -86
  79. dub/models/operations/updatetag.py +34 -1
  80. dub/models/operations/upsertlink.py +86 -87
  81. dub/models/operations/upsertpartnerlink.py +72 -78
  82. dub/partners.py +288 -0
  83. dub/sdk.py +0 -3
  84. dub/utils/__init__.py +10 -1
  85. {dub-0.34.1.dist-info → dub-0.35.0.dist-info}/METADATA +4 -8
  86. dub-0.35.0.dist-info/RECORD +143 -0
  87. dub/models/components/workspaceschema.py +0 -328
  88. dub/models/operations/getworkspace.py +0 -21
  89. dub/models/operations/updateworkspace.py +0 -78
  90. dub/workspaces.py +0 -561
  91. dub-0.34.1.dist-info/RECORD +0 -146
  92. {dub-0.34.1.dist-info → dub-0.35.0.dist-info}/WHEEL +0 -0
  93. {dub-0.34.1.dist-info → dub-0.35.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,9 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
  from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
5
+ from dub.utils import get_discriminator
5
6
  from enum import Enum
6
7
  import pydantic
7
- from pydantic import model_serializer
8
+ from pydantic import Discriminator, Tag, model_serializer
8
9
  from typing import List, Optional, Union
9
10
  from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict
10
11
 
@@ -184,71 +185,70 @@ class LinkProps(BaseModel):
184
185
 
185
186
  @model_serializer(mode="wrap")
186
187
  def serialize_model(self, handler):
187
- optional_fields = [
188
- "keyLength",
189
- "externalId",
190
- "tenantId",
191
- "prefix",
192
- "archived",
193
- "tagIds",
194
- "tagNames",
195
- "comments",
196
- "expiresAt",
197
- "expiredUrl",
198
- "password",
199
- "proxy",
200
- "title",
201
- "description",
202
- "image",
203
- "video",
204
- "rewrite",
205
- "ios",
206
- "android",
207
- "doIndex",
208
- "testVariants",
209
- "testStartedAt",
210
- "testCompletedAt",
211
- ]
212
- nullable_fields = [
213
- "externalId",
214
- "tenantId",
215
- "comments",
216
- "expiresAt",
217
- "expiredUrl",
218
- "password",
219
- "title",
220
- "description",
221
- "image",
222
- "video",
223
- "ios",
224
- "android",
225
- "testVariants",
226
- "testStartedAt",
227
- "testCompletedAt",
228
- ]
229
- null_default_fields = []
230
-
188
+ optional_fields = set(
189
+ [
190
+ "keyLength",
191
+ "externalId",
192
+ "tenantId",
193
+ "prefix",
194
+ "archived",
195
+ "tagIds",
196
+ "tagNames",
197
+ "comments",
198
+ "expiresAt",
199
+ "expiredUrl",
200
+ "password",
201
+ "proxy",
202
+ "title",
203
+ "description",
204
+ "image",
205
+ "video",
206
+ "rewrite",
207
+ "ios",
208
+ "android",
209
+ "doIndex",
210
+ "testVariants",
211
+ "testStartedAt",
212
+ "testCompletedAt",
213
+ ]
214
+ )
215
+ nullable_fields = set(
216
+ [
217
+ "externalId",
218
+ "tenantId",
219
+ "comments",
220
+ "expiresAt",
221
+ "expiredUrl",
222
+ "password",
223
+ "title",
224
+ "description",
225
+ "image",
226
+ "video",
227
+ "ios",
228
+ "android",
229
+ "testVariants",
230
+ "testStartedAt",
231
+ "testCompletedAt",
232
+ ]
233
+ )
231
234
  serialized = handler(self)
232
-
233
235
  m = {}
234
236
 
235
237
  for n, f in type(self).model_fields.items():
236
238
  k = f.alias or n
237
239
  val = serialized.get(k)
238
- serialized.pop(k, None)
239
-
240
- optional_nullable = k in optional_fields and k in nullable_fields
241
- is_set = (
242
- self.__pydantic_fields_set__.intersection({n})
243
- or k in null_default_fields
244
- ) # pylint: disable=no-member
245
-
246
- if val is not None and val != UNSET_SENTINEL:
247
- m[k] = val
248
- elif val != UNSET_SENTINEL and (
249
- not k in optional_fields or (optional_nullable and is_set)
250
- ):
251
- m[k] = val
240
+ is_nullable_and_explicitly_set = (
241
+ k in nullable_fields
242
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
243
+ )
244
+
245
+ if val != UNSET_SENTINEL:
246
+ if (
247
+ val is not None
248
+ or k not in optional_fields
249
+ or is_nullable_and_explicitly_set
250
+ ):
251
+ m[k] = val
252
252
 
253
253
  return m
254
254
 
@@ -304,40 +304,37 @@ class CreatePartnerRequestBody(BaseModel):
304
304
 
305
305
  @model_serializer(mode="wrap")
306
306
  def serialize_model(self, handler):
307
- optional_fields = [
308
- "name",
309
- "username",
310
- "image",
311
- "tenantId",
312
- "groupId",
313
- "country",
314
- "description",
315
- "linkProps",
316
- ]
317
- nullable_fields = ["name", "username", "image", "country", "description"]
318
- null_default_fields = []
319
-
307
+ optional_fields = set(
308
+ [
309
+ "name",
310
+ "username",
311
+ "image",
312
+ "tenantId",
313
+ "groupId",
314
+ "country",
315
+ "description",
316
+ "linkProps",
317
+ ]
318
+ )
319
+ nullable_fields = set(["name", "username", "image", "country", "description"])
320
320
  serialized = handler(self)
321
-
322
321
  m = {}
323
322
 
324
323
  for n, f in type(self).model_fields.items():
325
324
  k = f.alias or n
326
325
  val = serialized.get(k)
327
- serialized.pop(k, None)
328
-
329
- optional_nullable = k in optional_fields and k in nullable_fields
330
- is_set = (
331
- self.__pydantic_fields_set__.intersection({n})
332
- or k in null_default_fields
333
- ) # pylint: disable=no-member
334
-
335
- if val is not None and val != UNSET_SENTINEL:
336
- m[k] = val
337
- elif val != UNSET_SENTINEL and (
338
- not k in optional_fields or (optional_nullable and is_set)
339
- ):
340
- m[k] = val
326
+ is_nullable_and_explicitly_set = (
327
+ k in nullable_fields
328
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
329
+ )
330
+
331
+ if val != UNSET_SENTINEL:
332
+ if (
333
+ val is not None
334
+ or k not in optional_fields
335
+ or is_nullable_and_explicitly_set
336
+ ):
337
+ m[k] = val
341
338
 
342
339
  return m
343
340
 
@@ -409,6 +406,22 @@ class Links(BaseModel):
409
406
  sale_amount: Annotated[Optional[float], pydantic.Field(alias="saleAmount")] = 0
410
407
  r"""The total dollar value of sales (in cents) generated by the short link."""
411
408
 
409
+ @model_serializer(mode="wrap")
410
+ def serialize_model(self, handler):
411
+ optional_fields = set(["clicks", "leads", "conversions", "sales", "saleAmount"])
412
+ serialized = handler(self)
413
+ m = {}
414
+
415
+ for n, f in type(self).model_fields.items():
416
+ k = f.alias or n
417
+ val = serialized.get(k)
418
+
419
+ if val != UNSET_SENTINEL:
420
+ if val is not None or k not in optional_fields:
421
+ m[k] = val
422
+
423
+ return m
424
+
412
425
 
413
426
  class BannedReason(str, Enum):
414
427
  r"""If the partner was banned from the program, this is the reason for the ban."""
@@ -421,6 +434,379 @@ class BannedReason(str, Enum):
421
434
  BRAND_ABUSE = "brand_abuse"
422
435
 
423
436
 
437
+ class CreatePartnerFieldsPartnersResponse201ApplicationJSONResponseBodyReferralFormDataType(
438
+ str, Enum
439
+ ):
440
+ PHONE = "phone"
441
+
442
+
443
+ class EightTypedDict(TypedDict):
444
+ key: str
445
+ label: str
446
+ required: bool
447
+ locked: bool
448
+ position: int
449
+ type: CreatePartnerFieldsPartnersResponse201ApplicationJSONResponseBodyReferralFormDataType
450
+
451
+
452
+ class Eight(BaseModel):
453
+ key: str
454
+
455
+ label: str
456
+
457
+ required: bool
458
+
459
+ locked: bool
460
+
461
+ position: int
462
+
463
+ type: CreatePartnerFieldsPartnersResponse201ApplicationJSONResponseBodyReferralFormDataType
464
+
465
+
466
+ class CreatePartnerFieldsPartnersResponse201ApplicationJSONResponseBodyType(str, Enum):
467
+ NUMBER = "number"
468
+
469
+
470
+ class SevenTypedDict(TypedDict):
471
+ key: str
472
+ label: str
473
+ required: bool
474
+ locked: bool
475
+ position: int
476
+ type: CreatePartnerFieldsPartnersResponse201ApplicationJSONResponseBodyType
477
+
478
+
479
+ class Seven(BaseModel):
480
+ key: str
481
+
482
+ label: str
483
+
484
+ required: bool
485
+
486
+ locked: bool
487
+
488
+ position: int
489
+
490
+ type: CreatePartnerFieldsPartnersResponse201ApplicationJSONResponseBodyType
491
+
492
+
493
+ class CreatePartnerFieldsPartnersResponse201ApplicationJSONType(str, Enum):
494
+ MULTI_SELECT = "multiSelect"
495
+
496
+
497
+ class FieldsOptionsTypedDict(TypedDict):
498
+ label: str
499
+ value: str
500
+
501
+
502
+ class FieldsOptions(BaseModel):
503
+ label: str
504
+
505
+ value: str
506
+
507
+
508
+ class SixTypedDict(TypedDict):
509
+ key: str
510
+ label: str
511
+ required: bool
512
+ locked: bool
513
+ position: int
514
+ type: CreatePartnerFieldsPartnersResponse201ApplicationJSONType
515
+ options: List[FieldsOptionsTypedDict]
516
+
517
+
518
+ class Six(BaseModel):
519
+ key: str
520
+
521
+ label: str
522
+
523
+ required: bool
524
+
525
+ locked: bool
526
+
527
+ position: int
528
+
529
+ type: CreatePartnerFieldsPartnersResponse201ApplicationJSONType
530
+
531
+ options: List[FieldsOptions]
532
+
533
+
534
+ class CreatePartnerFieldsPartnersResponse201Type(str, Enum):
535
+ DATE = "date"
536
+
537
+
538
+ class FiveTypedDict(TypedDict):
539
+ key: str
540
+ label: str
541
+ required: bool
542
+ locked: bool
543
+ position: int
544
+ type: CreatePartnerFieldsPartnersResponse201Type
545
+
546
+
547
+ class Five(BaseModel):
548
+ key: str
549
+
550
+ label: str
551
+
552
+ required: bool
553
+
554
+ locked: bool
555
+
556
+ position: int
557
+
558
+ type: CreatePartnerFieldsPartnersResponse201Type
559
+
560
+
561
+ class CreatePartnerFieldsPartnersResponseType(str, Enum):
562
+ COUNTRY = "country"
563
+
564
+
565
+ class Fields4TypedDict(TypedDict):
566
+ key: str
567
+ label: str
568
+ required: bool
569
+ locked: bool
570
+ position: int
571
+ type: CreatePartnerFieldsPartnersResponseType
572
+
573
+
574
+ class Fields4(BaseModel):
575
+ key: str
576
+
577
+ label: str
578
+
579
+ required: bool
580
+
581
+ locked: bool
582
+
583
+ position: int
584
+
585
+ type: CreatePartnerFieldsPartnersResponseType
586
+
587
+
588
+ class CreatePartnerFieldsPartnersType(str, Enum):
589
+ SELECT = "select"
590
+
591
+
592
+ class OptionsTypedDict(TypedDict):
593
+ label: str
594
+ value: str
595
+
596
+
597
+ class Options(BaseModel):
598
+ label: str
599
+
600
+ value: str
601
+
602
+
603
+ class Fields3TypedDict(TypedDict):
604
+ key: str
605
+ label: str
606
+ required: bool
607
+ locked: bool
608
+ position: int
609
+ type: CreatePartnerFieldsPartnersType
610
+ options: List[OptionsTypedDict]
611
+
612
+
613
+ class Fields3(BaseModel):
614
+ key: str
615
+
616
+ label: str
617
+
618
+ required: bool
619
+
620
+ locked: bool
621
+
622
+ position: int
623
+
624
+ type: CreatePartnerFieldsPartnersType
625
+
626
+ options: List[Options]
627
+
628
+
629
+ class CreatePartnerFieldsType(str, Enum):
630
+ TEXTAREA = "textarea"
631
+
632
+
633
+ class FieldsConstraintsTypedDict(TypedDict):
634
+ max_length: NotRequired[int]
635
+
636
+
637
+ class FieldsConstraints(BaseModel):
638
+ max_length: Annotated[Optional[int], pydantic.Field(alias="maxLength")] = None
639
+
640
+ @model_serializer(mode="wrap")
641
+ def serialize_model(self, handler):
642
+ optional_fields = set(["maxLength"])
643
+ serialized = handler(self)
644
+ m = {}
645
+
646
+ for n, f in type(self).model_fields.items():
647
+ k = f.alias or n
648
+ val = serialized.get(k)
649
+
650
+ if val != UNSET_SENTINEL:
651
+ if val is not None or k not in optional_fields:
652
+ m[k] = val
653
+
654
+ return m
655
+
656
+
657
+ class Fields2TypedDict(TypedDict):
658
+ key: str
659
+ label: str
660
+ required: bool
661
+ locked: bool
662
+ position: int
663
+ type: CreatePartnerFieldsType
664
+ constraints: NotRequired[FieldsConstraintsTypedDict]
665
+
666
+
667
+ class Fields2(BaseModel):
668
+ key: str
669
+
670
+ label: str
671
+
672
+ required: bool
673
+
674
+ locked: bool
675
+
676
+ position: int
677
+
678
+ type: CreatePartnerFieldsType
679
+
680
+ constraints: Optional[FieldsConstraints] = None
681
+
682
+ @model_serializer(mode="wrap")
683
+ def serialize_model(self, handler):
684
+ optional_fields = set(["constraints"])
685
+ serialized = handler(self)
686
+ m = {}
687
+
688
+ for n, f in type(self).model_fields.items():
689
+ k = f.alias or n
690
+ val = serialized.get(k)
691
+
692
+ if val != UNSET_SENTINEL:
693
+ if val is not None or k not in optional_fields:
694
+ m[k] = val
695
+
696
+ return m
697
+
698
+
699
+ class FieldsType(str, Enum):
700
+ TEXT = "text"
701
+
702
+
703
+ class ConstraintsTypedDict(TypedDict):
704
+ max_length: NotRequired[int]
705
+ pattern: NotRequired[str]
706
+
707
+
708
+ class Constraints(BaseModel):
709
+ max_length: Annotated[Optional[int], pydantic.Field(alias="maxLength")] = None
710
+
711
+ pattern: Optional[str] = None
712
+
713
+ @model_serializer(mode="wrap")
714
+ def serialize_model(self, handler):
715
+ optional_fields = set(["maxLength", "pattern"])
716
+ serialized = handler(self)
717
+ m = {}
718
+
719
+ for n, f in type(self).model_fields.items():
720
+ k = f.alias or n
721
+ val = serialized.get(k)
722
+
723
+ if val != UNSET_SENTINEL:
724
+ if val is not None or k not in optional_fields:
725
+ m[k] = val
726
+
727
+ return m
728
+
729
+
730
+ class Fields1TypedDict(TypedDict):
731
+ key: str
732
+ label: str
733
+ required: bool
734
+ locked: bool
735
+ position: int
736
+ type: FieldsType
737
+ constraints: NotRequired[ConstraintsTypedDict]
738
+
739
+
740
+ class Fields1(BaseModel):
741
+ key: str
742
+
743
+ label: str
744
+
745
+ required: bool
746
+
747
+ locked: bool
748
+
749
+ position: int
750
+
751
+ type: FieldsType
752
+
753
+ constraints: Optional[Constraints] = None
754
+
755
+ @model_serializer(mode="wrap")
756
+ def serialize_model(self, handler):
757
+ optional_fields = set(["constraints"])
758
+ serialized = handler(self)
759
+ m = {}
760
+
761
+ for n, f in type(self).model_fields.items():
762
+ k = f.alias or n
763
+ val = serialized.get(k)
764
+
765
+ if val != UNSET_SENTINEL:
766
+ if val is not None or k not in optional_fields:
767
+ m[k] = val
768
+
769
+ return m
770
+
771
+
772
+ FieldsTypedDict = TypeAliasType(
773
+ "FieldsTypedDict",
774
+ Union[
775
+ Fields4TypedDict,
776
+ FiveTypedDict,
777
+ SevenTypedDict,
778
+ EightTypedDict,
779
+ Fields1TypedDict,
780
+ Fields2TypedDict,
781
+ Fields3TypedDict,
782
+ SixTypedDict,
783
+ ],
784
+ )
785
+
786
+
787
+ Fields = Annotated[
788
+ Union[
789
+ Annotated[Fields1, Tag("text")],
790
+ Annotated[Fields2, Tag("textarea")],
791
+ Annotated[Fields3, Tag("select")],
792
+ Annotated[Fields4, Tag("country")],
793
+ Annotated[Five, Tag("date")],
794
+ Annotated[Six, Tag("multiSelect")],
795
+ Annotated[Seven, Tag("number")],
796
+ Annotated[Eight, Tag("phone")],
797
+ ],
798
+ Discriminator(lambda m: get_discriminator(m, "type", "type")),
799
+ ]
800
+
801
+
802
+ class ReferralFormDataTypedDict(TypedDict):
803
+ fields: List[FieldsTypedDict]
804
+
805
+
806
+ class ReferralFormData(BaseModel):
807
+ fields: List[Fields]
808
+
809
+
424
810
  class CreatePartnerResponseBodyTypedDict(TypedDict):
425
811
  r"""The created or updated partner"""
426
812
 
@@ -471,6 +857,7 @@ class CreatePartnerResponseBodyTypedDict(TypedDict):
471
857
  r"""If the partner was banned from the program, this is the date of the ban."""
472
858
  banned_reason: NotRequired[Nullable[BannedReason]]
473
859
  r"""If the partner was banned from the program, this is the reason for the ban."""
860
+ referral_form_data: NotRequired[Nullable[ReferralFormDataTypedDict]]
474
861
  total_clicks: NotRequired[float]
475
862
  r"""The total number of clicks on the partner's links"""
476
863
  total_leads: NotRequired[float]
@@ -603,6 +990,10 @@ class CreatePartnerResponseBody(BaseModel):
603
990
  ] = UNSET
604
991
  r"""If the partner was banned from the program, this is the reason for the ban."""
605
992
 
993
+ referral_form_data: Annotated[
994
+ OptionalNullable[ReferralFormData], pydantic.Field(alias="referralFormData")
995
+ ] = UNSET
996
+
606
997
  total_clicks: Annotated[Optional[float], pydantic.Field(alias="totalClicks")] = 0
607
998
  r"""The total number of clicks on the partner's links"""
608
999
 
@@ -675,91 +1066,92 @@ class CreatePartnerResponseBody(BaseModel):
675
1066
 
676
1067
  @model_serializer(mode="wrap")
677
1068
  def serialize_model(self, handler):
678
- optional_fields = [
679
- "description",
680
- "groupId",
681
- "totalCommissions",
682
- "clickRewardId",
683
- "leadRewardId",
684
- "saleRewardId",
685
- "discountId",
686
- "applicationId",
687
- "bannedAt",
688
- "bannedReason",
689
- "totalClicks",
690
- "totalLeads",
691
- "totalConversions",
692
- "totalSales",
693
- "totalSaleAmount",
694
- "netRevenue",
695
- "earningsPerClick",
696
- "averageLifetimeValue",
697
- "clickToLeadRate",
698
- "clickToConversionRate",
699
- "leadToConversionRate",
700
- "returnOnAdSpend",
701
- "website",
702
- "youtube",
703
- "twitter",
704
- "linkedin",
705
- "instagram",
706
- "tiktok",
707
- ]
708
- nullable_fields = [
709
- "companyName",
710
- "email",
711
- "image",
712
- "description",
713
- "country",
714
- "paypalEmail",
715
- "stripeConnectId",
716
- "payoutsEnabledAt",
717
- "trustedAt",
718
- "groupId",
719
- "tenantId",
720
- "links",
721
- "clickRewardId",
722
- "leadRewardId",
723
- "saleRewardId",
724
- "discountId",
725
- "applicationId",
726
- "bannedAt",
727
- "bannedReason",
728
- "earningsPerClick",
729
- "averageLifetimeValue",
730
- "clickToLeadRate",
731
- "clickToConversionRate",
732
- "leadToConversionRate",
733
- "returnOnAdSpend",
734
- "website",
735
- "youtube",
736
- "twitter",
737
- "linkedin",
738
- "instagram",
739
- "tiktok",
740
- ]
741
- null_default_fields = []
742
-
1069
+ optional_fields = set(
1070
+ [
1071
+ "description",
1072
+ "groupId",
1073
+ "totalCommissions",
1074
+ "clickRewardId",
1075
+ "leadRewardId",
1076
+ "saleRewardId",
1077
+ "discountId",
1078
+ "applicationId",
1079
+ "bannedAt",
1080
+ "bannedReason",
1081
+ "referralFormData",
1082
+ "totalClicks",
1083
+ "totalLeads",
1084
+ "totalConversions",
1085
+ "totalSales",
1086
+ "totalSaleAmount",
1087
+ "netRevenue",
1088
+ "earningsPerClick",
1089
+ "averageLifetimeValue",
1090
+ "clickToLeadRate",
1091
+ "clickToConversionRate",
1092
+ "leadToConversionRate",
1093
+ "returnOnAdSpend",
1094
+ "website",
1095
+ "youtube",
1096
+ "twitter",
1097
+ "linkedin",
1098
+ "instagram",
1099
+ "tiktok",
1100
+ ]
1101
+ )
1102
+ nullable_fields = set(
1103
+ [
1104
+ "companyName",
1105
+ "email",
1106
+ "image",
1107
+ "description",
1108
+ "country",
1109
+ "paypalEmail",
1110
+ "stripeConnectId",
1111
+ "payoutsEnabledAt",
1112
+ "trustedAt",
1113
+ "groupId",
1114
+ "tenantId",
1115
+ "links",
1116
+ "clickRewardId",
1117
+ "leadRewardId",
1118
+ "saleRewardId",
1119
+ "discountId",
1120
+ "applicationId",
1121
+ "bannedAt",
1122
+ "bannedReason",
1123
+ "referralFormData",
1124
+ "earningsPerClick",
1125
+ "averageLifetimeValue",
1126
+ "clickToLeadRate",
1127
+ "clickToConversionRate",
1128
+ "leadToConversionRate",
1129
+ "returnOnAdSpend",
1130
+ "website",
1131
+ "youtube",
1132
+ "twitter",
1133
+ "linkedin",
1134
+ "instagram",
1135
+ "tiktok",
1136
+ ]
1137
+ )
743
1138
  serialized = handler(self)
744
-
745
1139
  m = {}
746
1140
 
747
1141
  for n, f in type(self).model_fields.items():
748
1142
  k = f.alias or n
749
1143
  val = serialized.get(k)
750
- serialized.pop(k, None)
751
-
752
- optional_nullable = k in optional_fields and k in nullable_fields
753
- is_set = (
754
- self.__pydantic_fields_set__.intersection({n})
755
- or k in null_default_fields
756
- ) # pylint: disable=no-member
757
-
758
- if val is not None and val != UNSET_SENTINEL:
759
- m[k] = val
760
- elif val != UNSET_SENTINEL and (
761
- not k in optional_fields or (optional_nullable and is_set)
762
- ):
763
- m[k] = val
1144
+ is_nullable_and_explicitly_set = (
1145
+ k in nullable_fields
1146
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
1147
+ )
1148
+
1149
+ if val != UNSET_SENTINEL:
1150
+ if (
1151
+ val is not None
1152
+ or k not in optional_fields
1153
+ or is_nullable_and_explicitly_set
1154
+ ):
1155
+ m[k] = val
764
1156
 
765
1157
  return m