FluxFinance commited on
Commit
0bd118d
·
verified ·
1 Parent(s): 05826ec

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +32 -19
  2. packages.txt +1 -0
  3. requirements.txt +2 -2
  4. test_libreoffice_recalc.py +77 -0
README.md CHANGED
@@ -1,19 +1,32 @@
1
- ---
2
- title: UMI
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: red
6
- sdk: docker
7
- app_port: 8501
8
- tags:
9
- - streamlit
10
- pinned: false
11
- short_description: Streamlit template space
12
- ---
13
-
14
- # Welcome to Streamlit!
15
-
16
- Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
-
18
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
- forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NZ Mortgage Servicing Calculator
2
+
3
+ Pure Python Streamlit app for Hugging Face Spaces.
4
+
5
+ ## Hugging Face Spaces
6
+
7
+ 1. Create a new Space.
8
+ 2. Select **Streamlit** as the SDK.
9
+ 3. Upload `app.py`, `requirements.txt`, `packages.txt`, and this `README.md`.
10
+ 4. The app will run without Excel, VBA, Windows COM, or local macro files.
11
+
12
+ ## LibreOffice Formula Recalculation Test
13
+
14
+ Hugging Face installs system packages from `packages.txt`. This project uses that file to install LibreOffice for headless spreadsheet recalculation.
15
+
16
+ Run this after the Space builds, or locally after installing LibreOffice:
17
+
18
+ ```bash
19
+ python test_libreoffice_recalc.py
20
+ ```
21
+
22
+ Expected result:
23
+
24
+ ```text
25
+ LibreOffice formula recalc test: PASS
26
+ ```
27
+
28
+ ## Notes
29
+
30
+ This version replaces the old Excel macro execution with Python repayment, LVR, UMI, NSR, DTI, lender rate, LEM, and servicing-rule logic.
31
+
32
+ For production use, validate several real client scenarios against the previous workbook and tune each lender rule until the results match your accepted policy model.
packages.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ libreoffice
requirements.txt CHANGED
@@ -1,3 +1,3 @@
1
- altair
2
  pandas
3
- streamlit
 
1
+ streamlit
2
  pandas
3
+ openpyxl
test_libreoffice_recalc.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import shutil
2
+ import subprocess
3
+ import sys
4
+ import tempfile
5
+ from pathlib import Path
6
+
7
+ from openpyxl import Workbook, load_workbook
8
+
9
+
10
+ def find_soffice() -> str:
11
+ for name in ("soffice", "libreoffice"):
12
+ path = shutil.which(name)
13
+ if path:
14
+ return path
15
+ common_windows_paths = [
16
+ r"C:\Program Files\LibreOffice\program\soffice.exe",
17
+ r"C:\Program Files (x86)\LibreOffice\program\soffice.exe",
18
+ ]
19
+ for path in common_windows_paths:
20
+ if Path(path).exists():
21
+ return path
22
+ raise RuntimeError("LibreOffice/soffice was not found on PATH.")
23
+
24
+
25
+ def main() -> int:
26
+ soffice = find_soffice()
27
+ workdir = Path(tempfile.mkdtemp(prefix="lo_recalc_"))
28
+ input_path = workdir / "formula_test.xlsx"
29
+
30
+ wb = Workbook()
31
+ ws = wb.active
32
+ ws.title = "Dashboard"
33
+ ws["A1"] = 10
34
+ ws["A2"] = 25
35
+ ws["A3"] = "=SUM(A1:A2)"
36
+ ws["B1"] = '=IF(A3=35,"PASS","FAIL")'
37
+ wb.save(input_path)
38
+
39
+ subprocess.run(
40
+ [
41
+ soffice,
42
+ "--headless",
43
+ "--convert-to",
44
+ "xlsx",
45
+ "--outdir",
46
+ str(workdir),
47
+ str(input_path),
48
+ ],
49
+ check=True,
50
+ stdout=subprocess.PIPE,
51
+ stderr=subprocess.PIPE,
52
+ text=True,
53
+ )
54
+
55
+ recalculated = load_workbook(input_path, data_only=True)
56
+ ws_data = recalculated["Dashboard"]
57
+ sum_value = ws_data["A3"].value
58
+ pass_value = ws_data["B1"].value
59
+
60
+ print(f"soffice={soffice}")
61
+ print(f"A3={sum_value!r}")
62
+ print(f"B1={pass_value!r}")
63
+
64
+ if sum_value == 35 and pass_value == "PASS":
65
+ print("LibreOffice formula recalc test: PASS")
66
+ return 0
67
+
68
+ print("LibreOffice formula recalc test: FAIL")
69
+ return 1
70
+
71
+
72
+ if __name__ == "__main__":
73
+ try:
74
+ raise SystemExit(main())
75
+ except Exception as exc:
76
+ print(f"LibreOffice formula recalc test: ERROR - {exc}")
77
+ raise SystemExit(1)