You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Support additional operators in field based search
* Add index on table lines
* Add index on account ID to lines
* Remove unnecessary logs
* Remove unnecessary logs
* Introduce in and is operators in range
* Fix issue with null values
* Add test cases for in and is operators
* Sort transactions by timestamp
* Fix lines sorting
* test uuid table
* Remove test table
* Fix docs
* Fix docs
* Fix docs
* Remove QBank specific indexes
* Add docs on environment variables
Copy file name to clipboardExpand all lines: README.md
+83-40Lines changed: 83 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,15 +5,19 @@ Systems that manage money do so by managing its movement - by tracking where it
5
5
6
6
The there are two primitives in the system: **accounts** and **transactions**. Money moves between accounts by means of a transaction.
7
7
8
-
A **transaction** may have multiple *lines* - each line represents the change (*delta*) of money in one account. A valid transaction has a total delta of zero - no money is created or destroyed, and all money moved out of any account(s) has moved in to other account(s). QLedger validates all transactions made via the API with a zero delta check.
8
+
A **transaction** may have multiple *lines* - each line represents the change (*delta*) of money in one *account*. A valid transaction has a total delta of zero - no money is created or destroyed, and all money moved out of any account(s) has moved in to other account(s). QLedger validates all transactions made via the API with a zero delta check.
9
9
10
10
> Phrased another way, the law of conversation of money is formalized by the rules of double entry bookkeeping - money debited from any account must be credited to another account (and vice versa), implying that all transactions must have at least two entries (double entry) with a zero sum delta. QLedger makes it easy to follow these rules.
11
11
12
12
Accounts do not need to be predefined - they are called into existence when they are first used.
13
13
14
-
All accounts and transactions are identified by a string identifier, which also acts an idempotency and an immutability key. Transactions once sent to the ledger cannot be changed - any 'modification' or reversal requires a new transaction. The safe recovery mechanism for all network errors is also a simple retry - as long as the identifier does not change the transaction will never be indavertently duplicated.
14
+
All accounts and transactions are identified by a string identifier, which also acts an idempotency and an immutability key. Transactions once sent to the ledger cannot be changed - any 'modification' or reversal requires a new transaction. The safe recovery mechanism for all network errors is also a simple retry - as long as the identifier does not change the transaction will never be inadvertently duplicated.
15
15
16
-
#### POST `/v1/transactions`
16
+
## Transactions
17
+
18
+
Transaction can be created as follows:
19
+
20
+
`POST /v1/transactions`
17
21
```
18
22
{
19
23
"id": "abcd1234",
@@ -32,27 +36,37 @@ All accounts and transactions are identified by a string identifier, which also
32
36
```
33
37
> Transactions with a total delta not equal to zero will result in a `400 BAD REQUEST` error.
34
38
39
+
Transaction `timestamp` by default will be the time at which it is created. If necessary(such as migration of existing
40
+
transactions), can be overridden using the `timestamp` property in the payload as follows:
41
+
42
+
`POST /v1/transactions`
43
+
```
44
+
{
45
+
"id": "abcd1234",
46
+
"timestamp": "2017-01-01 13:01:05.000",
47
+
...
35
48
36
-
#### Metadata for Querying and Reports
49
+
}
50
+
```
37
51
38
-
Transactions and accounts can have arbitrary number of key-value pairs maintained as a single JSON `data` which helps in grouping and filtering them by one or more criteria.
52
+
> The `timestamp`in the payload should be in the format `2006-01-02 15:04:05.000`.
39
53
40
-
Both transactions and accounts can be updated multiple times with `data`. The existing`data`is always overwritten with the new `data` value.
54
+
Transactions can have arbitrary number of key-value pairs maintained as a single JSON`data`which helps in grouping and filtering them by one or more criteria.
41
55
42
56
The `data` can be arbitrary JSON value as follows:
43
57
```
44
58
{
45
59
"data": {
46
-
"k1": "",
47
-
"k2": "strval",
48
-
"k3": ["av1", "av2", "av3"],
49
-
"k4": {
50
-
"nest1": {
51
-
"nest2": "val"
60
+
"active": true,
61
+
"status": "completed",
62
+
"codes": ["O123", "C123", "F123"],
63
+
"client_data": {
64
+
"interval": {
65
+
"invoice": "monthly"
52
66
}
53
67
},
54
-
"k5": 2017,
55
-
"k6": "2017-12-01"
68
+
"amount": 2000,
69
+
"expiry": "2017-12-01T05:00:00Z"
56
70
}
57
71
}
58
72
```
@@ -87,20 +101,7 @@ The transactions can be created with `data` as follows:
87
101
}
88
102
```
89
103
90
-
The accounts can be created with `data` as follows:
91
-
92
-
`POST /v1/accounts`
93
-
```
94
-
{
95
-
"id": "alice",
96
-
"data": {
97
-
"product": "qw",
98
-
"date": "2017-01-01"
99
-
}
100
-
}
101
-
```
102
-
103
-
The transactions or accounts can be updated with `data` using endpoints `PUT /v1/transactions` and `PUT /v1/accounts`
104
+
Transactions can be updated multiple times with `data`. The existing `data` is always overwritten with the new `data` value.
104
105
105
106
The transaction with ID `abcd1234` is updated with `data` as follows:
106
107
@@ -125,24 +126,56 @@ The transaction with ID `abcd1234` is updated with `data` as follows:
125
126
}
126
127
```
127
128
128
-
#### Searching of accounts and transactions
129
+
## Accounts
130
+
131
+
An account with ID `alice` can be created with `data` as follows:
132
+
133
+
`POST /v1/accounts`
134
+
```
135
+
{
136
+
"id": "alice",
137
+
"data": {
138
+
"product": "qw",
139
+
"date": "2017-01-01"
140
+
}
141
+
}
142
+
```
143
+
144
+
An account can be updated with `data` as follows:
145
+
146
+
`PUT /v1/accounts`
147
+
```
148
+
{
149
+
"id": "alice",
150
+
"data": {
151
+
"product": "qw",
152
+
"date": "2017-01-05"
153
+
}
154
+
}
155
+
```
156
+
157
+
## Searching of accounts and transactions
129
158
130
159
The transactions and accounts can be filtered from the endpoints `GET /v1/transactions` and `GET /v1/accounts` with the search query formed using the bool clauses(`must` and `should`) and query types(`fields`, `terms` and `ranges`).
131
160
132
-
#####Query types:
161
+
### Query types:
133
162
134
-
###### -`fields` query
163
+
##### `fields` query
135
164
136
165
Find items where the specified column exists with the specified value in the specified range.
137
166
138
167
Example fields:
139
168
- Field `{"id": {"eq": "ACME.CREDIT"}}` filters items where the column `id` is equal to `ACME.CREDIT`
169
+
- Field `{"balance": {"ne": 0}}` filters items where the column `balance` is not equal to `0`.
140
170
- Field `{"balance": {"lt": 0}}` filters items where the column `balance` is less than `0`
141
171
- Field `{"timestamp": {"gte": "2017-01-01T05:30"}}` filters items where `timestamp` is greater than or equal to `2017-01-01T05:30`
172
+
- Field `{"id": {"ne": "ACME.CREDIT"}}` filters items where the column `id` is not equal to `ACME.CREDIT`
173
+
- Field `{"id": {"like": "%.DEBIT"}}` filters items where the column `id` ends with `.DEBIT`
174
+
- Field `{"id": {"notlike": "%.DEBIT"}}` filters items where the column `id` doesn't ends with `.DEBIT`
142
175
143
-
> The supported range operators are `lt`(less than), `lte`(less than or equal), `gt`(greater than), `gte`(greater than or equal), `eq`(equal).
176
+
> The supported field operators are `lt`(less than), `lte`(less than or equal), `gt`(greater than), `gte`(greater than or equal), `eq`(equal), `ne`(not equal), `like`(like patterns), `notlike`(not like patterns).
144
177
145
-
###### -`terms` query
178
+
##### `terms` query
146
179
147
180
Filters items where the specified key-value pairs in a term exists in the `data` JSON.
148
181
@@ -151,20 +184,25 @@ Example terms:
151
184
- Term `{"months": ["jan", "feb", "mar"]}` filters items where values `jan`, `feb` AND `mar` in `data.months` array
152
185
- Term `{"products":{"qw":{"tax":18.0}}}` filters items where subset `{"qw": {"tax": 18.0}}` in `products` object
153
186
154
-
155
-
###### - `range` query
187
+
##### `range` query
156
188
157
189
Filters items which the specified key in `data` JSON exists in the specified range of values.
158
190
159
191
Example range:
160
192
- Range `{"charge": {"gte": 2000, "lte": 4000}}` filters items where `data.charge >= 2000` AND `data.charge <= 4000`
161
193
- Range `{"date": {"gt": "2017-01-01","lt": "2017-06-31"}}` filters items where `data.date > '2017-01-01'` AND `data.date < '2017-01-31'`
194
+
- Range `{"type": {"is": null}}` filters items where `data.type` is `NIL`
195
+
- Range `{"type": {"is": null}}` filters items where `data.type` is not `NIL`
196
+
- Range `{"action": {"in": ["intent", "invoice"]}}` filters items where `data.action` is ANY of `("intent", "invoice")`
197
+
- Range `{"action": {"nin": ["charge", "refund"]}}` filters items where `data.action` is NOT ANY of `("charge", "refund")`
162
198
199
+
> The supported range operators are `lt`(less than), `lte`(less than or equal), `gt`(greater than), `gte`(greater than or equal), `eq`(equal), `ne`(not equal), `like`(like patterns), `notlike`(not like patterns), `is`(is null checks), `isnot`(not null checks), `in`(ANY of list), `nin`(NOT ANY of list).
163
200
164
-
##### Bool clauses:
201
+
202
+
### Bool clauses:
165
203
The following bool clauses determine whether all or any of the queries needs to be satisfied.
166
204
167
-
###### -`must` clause
205
+
##### `must` clause
168
206
All of the query items in the `must` clause must be satisfied to get results.
169
207
170
208
> The `must` clause can be equated with boolean `AND`
@@ -198,9 +236,7 @@ Example: The following query matches requests to match accounts which satisfies
198
236
}
199
237
```
200
238
201
-
202
-
203
-
###### - `should` clause
239
+
##### `should` clause
204
240
Any of the query items in the `should` clause should be satisfied to get results.
205
241
206
242
> The `should` clause can be equated with boolean `OR`
@@ -238,3 +274,10 @@ Example: The following query matches requests to match transactions which satisf
238
274
- Clients those doesn't support passing search payload in the `GET`, can alternatively use the `POST` endpoints: `POST /v1/transactions/_search` and `POST /v1/accounts/_search`.
239
275
240
276
- A search query can have both `must` and `should` clauses.
277
+
278
+
- Transactions in the search result are ordered chronological by default.
279
+
280
+
281
+
## Environment Variables:
282
+
283
+
Please read the documentation of all QLedger environment variables [here](./context#environment-variables)
0 commit comments