rcvatkit 0.1.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.
rcvatkit/__init__.py ADDED
@@ -0,0 +1,34 @@
1
+ """
2
+ rcvatkit -- find and calculate the UK VAT reverse-charge adjustment for
3
+ foreign-currency purchase invoices sitting in Sage 50, when they've been
4
+ posted at the wrong tax code by an OCR/import tool.
5
+
6
+ from rcvatkit import find_reverse_charge_candidates, compute_adjustment
7
+ from rcvatkit import last_completed_quarter
8
+
9
+ See README.md for the full walkthrough.
10
+ """
11
+
12
+ from .checker import (
13
+ DEFAULT_BASE_CURRENCY_ID,
14
+ DEFAULT_TARGET_TAX_CODE,
15
+ DEFAULT_VAT_RATE,
16
+ ReverseChargeLine,
17
+ compute_adjustment,
18
+ find_reverse_charge_candidates,
19
+ )
20
+ from .quarters import VAT_STAGGERS, last_completed_quarter
21
+
22
+ __version__ = "0.1.0"
23
+
24
+ __all__ = [
25
+ "find_reverse_charge_candidates",
26
+ "compute_adjustment",
27
+ "ReverseChargeLine",
28
+ "last_completed_quarter",
29
+ "VAT_STAGGERS",
30
+ "DEFAULT_VAT_RATE",
31
+ "DEFAULT_TARGET_TAX_CODE",
32
+ "DEFAULT_BASE_CURRENCY_ID",
33
+ "__version__",
34
+ ]
rcvatkit/checker.py ADDED
@@ -0,0 +1,170 @@
1
+ """
2
+ rcvatkit.checker
3
+ ================
4
+ Finds foreign-currency purchase invoices/credits in Sage 50 that have
5
+ NOT yet been coded with the reverse-charge tax code, and calculates the
6
+ VAT return manual adjustment needed to correct it.
7
+
8
+ Background
9
+ ----------
10
+ Many UK businesses receive non-GBP supplier invoices via an OCR/import
11
+ tool (AutoEntry, Dext, Hubdoc, etc.), and these tools commonly post
12
+ them at the standard "no VAT" tax code (often T0) rather than the
13
+ reverse-charge code Sage expects for EU/foreign purchases (often T18).
14
+ Sage 50 will not accept a reverse-charge tax code on a manual journal
15
+ ("This tax code cannot be used for Journal transactions"), so the fix
16
+ is not a journal at all -- it's a manual adjustment on the VAT return
17
+ itself: add the same amount to Box 1 (output VAT) and Box 4 (input
18
+ VAT). The net effect on the VAT bill is nil, but the boxes are
19
+ populated correctly for HMRC.
20
+
21
+ This module finds the underlying transactions and does the arithmetic.
22
+ It does not touch Sage or submit anything -- applying the adjustment is
23
+ a manual step in Sage's VAT Return "Adjustments" screen (see README).
24
+
25
+ A note on tax codes and VAT rates: T18 / 20% are the common UK default,
26
+ but your Sage configuration may differ (different tax code numbering,
27
+ a different rate for what you buy). Both are parameters here, not
28
+ hardcoded assumptions -- check your own Sage tax code list if unsure.
29
+ """
30
+
31
+ from dataclasses import dataclass
32
+ from datetime import date
33
+ from typing import Dict, List, Sequence
34
+
35
+ from sagekit import get_columns
36
+
37
+ DEFAULT_VAT_RATE = 0.20
38
+ DEFAULT_TARGET_TAX_CODE = "T18"
39
+
40
+ # Sage's ODBC currency IDs are offset by one from what the Sage 50 UI
41
+ # dropdown shows (UI "0 -- Pound Sterling" is ODBC value 1, UI "1 -- US
42
+ # Dollar" is ODBC value 2, and so on) -- confirmed by testing against a
43
+ # live Sage 50 install. 1 is the near-universal default for a UK
44
+ # company's base currency, but if your GBP shows up as a different ID,
45
+ # override it -- see README for how to check.
46
+ DEFAULT_BASE_CURRENCY_ID = 1
47
+
48
+
49
+ @dataclass
50
+ class ReverseChargeLine:
51
+ account_ref: str
52
+ txn_type: str
53
+ invoice_ref: str
54
+ txn_date: date
55
+ foreign_gross: float
56
+ gbp_gross: float
57
+
58
+
59
+ def _find_col(available, candidates, label):
60
+ for c in candidates:
61
+ if c.upper() in available:
62
+ return c.upper()
63
+ raise KeyError(
64
+ f"Could not find a column for '{label}'.\n"
65
+ f" Tried: {candidates}\n"
66
+ f" Available: {sorted(available)}"
67
+ )
68
+
69
+
70
+ def find_reverse_charge_candidates(
71
+ cursor,
72
+ date_from: date,
73
+ date_to: date,
74
+ target_tax_code: str = DEFAULT_TARGET_TAX_CODE,
75
+ base_currency_id: int = DEFAULT_BASE_CURRENCY_ID,
76
+ purchase_types: Sequence[str] = ("PI", "PC"),
77
+ ) -> List[ReverseChargeLine]:
78
+ """
79
+ Query Sage 50 for purchase invoices/credits (types PI/PC by
80
+ default) dated between date_from and date_to, in a currency other
81
+ than base_currency_id, that are NOT yet coded with
82
+ target_tax_code.
83
+
84
+ Column names are auto-detected against the live database (Sage
85
+ 50's ODBC schema varies a little between versions), so this works
86
+ across installs without editing any SQL.
87
+ """
88
+ ah_cols = get_columns(cursor, "AUDIT_HEADER")
89
+ as_cols = get_columns(cursor, "AUDIT_SPLIT")
90
+ pl_cols = get_columns(cursor, "PURCHASE_LEDGER")
91
+
92
+ ah_date = _find_col(ah_cols, ["DATE", "INV_DATE", "TRANS_DATE"], "transaction date")
93
+ ah_fgross = _find_col(ah_cols, ["FOREIGN_GROSS_AMOUNT"], "foreign gross amount")
94
+ ah_gross = _find_col(ah_cols, ["GROSS_AMOUNT"], "GBP gross amount")
95
+ ah_ref = _find_col(ah_cols, ["ACCOUNT_REF"], "account ref")
96
+ ah_inv = _find_col(ah_cols, ["INV_REF", "REFERENCE"], "invoice ref")
97
+ ah_del = _find_col(ah_cols, ["DELETED_FLAG", "DELETED", "RECORD_DELETED"], "deleted flag")
98
+ ah_pk = _find_col(ah_cols, ["HEADER_NUMBER", "TRAN_NUMBER", "RECORD_NUMBER"], "header key")
99
+ as_fk = _find_col(as_cols, ["HEADER_NUMBER", "TRAN_NUMBER", "RECORD_NUMBER"], "split key")
100
+ as_tax = _find_col(as_cols, ["TAX_CODE", "TAX_TYPE", "VAT_CODE"], "tax code")
101
+ pl_ref = _find_col(pl_cols, ["ACCOUNT_REF"], "PL account ref")
102
+ pl_curr = _find_col(pl_cols, ["CURRENCY", "CURRENCY_CODE"], "PL currency")
103
+
104
+ type_list = ", ".join(f"'{t}'" for t in purchase_types)
105
+
106
+ # Sage's ODBC driver rejects INNER JOIN across 3+ tables ("Invalid
107
+ # outer join specification") -- the implicit (comma) join style
108
+ # below is required for a 3-table query, not a style choice.
109
+ sql = f"""
110
+ SELECT
111
+ h.{ah_ref} AS ACCOUNT_REF,
112
+ h.TYPE AS TXN_TYPE,
113
+ h.{ah_inv} AS INV_REF,
114
+ h.{ah_date} AS TXN_DATE,
115
+ h.{ah_fgross} AS FOREIGN_GROSS,
116
+ h.{ah_gross} AS GBP_GROSS
117
+ FROM AUDIT_HEADER h, AUDIT_SPLIT s, PURCHASE_LEDGER p
118
+ WHERE h.{ah_pk} = s.{as_fk}
119
+ AND h.{ah_ref} = p.{pl_ref}
120
+ AND h.TYPE IN ({type_list})
121
+ AND h.{ah_del} = 0
122
+ AND p.{pl_curr} <> {int(base_currency_id)}
123
+ AND s.{as_tax} <> '{target_tax_code}'
124
+ AND h.{ah_date} >= {{d '{date_from.strftime("%Y-%m-%d")}'}}
125
+ AND h.{ah_date} <= {{d '{date_to.strftime("%Y-%m-%d")}'}}
126
+ ORDER BY h.{ah_ref}, h.{ah_date}, h.{ah_inv}
127
+ """
128
+
129
+ cursor.execute(sql)
130
+ rows = cursor.fetchall()
131
+
132
+ return [
133
+ ReverseChargeLine(
134
+ account_ref=str(r[0]),
135
+ txn_type=str(r[1]),
136
+ invoice_ref=str(r[2]),
137
+ txn_date=r[3],
138
+ foreign_gross=float(r[4] or 0),
139
+ gbp_gross=float(r[5] or 0),
140
+ )
141
+ for r in rows
142
+ ]
143
+
144
+
145
+ def compute_adjustment(
146
+ lines: List[ReverseChargeLine], vat_rate: float = DEFAULT_VAT_RATE
147
+ ) -> Dict[str, float]:
148
+ """
149
+ Given the lines found by find_reverse_charge_candidates, calculate
150
+ the manual VAT return adjustment: the same amount added to both
151
+ Box 1 (output VAT) and Box 4 (input VAT), so the net effect on the
152
+ VAT bill is nil but both boxes are correctly populated for HMRC.
153
+
154
+ Returns a dict with net_gbp, vat_rate, box_1, box_4 and
155
+ net_liability_effect (always 0.0 -- included so callers don't have
156
+ to know that fact themselves).
157
+ """
158
+ total_gbp = sum(line.gbp_gross for line in lines)
159
+ # Purchase invoices are stored as negative amounts in Sage; take the
160
+ # absolute value to get a positive net figure to apply the rate to.
161
+ net_gbp = abs(total_gbp)
162
+ vat_gbp = round(net_gbp * vat_rate, 2)
163
+
164
+ return {
165
+ "net_gbp": net_gbp,
166
+ "vat_rate": vat_rate,
167
+ "box_1": vat_gbp,
168
+ "box_4": vat_gbp,
169
+ "net_liability_effect": 0.0,
170
+ }
rcvatkit/quarters.py ADDED
@@ -0,0 +1,85 @@
1
+ """
2
+ rcvatkit.quarters
3
+ ==================
4
+ Helpers for working with UK VAT quarters.
5
+
6
+ HMRC assigns every VAT-registered business to one of three "stagger
7
+ groups", which determine which months your VAT quarters end in:
8
+
9
+ Stagger 1 -- quarters end Mar / Jun / Sep / Dec
10
+ Stagger 2 -- quarters end Jan / Apr / Jul / Oct
11
+ Stagger 3 -- quarters end Feb / May / Aug / Nov
12
+
13
+ You can find which stagger group you're in from your VAT registration
14
+ certificate or your HMRC online account -- it doesn't change unless you
15
+ specifically request it.
16
+
17
+ These helpers don't touch Sage or make any network calls -- they're
18
+ pure date arithmetic, useful for scripts that need to know "which VAT
19
+ quarter just finished" without hardcoding one business's quarter-end
20
+ months.
21
+ """
22
+
23
+ import calendar
24
+ from datetime import date
25
+ from typing import Optional, Tuple
26
+
27
+ # The four quarter-end months for each HMRC VAT stagger group.
28
+ VAT_STAGGERS = {
29
+ 1: (3, 6, 9, 12),
30
+ 2: (1, 4, 7, 10),
31
+ 3: (2, 5, 8, 11),
32
+ }
33
+
34
+
35
+ def last_completed_quarter(
36
+ stagger: int = 1, today: Optional[date] = None
37
+ ) -> Tuple[date, date]:
38
+ """
39
+ Return (start_date, end_date) of the most recently *completed* VAT
40
+ quarter for the given stagger group, as of `today` (defaults to the
41
+ real current date).
42
+
43
+ "Completed" means the quarter that has already ended -- if today
44
+ falls inside an in-progress quarter, this returns the one before it,
45
+ not the current one.
46
+
47
+ Example: stagger=3 (quarters ending Feb/May/Aug/Nov). If today is
48
+ any date in Mar/Apr/May, the last completed quarter is Dec-Feb.
49
+ """
50
+ if stagger not in VAT_STAGGERS:
51
+ raise ValueError(
52
+ f"Unknown stagger group {stagger!r} -- must be 1, 2, or 3. "
53
+ "Check your VAT registration certificate or HMRC online "
54
+ "account for which group you're in."
55
+ )
56
+
57
+ end_months = VAT_STAGGERS[stagger]
58
+ today = today or date.today()
59
+ y, m = today.year, today.month
60
+
61
+ # Walk backwards month by month looking for a quarter-end month whose
62
+ # quarter has genuinely finished (its end date is before the 1st of
63
+ # the month we're in now). A couple of years' worth of lookback is
64
+ # more than enough headroom.
65
+ for offset in range(0, 15):
66
+ mm = m - offset
67
+ yy = y
68
+ while mm <= 0:
69
+ mm += 12
70
+ yy -= 1
71
+
72
+ if mm in end_months:
73
+ end_date = date(yy, mm, calendar.monthrange(yy, mm)[1])
74
+ if end_date < date(y, m, 1):
75
+ start_month = mm - 2
76
+ start_year = yy
77
+ while start_month <= 0:
78
+ start_month += 12
79
+ start_year -= 1
80
+ return date(start_year, start_month, 1), end_date
81
+
82
+ raise RuntimeError(
83
+ "Could not determine the last completed VAT quarter -- "
84
+ "this shouldn't happen; please report it as a bug."
85
+ )
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: rcvatkit
3
+ Version: 0.1.0
4
+ Summary: Find UK VAT reverse-charge purchase invoices sitting in Sage 50 at the wrong tax code, and calculate the Box 1 / Box 4 VAT return adjustment to correct it.
5
+ Author: Duckboard
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Duckboard/rcvatkit
8
+ Project-URL: Buy me a coffee, https://ko-fi.com/duckboard
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
15
+ Requires-Python: >=3.8
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: sagekit>=0.1.0
19
+ Dynamic: license-file
20
+
21
+ # rcvatkit
22
+
23
+ Finds UK VAT **reverse-charge** purchase invoices sitting in **Sage 50**
24
+ at the wrong tax code, and calculates the VAT return manual adjustment
25
+ needed to correct it.
26
+
27
+ If this saves you time, consider [buying me a coffee](https://ko-fi.com/duckboard).
28
+
29
+ ## What problem this solves
30
+
31
+ If you receive foreign-currency (non-GBP) supplier invoices and use an
32
+ OCR/import tool such as AutoEntry, Dext, or Hubdoc, there's a good
33
+ chance those invoices are landing in Sage at the default "no VAT" tax
34
+ code (often `T0`) instead of the reverse-charge code Sage expects
35
+ (often `T18`). HMRC needs Boxes 1 and 4 of your VAT return to reflect
36
+ these transactions correctly.
37
+
38
+ Sage 50 won't let you post the reverse-charge code on a manual journal
39
+ ("This tax code cannot be used for Journal transactions"), so the fix
40
+ isn't a journal at all -- it's a **manual adjustment** on the VAT
41
+ return itself: add the same amount to Box 1 (output VAT) and Box 4
42
+ (input VAT). The net effect on your VAT bill is nil, but the boxes are
43
+ populated the way HMRC expects.
44
+
45
+ This toolkit finds the transactions and does the arithmetic. It does
46
+ not touch Sage or submit anything -- applying the adjustment is a
47
+ manual step in Sage's VAT Return "Adjustments" screen.
48
+
49
+ ## Features
50
+
51
+ - Finds non-GBP purchase invoices/credits not yet coded with your
52
+ reverse-charge tax code, using [sagekit](https://github.com/Duckboard/sagekit)
53
+ for the Sage 50 ODBC connection and its column auto-detection
54
+ - Calculates the Box 1 / Box 4 adjustment amount
55
+ - Built-in helper for UK VAT "stagger groups" -- works out which VAT
56
+ quarter just finished without you having to calculate the dates
57
+ by hand
58
+ - One worked example, ready to adapt: a CLI script with date prompts,
59
+ a results table, and a saved log file
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install -r requirements.txt
65
+ ```
66
+
67
+ or, to install as an editable package:
68
+
69
+ ```bash
70
+ pip install -e .
71
+ ```
72
+
73
+ This installs [sagekit](https://github.com/Duckboard/sagekit)
74
+ automatically -- rcvatkit builds on it rather than reimplementing the
75
+ Sage connection. You'll also need the **Sage Line 50 ODBC driver**
76
+ (installed alongside Sage 50 itself) and Sage 50 running while you
77
+ query it -- see sagekit's README for how to find your DSN.
78
+
79
+ ## Configuration
80
+
81
+ Copy `.env.example` to `.env` if you want to pre-fill values:
82
+
83
+ ```bash
84
+ cp .env.example .env
85
+ ```
86
+
87
+ ```
88
+ SAGE_DSN=SageLine50v33
89
+ SAGE_UID=MANAGER
90
+ SAGE_PWD=
91
+
92
+ RCVAT_STAGGER=1
93
+ RCVAT_TARGET_CODE=T18
94
+ RCVAT_VAT_RATE=0.20
95
+ ```
96
+
97
+ `.env` is already in `.gitignore` -- never commit real credentials.
98
+
99
+ ## Which VAT stagger group are you in?
100
+
101
+ HMRC assigns every VAT-registered business to one of three stagger
102
+ groups, which determine which months your VAT quarters end in. Check
103
+ your VAT registration certificate or HMRC online account if you're not
104
+ sure.
105
+
106
+ | Stagger | Quarters end |
107
+ |---|---|
108
+ | 1 | Mar / Jun / Sep / Dec |
109
+ | 2 | Jan / Apr / Jul / Oct |
110
+ | 3 | Feb / May / Aug / Nov |
111
+
112
+ ## Usage
113
+
114
+ ```python
115
+ from datetime import date
116
+ from sagekit import connect_or_exit
117
+ from rcvatkit import find_reverse_charge_candidates, compute_adjustment, last_completed_quarter
118
+
119
+ conn = connect_or_exit()
120
+ cursor = conn.cursor()
121
+
122
+ # Work out the last completed quarter automatically...
123
+ date_from, date_to = last_completed_quarter(stagger=1)
124
+
125
+ # ...or just pass your own dates:
126
+ # date_from, date_to = date(2026, 1, 1), date(2026, 3, 31)
127
+
128
+ lines = find_reverse_charge_candidates(cursor, date_from, date_to)
129
+ adjustment = compute_adjustment(lines)
130
+
131
+ print(f"{len(lines)} invoice line(s) found, net GBP {adjustment['net_gbp']:.2f}")
132
+ print(f"Add £{adjustment['box_1']:.2f} to Box 1 AND Box 4")
133
+
134
+ conn.close()
135
+ ```
136
+
137
+ ### Example script
138
+
139
+ ```bash
140
+ python examples/check_reverse_charge.py
141
+ ```
142
+
143
+ Prompts for a date range (defaulting to the last completed quarter for
144
+ your stagger group), connects to Sage, prints a table of the affected
145
+ invoices grouped by supplier plus the Box 1/Box 4 adjustment, and saves
146
+ everything to a timestamped log file alongside the script. Copy and
147
+ adapt it -- it's a starting point, not a fixed report.
148
+
149
+ ### Concept reference
150
+
151
+ | Concept | What it means |
152
+ |---|---|
153
+ | Reverse charge | The VAT treatment HMRC requires for certain foreign-currency purchases -- both output and input VAT are recorded, netting to nil but keeping Boxes 1 and 4 accurate |
154
+ | `T18` | Sage's common default reverse-charge tax code (yours may differ -- check your Sage tax code list) |
155
+ | Stagger group | Which three months your VAT quarters end in -- see table above |
156
+ | `AUDIT_HEADER` / `AUDIT_SPLIT` / `PURCHASE_LEDGER` | The three Sage ODBC tables this toolkit joins to find purchase invoices, their tax code, and the supplier's currency |
157
+
158
+ ## A Sage ODBC quirk worth knowing
159
+
160
+ Sage's ODBC driver **rejects `INNER JOIN` across three or more tables**
161
+ ("Invalid outer join specification"). `find_reverse_charge_candidates`
162
+ uses the older implicit (comma) join style for exactly this reason --
163
+ if you're adapting the SQL yourself and add a fourth table, keep using
164
+ commas rather than `INNER JOIN`.
165
+
166
+ Also, Sage's ODBC currency IDs are offset by one from what the Sage 50
167
+ UI dropdown shows (UI "0 -- Pound Sterling" is ODBC value `1`, UI
168
+ "1 -- US Dollar" is ODBC value `2`, and so on). `base_currency_id`
169
+ defaults to `1` (the near-universal UK base currency ID), but if your
170
+ own install differs, pass your own value -- run
171
+ `SELECT DISTINCT CURRENCY FROM PURCHASE_LEDGER` via sagekit to check.
172
+
173
+ ## Testing
174
+
175
+ ```bash
176
+ pip install pytest
177
+ pytest
178
+ ```
179
+
180
+ Tests use a fake cursor object, so they run offline without a real
181
+ Sage install, ODBC driver, or sagekit dependency needing to connect
182
+ anywhere.
183
+
184
+ ## Troubleshooting
185
+
186
+ | Symptom | Likely cause | Fix |
187
+ |---|---|---|
188
+ | `Invalid outer join specification` | SQL changed to use `INNER JOIN` across 3+ tables | Use the comma-join style -- see above |
189
+ | `Column not found` / `COLUMN DETECTION ERROR` | Column name varies by Sage version | Check the error message's "Available" list against your install |
190
+ | No rows returned | Wrong date range, or no non-GBP suppliers in that period | Confirm Sage is open, widen the date range, check `RCVAT_TARGET_CODE` matches what your install actually uses |
191
+ | Adjustment looks too big/small | Wrong `RCVAT_VAT_RATE` or wrong `base_currency_id` | Confirm your VAT rate and check `PURCHASE_LEDGER.CURRENCY` values for your GBP accounts |
192
+ | `This tax code cannot be used for Journal transactions` | Expected -- you tried to journal the reverse charge instead of using a manual VAT return adjustment | Use the Adjustments screen on the VAT return, not a journal |
193
+
194
+ ## Notes
195
+
196
+ - This calculates the adjustment; it does not post anything to Sage or
197
+ submit your VAT return. Always sanity-check the figures before
198
+ applying them.
199
+ - Not tax advice -- if you're unsure whether reverse charge applies to
200
+ your purchases, check with HMRC guidance or your accountant.
201
+
202
+ ## License
203
+
204
+ MIT -- see [LICENSE](LICENSE). Do whatever you like with this; a
205
+ credit or a [Ko-fi tip](https://ko-fi.com/duckboard) is appreciated
206
+ but never required.
@@ -0,0 +1,8 @@
1
+ rcvatkit/__init__.py,sha256=8C7dw51_LILp7DTMG9m9LzJpaqYB3Pf2KxYPM7s3C8E,903
2
+ rcvatkit/checker.py,sha256=v63Ri7UsOJsC-finwmTukhsyDH3_WLVqM-HiqQp5P7s,6611
3
+ rcvatkit/quarters.py,sha256=HS_QEJJ1PIYfzVo-K10vozgtODMYw-S9Jxi3Glnojy4,2886
4
+ rcvatkit-0.1.0.dist-info/licenses/LICENSE,sha256=ChymOtwCDSjsL0VwJuqUn7dw8gqHr0Rt4jHcFsJa8Ec,1066
5
+ rcvatkit-0.1.0.dist-info/METADATA,sha256=p3F830_mLwscRPlEIp_gwPyPxa0b7lgv7Cxl_a65MNQ,8000
6
+ rcvatkit-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
7
+ rcvatkit-0.1.0.dist-info/top_level.txt,sha256=OoTWKIMPuBWw-GkCe4l5pBMWKV4TO_veF4F1O_YnJ4U,9
8
+ rcvatkit-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Duckboard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ rcvatkit