lunchmoney-python 2.9.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 (92) hide show
  1. lunchmoney/__init__.py +205 -0
  2. lunchmoney/api/__init__.py +16 -0
  3. lunchmoney/api/categories_api.py +1499 -0
  4. lunchmoney/api/manual_accounts_api.py +1479 -0
  5. lunchmoney/api/me_api.py +293 -0
  6. lunchmoney/api/plaid_accounts_api.py +909 -0
  7. lunchmoney/api/recurring_items_api.py +702 -0
  8. lunchmoney/api/summary_api.py +434 -0
  9. lunchmoney/api/tags_api.py +1465 -0
  10. lunchmoney/api/transactions_api.py +914 -0
  11. lunchmoney/api/transactions_bulk_api.py +1527 -0
  12. lunchmoney/api/transactions_files_api.py +891 -0
  13. lunchmoney/api/transactions_group_api.py +601 -0
  14. lunchmoney/api/transactions_split_api.py +616 -0
  15. lunchmoney/api_client.py +805 -0
  16. lunchmoney/api_response.py +21 -0
  17. lunchmoney/configuration.py +620 -0
  18. lunchmoney/exceptions.py +217 -0
  19. lunchmoney/models/__init__.py +84 -0
  20. lunchmoney/models/account_type_enum.py +46 -0
  21. lunchmoney/models/aligned_category_totals_object.py +108 -0
  22. lunchmoney/models/aligned_summary_category_object.py +110 -0
  23. lunchmoney/models/aligned_summary_response_object.py +104 -0
  24. lunchmoney/models/category_object.py +146 -0
  25. lunchmoney/models/child_category_object.py +141 -0
  26. lunchmoney/models/child_transaction_object.py +219 -0
  27. lunchmoney/models/create_category_request_object.py +137 -0
  28. lunchmoney/models/create_category_request_object_children_inner.py +159 -0
  29. lunchmoney/models/create_manual_account_request_object.py +138 -0
  30. lunchmoney/models/create_manual_account_request_object_balance.py +145 -0
  31. lunchmoney/models/create_new_transactions_request.py +103 -0
  32. lunchmoney/models/create_tag_request_object.py +112 -0
  33. lunchmoney/models/currency_enum.py +198 -0
  34. lunchmoney/models/delete_category_response_with_dependencies.py +94 -0
  35. lunchmoney/models/delete_category_response_with_dependencies_dependents.py +98 -0
  36. lunchmoney/models/delete_tag_response_with_dependencies.py +94 -0
  37. lunchmoney/models/delete_tag_response_with_dependencies_dependents.py +90 -0
  38. lunchmoney/models/delete_transactions_request.py +89 -0
  39. lunchmoney/models/error_response_object.py +98 -0
  40. lunchmoney/models/error_response_object_errors_inner.py +101 -0
  41. lunchmoney/models/get_all_categories200_response.py +96 -0
  42. lunchmoney/models/get_all_manual_accounts200_response.py +96 -0
  43. lunchmoney/models/get_all_plaid_accounts200_response.py +96 -0
  44. lunchmoney/models/get_all_recurring200_response.py +96 -0
  45. lunchmoney/models/get_all_tags200_response.py +96 -0
  46. lunchmoney/models/get_all_transactions200_response.py +100 -0
  47. lunchmoney/models/get_all_transactions_created_since_parameter.py +145 -0
  48. lunchmoney/models/get_budget_summary200_response.py +138 -0
  49. lunchmoney/models/get_transaction_attachment_url200_response.py +91 -0
  50. lunchmoney/models/group_transactions_request.py +122 -0
  51. lunchmoney/models/insert_transaction_object.py +164 -0
  52. lunchmoney/models/insert_transaction_object_amount.py +145 -0
  53. lunchmoney/models/insert_transactions_response_object.py +106 -0
  54. lunchmoney/models/manual_account_object.py +158 -0
  55. lunchmoney/models/non_aligned_category_totals_object.py +94 -0
  56. lunchmoney/models/non_aligned_summary_category_object.py +94 -0
  57. lunchmoney/models/non_aligned_summary_response_object.py +104 -0
  58. lunchmoney/models/plaid_account_object.py +168 -0
  59. lunchmoney/models/recurring_object.py +143 -0
  60. lunchmoney/models/recurring_object_matches.py +105 -0
  61. lunchmoney/models/recurring_object_matches_found_transactions_inner.py +91 -0
  62. lunchmoney/models/recurring_object_overrides.py +92 -0
  63. lunchmoney/models/recurring_object_transaction_criteria.py +149 -0
  64. lunchmoney/models/skipped_existing_external_id_object.py +108 -0
  65. lunchmoney/models/split_transaction_object.py +102 -0
  66. lunchmoney/models/split_transaction_object_amount.py +145 -0
  67. lunchmoney/models/split_transaction_request.py +97 -0
  68. lunchmoney/models/summary_category_occurrence_object.py +126 -0
  69. lunchmoney/models/summary_recurring_transaction_object.py +100 -0
  70. lunchmoney/models/summary_rollover_pool_adjustment_object.py +98 -0
  71. lunchmoney/models/summary_rollover_pool_object.py +98 -0
  72. lunchmoney/models/summary_totals_breakdown_object.py +98 -0
  73. lunchmoney/models/summary_totals_object.py +97 -0
  74. lunchmoney/models/tag_object.py +125 -0
  75. lunchmoney/models/transaction_attachment_object.py +106 -0
  76. lunchmoney/models/transaction_object.py +229 -0
  77. lunchmoney/models/update_category_request_object.py +156 -0
  78. lunchmoney/models/update_manual_account_request_object.py +156 -0
  79. lunchmoney/models/update_manual_account_request_object_balance.py +145 -0
  80. lunchmoney/models/update_tag_request_object.py +126 -0
  81. lunchmoney/models/update_transaction_object.py +228 -0
  82. lunchmoney/models/update_transaction_object_amount.py +145 -0
  83. lunchmoney/models/update_transactions200_response.py +96 -0
  84. lunchmoney/models/update_transactions_request.py +97 -0
  85. lunchmoney/models/update_transactions_request_transactions_inner.py +228 -0
  86. lunchmoney/models/user_object.py +106 -0
  87. lunchmoney/py.typed +0 -0
  88. lunchmoney/rest.py +259 -0
  89. lunchmoney_python-2.9.0.dist-info/METADATA +285 -0
  90. lunchmoney_python-2.9.0.dist-info/RECORD +92 -0
  91. lunchmoney_python-2.9.0.dist-info/WHEEL +5 -0
  92. lunchmoney_python-2.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,104 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Lunch Money API - v2
5
+
6
+ Welcome to the Lunch Money v2 API. A working version of this API is now available through these docs, or directly at: `https://api.lunchmoney.dev/v2` <span class=\"red-text\"><strong>This is in alpha launch of a major API update. It is still subject to change during this alpha review period and bugs may still exist. Users are strongly encouraged to use the mock service or to create a test budget with example data as the first step to interacting with the v2 API.</strong></span> See the [Getting Started Guide](https://alpha.lunchmoney.dev/v2/getting-started) for more information on using a test budget.<br<br> If you are new to the v2 API, you may wish to review the [v2 API Overview of Changes](https://alpha.lunchmoney.dev/v2/changelog). ### Static Mock Server You may also use these docs to explore the API using a static mock server endpoint.<p> This enables users to become familiar with the API without having to create an access token, and eliminates the possibility of modifying real data. <p> To access this endpoint select the second endpoint in the the \"Server\" dropdown to the right. When selected you should see \"Static Mock v2 Lunch Money API Server\".<br> When using this server, set your Bearer token to any string with 11 or more characters. ### Migrating from V1 The v2 API is NOT backwards compatible with the v1 API. Developers are encouraged to review the [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) to understand the changes and plan their migration. ### Acknowledgments If you have been providing feedback on the API during our iterative design process, **THANK YOU**. We are happy to provide the opportunity to finally interact with the working API that was built based on your feedback. ### Useful links: - [Getting Started](https://alpha.lunchmoney.dev/v2/getting-started) - [v2 API Changelog](https://alpha.lunchmoney.dev/v2/changelog) - [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) - [Rate Limits](https://alpha.lunchmoney.dev/v2/rate-limits) - [Current v1 Lunch Money API Documentation](https://lunchmoney.dev) - [Awesome Lunch Money Projects](https://github.com/lunch-money/awesome-lunchmoney?tab=readme-ov-file)
7
+
8
+ The version of the OpenAPI document: 2.8.4
9
+ Contact: devsupport@lunchmoney.app
10
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
11
+
12
+ Do not edit the class manually.
13
+ """ # noqa: E501
14
+
15
+
16
+ from __future__ import annotations
17
+ import pprint
18
+ import re # noqa: F401
19
+ import json
20
+
21
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool
22
+ from typing import Any, ClassVar, Dict, List, Optional
23
+ from lunchmoney.models.aligned_summary_category_object import AlignedSummaryCategoryObject
24
+ from lunchmoney.models.summary_totals_object import SummaryTotalsObject
25
+ from typing import Optional, Set
26
+ from typing_extensions import Self
27
+
28
+ class AlignedSummaryResponseObject(BaseModel):
29
+ """
30
+ AlignedSummaryResponseObject
31
+ """ # noqa: E501
32
+ totals: Optional[SummaryTotalsObject] = None
33
+ aligned: StrictBool = Field(description="`true` if start_date and end_date are aligned with budget period setting")
34
+ categories: List[AlignedSummaryCategoryObject]
35
+ __properties: ClassVar[List[str]] = ["totals", "aligned", "categories"]
36
+
37
+ model_config = ConfigDict(
38
+ populate_by_name=True,
39
+ validate_assignment=True,
40
+ protected_namespaces=(),
41
+ )
42
+
43
+
44
+ def to_str(self) -> str:
45
+ """Returns the string representation of the model using alias"""
46
+ return pprint.pformat(self.model_dump(by_alias=True))
47
+
48
+ def to_json(self) -> str:
49
+ """Returns the JSON representation of the model using alias"""
50
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
51
+ return json.dumps(self.to_dict())
52
+
53
+ @classmethod
54
+ def from_json(cls, json_str: str) -> Optional[Self]:
55
+ """Create an instance of AlignedSummaryResponseObject from a JSON string"""
56
+ return cls.from_dict(json.loads(json_str))
57
+
58
+ def to_dict(self) -> Dict[str, Any]:
59
+ """Return the dictionary representation of the model using alias.
60
+
61
+ This has the following differences from calling pydantic's
62
+ `self.model_dump(by_alias=True)`:
63
+
64
+ * `None` is only added to the output dict for nullable fields that
65
+ were set at model initialization. Other fields with value `None`
66
+ are ignored.
67
+ """
68
+ excluded_fields: Set[str] = set([
69
+ ])
70
+
71
+ _dict = self.model_dump(
72
+ by_alias=True,
73
+ exclude=excluded_fields,
74
+ exclude_none=True,
75
+ )
76
+ # override the default output from pydantic by calling `to_dict()` of totals
77
+ if self.totals:
78
+ _dict['totals'] = self.totals.to_dict()
79
+ # override the default output from pydantic by calling `to_dict()` of each item in categories (list)
80
+ _items = []
81
+ if self.categories:
82
+ for _item_categories in self.categories:
83
+ if _item_categories:
84
+ _items.append(_item_categories.to_dict())
85
+ _dict['categories'] = _items
86
+ return _dict
87
+
88
+ @classmethod
89
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
90
+ """Create an instance of AlignedSummaryResponseObject from a dict"""
91
+ if obj is None:
92
+ return None
93
+
94
+ if not isinstance(obj, dict):
95
+ return cls.model_validate(obj)
96
+
97
+ _obj = cls.model_validate({
98
+ "totals": SummaryTotalsObject.from_dict(obj["totals"]) if obj.get("totals") is not None else None,
99
+ "aligned": obj.get("aligned"),
100
+ "categories": [AlignedSummaryCategoryObject.from_dict(_item) for _item in obj["categories"]] if obj.get("categories") is not None else None
101
+ })
102
+ return _obj
103
+
104
+
@@ -0,0 +1,146 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Lunch Money API - v2
5
+
6
+ Welcome to the Lunch Money v2 API. A working version of this API is now available through these docs, or directly at: `https://api.lunchmoney.dev/v2` <span class=\"red-text\"><strong>This is in alpha launch of a major API update. It is still subject to change during this alpha review period and bugs may still exist. Users are strongly encouraged to use the mock service or to create a test budget with example data as the first step to interacting with the v2 API.</strong></span> See the [Getting Started Guide](https://alpha.lunchmoney.dev/v2/getting-started) for more information on using a test budget.<br<br> If you are new to the v2 API, you may wish to review the [v2 API Overview of Changes](https://alpha.lunchmoney.dev/v2/changelog). ### Static Mock Server You may also use these docs to explore the API using a static mock server endpoint.<p> This enables users to become familiar with the API without having to create an access token, and eliminates the possibility of modifying real data. <p> To access this endpoint select the second endpoint in the the \"Server\" dropdown to the right. When selected you should see \"Static Mock v2 Lunch Money API Server\".<br> When using this server, set your Bearer token to any string with 11 or more characters. ### Migrating from V1 The v2 API is NOT backwards compatible with the v1 API. Developers are encouraged to review the [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) to understand the changes and plan their migration. ### Acknowledgments If you have been providing feedback on the API during our iterative design process, **THANK YOU**. We are happy to provide the opportunity to finally interact with the working API that was built based on your feedback. ### Useful links: - [Getting Started](https://alpha.lunchmoney.dev/v2/getting-started) - [v2 API Changelog](https://alpha.lunchmoney.dev/v2/changelog) - [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) - [Rate Limits](https://alpha.lunchmoney.dev/v2/rate-limits) - [Current v1 Lunch Money API Documentation](https://lunchmoney.dev) - [Awesome Lunch Money Projects](https://github.com/lunch-money/awesome-lunchmoney?tab=readme-ov-file)
7
+
8
+ The version of the OpenAPI document: 2.8.4
9
+ Contact: devsupport@lunchmoney.app
10
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
11
+
12
+ Do not edit the class manually.
13
+ """ # noqa: E501
14
+
15
+
16
+ from __future__ import annotations
17
+ import pprint
18
+ import re # noqa: F401
19
+ import json
20
+
21
+ from datetime import datetime
22
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt
23
+ from typing import Any, ClassVar, Dict, List, Optional
24
+ from typing_extensions import Annotated
25
+ from lunchmoney.models.child_category_object import ChildCategoryObject
26
+ from typing import Optional, Set
27
+ from typing_extensions import Self
28
+
29
+ class CategoryObject(BaseModel):
30
+ """
31
+ CategoryObject
32
+ """ # noqa: E501
33
+ id: StrictInt = Field(description="A system defined unique identifier for the category.")
34
+ name: Annotated[str, Field(min_length=1, strict=True, max_length=100)] = Field(description="The name of the category.")
35
+ description: Optional[Annotated[str, Field(strict=True, max_length=200)]] = Field(description="The description of the category or `null` if not set.")
36
+ is_income: StrictBool = Field(description="If `true`, the transactions in this category will be treated as income. (See <a href=\"https://support.lunchmoney.app/setup/categories/category-properties\">Category Properties</a> for more details)")
37
+ exclude_from_budget: StrictBool = Field(description="If `true`, the transactions in this category will be excluded from the budget. (See <a href=\"https://support.lunchmoney.app/setup/categories/category-properties\">Category Properties</a> for more details)")
38
+ exclude_from_totals: StrictBool = Field(description="If `true`, the transactions in this category will be excluded from totals. (See <a href=\"https://support.lunchmoney.app/setup/categories/category-properties\">Category Properties</a> for more details)")
39
+ updated_at: datetime = Field(description="The date and time of when the category was last updated (in the ISO 8601 extended format).")
40
+ created_at: datetime = Field(description="The date and time of when the category was created (in the ISO 8601 extended format).")
41
+ group_id: Optional[StrictInt] = Field(description="The ID of the category group this category belongs to or `null` if the category doesn't belong to a group, or is itself a category group.")
42
+ is_group: StrictBool = Field(description="If `true`, the category is created as a category group.")
43
+ children: Optional[List[ChildCategoryObject]] = Field(default=None, description="For category groups, this will populate with details about the categories that belong to this group. The objects in this array are similar to Category Objects but do not include the `is_income`, `exclude_from_budget`, and `exclude_from_totals` properties as these are inherited from the category group. In addition, the `is_group` property will always be `false`, and there will be no `children` attribute.")
44
+ archived: StrictBool = Field(description="If true, the category is archived and not displayed in relevant areas of the Lunch Money app.")
45
+ archived_at: Optional[datetime] = Field(description="The date and time of when the category was last archived (in the ISO 8601 extended format).")
46
+ order: Optional[StrictInt] = Field(description="An integer specifying the position in which the category is displayed on the categories page in the Lunch Money GUI. For categories within a category group the order is relative to the other categories within the group.<br>Categories with `order: null` will be displayed in alphabetical order by name, prior to any categories with an order")
47
+ collapsed: StrictBool = Field(description="If `true`, the category is collapsed in the Lunch Money GUI.")
48
+ __properties: ClassVar[List[str]] = ["id", "name", "description", "is_income", "exclude_from_budget", "exclude_from_totals", "updated_at", "created_at", "group_id", "is_group", "children", "archived", "archived_at", "order", "collapsed"]
49
+
50
+ model_config = ConfigDict(
51
+ populate_by_name=True,
52
+ validate_assignment=True,
53
+ protected_namespaces=(),
54
+ )
55
+
56
+
57
+ def to_str(self) -> str:
58
+ """Returns the string representation of the model using alias"""
59
+ return pprint.pformat(self.model_dump(by_alias=True))
60
+
61
+ def to_json(self) -> str:
62
+ """Returns the JSON representation of the model using alias"""
63
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
64
+ return json.dumps(self.to_dict())
65
+
66
+ @classmethod
67
+ def from_json(cls, json_str: str) -> Optional[Self]:
68
+ """Create an instance of CategoryObject from a JSON string"""
69
+ return cls.from_dict(json.loads(json_str))
70
+
71
+ def to_dict(self) -> Dict[str, Any]:
72
+ """Return the dictionary representation of the model using alias.
73
+
74
+ This has the following differences from calling pydantic's
75
+ `self.model_dump(by_alias=True)`:
76
+
77
+ * `None` is only added to the output dict for nullable fields that
78
+ were set at model initialization. Other fields with value `None`
79
+ are ignored.
80
+ """
81
+ excluded_fields: Set[str] = set([
82
+ ])
83
+
84
+ _dict = self.model_dump(
85
+ by_alias=True,
86
+ exclude=excluded_fields,
87
+ exclude_none=True,
88
+ )
89
+ # override the default output from pydantic by calling `to_dict()` of each item in children (list)
90
+ _items = []
91
+ if self.children:
92
+ for _item_children in self.children:
93
+ if _item_children:
94
+ _items.append(_item_children.to_dict())
95
+ _dict['children'] = _items
96
+ # set to None if description (nullable) is None
97
+ # and model_fields_set contains the field
98
+ if self.description is None and "description" in self.model_fields_set:
99
+ _dict['description'] = None
100
+
101
+ # set to None if group_id (nullable) is None
102
+ # and model_fields_set contains the field
103
+ if self.group_id is None and "group_id" in self.model_fields_set:
104
+ _dict['group_id'] = None
105
+
106
+ # set to None if archived_at (nullable) is None
107
+ # and model_fields_set contains the field
108
+ if self.archived_at is None and "archived_at" in self.model_fields_set:
109
+ _dict['archived_at'] = None
110
+
111
+ # set to None if order (nullable) is None
112
+ # and model_fields_set contains the field
113
+ if self.order is None and "order" in self.model_fields_set:
114
+ _dict['order'] = None
115
+
116
+ return _dict
117
+
118
+ @classmethod
119
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
120
+ """Create an instance of CategoryObject from a dict"""
121
+ if obj is None:
122
+ return None
123
+
124
+ if not isinstance(obj, dict):
125
+ return cls.model_validate(obj)
126
+
127
+ _obj = cls.model_validate({
128
+ "id": obj.get("id"),
129
+ "name": obj.get("name"),
130
+ "description": obj.get("description"),
131
+ "is_income": obj.get("is_income"),
132
+ "exclude_from_budget": obj.get("exclude_from_budget"),
133
+ "exclude_from_totals": obj.get("exclude_from_totals"),
134
+ "updated_at": obj.get("updated_at"),
135
+ "created_at": obj.get("created_at"),
136
+ "group_id": obj.get("group_id"),
137
+ "is_group": obj.get("is_group"),
138
+ "children": [ChildCategoryObject.from_dict(_item) for _item in obj["children"]] if obj.get("children") is not None else None,
139
+ "archived": obj.get("archived"),
140
+ "archived_at": obj.get("archived_at"),
141
+ "order": obj.get("order"),
142
+ "collapsed": obj.get("collapsed") if obj.get("collapsed") is not None else False
143
+ })
144
+ return _obj
145
+
146
+
@@ -0,0 +1,141 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Lunch Money API - v2
5
+
6
+ Welcome to the Lunch Money v2 API. A working version of this API is now available through these docs, or directly at: `https://api.lunchmoney.dev/v2` <span class=\"red-text\"><strong>This is in alpha launch of a major API update. It is still subject to change during this alpha review period and bugs may still exist. Users are strongly encouraged to use the mock service or to create a test budget with example data as the first step to interacting with the v2 API.</strong></span> See the [Getting Started Guide](https://alpha.lunchmoney.dev/v2/getting-started) for more information on using a test budget.<br<br> If you are new to the v2 API, you may wish to review the [v2 API Overview of Changes](https://alpha.lunchmoney.dev/v2/changelog). ### Static Mock Server You may also use these docs to explore the API using a static mock server endpoint.<p> This enables users to become familiar with the API without having to create an access token, and eliminates the possibility of modifying real data. <p> To access this endpoint select the second endpoint in the the \"Server\" dropdown to the right. When selected you should see \"Static Mock v2 Lunch Money API Server\".<br> When using this server, set your Bearer token to any string with 11 or more characters. ### Migrating from V1 The v2 API is NOT backwards compatible with the v1 API. Developers are encouraged to review the [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) to understand the changes and plan their migration. ### Acknowledgments If you have been providing feedback on the API during our iterative design process, **THANK YOU**. We are happy to provide the opportunity to finally interact with the working API that was built based on your feedback. ### Useful links: - [Getting Started](https://alpha.lunchmoney.dev/v2/getting-started) - [v2 API Changelog](https://alpha.lunchmoney.dev/v2/changelog) - [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) - [Rate Limits](https://alpha.lunchmoney.dev/v2/rate-limits) - [Current v1 Lunch Money API Documentation](https://lunchmoney.dev) - [Awesome Lunch Money Projects](https://github.com/lunch-money/awesome-lunchmoney?tab=readme-ov-file)
7
+
8
+ The version of the OpenAPI document: 2.8.4
9
+ Contact: devsupport@lunchmoney.app
10
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
11
+
12
+ Do not edit the class manually.
13
+ """ # noqa: E501
14
+
15
+
16
+ from __future__ import annotations
17
+ import pprint
18
+ import re # noqa: F401
19
+ import json
20
+
21
+ from datetime import datetime
22
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt
23
+ from typing import Any, ClassVar, Dict, List, Optional
24
+ from typing_extensions import Annotated
25
+ from typing import Optional, Set
26
+ from typing_extensions import Self
27
+
28
+ class ChildCategoryObject(BaseModel):
29
+ """
30
+ ChildCategoryObject
31
+ """ # noqa: E501
32
+ id: StrictInt = Field(description="A system defined unique identifier for the category.")
33
+ name: Annotated[str, Field(min_length=1, strict=True, max_length=100)] = Field(description="The name of the category.")
34
+ description: Optional[Annotated[str, Field(strict=True, max_length=200)]] = Field(description="The description of the category or `null` if not set.")
35
+ is_income: StrictBool = Field(description="If true, the transactions in this category will be treated as income. Inherited from Category Group.")
36
+ exclude_from_budget: StrictBool = Field(description="If true, the transactions in this category will be excluded from the budget. Inherited from Category Group.")
37
+ exclude_from_totals: StrictBool = Field(description="If true, the transactions in this category will be excluded from totals. Inherited from Category Group.")
38
+ updated_at: datetime = Field(description="The date and time of when the category was last updated (in the ISO 8601 extended format).")
39
+ created_at: datetime = Field(description="The date and time of when the category was created (in the ISO 8601 extended format).")
40
+ group_id: Optional[StrictInt] = Field(description="The ID of the category group this category belongs to or `null` if the category doesn't belong to a group, or is itself a category group.")
41
+ is_group: StrictBool = Field(description="Will always be false for a category that is part of category group.")
42
+ archived: StrictBool = Field(description="If true, the category is archived and not displayed in relevant areas of the Lunch Money app.")
43
+ archived_at: Optional[datetime] = Field(description="The date and time of when the category was last archived (in the ISO 8601 extended format).")
44
+ order: Optional[StrictInt] = Field(description="An index specifying the position in which the category is displayed on the categories page in the Lunch Money GUI. For categories within a category group the order is relative to the other categories within the group.<br> API.")
45
+ collapsed: Optional[StrictBool] = Field(default=None, description="If `true`, the category is collapsed in the Lunch Money GUI.")
46
+ __properties: ClassVar[List[str]] = ["id", "name", "description", "is_income", "exclude_from_budget", "exclude_from_totals", "updated_at", "created_at", "group_id", "is_group", "archived", "archived_at", "order", "collapsed"]
47
+
48
+ model_config = ConfigDict(
49
+ populate_by_name=True,
50
+ validate_assignment=True,
51
+ protected_namespaces=(),
52
+ )
53
+
54
+
55
+ def to_str(self) -> str:
56
+ """Returns the string representation of the model using alias"""
57
+ return pprint.pformat(self.model_dump(by_alias=True))
58
+
59
+ def to_json(self) -> str:
60
+ """Returns the JSON representation of the model using alias"""
61
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
62
+ return json.dumps(self.to_dict())
63
+
64
+ @classmethod
65
+ def from_json(cls, json_str: str) -> Optional[Self]:
66
+ """Create an instance of ChildCategoryObject from a JSON string"""
67
+ return cls.from_dict(json.loads(json_str))
68
+
69
+ def to_dict(self) -> Dict[str, Any]:
70
+ """Return the dictionary representation of the model using alias.
71
+
72
+ This has the following differences from calling pydantic's
73
+ `self.model_dump(by_alias=True)`:
74
+
75
+ * `None` is only added to the output dict for nullable fields that
76
+ were set at model initialization. Other fields with value `None`
77
+ are ignored.
78
+ """
79
+ excluded_fields: Set[str] = set([
80
+ ])
81
+
82
+ _dict = self.model_dump(
83
+ by_alias=True,
84
+ exclude=excluded_fields,
85
+ exclude_none=True,
86
+ )
87
+ # set to None if description (nullable) is None
88
+ # and model_fields_set contains the field
89
+ if self.description is None and "description" in self.model_fields_set:
90
+ _dict['description'] = None
91
+
92
+ # set to None if group_id (nullable) is None
93
+ # and model_fields_set contains the field
94
+ if self.group_id is None and "group_id" in self.model_fields_set:
95
+ _dict['group_id'] = None
96
+
97
+ # set to None if archived_at (nullable) is None
98
+ # and model_fields_set contains the field
99
+ if self.archived_at is None and "archived_at" in self.model_fields_set:
100
+ _dict['archived_at'] = None
101
+
102
+ # set to None if order (nullable) is None
103
+ # and model_fields_set contains the field
104
+ if self.order is None and "order" in self.model_fields_set:
105
+ _dict['order'] = None
106
+
107
+ # set to None if collapsed (nullable) is None
108
+ # and model_fields_set contains the field
109
+ if self.collapsed is None and "collapsed" in self.model_fields_set:
110
+ _dict['collapsed'] = None
111
+
112
+ return _dict
113
+
114
+ @classmethod
115
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
116
+ """Create an instance of ChildCategoryObject from a dict"""
117
+ if obj is None:
118
+ return None
119
+
120
+ if not isinstance(obj, dict):
121
+ return cls.model_validate(obj)
122
+
123
+ _obj = cls.model_validate({
124
+ "id": obj.get("id"),
125
+ "name": obj.get("name"),
126
+ "description": obj.get("description"),
127
+ "is_income": obj.get("is_income"),
128
+ "exclude_from_budget": obj.get("exclude_from_budget"),
129
+ "exclude_from_totals": obj.get("exclude_from_totals"),
130
+ "updated_at": obj.get("updated_at"),
131
+ "created_at": obj.get("created_at"),
132
+ "group_id": obj.get("group_id"),
133
+ "is_group": obj.get("is_group"),
134
+ "archived": obj.get("archived"),
135
+ "archived_at": obj.get("archived_at"),
136
+ "order": obj.get("order"),
137
+ "collapsed": obj.get("collapsed")
138
+ })
139
+ return _obj
140
+
141
+
@@ -0,0 +1,219 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Lunch Money API - v2
5
+
6
+ Welcome to the Lunch Money v2 API. A working version of this API is now available through these docs, or directly at: `https://api.lunchmoney.dev/v2` <span class=\"red-text\"><strong>This is in alpha launch of a major API update. It is still subject to change during this alpha review period and bugs may still exist. Users are strongly encouraged to use the mock service or to create a test budget with example data as the first step to interacting with the v2 API.</strong></span> See the [Getting Started Guide](https://alpha.lunchmoney.dev/v2/getting-started) for more information on using a test budget.<br<br> If you are new to the v2 API, you may wish to review the [v2 API Overview of Changes](https://alpha.lunchmoney.dev/v2/changelog). ### Static Mock Server You may also use these docs to explore the API using a static mock server endpoint.<p> This enables users to become familiar with the API without having to create an access token, and eliminates the possibility of modifying real data. <p> To access this endpoint select the second endpoint in the the \"Server\" dropdown to the right. When selected you should see \"Static Mock v2 Lunch Money API Server\".<br> When using this server, set your Bearer token to any string with 11 or more characters. ### Migrating from V1 The v2 API is NOT backwards compatible with the v1 API. Developers are encouraged to review the [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) to understand the changes and plan their migration. ### Acknowledgments If you have been providing feedback on the API during our iterative design process, **THANK YOU**. We are happy to provide the opportunity to finally interact with the working API that was built based on your feedback. ### Useful links: - [Getting Started](https://alpha.lunchmoney.dev/v2/getting-started) - [v2 API Changelog](https://alpha.lunchmoney.dev/v2/changelog) - [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) - [Rate Limits](https://alpha.lunchmoney.dev/v2/rate-limits) - [Current v1 Lunch Money API Documentation](https://lunchmoney.dev) - [Awesome Lunch Money Projects](https://github.com/lunch-money/awesome-lunchmoney?tab=readme-ov-file)
7
+
8
+ The version of the OpenAPI document: 2.8.4
9
+ Contact: devsupport@lunchmoney.app
10
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
11
+
12
+ Do not edit the class manually.
13
+ """ # noqa: E501
14
+
15
+
16
+ from __future__ import annotations
17
+ import pprint
18
+ import re # noqa: F401
19
+ import json
20
+
21
+ from datetime import date, datetime
22
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator
23
+ from typing import Any, ClassVar, Dict, List, Optional, Union
24
+ from typing_extensions import Annotated
25
+ from lunchmoney.models.currency_enum import CurrencyEnum
26
+ from lunchmoney.models.transaction_attachment_object import TransactionAttachmentObject
27
+ from typing import Optional, Set
28
+ from typing_extensions import Self
29
+
30
+ class ChildTransactionObject(BaseModel):
31
+ """
32
+ ChildTransactionObject
33
+ """ # noqa: E501
34
+ id: StrictInt = Field(description="System created unique identifier for transaction")
35
+ var_date: date = Field(description="Date of transaction in ISO 8601 format", alias="date")
36
+ amount: StrictStr = Field(description="Amount of the transaction in numeric format to 4 decimal places. Positive values indicate a debit transaction, negative values indicate a credit transaction.")
37
+ currency: CurrencyEnum = Field(description="Three-letter lowercase currency code of the transaction in ISO 4217 format")
38
+ to_base: Union[StrictFloat, StrictInt] = Field(description="The amount converted to the user's primary currency. If the transaction currency is the same as the user's primary currency, to_base and amount will be the same. Positive values indicate a debit transaction, negative values indicate a credit transaction.")
39
+ recurring_id: Optional[StrictInt] = Field(description="The unique identifier of the associated recurring item that this transaction matched.")
40
+ payee: Annotated[str, Field(min_length=0, strict=True, max_length=140)] = Field(description="Name of payee set by the user, the financial institution, or by a matched recurring item. This will match the value displayed in payee field on the transactions page in the GUI. ")
41
+ category_id: Optional[StrictInt] = Field(description="Unique identifier of associated category set by the user or by a matched recurring item.<br> Category details can be obtained by passing the value of this property to the [Get A Single Category](../operations/getCategoryById) API")
42
+ notes: Optional[Annotated[str, Field(min_length=0, strict=True, max_length=350)]] = Field(description="Any transaction notes set by the user or by a matched recurring item. This will match the value displayed in notes field on the transactions page in the GUI. ")
43
+ status: StrictStr = Field(description="Status of the transaction. Will be one of the following values: ")
44
+ is_pending: StrictBool = Field(description="Denotes if the transaction is pending (not posted). Applies only to transactions in synced accounts and will always be false for transactions associated with manual accounts.")
45
+ created_at: datetime = Field(description="The date and time of when the transaction was created (in the ISO 8601 extended format).")
46
+ updated_at: datetime = Field(description="The date and time of when the transaction was last updated (in the ISO 8601 extended format).")
47
+ is_split_parent: Optional[StrictBool] = Field(default=None, description="If true this transaction has been split into two or more other transactions. By default parent transactions are not returned in call to `GET /transactions` but they can be queried directly by their ID.")
48
+ split_parent_id: Optional[StrictInt] = Field(description="A transaction ID if this is a split transaction. Denotes the transaction ID of the original, or parent, transaction. Is null if this is not a split transaction")
49
+ is_group_parent: StrictBool = Field(description="True if this transaction represents a group of transactions. If so, amount and currency represent the totalled amount of transactions bearing this transaction's id as their group_parent_id. Amount is calculated based on the user's primary currency.")
50
+ group_parent_id: Optional[StrictInt] = Field(description="Is set if this transaction is part of a group. Denotes the ID of the grouped transaction this is now included in. By default the transactions that were grouped are not returned in a call to `GET /transactions` but they can be queried directly by calling the `GET /transactions/group/{id}`, where the id passed is associated with a transaction where the `is_group_parent` attribute is true")
51
+ manual_account_id: Optional[StrictInt] = Field(description="The unique identifier of the manual account associated with this transaction. This will always be null if this transaction is associated with a synced account or if this transaction has no associated account and appears as a \"Cash Transaction\" in the Lunch Money GUI.")
52
+ plaid_account_id: Optional[StrictInt] = Field(description="The unique identifier of the plaid account associated with this transaction. This will always be null if this transaction is associated with a manual account or if this transaction has no associated account and appears as a \"Cash Transaction\" in the Lunch Money GUI.")
53
+ tag_ids: List[StrictInt] = Field(description="A list of tag_ids for the tags associated with this transaction. If the transaction has no tags this will be an empty list.<br> Tag details can be obtained by passing the value of this attribute as the `ids` query parameter to the [List Tags](../operations/getTags) API")
54
+ source: Optional[StrictStr] = Field(description="Source of the transaction: - `api`: Transaction was added by a call to the [POST /transactions](../operations/createTransaction) API - `csv`: Transaction was added via a CSV Import - `manual`: Transaction was created via the \"Add to Cash\" button on the Transactions page - `merge`: Transactions were originally in an account that was merged into another account - `plaid`: Transaction came from a Financial Institution synced via Plaid - `recurring`: Transaction was created from the Recurring page - `rule`: Transaction was created by a rule to split a transaction - `split`: This is a transaction created by splitting another transaction - `user`: This is a legacy value and is replaced by either csv or manual ")
55
+ external_id: Optional[Annotated[str, Field(min_length=0, strict=True, max_length=75)]] = Field(description="A user-defined external ID for any transaction that was added via csv import, `POST /transactions` API call, or manually added via the Lunch Money GUI. No external ID exists for transactions associated with synced accounts, and they cannot be added. For transactions associated with manual accounts, the external ID must be unique as attempts to add a subsequent transaction with the same external_id and manual_account_id will be flagged as duplicates and fail.")
56
+ plaid_metadata: Optional[Dict[str, Any]] = Field(default=None, description="If requested, the transaction's plaid_metadata that came when this transaction was obtained. This will be a json object, but the schema is variable. This will only be present for transactions associated with a plaid account.")
57
+ custom_metadata: Optional[Dict[str, Any]] = Field(default=None, description="If requested, the transaction's custom_metadata that was included when the transaction was inserted via the API. This will be a json object, but the schema is variable.")
58
+ files: Optional[List[TransactionAttachmentObject]] = Field(default=None, description="A list of objects that describe any attachments to the transaction")
59
+ __properties: ClassVar[List[str]] = ["id", "date", "amount", "currency", "to_base", "recurring_id", "payee", "category_id", "notes", "status", "is_pending", "created_at", "updated_at", "is_split_parent", "split_parent_id", "is_group_parent", "group_parent_id", "manual_account_id", "plaid_account_id", "tag_ids", "source", "external_id", "plaid_metadata", "custom_metadata", "files"]
60
+
61
+ @field_validator('status')
62
+ def status_validate_enum(cls, value):
63
+ """Validates the enum"""
64
+ if value not in set(['reviewed', 'unreviewed', 'delete_pending']):
65
+ raise ValueError("must be one of enum values ('reviewed', 'unreviewed', 'delete_pending')")
66
+ return value
67
+
68
+ @field_validator('source')
69
+ def source_validate_enum(cls, value):
70
+ """Validates the enum"""
71
+ if value is None:
72
+ return value
73
+
74
+ if value not in set(['api', 'csv', 'manual', 'merge', 'plaid', 'recurring', 'rule', 'split', 'user']):
75
+ raise ValueError("must be one of enum values ('api', 'csv', 'manual', 'merge', 'plaid', 'recurring', 'rule', 'split', 'user')")
76
+ return value
77
+
78
+ model_config = ConfigDict(
79
+ populate_by_name=True,
80
+ validate_assignment=True,
81
+ protected_namespaces=(),
82
+ )
83
+
84
+
85
+ def to_str(self) -> str:
86
+ """Returns the string representation of the model using alias"""
87
+ return pprint.pformat(self.model_dump(by_alias=True))
88
+
89
+ def to_json(self) -> str:
90
+ """Returns the JSON representation of the model using alias"""
91
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
92
+ return json.dumps(self.to_dict())
93
+
94
+ @classmethod
95
+ def from_json(cls, json_str: str) -> Optional[Self]:
96
+ """Create an instance of ChildTransactionObject from a JSON string"""
97
+ return cls.from_dict(json.loads(json_str))
98
+
99
+ def to_dict(self) -> Dict[str, Any]:
100
+ """Return the dictionary representation of the model using alias.
101
+
102
+ This has the following differences from calling pydantic's
103
+ `self.model_dump(by_alias=True)`:
104
+
105
+ * `None` is only added to the output dict for nullable fields that
106
+ were set at model initialization. Other fields with value `None`
107
+ are ignored.
108
+ """
109
+ excluded_fields: Set[str] = set([
110
+ ])
111
+
112
+ _dict = self.model_dump(
113
+ by_alias=True,
114
+ exclude=excluded_fields,
115
+ exclude_none=True,
116
+ )
117
+ # override the default output from pydantic by calling `to_dict()` of each item in files (list)
118
+ _items = []
119
+ if self.files:
120
+ for _item_files in self.files:
121
+ if _item_files:
122
+ _items.append(_item_files.to_dict())
123
+ _dict['files'] = _items
124
+ # set to None if recurring_id (nullable) is None
125
+ # and model_fields_set contains the field
126
+ if self.recurring_id is None and "recurring_id" in self.model_fields_set:
127
+ _dict['recurring_id'] = None
128
+
129
+ # set to None if category_id (nullable) is None
130
+ # and model_fields_set contains the field
131
+ if self.category_id is None and "category_id" in self.model_fields_set:
132
+ _dict['category_id'] = None
133
+
134
+ # set to None if notes (nullable) is None
135
+ # and model_fields_set contains the field
136
+ if self.notes is None and "notes" in self.model_fields_set:
137
+ _dict['notes'] = None
138
+
139
+ # set to None if split_parent_id (nullable) is None
140
+ # and model_fields_set contains the field
141
+ if self.split_parent_id is None and "split_parent_id" in self.model_fields_set:
142
+ _dict['split_parent_id'] = None
143
+
144
+ # set to None if group_parent_id (nullable) is None
145
+ # and model_fields_set contains the field
146
+ if self.group_parent_id is None and "group_parent_id" in self.model_fields_set:
147
+ _dict['group_parent_id'] = None
148
+
149
+ # set to None if manual_account_id (nullable) is None
150
+ # and model_fields_set contains the field
151
+ if self.manual_account_id is None and "manual_account_id" in self.model_fields_set:
152
+ _dict['manual_account_id'] = None
153
+
154
+ # set to None if plaid_account_id (nullable) is None
155
+ # and model_fields_set contains the field
156
+ if self.plaid_account_id is None and "plaid_account_id" in self.model_fields_set:
157
+ _dict['plaid_account_id'] = None
158
+
159
+ # set to None if source (nullable) is None
160
+ # and model_fields_set contains the field
161
+ if self.source is None and "source" in self.model_fields_set:
162
+ _dict['source'] = None
163
+
164
+ # set to None if external_id (nullable) is None
165
+ # and model_fields_set contains the field
166
+ if self.external_id is None and "external_id" in self.model_fields_set:
167
+ _dict['external_id'] = None
168
+
169
+ # set to None if plaid_metadata (nullable) is None
170
+ # and model_fields_set contains the field
171
+ if self.plaid_metadata is None and "plaid_metadata" in self.model_fields_set:
172
+ _dict['plaid_metadata'] = None
173
+
174
+ # set to None if custom_metadata (nullable) is None
175
+ # and model_fields_set contains the field
176
+ if self.custom_metadata is None and "custom_metadata" in self.model_fields_set:
177
+ _dict['custom_metadata'] = None
178
+
179
+ return _dict
180
+
181
+ @classmethod
182
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
183
+ """Create an instance of ChildTransactionObject from a dict"""
184
+ if obj is None:
185
+ return None
186
+
187
+ if not isinstance(obj, dict):
188
+ return cls.model_validate(obj)
189
+
190
+ _obj = cls.model_validate({
191
+ "id": obj.get("id"),
192
+ "date": obj.get("date"),
193
+ "amount": obj.get("amount"),
194
+ "currency": obj.get("currency"),
195
+ "to_base": obj.get("to_base"),
196
+ "recurring_id": obj.get("recurring_id"),
197
+ "payee": obj.get("payee"),
198
+ "category_id": obj.get("category_id"),
199
+ "notes": obj.get("notes"),
200
+ "status": obj.get("status"),
201
+ "is_pending": obj.get("is_pending"),
202
+ "created_at": obj.get("created_at"),
203
+ "updated_at": obj.get("updated_at"),
204
+ "is_split_parent": obj.get("is_split_parent"),
205
+ "split_parent_id": obj.get("split_parent_id"),
206
+ "is_group_parent": obj.get("is_group_parent"),
207
+ "group_parent_id": obj.get("group_parent_id"),
208
+ "manual_account_id": obj.get("manual_account_id"),
209
+ "plaid_account_id": obj.get("plaid_account_id"),
210
+ "tag_ids": obj.get("tag_ids"),
211
+ "source": obj.get("source"),
212
+ "external_id": obj.get("external_id"),
213
+ "plaid_metadata": obj.get("plaid_metadata"),
214
+ "custom_metadata": obj.get("custom_metadata"),
215
+ "files": [TransactionAttachmentObject.from_dict(_item) for _item in obj["files"]] if obj.get("files") is not None else None
216
+ })
217
+ return _obj
218
+
219
+