Compare commits
44 Commits
d1dca531c3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cf0093029 | |||
| 73cd97f3c8 | |||
| 0b72adef7d | |||
| 225475e843 | |||
|
|
d84ba520cf | ||
| 0aeaf775dd | |||
| 88e8771b51 | |||
| 6c74b5d3bf | |||
| 47ba78d72c | |||
| 1946a98d59 | |||
| 8f35e08429 | |||
| 82bedc3117 | |||
| cb68e454bc | |||
|
|
91b078a0c3 | ||
|
|
eb46929893 | ||
| 675301df7f | |||
|
|
14e799a1d4 | ||
| 8ab1b69033 | |||
| dbeec9962d | |||
| 8750f268db | |||
|
|
b78526ad9f | ||
| 7146391c18 | |||
| 94b5563d15 | |||
| 937018dc16 | |||
| eda238c235 | |||
| f184d6cecc | |||
| e7646eee76 | |||
| 64ca39944b | |||
|
|
6b4beb5af8 | ||
|
|
d092eb0527 | ||
|
|
f9e9612df5 | ||
|
|
46ec2c0276 | ||
|
|
630ee1744f | ||
| 2679554e98 | |||
| 0912aef85e | |||
| ce90c6b350 | |||
| bc20a53f26 | |||
| 42f69773ec | |||
| 79ea359b1c | |||
| acbea7942c | |||
| 13a4c5836e | |||
| 315e972e1f | |||
| dffa9769bc | |||
| af15b3934e |
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
venv/
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
static/downloads/
|
||||||
|
static/uploads/
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
7989
activity.log
7989
activity.log
File diff suppressed because it is too large
Load Diff
114
app.log
114
app.log
@@ -1,114 +0,0 @@
|
|||||||
2025-02-15 11:07:16,100 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:07:16,100 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:07:16,131 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:07:16,131 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:07:16,137 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:07:16,137 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:13:26,290 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "GET / HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:13:26,290 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "GET / HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:13:26,315 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/css/index.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,315 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/css/index.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,504 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,504 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,626 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/js/validateFileInput.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,626 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/js/validateFileInput.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,633 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/js/searchContractor.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,633 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[36mGET /static/js/searchContractor.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:26,950 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
|
||||||
2025-02-15 11:13:26,950 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:26] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
|
||||||
2025-02-15 11:13:28,623 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "GET / HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:13:28,623 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "GET / HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:13:28,933 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/css/index.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,933 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/css/index.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,952 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/js/validateFileInput.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,952 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/js/validateFileInput.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,954 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/js/searchContractor.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,955 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,954 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/js/searchContractor.js HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:28,955 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:28] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:31,608 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:13:31,608 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:13:31,639 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:31,639 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:31,649 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:31,649 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:31,967 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:13:31,967 - INFO - 127.0.0.1 - - [15/Feb/2025 11:13:31] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:15:01,349 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:01] "[31m[1mPOST /check_state HTTP/1.1[0m" 409 -
|
|
||||||
2025-02-15 11:15:01,349 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:01] "[31m[1mPOST /check_state HTTP/1.1[0m" 409 -
|
|
||||||
2025-02-15 11:15:21,783 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:21] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:21,783 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:21] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,127 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,127 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,151 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,151 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,391 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,391 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,440 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:22,440 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:22] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:24,266 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:24] "POST /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:24,266 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:24] "POST /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:25,418 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:25,418 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:15:25,716 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:15:25,716 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:15:25,749 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:15:25,749 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:15:25,752 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:15:25,752 - INFO - 127.0.0.1 - - [15/Feb/2025 11:15:25] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:46,338 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:16:46,338 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:16:48,798 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:16:48,798 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:16:48,843 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:16:48,843 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:16:48,847 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:16:48,847 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:16:52,045 - DEBUG - Fetched state data successfully.
|
|
||||||
2025-02-15 11:16:52,045 - DEBUG - Fetched state data successfully.
|
|
||||||
2025-02-15 11:16:52,054 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:52,054 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:52,076 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:52,076 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:52,078 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:52,078 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:52,377 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:52,377 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:52] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:54,758 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:54] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:54,758 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:54] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:54,992 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:54] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:54,992 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:54] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:55,016 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:55] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:55,016 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:55] "POST /check_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:55,669 - INFO - State 'sss' added successfully.
|
|
||||||
2025-02-15 11:16:55,669 - INFO - 'State 'sss added successfully.
|
|
||||||
2025-02-15 11:16:55,670 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:55] "POST /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:55,670 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:55] "POST /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:57,235 - DEBUG - Fetched state data successfully.
|
|
||||||
2025-02-15 11:16:57,235 - DEBUG - Fetched state data successfully.
|
|
||||||
2025-02-15 11:16:57,239 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:57,239 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "GET /add_state HTTP/1.1" 200 -
|
|
||||||
2025-02-15 11:16:57,263 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:57,263 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "[36mGET /static/css/style.css HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:57,483 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:57,483 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "[36mGET /static/images/icons/pen_blue_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:57,567 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:16:57,567 - INFO - 127.0.0.1 - - [15/Feb/2025 11:16:57] "[36mGET /static/images/icons/bin_red_icon.png HTTP/1.1[0m" 304 -
|
|
||||||
2025-02-15 11:20:55,547 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:20:55,547 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:20:56,800 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:20:56,800 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:20:56,835 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:20:56,835 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:20:56,837 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:20:56,837 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:21:04,060 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:21:04,060 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:21:05,429 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:21:05,429 - INFO - Logging is set up.
|
|
||||||
2025-02-15 11:21:05,461 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:21:05,461 - WARNING - * Debugger is active!
|
|
||||||
2025-02-15 11:21:05,463 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:21:05,463 - INFO - * Debugger PIN: 558-213-972
|
|
||||||
2025-02-15 11:21:17,911 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
2025-02-15 11:21:17,911 - INFO - * Detected change in 'C:\\Users\\ADMIN\\PycharmProjects\\ManagementApplicationt\\main.py', reloading
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -6,7 +6,6 @@ from model.Log import LogHelper
|
|||||||
|
|
||||||
auth_bp = Blueprint('auth', __name__)
|
auth_bp = Blueprint('auth', __name__)
|
||||||
|
|
||||||
|
|
||||||
@auth_bp.route('/login', methods=['GET', 'POST'])
|
@auth_bp.route('/login', methods=['GET', 'POST'])
|
||||||
def login():
|
def login():
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +1,28 @@
|
|||||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
import config
|
||||||
|
from flask import Blueprint, render_template, request, redirect, url_for, jsonify, flash
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
import config
|
from model.State import State
|
||||||
import mysql.connector
|
|
||||||
|
|
||||||
from model.Block import Block
|
from model.Block import Block
|
||||||
from model.Utilities import HtmlHelper
|
from model.Utilities import HtmlHelper
|
||||||
|
|
||||||
block_bp = Blueprint('block', __name__)
|
block_bp = Blueprint('block', __name__)
|
||||||
|
block = Block()
|
||||||
|
# --- Add Block page -------
|
||||||
@block_bp.route('/add_block', methods=['GET', 'POST'])
|
@block_bp.route('/add_block', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_block():
|
def add_block():
|
||||||
|
# block = Block()
|
||||||
block = Block()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
block.AddBlock(request)
|
block.AddBlock(request)
|
||||||
return block.resultMessage
|
return block.resultMessage
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
state = State()
|
||||||
cursor = connection.cursor()
|
states = state.GetAllStates(request=request)
|
||||||
|
|
||||||
cursor.callproc("GetAllStates")
|
|
||||||
for rs in cursor.stored_results():
|
|
||||||
states = rs.fetchall()
|
|
||||||
|
|
||||||
block_data = block.GetAllBlocks(request)
|
block_data = block.GetAllBlocks(request)
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'add_block.html',
|
'add_block.html',
|
||||||
states=states,
|
states=states,
|
||||||
@@ -71,7 +62,7 @@ def get_districts(state_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def check_block():
|
def check_block():
|
||||||
|
|
||||||
block = Block()
|
# block = Block()
|
||||||
return block.CheckBlock(request)
|
return block.CheckBlock(request)
|
||||||
|
|
||||||
|
|
||||||
@@ -79,12 +70,19 @@ def check_block():
|
|||||||
@login_required
|
@login_required
|
||||||
def edit_block(block_id):
|
def edit_block(block_id):
|
||||||
|
|
||||||
block = Block()
|
|
||||||
|
# block = Block()
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
block.EditBlock(request, block_id)
|
block.EditBlock(request, block_id)
|
||||||
return block.resultMessage
|
block.resultMessage
|
||||||
|
|
||||||
|
if block.resultMessage:
|
||||||
|
flash("Block updated successfully!", "success")
|
||||||
|
return redirect(url_for('block.add_block'))
|
||||||
|
else:
|
||||||
|
flash(block.resultMessage, "error")
|
||||||
|
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
@@ -92,7 +90,10 @@ def edit_block(block_id):
|
|||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
states = rs.fetchall()
|
states = rs.fetchall()
|
||||||
|
|
||||||
cursor.callproc("GetAllDistrictsData")
|
# cursor.callproc("GetAllDistrictsData")
|
||||||
|
# for rs in cursor.stored_results():
|
||||||
|
# districts = rs.fetchall()
|
||||||
|
cursor.callproc("GetAllDistricts")
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
districts = rs.fetchall()
|
districts = rs.fetchall()
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ def edit_block(block_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def delete_block(block_id):
|
def delete_block(block_id):
|
||||||
|
|
||||||
block = Block()
|
# block = Block()
|
||||||
block.DeleteBlock(request, block_id)
|
block.DeleteBlock(request, block_id)
|
||||||
|
|
||||||
return redirect(url_for('block.add_block'))
|
return redirect(url_for('block.add_block'))
|
||||||
@@ -5,13 +5,13 @@ from model.District import District
|
|||||||
from model.State import State
|
from model.State import State
|
||||||
|
|
||||||
district_bp = Blueprint('district', __name__)
|
district_bp = Blueprint('district', __name__)
|
||||||
|
district = District()
|
||||||
|
|
||||||
|
# ------- District page --------
|
||||||
@district_bp.route('/add_district', methods=['GET', 'POST'])
|
@district_bp.route('/add_district', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_district():
|
def add_district():
|
||||||
|
# district = District()
|
||||||
district = District()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
district.AddDistrict(request=request)
|
district.AddDistrict(request=request)
|
||||||
@@ -28,21 +28,21 @@ def add_district():
|
|||||||
states=states
|
states=states
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ------- District check --------
|
||||||
@district_bp.route('/check_district', methods=['POST'])
|
@district_bp.route('/check_district', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def check_district():
|
def check_district():
|
||||||
|
|
||||||
district = District()
|
# district = District()
|
||||||
|
|
||||||
return district.CheckDistrict(request=request)
|
return district.CheckDistrict(request=request)
|
||||||
|
|
||||||
|
# ------- District delete by district id --------
|
||||||
@district_bp.route('/delete_district/<int:district_id>')
|
@district_bp.route('/delete_district/<int:district_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def delete_district(district_id):
|
def delete_district(district_id):
|
||||||
|
|
||||||
district = District()
|
# district = District()
|
||||||
|
|
||||||
district.DeleteDistrict(request=request, district_id=district_id)
|
district.DeleteDistrict(request=request, district_id=district_id)
|
||||||
|
|
||||||
@@ -52,11 +52,12 @@ def delete_district(district_id):
|
|||||||
return redirect(url_for('district.add_district'))
|
return redirect(url_for('district.add_district'))
|
||||||
|
|
||||||
|
|
||||||
|
# ------- District update by district id --------
|
||||||
@district_bp.route('/edit_district/<int:district_id>', methods=['GET', 'POST'])
|
@district_bp.route('/edit_district/<int:district_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def edit_district(district_id):
|
def edit_district(district_id):
|
||||||
|
|
||||||
district = District()
|
# district = District()
|
||||||
state = State()
|
state = State()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|||||||
@@ -1,28 +1,16 @@
|
|||||||
import os
|
import config
|
||||||
import ast
|
import ast
|
||||||
import re
|
import re
|
||||||
from flask_login import login_required
|
|
||||||
import openpyxl
|
import openpyxl
|
||||||
from flask import Blueprint, request, render_template, redirect, url_for, jsonify, current_app
|
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
from flask_login import login_required
|
||||||
|
from flask import Blueprint, request, render_template, redirect, url_for, jsonify
|
||||||
|
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
import config
|
|
||||||
from model.FolderAndFile import FolderAndFile
|
from model.FolderAndFile import FolderAndFile
|
||||||
|
|
||||||
excel_bp = Blueprint('excel', __name__)
|
excel_bp = Blueprint('excel', __name__)
|
||||||
|
|
||||||
# Default folder in case config not set
|
|
||||||
# DEFAULT_UPLOAD_FOLDER = 'uploads'
|
|
||||||
|
|
||||||
|
|
||||||
# def get_upload_folder():
|
|
||||||
# """Returns the upload folder from Flask config or default, ensures it exists."""
|
|
||||||
# folder = current_app.config.get('UPLOAD_FOLDER', DEFAULT_UPLOAD_FOLDER)
|
|
||||||
# if not os.path.exists(folder):
|
|
||||||
# os.makedirs(folder)
|
|
||||||
# return folder
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------- Upload Excel File ----------------
|
# ---------------- Upload Excel File ----------------
|
||||||
@excel_bp.route('/upload_excel_file', methods=['GET', 'POST'])
|
@excel_bp.route('/upload_excel_file', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@@ -30,9 +18,6 @@ def upload():
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
file = request.files.get('file')
|
file = request.files.get('file')
|
||||||
if file and file.filename.endswith('.xlsx'):
|
if file and file.filename.endswith('.xlsx'):
|
||||||
# upload_folder = get_upload_folder()
|
|
||||||
# filepath = os.path.join(upload_folder, file.filename)
|
|
||||||
|
|
||||||
filepath =FolderAndFile.get_upload_path(file.filename)
|
filepath =FolderAndFile.get_upload_path(file.filename)
|
||||||
|
|
||||||
file.save(filepath)
|
file.save(filepath)
|
||||||
@@ -42,6 +27,7 @@ def upload():
|
|||||||
f"User {current_user.id} Upload Excel File '{file.filename}'"
|
f"User {current_user.id} Upload Excel File '{file.filename}'"
|
||||||
)
|
)
|
||||||
return redirect(url_for('excel.show_table', filename=file.filename))
|
return redirect(url_for('excel.show_table', filename=file.filename))
|
||||||
|
|
||||||
return render_template('uploadExcelFile.html')
|
return render_template('uploadExcelFile.html')
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +37,6 @@ def show_table(filename):
|
|||||||
global data
|
global data
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
# filepath = os.path.join(get_upload_folder(), filename)
|
|
||||||
filepath = FolderAndFile.get_upload_path(filename)
|
filepath = FolderAndFile.get_upload_path(filename)
|
||||||
wb = openpyxl.load_workbook(filepath, data_only=True)
|
wb = openpyxl.load_workbook(filepath, data_only=True)
|
||||||
sheet = wb.active
|
sheet = wb.active
|
||||||
@@ -74,21 +59,21 @@ def show_table(filename):
|
|||||||
try:
|
try:
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor = connection.cursor(dictionary=True)
|
||||||
|
|
||||||
cursor.callproc('GetStateByName', [file_info['State']])
|
cursor.callproc('CheckStateExists', [file_info['State']])
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
state_data = result.fetchone()
|
state_data = result.fetchone()
|
||||||
if not state_data:
|
if not state_data:
|
||||||
errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
||||||
|
|
||||||
if state_data:
|
if state_data:
|
||||||
cursor.callproc('GetDistrictByNameAndStates', [file_info['District'], state_data['State_ID']])
|
cursor.callproc('GetDistrictByNameAndState', [file_info['District'], state_data['State_Id']]) # Change GetDistrictByNameAndStates to GetDistrictByNameAndState
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
district_data = result.fetchone()
|
district_data = result.fetchone()
|
||||||
if not district_data:
|
if not district_data:
|
||||||
errors.append(f"District '{file_info['District']}' is not valid under state '{file_info['State']}'.")
|
errors.append(f"District '{file_info['District']}' is not valid under state '{file_info['State']}'.")
|
||||||
|
|
||||||
if district_data:
|
if district_data:
|
||||||
cursor.callproc('GetBlockByNameAndDistricts', [file_info['Block'], district_data['District_ID']])
|
cursor.callproc('GetBlockByNameAndDistrict', [file_info['Block'], district_data['District_id']]) #Change District_ID to District_id and GetBlockByNameAndDistricts to GetBlockByNameAndDistrict
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
block_data = result.fetchone()
|
block_data = result.fetchone()
|
||||||
if not block_data:
|
if not block_data:
|
||||||
@@ -99,7 +84,9 @@ def show_table(filename):
|
|||||||
subcontractor_data = result.fetchone()
|
subcontractor_data = result.fetchone()
|
||||||
|
|
||||||
if not subcontractor_data:
|
if not subcontractor_data:
|
||||||
cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']])
|
# cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']])
|
||||||
|
# connection.commit()
|
||||||
|
cursor.callproc('SaveContractor', [file_info.get('Subcontractor'),None,None,None,None,None,None,None,None])
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
@@ -244,7 +231,7 @@ def save_data():
|
|||||||
else:
|
else:
|
||||||
work_type = " ".join(words[:work_pos + 1])
|
work_type = " ".join(words[:work_pos + 1])
|
||||||
if Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower():
|
if Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower():
|
||||||
print("village_name ::", village_name, "|| work_type ::", work_type)
|
# print("village_name ::", village_name, "|| work_type ::", work_type)
|
||||||
if block_id and village_name:
|
if block_id and village_name:
|
||||||
village_id = None
|
village_id = None
|
||||||
cursor.callproc("GetVillageId", (block_id, village_name))
|
cursor.callproc("GetVillageId", (block_id, village_name))
|
||||||
@@ -257,11 +244,11 @@ def save_data():
|
|||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
result = result.fetchone()
|
result = result.fetchone()
|
||||||
village_id = result[0] if result else None
|
village_id = result[0] if result else None
|
||||||
print("village_id :", village_id)
|
# print("village_id :", village_id)
|
||||||
print("block_id :", block_id)
|
# print("block_id :", block_id)
|
||||||
print("invoice :", PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
# print("invoice :", PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||||||
Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
# Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
||||||
SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount)
|
# SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount)
|
||||||
|
|
||||||
args = (
|
args = (
|
||||||
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||||||
@@ -270,22 +257,39 @@ def save_data():
|
|||||||
subcontractor_id, 0
|
subcontractor_id, 0
|
||||||
)
|
)
|
||||||
|
|
||||||
print("All invoice Details ",args)
|
# print("All invoice Details ",args)
|
||||||
|
# add subcontarctor id in invoice table
|
||||||
results = cursor.callproc('SaveInvoice', args)
|
results = cursor.callproc('SaveInvoice', args)
|
||||||
invoice_id = results[-1]
|
invoice_id = results[-1]
|
||||||
print("invoice id from the excel ", invoice_id)
|
print("**************************************************************")
|
||||||
|
print(invoice_id)
|
||||||
|
print("**************************************************************")
|
||||||
|
cursor.callproc(
|
||||||
|
"SavePayment",
|
||||||
|
(
|
||||||
|
PMC_No,
|
||||||
|
Invoice_No, # required
|
||||||
|
Payment_Amount,
|
||||||
|
TDS_Payment_Amount,
|
||||||
|
Total_Amount,
|
||||||
|
UTR,
|
||||||
|
invoice_id # last
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# print("invoice id from the excel ", invoice_id)
|
||||||
if isinstance(hold_columns, str):
|
if isinstance(hold_columns, str):
|
||||||
hold_columns = ast.literal_eval(hold_columns)
|
hold_columns = ast.literal_eval(hold_columns)
|
||||||
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
|
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
|
||||||
for hold in hold_columns:
|
for hold in hold_columns:
|
||||||
print(f"Processing hold: {hold}")
|
# print(f"Processing hold: {hold}")
|
||||||
hold_column_name = hold.get('column_name') # Get column name
|
hold_column_name = hold.get('column_name') # Get column name
|
||||||
hold_type_id = hold.get('hold_type_id') # Get hold_type_id
|
hold_type_id = hold.get('hold_type_id') # Get hold_type_id
|
||||||
if hold_column_name:
|
if hold_column_name:
|
||||||
hold_amount = entry.get(
|
hold_amount = entry.get(
|
||||||
hold_column_name) # Get the value for that specific hold column
|
hold_column_name) # Get the value for that specific hold column
|
||||||
if hold_amount is not None:
|
if hold_amount is not None:
|
||||||
print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
|
# print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
|
||||||
hold_join_data = {
|
hold_join_data = {
|
||||||
"Contractor_Id": subcontractor_id,
|
"Contractor_Id": subcontractor_id,
|
||||||
"Invoice_Id": invoice_id,
|
"Invoice_Id": invoice_id,
|
||||||
@@ -304,8 +308,8 @@ def save_data():
|
|||||||
print("Hold columns data is not a valid list of dictionaries.")
|
print("Hold columns data is not a valid list of dictionaries.")
|
||||||
#---------------------------------------------Credit Note---------------------------------------------------------------------------
|
#---------------------------------------------Credit Note---------------------------------------------------------------------------
|
||||||
elif any(keyword in Invoice_Details.lower() for keyword in ['credit note','logging report']):
|
elif any(keyword in Invoice_Details.lower() for keyword in ['credit note','logging report']):
|
||||||
print("Credit note found:", PMC_No, Invoice_No, Basic_Amount, Debit_Amount, Final_Amount,
|
# print("Credit note found:", PMC_No, Invoice_No, Basic_Amount, Debit_Amount, Final_Amount,
|
||||||
After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No)
|
# After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No)
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
'AddCreditNoteFromExcel',
|
'AddCreditNoteFromExcel',
|
||||||
[
|
[
|
||||||
@@ -330,52 +334,108 @@ def save_data():
|
|||||||
]
|
]
|
||||||
# Step 3: Matching condition
|
# Step 3: Matching condition
|
||||||
if any(kw in normalized_details for kw in keywords):
|
if any(kw in normalized_details for kw in keywords):
|
||||||
print("✅ Match found. Inserting hold release for:", Invoice_Details)
|
# print("✅ Match found. Inserting hold release for:", Invoice_Details)
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
'AddHoldReleaseFromExcel',
|
'AddHoldReleaseFromExcel',
|
||||||
[PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id]
|
[PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id]
|
||||||
)
|
)
|
||||||
connection.commit()
|
connection.commit()
|
||||||
print("✅ Hold release inserted for:", PMC_No, Invoice_Details)
|
# print("✅ Hold release inserted for:", PMC_No, Invoice_Details)
|
||||||
#------------------------------------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------------------------------------
|
||||||
elif Invoice_Details and any(
|
elif Invoice_Details and any(
|
||||||
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'note']):
|
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'gst release note']):
|
||||||
print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount,Total_Amount,UTR, subcontractor_id)
|
# print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount,Total_Amount,UTR, subcontractor_id)
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
'AddGSTReleaseFromExcel',
|
'AddGSTReleaseFromExcel',
|
||||||
[PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id]
|
[PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id]
|
||||||
)
|
)
|
||||||
|
|
||||||
if PMC_No and Total_Amount and UTR:
|
# --------------------------------------
|
||||||
print("Payment :", PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR )
|
# If no village/work detected, only PMC/Payment
|
||||||
cursor.callproc("SavePayment",(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR ))
|
if not (Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower()):
|
||||||
if not village_id:
|
# if not (Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower() and 'gst' in Invoice_Details.lower() and 'gst release note' in Invoice_Details.lower() and 'release' in Invoice_Details.lower()):
|
||||||
village_id = None
|
|
||||||
cursor.callproc('InsertOrUpdateInPayment', (
|
# ---------- Only PMC / Payment rows ----------
|
||||||
PMC_No,
|
if PMC_No and not Invoice_No and UTR :
|
||||||
village_id,
|
# print("No village/work, using PMC only :", PMC_No)
|
||||||
work_type,
|
|
||||||
Invoice_Details,
|
# check invoice exists
|
||||||
Invoice_Date,
|
# cursor.execute(
|
||||||
Invoice_No,
|
# "SELECT invoice_id FROM invoice WHERE PMC_No=%s ORDER BY invoice_id DESC LIMIT 1",
|
||||||
Basic_Amount,
|
# (PMC_No,)
|
||||||
Debit_Amount,
|
# )
|
||||||
After_Debit_Amount,
|
# row = cursor.fetchone()
|
||||||
Amount,
|
# invoice_id = row[0] if row else None
|
||||||
GST_Amount,
|
|
||||||
TDS_Amount,
|
# # insert invoice if not exists
|
||||||
SD_Amount,
|
|
||||||
On_Commission,
|
# if not invoice_id:
|
||||||
Hydro_Testing,
|
print(" extra payment :", PMC_No,Total_Amount,UTR, subcontractor_id)
|
||||||
0,
|
|
||||||
GST_SD_Amount,
|
# cursor.execute(
|
||||||
Final_Amount,
|
# """
|
||||||
Payment_Amount,
|
# INSERT INTO invoice (PMC_No,Contractor_Id) VALUES (%s, %s);
|
||||||
TDS_Payment_Amount,
|
# """,
|
||||||
Total_Amount,
|
# (PMC_No, subcontractor_id)
|
||||||
UTR,
|
# )
|
||||||
subcontractor_id
|
# connection.commit()
|
||||||
))
|
|
||||||
|
# cursor.execute(
|
||||||
|
# "SELECT invoice_id FROM invoice WHERE PMC_No=%s AND Contractor_Id =%s ORDER BY invoice_id DESC LIMIT 1",
|
||||||
|
# (PMC_No, subcontractor_id)
|
||||||
|
# )
|
||||||
|
# row = cursor.fetchone()
|
||||||
|
cursor.callproc("insertExtrapaymet",(PMC_No, subcontractor_id))
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
row = result.fetchone()
|
||||||
|
invoice_id = row[0] if row else None
|
||||||
|
# insert payment
|
||||||
|
cursor.callproc(
|
||||||
|
"SavePayment",
|
||||||
|
(
|
||||||
|
PMC_No,
|
||||||
|
Invoice_No, # required
|
||||||
|
Payment_Amount,
|
||||||
|
TDS_Payment_Amount,
|
||||||
|
Total_Amount,
|
||||||
|
UTR,
|
||||||
|
invoice_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# if PMC_No and Total_Amount and UTR:
|
||||||
|
# print("Payment :", PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR )
|
||||||
|
|
||||||
|
# Add inoice id in payment table
|
||||||
|
# cursor.callproc("SavePayment",(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR, invoice_id))
|
||||||
|
|
||||||
|
# if not village_id:
|
||||||
|
# village_id = None
|
||||||
|
# cursor.callproc('InsertOrUpdateInPayment', (
|
||||||
|
# PMC_No,
|
||||||
|
# village_id,
|
||||||
|
# work_type,
|
||||||
|
# Invoice_Details,
|
||||||
|
# Invoice_Date,
|
||||||
|
# Invoice_No,
|
||||||
|
# Basic_Amount,
|
||||||
|
# Debit_Amount,
|
||||||
|
# After_Debit_Amount,
|
||||||
|
# Amount,
|
||||||
|
# GST_Amount,
|
||||||
|
# TDS_Amount,
|
||||||
|
# SD_Amount,
|
||||||
|
# On_Commission,
|
||||||
|
# Hydro_Testing,
|
||||||
|
# 0,
|
||||||
|
# GST_SD_Amount,
|
||||||
|
# Final_Amount,
|
||||||
|
# Payment_Amount,
|
||||||
|
# TDS_Payment_Amount,
|
||||||
|
# Total_Amount,
|
||||||
|
# UTR,f
|
||||||
|
# subcontractor_id
|
||||||
|
# ))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
return jsonify({"success": "Data saved successfully!"}), 200
|
return jsonify({"success": "Data saved successfully!"}), 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -1,70 +1,46 @@
|
|||||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
# routes/gst_release_routes.py
|
||||||
from flask_login import login_required, current_user
|
from flask import Blueprint, render_template, request, redirect, url_for, flash
|
||||||
from model.gst_release import GSTReleasemodel
|
from flask_login import login_required
|
||||||
|
from model.gst_release import GSTRelease
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
|
|
||||||
gst_release_bp = Blueprint('gst_release_bp', __name__)
|
gst_release_bp = Blueprint('gst_release_bp', __name__)
|
||||||
|
gst_service = GSTRelease()
|
||||||
|
|
||||||
# ------------------- Add GST Release -------------------
|
# ---------------- ADD GST RELEASE ----------------
|
||||||
@gst_release_bp.route('/add_gst_release', methods=['GET', 'POST'])
|
@gst_release_bp.route('/add_gst_release', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_gst_release():
|
def add_gst_release():
|
||||||
gst_releases_dict = GSTReleasemodel.fetch_all_gst_releases()
|
|
||||||
gst_releases = [
|
|
||||||
[
|
|
||||||
g['GST_Release_Id'], g['PMC_No'], g['invoice_no'],
|
|
||||||
g['Basic_Amount'], g['Final_Amount'], g['Total_Amount'], g['UTR']
|
|
||||||
] for g in gst_releases_dict
|
|
||||||
] if gst_releases_dict else []
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
pmc_no = request.form['PMC_No']
|
gst_service.AddGSTRelease(request)
|
||||||
invoice_no = request.form['invoice_No']
|
LogHelper.log_action("Add GST Release", "User added GST release")
|
||||||
basic_amount = request.form['basic_amount']
|
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||||
final_amount = request.form['final_amount']
|
|
||||||
total_amount = request.form['total_amount']
|
|
||||||
utr = request.form['utr']
|
|
||||||
contractor_id = request.form['subcontractor_id']
|
|
||||||
|
|
||||||
LogHelper.log_action("Add GST Release", f"User {current_user.id} added GST release '{pmc_no}'")
|
|
||||||
GSTReleasemodel.insert_gst_release(pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id)
|
|
||||||
|
|
||||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||||
|
|
||||||
return render_template('add_gst_release.html', gst_releases=gst_releases, invoices=[])
|
gst_releases = gst_service.GetAllGSTReleases()
|
||||||
|
return render_template('add_gst_release.html', gst_releases=gst_releases)
|
||||||
|
|
||||||
|
# ---------------- EDIT GST RELEASE ----------------
|
||||||
# ------------------- Edit GST Release -------------------
|
|
||||||
@gst_release_bp.route('/edit_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
@gst_release_bp.route('/edit_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def edit_gst_release(gst_release_id):
|
def edit_gst_release(gst_release_id):
|
||||||
gst_release_data = GSTReleasemodel.fetch_gst_release_by_id(gst_release_id)
|
gst_data = gst_service.GetGSTReleaseByID(gst_release_id)
|
||||||
if not gst_release_data:
|
if not gst_data:
|
||||||
return "GST Release not found", 404
|
return "GST Release not found", 404
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
pmc_no = request.form['PMC_No']
|
gst_service.EditGSTRelease(request, gst_release_id)
|
||||||
invoice_no = request.form['invoice_No']
|
LogHelper.log_action("Edit GST Release", "User edited GST release")
|
||||||
basic_amount = request.form['basic_amount']
|
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||||
final_amount = request.form['final_amount']
|
|
||||||
total_amount = request.form['total_amount']
|
|
||||||
utr = request.form['utr']
|
|
||||||
|
|
||||||
LogHelper.log_action("Edit GST Release", f"User {current_user.id} edited GST release '{pmc_no}'")
|
|
||||||
GSTReleasemodel.update_gst_release(gst_release_id, pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr)
|
|
||||||
|
|
||||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||||
|
|
||||||
return render_template('edit_gst_release.html', gst_release_data=gst_release_data, invoices=[])
|
return render_template('edit_gst_release.html', gst_release_data=gst_data)
|
||||||
|
|
||||||
|
# ---------------- DELETE GST RELEASE ----------------
|
||||||
# ------------------- Delete GST Release -------------------
|
|
||||||
@gst_release_bp.route('/delete_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
@gst_release_bp.route('/delete_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_gst_release(gst_release_id):
|
def delete_gst_release(gst_release_id):
|
||||||
success, utr = GSTReleasemodel.delete_gst_release(gst_release_id)
|
gst_service.DeleteGSTRelease(gst_release_id)
|
||||||
if not success:
|
LogHelper.log_action("Delete GST Release", "User deleted GST release")
|
||||||
return jsonify({"message": "GST Release not found or failed to delete", "status": "error"}), 404
|
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||||
|
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||||
LogHelper.log_action("Delete GST Release", f"User {current_user.id} deleted GST release '{gst_release_id}'")
|
|
||||||
return jsonify({"message": f"GST Release {gst_release_id} deleted successfully.", "status": "success"}), 200
|
|
||||||
@@ -5,32 +5,32 @@ from model.GST import GST
|
|||||||
|
|
||||||
hold_bp = Blueprint("hold_types", __name__)
|
hold_bp = Blueprint("hold_types", __name__)
|
||||||
|
|
||||||
|
hold = HoldTypes()
|
||||||
# ---------------- ADD HOLD TYPE ----------------
|
# ---------------- ADD HOLD TYPE ----------------
|
||||||
@hold_bp.route('/add_hold_type', methods=['GET','POST'])
|
@hold_bp.route('/add_hold_type', methods=['GET','POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_hold_type():
|
def add_hold_type():
|
||||||
|
# hold = HoldTypes()
|
||||||
hold = HoldTypes()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
hold.AddHoldType(request) # ✅
|
hold.AddHoldType(request)
|
||||||
return hold.resultMessage
|
# ✅ Always redirect to same page (NO JSON)
|
||||||
|
return redirect(url_for("hold_types.add_hold_type"))
|
||||||
|
|
||||||
hold_types = hold.GetAllHoldTypes() # ✅
|
# GET request → show data
|
||||||
|
hold_types = hold.GetAllHoldTypes()
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"add_hold_type.html",
|
"add_hold_type.html",
|
||||||
Hold_Types_data=hold_types
|
Hold_Types_data=hold_types
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------- CHECK HOLD TYPE (OPTIONAL LIKE BLOCK) ----------------
|
# ---------------- CHECK HOLD TYPE (OPTIONAL LIKE BLOCK) ----------------
|
||||||
@hold_bp.route('/check_hold_type', methods=['POST'])
|
@hold_bp.route('/check_hold_type', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def check_hold_type():
|
def check_hold_type():
|
||||||
|
|
||||||
hold = HoldTypes()
|
# hold = HoldTypes()
|
||||||
return hold.CheckHoldType(request) # if exists
|
return hold.CheckHoldType(request) # if exists
|
||||||
|
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ def check_hold_type():
|
|||||||
@login_required
|
@login_required
|
||||||
def edit_hold_type(id):
|
def edit_hold_type(id):
|
||||||
|
|
||||||
hold = HoldTypes()
|
# hold = HoldTypes()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
hold.EditHoldType(request, id) # ✅
|
hold.EditHoldType(request, id) # ✅
|
||||||
@@ -58,7 +58,7 @@ def edit_hold_type(id):
|
|||||||
@login_required
|
@login_required
|
||||||
def delete_hold_type(id):
|
def delete_hold_type(id):
|
||||||
|
|
||||||
hold = HoldTypes()
|
# hold = HoldTypes()
|
||||||
hold.DeleteHoldType(request, id) # ✅
|
hold.DeleteHoldType(request, id) # ✅
|
||||||
|
|
||||||
return redirect(url_for("hold_types.add_hold_type"))
|
return redirect(url_for("hold_types.add_hold_type"))
|
||||||
|
|||||||
@@ -3,96 +3,100 @@
|
|||||||
from flask import Blueprint, request, jsonify, render_template
|
from flask import Blueprint, request, jsonify, render_template
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from model.Invoice import *
|
from model.Invoice import *
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
|
|
||||||
invoice_bp = Blueprint('invoice', __name__)
|
invoice_bp = Blueprint('invoice', __name__)
|
||||||
|
|
||||||
# -------------------------------- Add Invoice ---------------------------------
|
# ------------------------------- Helpers -------------------------------
|
||||||
@invoice_bp.route('/add_invoice', methods=['GET', 'POST'])
|
def handle_exception(func):
|
||||||
@login_required
|
"""Decorator to handle exceptions and return JSON error responses."""
|
||||||
def add_invoice():
|
def wrapper(*args, **kwargs):
|
||||||
if request.method == 'POST':
|
|
||||||
try:
|
try:
|
||||||
village_name = request.form.get('village')
|
return func(*args, **kwargs)
|
||||||
village_result = get_village_id(village_name)
|
|
||||||
|
|
||||||
if not village_result:
|
|
||||||
return jsonify({"status": "error", "message": f"Village '{village_name}' not found"}), 400
|
|
||||||
|
|
||||||
village_id = village_result['Village_Id']
|
|
||||||
data = request.form
|
|
||||||
|
|
||||||
invoice_id = insert_invoice(data, village_id)
|
|
||||||
assign_subcontractor(data, village_id)
|
|
||||||
insert_hold_types(data, invoice_id)
|
|
||||||
|
|
||||||
LogHelper.log_action("Add invoice", f"User {current_user.id} Added invoice '{data.get('pmc_no')}'")
|
|
||||||
|
|
||||||
return jsonify({"status": "success", "message": "Invoice added successfully"}), 201
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"status": "error", "message": str(e)}), 500
|
return jsonify({"status": "error", "message": str(e)}), 500
|
||||||
|
wrapper.__name__ = func.__name__
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
def log_action(action: str, detail: str):
|
||||||
|
LogHelper.log_action(action, f"User {current_user.id} {detail}")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------- Add Invoice -------------------------------
|
||||||
|
@invoice_bp.route('/add_invoice', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
@handle_exception
|
||||||
|
def add_invoice():
|
||||||
|
if request.method == 'POST':
|
||||||
|
data = request.form
|
||||||
|
village_name = data.get('village')
|
||||||
|
village_result = get_village_id(village_name)
|
||||||
|
|
||||||
|
if not village_result:
|
||||||
|
return jsonify({"status": "error", "message": f"Village '{village_name}' not found"}), 400
|
||||||
|
|
||||||
|
village_id = village_result['Village_Id']
|
||||||
|
invoice_id = insert_invoice(data, village_id)
|
||||||
|
# assign_subcontractor(data, village_id)
|
||||||
|
print("********************************************************************")
|
||||||
|
print("Manully added invoice id :",invoice_id)
|
||||||
|
print("********************************************************************")
|
||||||
|
|
||||||
|
insert_hold_types(data, invoice_id)
|
||||||
|
|
||||||
|
log_action("Add invoice", f"added invoice '{data.get('pmc_no')}'")
|
||||||
|
return jsonify({"status": "success", "message": "Invoice added successfully"}), 201
|
||||||
|
|
||||||
invoices = get_all_invoice_details()
|
invoices = get_all_invoice_details()
|
||||||
villages = get_all_villages()
|
villages = get_all_villages()
|
||||||
return render_template('add_invoice.html', invoices=invoices, villages=villages)
|
return render_template('add_invoice.html', invoices=invoices, villages=villages)
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Search Subcontractor -------------------
|
# ------------------------------- Search Subcontractor -------------------------------
|
||||||
@invoice_bp.route('/search_subcontractor', methods=['POST'])
|
@invoice_bp.route('/search_subcontractor', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@handle_exception
|
||||||
def search_subcontractor():
|
def search_subcontractor():
|
||||||
sub_query = request.form.get("query")
|
query = request.form.get("query", "").strip()
|
||||||
results = search_contractors(sub_query)
|
results = search_contractors(query)
|
||||||
|
|
||||||
if not results:
|
if not results:
|
||||||
return "<li>No subcontractor found</li>"
|
return "<li>No subcontractor found</li>"
|
||||||
|
|
||||||
output = "".join(
|
return "".join(f"<li data-id='{r['Contractor_Id']}'>{r['Contractor_Name']}</li>" for r in results)
|
||||||
f"<li data-id='{row['Contractor_Id']}'>{row['Contractor_Name']}</li>"
|
|
||||||
for row in results
|
|
||||||
)
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Get Hold Types -------------------
|
# ------------------------------- Get Hold Types -------------------------------
|
||||||
@invoice_bp.route('/get_hold_types', methods=['GET'])
|
@invoice_bp.route('/get_hold_types', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@handle_exception
|
||||||
def get_hold_types():
|
def get_hold_types():
|
||||||
hold_types = get_all_hold_types()
|
hold_types = get_all_hold_types()
|
||||||
LogHelper.log_action("Get hold type", f"User {current_user.id} Get hold type '{hold_types}'")
|
log_action("Get hold type", f"retrieved hold types '{hold_types}'")
|
||||||
return jsonify(hold_types)
|
return jsonify(hold_types)
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Edit Invoice -------------------
|
# ------------------------------- Edit Invoice -------------------------------
|
||||||
@invoice_bp.route('/edit_invoice/<int:invoice_id>', methods=['GET', 'POST'])
|
@invoice_bp.route('/edit_invoice/<int:invoice_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@handle_exception
|
||||||
def edit_invoice(invoice_id):
|
def edit_invoice(invoice_id):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
data = request.form
|
data = request.form
|
||||||
update_invoice(data, invoice_id)
|
update_invoice(data, invoice_id)
|
||||||
update_inpayment(data)
|
# update_inpayment(data)
|
||||||
|
log_action("Edit invoice", f"edited invoice '{invoice_id}'")
|
||||||
LogHelper.log_action("Edit invoice", f"User {current_user.id} Edit invoice '{invoice_id}'")
|
|
||||||
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
||||||
|
|
||||||
invoice = get_invoice_by_id(invoice_id)
|
invoice = get_invoice_by_id(invoice_id)
|
||||||
return render_template('edit_invoice.html', invoice=invoice)
|
return render_template('edit_invoice.html', invoice=invoice)
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Delete Invoice -------------------
|
# ------------------------------- Delete Invoice -------------------------------
|
||||||
@invoice_bp.route('/delete_invoice/<int:invoice_id>', methods=['GET'])
|
@invoice_bp.route('/delete_invoice/<int:invoice_id>', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@handle_exception
|
||||||
def delete_invoice_route(invoice_id):
|
def delete_invoice_route(invoice_id):
|
||||||
try:
|
delete_invoice_data(invoice_id, current_user.id)
|
||||||
delete_invoice_data(invoice_id, current_user.id)
|
log_action("Delete invoice", f"deleted invoice '{invoice_id}'")
|
||||||
LogHelper.log_action("Delete Invoice", f"User {current_user.id} deleted Invoice '{invoice_id}'")
|
return jsonify({"status": "success", "message": f"Invoice {invoice_id} deleted successfully."})
|
||||||
return jsonify({
|
|
||||||
"message": f"Invoice {invoice_id} deleted successfully.",
|
|
||||||
"status": "success"
|
|
||||||
})
|
|
||||||
except Exception as e:
|
|
||||||
return jsonify({
|
|
||||||
"message": str(e),
|
|
||||||
"status": "error"
|
|
||||||
}), 500
|
|
||||||
@@ -21,7 +21,6 @@ def activity_log():
|
|||||||
end_date,
|
end_date,
|
||||||
user_name
|
user_name
|
||||||
)
|
)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"activity_log.html",
|
"activity_log.html",
|
||||||
logs=filtered_logs,
|
logs=filtered_logs,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
from flask import Blueprint, render_template, request, redirect, url_for, jsonify, flash
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from model.payment import Paymentmodel
|
from model.payment import Paymentmodel
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
@@ -28,8 +28,8 @@ def add_payment():
|
|||||||
utr = request.form['utr']
|
utr = request.form['utr']
|
||||||
|
|
||||||
LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'")
|
LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'")
|
||||||
Paymentmodel.insert_payment(pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
Paymentmodel.insert_payment(subcontractor_id,pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||||
Paymentmodel.update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
# Paymentmodel.update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||||
|
|
||||||
return redirect(url_for('payment_bp.add_payment'))
|
return redirect(url_for('payment_bp.add_payment'))
|
||||||
|
|
||||||
@@ -72,32 +72,28 @@ def edit_payment(payment_id):
|
|||||||
Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||||
|
|
||||||
# Update inpayment
|
# Update inpayment
|
||||||
connection = Paymentmodel.get_connection()
|
# connection = Paymentmodel.get_connection()
|
||||||
cursor = connection.cursor()
|
# cursor = connection.cursor()
|
||||||
cursor.callproc(
|
# cursor.callproc('UpdateInpaymentByPMCInvoiceUTR',[amount, tds_amount, total_amount, pmc_no, invoice_no, utr])
|
||||||
'UpdateInpaymentByPMCInvoiceUTR',
|
|
||||||
[amount, tds_amount, total_amount, pmc_no, invoice_no, utr]
|
# connection.commit()
|
||||||
)
|
# cursor.close()
|
||||||
connection.commit()
|
# connection.close()
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return redirect(url_for('payment_bp.add_payment'))
|
return redirect(url_for('payment_bp.add_payment'))
|
||||||
|
|
||||||
return render_template('edit_payment.html', payment_data=payment_data)
|
return render_template('edit_payment.html', payment_data=payment_data)
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Delete Payment -------------------
|
# ------------------- Delete Payment -------------------
|
||||||
@payment_bp.route('/delete_payment/<int:payment_id>', methods=['GET', 'POST'])
|
@payment_bp.route('/delete_payment/<int:payment_id>', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_payment(payment_id):
|
def delete_payment(payment_id):
|
||||||
success, pmc_no, invoice_no = Paymentmodel.delete_payment(payment_id)
|
success, pmc_no, invoice_no = Paymentmodel.delete_payment(payment_id)
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
return jsonify({"message": "Payment not found or failed to delete", "status": "error"}), 404
|
flash("Payment not found or failed to delete", "error")
|
||||||
|
else:
|
||||||
|
LogHelper.log_action("Delete Payment", f"User {current_user.id} deleted Payment '{payment_id}'")
|
||||||
|
flash(f"Payment ID {payment_id} deleted successfully.", "success")
|
||||||
|
|
||||||
LogHelper.log_action("Delete Payment", f"User {current_user.id} deleted Payment '{payment_id}'")
|
return redirect(url_for('payment_bp.add_payment'))
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
"message": f"Payment ID {payment_id} deleted successfully.",
|
|
||||||
"status": "success"
|
|
||||||
}), 200
|
|
||||||
@@ -1,37 +1,40 @@
|
|||||||
from flask import Blueprint, render_template, send_from_directory
|
# from flask import Blueprint, render_template, send_from_directory
|
||||||
from flask_login import login_required, current_user
|
# from flask_login import login_required
|
||||||
from model.PmcReport import PmcReport
|
# from model.PmcReport import PmcReport
|
||||||
|
|
||||||
pmc_report_bp = Blueprint("pmc_report", __name__)
|
# pmc_report_bp = Blueprint("pmc_report", __name__)
|
||||||
|
|
||||||
@pmc_report_bp.route("/pmc_report/<pmc_no>")
|
# # ---------------- Contractor Report by pmc no ----------------
|
||||||
@login_required
|
# @pmc_report_bp.route("/pmc_report/<pmc_no>")
|
||||||
def pmc_report(pmc_no):
|
# @login_required
|
||||||
data = PmcReport.get_pmc_report(pmc_no)
|
# def pmc_report(pmc_no):
|
||||||
if not data:
|
# data = PmcReport.get_pmc_report(pmc_no)
|
||||||
return "No PMC found with this number", 404
|
# if not data:
|
||||||
|
# return "No PMC found with this number", 404
|
||||||
|
|
||||||
return render_template(
|
# return render_template(
|
||||||
"pmc_report.html",
|
# "pmc_report.html",
|
||||||
info=data["info"],
|
# info=data["info"],
|
||||||
invoices=data["invoices"],
|
# invoices=data["invoices"],
|
||||||
hold_types=data["hold_types"],
|
# hold_types=data["hold_types"],
|
||||||
gst_rel=data["gst_rel"],
|
# gst_rel=data["gst_rel"],
|
||||||
payments=data["payments"],
|
# payments=data["payments"],
|
||||||
credit_note=data["credit_note"],
|
# credit_note=data["credit_note"],
|
||||||
hold_release=data["hold_release"],
|
# hold_release=data["hold_release"],
|
||||||
total=data["total"]
|
# total=data["total"]
|
||||||
)
|
# )
|
||||||
|
|
||||||
@pmc_report_bp.route("/download_pmc_report/<pmc_no>")
|
# # ---------------- Contractor Download Report by pmc no ----------------
|
||||||
@login_required
|
# @pmc_report_bp.route("/download_pmc_report/<pmc_no>")
|
||||||
def download_pmc_report(pmc_no):
|
# @login_required
|
||||||
|
# def download_pmc_report(pmc_no):
|
||||||
|
|
||||||
result = PmcReport.download_pmc_report(pmc_no)
|
# result = PmcReport.download_pmc_report(pmc_no)
|
||||||
|
|
||||||
if not result:
|
# if not result:
|
||||||
return "No contractor found for this PMC No", 404
|
# return "No contractor found for this PMC No", 404
|
||||||
|
|
||||||
output_folder, file_name = result
|
# output_folder, file_name = result
|
||||||
|
|
||||||
|
# return send_from_directory(output_folder, file_name, as_attachment=True)
|
||||||
|
|
||||||
return send_from_directory(output_folder, file_name, as_attachment=True)
|
|
||||||
@@ -1,18 +1,10 @@
|
|||||||
from flask import Blueprint, render_template, request, jsonify, send_file
|
from flask import Blueprint, render_template, request, jsonify, send_file
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
|
from services.ReportService import ReportService
|
||||||
from model.Report import ReportHelper
|
from model.Report import ReportHelper
|
||||||
from model.Log import LogHelper
|
|
||||||
import config
|
|
||||||
import os
|
|
||||||
import openpyxl
|
|
||||||
from openpyxl.styles import Font
|
|
||||||
from model.ContractorInfo import ContractorInfo
|
|
||||||
from model.FolderAndFile import FolderAndFile
|
|
||||||
|
|
||||||
|
|
||||||
report_bp = Blueprint("report", __name__)
|
report_bp = Blueprint("report", __name__)
|
||||||
|
|
||||||
|
|
||||||
# ---------------- Report Page ----------------
|
# ---------------- Report Page ----------------
|
||||||
@report_bp.route("/report")
|
@report_bp.route("/report")
|
||||||
@login_required
|
@login_required
|
||||||
@@ -25,169 +17,70 @@ def report_page():
|
|||||||
@login_required
|
@login_required
|
||||||
def search_contractor():
|
def search_contractor():
|
||||||
|
|
||||||
subcontractor_name = request.form.get("subcontractor_name")
|
|
||||||
|
|
||||||
LogHelper.log_action(
|
|
||||||
"Search Contractor",
|
|
||||||
f"User {current_user.id} searched contractor '{subcontractor_name}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
data = ReportHelper.search_contractor(request)
|
data = ReportHelper.search_contractor(request)
|
||||||
|
|
||||||
return jsonify(data)
|
# Pagination (basic)
|
||||||
|
page = int(request.form.get("page", 1))
|
||||||
|
per_page = 20
|
||||||
|
|
||||||
# ---------------- Contractor Report ----------------
|
start = (page - 1) * per_page
|
||||||
|
end = start + per_page
|
||||||
|
|
||||||
|
paginated_data = data[start:end]
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"data": paginated_data,
|
||||||
|
"total": len(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
# ---------------- Contractor Report by contractor id ----------------
|
||||||
@report_bp.route('/contractor_report/<int:contractor_id>')
|
@report_bp.route('/contractor_report/<int:contractor_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def contractor_report(contractor_id):
|
def contractor_report(contractor_id):
|
||||||
|
|
||||||
data = ReportHelper.get_contractor_report(contractor_id)
|
service = ReportService(contractor_id=contractor_id).load_data()
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'subcontractor_report.html',
|
'subcontractor_report.html',
|
||||||
contractor_id=contractor_id,
|
contractor_id=contractor_id,
|
||||||
**data
|
**service.get_web_data()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ---------------- Contractor Report by pmc no ----------------
|
||||||
|
@report_bp.route("/pmc_report/<pmc_no>")
|
||||||
|
@login_required
|
||||||
|
def pmc_report(pmc_no):
|
||||||
|
|
||||||
|
service = ReportService(pmc_no=pmc_no).load_data()
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"pmc_report.html",
|
||||||
|
**service.get_web_data()
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------- Contractor Download Report by contractor id ----------------
|
||||||
@report_bp.route('/download_report/<int:contractor_id>')
|
@report_bp.route('/download_report/<int:contractor_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def download_report(contractor_id):
|
def download_report(contractor_id):
|
||||||
|
|
||||||
return ReportHelper().download_report(contractor_id=contractor_id)
|
service = ReportService(contractor_id=contractor_id).load_data()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
file, error = service.download_excel()
|
||||||
|
|
||||||
# @report_bp.route('/download_report/<int:contractor_id>')
|
if error:
|
||||||
# @login_required
|
return error, 404
|
||||||
# def download_report(contractor_id):
|
|
||||||
# try:
|
|
||||||
# connection = config.get_db_connection()
|
|
||||||
# cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
# # -------- Contractor Info --------
|
return send_file(file, as_attachment=True)
|
||||||
# contractor = ContractorInfo(contractor_id)
|
|
||||||
# contInfo = contractor.contInfo
|
|
||||||
|
|
||||||
# if not contInfo:
|
# ---------------- Contractor Download Report by pmc no ----------------
|
||||||
# return "No contractor found", 404
|
@report_bp.route("/download_pmc_report/<pmc_no>")
|
||||||
|
@login_required
|
||||||
|
def download_pmc_report(pmc_no):
|
||||||
|
|
||||||
# # -------- Invoice Data --------
|
service = ReportService(pmc_no=pmc_no).load_data()
|
||||||
# cursor.callproc('FetchInvoicesByContractor', [contractor_id])
|
|
||||||
|
|
||||||
# invoices = []
|
file, error = service.download_excel()
|
||||||
# for result in cursor.stored_results():
|
if error:
|
||||||
# invoices.extend(result.fetchall())
|
return error, 404
|
||||||
|
|
||||||
# if not invoices:
|
return send_file(file, as_attachment=True)
|
||||||
# return "No invoice data found"
|
|
||||||
|
|
||||||
# # -------- Create Workbook --------
|
|
||||||
# workbook = openpyxl.Workbook()
|
|
||||||
# sheet = workbook.active
|
|
||||||
# sheet.title = "Contractor Report"
|
|
||||||
|
|
||||||
# # ================= CONTRACTOR DETAILS =================
|
|
||||||
# sheet.append(["SUB CONTRACTOR DETAILS"])
|
|
||||||
# sheet.cell(row=sheet.max_row, column=1).font = Font(bold=True)
|
|
||||||
# sheet.append([])
|
|
||||||
|
|
||||||
# sheet.append(["Name", contInfo.get("Contractor_Name") or ""])
|
|
||||||
# sheet.append(["Mobile No", contInfo.get("Mobile_No") or ""])
|
|
||||||
# sheet.append(["Email", contInfo.get("Email") or ""])
|
|
||||||
# sheet.append(["Village", contInfo.get("Village_Name") or ""])
|
|
||||||
# sheet.append(["Block", contInfo.get("Block_Name") or ""])
|
|
||||||
# sheet.append(["District", contInfo.get("District_Name") or ""])
|
|
||||||
# sheet.append(["State", contInfo.get("State_Name") or ""])
|
|
||||||
# sheet.append(["Address", contInfo.get("Address") or ""])
|
|
||||||
# sheet.append(["GST No", contInfo.get("GST_No") or ""])
|
|
||||||
# sheet.append(["PAN No", contInfo.get("PAN_No") or ""])
|
|
||||||
# sheet.append([])
|
|
||||||
# sheet.append([])
|
|
||||||
|
|
||||||
# # ================= TABLE HEADERS =================
|
|
||||||
# headers = [
|
|
||||||
# "PMC No", "Village", "Invoice No", "Invoice Date", "Work Type","Invoice_Details",
|
|
||||||
# "Basic Amount", "Debit Amount", "After Debit Amount",
|
|
||||||
# "Amount", "GST Amount", "TDS Amount", "SD Amount",
|
|
||||||
# "On Commission", "Hydro Testing", "Hold Amount",
|
|
||||||
# "GST SD Amount", "Final Amount",
|
|
||||||
# "Payment Amount", "TDS Payment",
|
|
||||||
# "Total Amount", "UTR"
|
|
||||||
# ]
|
|
||||||
# sheet.append(headers)
|
|
||||||
# for col in range(1, len(headers) + 1):
|
|
||||||
# sheet.cell(row=sheet.max_row, column=col).font = Font(bold=True)
|
|
||||||
|
|
||||||
# # ================= DATA =================
|
|
||||||
# total_final = 0
|
|
||||||
# total_payment = 0
|
|
||||||
# total_amount = 0
|
|
||||||
|
|
||||||
# for inv in invoices:
|
|
||||||
# row = [
|
|
||||||
# inv.get("PMC_No"),
|
|
||||||
# inv.get("Village_Name"),
|
|
||||||
# inv.get("invoice_no"),
|
|
||||||
# inv.get("Invoice_Date"),
|
|
||||||
# inv.get("Work_Type"),
|
|
||||||
# inv.get("Invoice_Details"),
|
|
||||||
# inv.get("Basic_Amount"),
|
|
||||||
# inv.get("Debit_Amount"),
|
|
||||||
# inv.get("After_Debit_Amount"),
|
|
||||||
# inv.get("Amount"),
|
|
||||||
# inv.get("GST_Amount"),
|
|
||||||
# inv.get("TDS_Amount"),
|
|
||||||
# inv.get("SD_Amount"),
|
|
||||||
# inv.get("On_Commission"),
|
|
||||||
# inv.get("Hydro_Testing"),
|
|
||||||
# inv.get("Hold_Amount"),
|
|
||||||
# inv.get("GST_SD_Amount"),
|
|
||||||
# inv.get("Final_Amount"),
|
|
||||||
# inv.get("Payment_Amount"),
|
|
||||||
# inv.get("TDS_Payment_Amount"),
|
|
||||||
# inv.get("Total_Amount"),
|
|
||||||
# inv.get("UTR")
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# total_final += float(inv.get("Final_Amount") or 0)
|
|
||||||
# total_payment += float(inv.get("Payment_Amount") or 0)
|
|
||||||
# total_amount += float(inv.get("Total_Amount") or 0)
|
|
||||||
|
|
||||||
# sheet.append(row)
|
|
||||||
|
|
||||||
# # ================= TOTAL ROW =================
|
|
||||||
# sheet.append([])
|
|
||||||
# sheet.append([
|
|
||||||
# "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
|
||||||
# "TOTAL",
|
|
||||||
# total_final,
|
|
||||||
# total_payment,
|
|
||||||
# "",
|
|
||||||
# total_amount,
|
|
||||||
# ""
|
|
||||||
# ])
|
|
||||||
|
|
||||||
# # ================= AUTO WIDTH =================
|
|
||||||
# for column in sheet.columns:
|
|
||||||
# max_length = 0
|
|
||||||
# column_letter = column[0].column_letter
|
|
||||||
# for cell in column:
|
|
||||||
# if cell.value:
|
|
||||||
# max_length = max(max_length, len(str(cell.value)))
|
|
||||||
# sheet.column_dimensions[column_letter].width = max_length + 2
|
|
||||||
|
|
||||||
# # ================= SAVE FILE =================
|
|
||||||
# # output_folder = "downloads"
|
|
||||||
# # os.makedirs(output_folder, exist_ok=True)
|
|
||||||
# # filename = f"Contractor_Report_{contInfo.get('Contractor_Name')}.xlsx"
|
|
||||||
# # output_file = os.path.join(output_folder, filename)
|
|
||||||
|
|
||||||
# filename = f"Contractor_Report_{contInfo.get('Contractor_Name')}.xlsx"
|
|
||||||
# output_file = FolderAndFile.get_download_path(filename)
|
|
||||||
# workbook.save(output_file)
|
|
||||||
|
|
||||||
# return send_file(output_file, as_attachment=True)
|
|
||||||
|
|
||||||
# except Exception as e:
|
|
||||||
# return str(e)
|
|
||||||
@@ -3,13 +3,13 @@ from flask_login import login_required
|
|||||||
from model.State import State
|
from model.State import State
|
||||||
|
|
||||||
state_bp = Blueprint('state', __name__)
|
state_bp = Blueprint('state', __name__)
|
||||||
|
state = State()
|
||||||
|
# ----- State page ------
|
||||||
@state_bp.route('/add_state', methods=['GET', 'POST'])
|
@state_bp.route('/add_state', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_state():
|
def add_state():
|
||||||
|
|
||||||
state = State()
|
# state = State()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
state.AddState(request=request)
|
state.AddState(request=request)
|
||||||
@@ -19,35 +19,35 @@ def add_state():
|
|||||||
|
|
||||||
return render_template('add_state.html', statedata=statedata)
|
return render_template('add_state.html', statedata=statedata)
|
||||||
|
|
||||||
|
# ----- State check ------
|
||||||
@state_bp.route('/check_state', methods=['POST'])
|
@state_bp.route('/check_state', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def check_state():
|
def check_state():
|
||||||
|
|
||||||
state = State()
|
# state = State()
|
||||||
|
|
||||||
return state.CheckState(request=request)
|
return state.CheckState(request=request)
|
||||||
|
|
||||||
|
# ----- State delete by state id ------
|
||||||
@state_bp.route('/delete_state/<int:id>')
|
@state_bp.route('/delete_state/<int:id>')
|
||||||
@login_required
|
@login_required
|
||||||
def deleteState(id):
|
def deleteState(id):
|
||||||
|
|
||||||
state = State()
|
# state = State()
|
||||||
|
|
||||||
msg = state.DeleteState(request=request, id=id)
|
state.DeleteState(request=request, id=id)
|
||||||
|
|
||||||
if not state.isSuccess:
|
if not state.isSuccess:
|
||||||
return state.resultMessage
|
return state.resultMessage
|
||||||
else:
|
else:
|
||||||
return redirect(url_for('state.add_state'))
|
return redirect(url_for('state.add_state'))
|
||||||
|
|
||||||
|
# ----- State update by state id ------
|
||||||
@state_bp.route('/edit_state/<int:id>', methods=['GET', 'POST'])
|
@state_bp.route('/edit_state/<int:id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def editState(id):
|
def editState(id):
|
||||||
|
|
||||||
state = State()
|
# state = State()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,11 @@
|
|||||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
from model.Subcontractor import Subcontractor
|
from model.Subcontractor import Subcontractor
|
||||||
|
from model.Utilities import HtmlHelper, ResponseHandler
|
||||||
|
|
||||||
|
|
||||||
subcontractor_bp = Blueprint('subcontractor', __name__)
|
subcontractor_bp = Blueprint('subcontractor', __name__)
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# Helpers (unchanged)
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
class HtmlHelper:
|
|
||||||
@staticmethod
|
|
||||||
def json_response(data, status=200):
|
|
||||||
return jsonify(data), status
|
|
||||||
|
|
||||||
class ResponseHandler:
|
|
||||||
@staticmethod
|
|
||||||
def fetch_failure(entity):
|
|
||||||
return {"status": "error", "message": f"Failed to fetch {entity}"}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def add_failure(entity):
|
|
||||||
return {"status": "error", "message": f"Failed to add {entity}"}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def update_failure(entity):
|
|
||||||
return {"status": "error", "message": f"Failed to update {entity}"}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def delete_failure(entity):
|
|
||||||
return {"status": "error", "message": f"Failed to delete {entity}"}
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# LIST + ADD
|
# LIST + ADD
|
||||||
|
|||||||
@@ -1,29 +1,31 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
|
||||||
from model.Village import Village
|
from model.Village import Village
|
||||||
from model.State import State
|
from model.State import State
|
||||||
|
|
||||||
# Create Blueprint
|
# Create Blueprint
|
||||||
village_bp = Blueprint('village', __name__)
|
village_bp = Blueprint('village', __name__)
|
||||||
|
village = Village()
|
||||||
|
|
||||||
# ------------------------- Add Village -------------------------
|
# ------------------------- Add Village -------------------------
|
||||||
@village_bp.route('/add_village', methods=['GET', 'POST'])
|
@village_bp.route('/add_village', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_village():
|
def add_village():
|
||||||
|
|
||||||
village = Village()
|
# village = Village()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
village.AddVillage(request=request)
|
village.AddVillage(request=request)
|
||||||
return village.resultMessage
|
return village.resultMessage
|
||||||
|
|
||||||
state = State()
|
state = State()
|
||||||
states = state.GetAllStates(request=request)
|
states = state.GetAllStates(request=request)
|
||||||
|
|
||||||
villages = village.GetAllVillages(request=request)
|
villages = village.GetAllVillages(request=request)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
@@ -42,7 +44,6 @@ def get_districts(state_id):
|
|||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
cursor.callproc("GetDistrictByStateID", [state_id])
|
cursor.callproc("GetDistrictByStateID", [state_id])
|
||||||
|
|
||||||
districts = []
|
districts = []
|
||||||
|
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
@@ -51,15 +52,7 @@ def get_districts(state_id):
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
district_list = []
|
return jsonify([{"id": d[0], "name": d[1]} for d in districts])
|
||||||
|
|
||||||
for d in districts:
|
|
||||||
district_list.append({
|
|
||||||
"id": d[0],
|
|
||||||
"name": d[1]
|
|
||||||
})
|
|
||||||
|
|
||||||
return jsonify(district_list)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------- Fetch Blocks -------------------------
|
# ------------------------- Fetch Blocks -------------------------
|
||||||
@@ -71,7 +64,6 @@ def get_blocks(district_id):
|
|||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
cursor.callproc("GetBlocksByDistrictID", [district_id])
|
cursor.callproc("GetBlocksByDistrictID", [district_id])
|
||||||
|
|
||||||
blocks = []
|
blocks = []
|
||||||
|
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
@@ -80,49 +72,47 @@ def get_blocks(district_id):
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
block_list = []
|
return jsonify([{"id": b[0], "name": b[1]} for b in blocks])
|
||||||
|
|
||||||
for b in blocks:
|
|
||||||
block_list.append({
|
|
||||||
"id": b[0],
|
|
||||||
"name": b[1]
|
|
||||||
})
|
|
||||||
|
|
||||||
return jsonify(block_list)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------- Check Village -------------------------
|
# ------------------------- Check Village -------------------------
|
||||||
@village_bp.route('/check_village', methods=['POST'])
|
@village_bp.route('/check_village', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def check_village():
|
def check_village():
|
||||||
|
# village = Village()
|
||||||
village = Village()
|
|
||||||
return village.CheckVillage(request=request)
|
return village.CheckVillage(request=request)
|
||||||
|
|
||||||
|
|
||||||
# ------------------------- Delete Village -------------------------
|
|
||||||
@village_bp.route('/delete_village/<int:village_id>')
|
@village_bp.route('/delete_village/<int:village_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def delete_village(village_id):
|
def delete_village(village_id):
|
||||||
|
# village = Village()
|
||||||
village = Village()
|
|
||||||
|
|
||||||
village.DeleteVillage(request=request, village_id=village_id)
|
village.DeleteVillage(request=request, village_id=village_id)
|
||||||
|
|
||||||
if not village.isSuccess:
|
# ✅ Convert resultMessage to string if it's a Response or tuple
|
||||||
flash(village.resultMessage, "error")
|
raw_msg = village.resultMessage
|
||||||
|
|
||||||
|
if isinstance(raw_msg, tuple):
|
||||||
|
# e.g., (<Response ...>, 200)
|
||||||
|
msg = "Village deleted successfully!"
|
||||||
|
elif hasattr(raw_msg, 'get_data'):
|
||||||
|
# Flask Response object
|
||||||
|
msg = raw_msg.get_data(as_text=True) # get raw text
|
||||||
else:
|
else:
|
||||||
flash(village.resultMessage, "success")
|
# fallback
|
||||||
|
msg = str(raw_msg) if raw_msg else "Village deleted successfully!"
|
||||||
return redirect(url_for('village.add_village'))
|
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"status": "success" if village.isSuccess else "error",
|
||||||
|
"message": msg
|
||||||
|
})
|
||||||
|
|
||||||
# ------------------------- Edit Village -------------------------
|
# ------------------------- Edit Village -------------------------
|
||||||
@village_bp.route('/edit_village/<int:village_id>', methods=['GET', 'POST'])
|
@village_bp.route('/edit_village/<int:village_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def edit_village(village_id):
|
def edit_village(village_id):
|
||||||
|
|
||||||
village = Village()
|
# village = Village()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|
||||||
@@ -135,8 +125,8 @@ def edit_village(village_id):
|
|||||||
else:
|
else:
|
||||||
flash(village.resultMessage, "error")
|
flash(village.resultMessage, "error")
|
||||||
|
|
||||||
village_data = village.GetVillageByID(request=request, id=village_id)
|
village_data = village.GetVillageByID(id=village_id) or []
|
||||||
blocks = village.GetAllBlocks(request=request)
|
blocks = village.GetAllBlocks() or []
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'edit_village.html',
|
'edit_village.html',
|
||||||
@@ -145,23 +135,17 @@ def edit_village(village_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
# ✅ FIXED HERE (removed request)
|
||||||
village_data = village.GetVillageByID(request=request, id=village_id)
|
village_data = village.GetVillageByID(id=village_id)
|
||||||
|
|
||||||
if not village.isSuccess:
|
if not village.isSuccess:
|
||||||
flash(village.resultMessage, "error")
|
flash(village.resultMessage, "error")
|
||||||
return redirect(url_for('village.add_village'))
|
return redirect(url_for('village.add_village'))
|
||||||
|
|
||||||
blocks = village.GetAllBlocks(request=request)
|
blocks = village.GetAllBlocks() or []
|
||||||
|
|
||||||
if village_data is None:
|
|
||||||
village_data = []
|
|
||||||
|
|
||||||
if blocks is None:
|
|
||||||
blocks = []
|
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'edit_village.html',
|
'edit_village.html',
|
||||||
village_data=village_data,
|
village_data=village_data or [],
|
||||||
blocks=blocks
|
blocks=blocks
|
||||||
)
|
)
|
||||||
4
main.py
4
main.py
@@ -16,7 +16,7 @@ from controllers.payment_controller import payment_bp
|
|||||||
from controllers.gst_release_controller import gst_release_bp
|
from controllers.gst_release_controller import gst_release_bp
|
||||||
from controllers.excel_upload_controller import excel_bp
|
from controllers.excel_upload_controller import excel_bp
|
||||||
from controllers.report_controller import report_bp
|
from controllers.report_controller import report_bp
|
||||||
from controllers.pmc_report_controller import pmc_report_bp
|
# from controllers.pmc_report_controller import pmc_report_bp
|
||||||
|
|
||||||
from controllers.hold_types_controller import hold_bp
|
from controllers.hold_types_controller import hold_bp
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
@@ -57,7 +57,7 @@ app.register_blueprint(payment_bp)
|
|||||||
app.register_blueprint(gst_release_bp)
|
app.register_blueprint(gst_release_bp)
|
||||||
app.register_blueprint(excel_bp)
|
app.register_blueprint(excel_bp)
|
||||||
app.register_blueprint(report_bp)
|
app.register_blueprint(report_bp)
|
||||||
app.register_blueprint(pmc_report_bp)
|
# app.register_blueprint(pmc_report_bp)
|
||||||
app.register_blueprint(hold_bp)
|
app.register_blueprint(hold_bp)
|
||||||
|
|
||||||
# ---------------- Run App ----------------
|
# ---------------- Run App ----------------
|
||||||
|
|||||||
@@ -1,20 +1,6 @@
|
|||||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
|
||||||
from flask import current_app
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
|
||||||
|
|
||||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||||
from model.Log import LogData, LogHelper
|
from model.Log import LogData, LogHelper
|
||||||
|
from model.ItemCRUD import ItemCRUD
|
||||||
import os
|
|
||||||
import config
|
|
||||||
import re
|
|
||||||
|
|
||||||
import mysql.connector
|
|
||||||
from mysql.connector import Error
|
|
||||||
|
|
||||||
from model.ItemCRUD import ItemCRUD, itemCRUDMapping
|
|
||||||
|
|
||||||
|
|
||||||
class Block:
|
class Block:
|
||||||
@@ -26,9 +12,7 @@ class Block:
|
|||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = ""
|
self.resultMessage = ""
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# Add Block
|
# Add Block
|
||||||
# ----------------------------------------------------------
|
|
||||||
def AddBlock(self, request):
|
def AddBlock(self, request):
|
||||||
|
|
||||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||||
@@ -41,17 +25,7 @@ class Block:
|
|||||||
self.resultMessage = block.resultMessage
|
self.resultMessage = block.resultMessage
|
||||||
return
|
return
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# Get All Blocks
|
||||||
# Get All Blocks
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# def GetAllBlocks(self):
|
|
||||||
|
|
||||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
|
||||||
# blocksdata = block.GetAllData(request=request, storedproc="GetAllBlock")
|
|
||||||
# self.isSuccess = block.isSuccess
|
|
||||||
# self.resultMessage = block.resultMessage
|
|
||||||
# return blocksdata
|
|
||||||
|
|
||||||
def GetAllBlocks(self, request):
|
def GetAllBlocks(self, request):
|
||||||
|
|
||||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||||
@@ -61,18 +35,8 @@ class Block:
|
|||||||
self.resultMessage = block.resultMessage
|
self.resultMessage = block.resultMessage
|
||||||
return blocksdata
|
return blocksdata
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# Check Block Exists
|
# Check Block Exists
|
||||||
# ----------------------------------------------------------
|
|
||||||
|
|
||||||
# def CheckBlock(self, request):
|
|
||||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
|
||||||
# block_name = request.json.get('block_Name', '').strip()
|
|
||||||
# district_id = request.json.get('district_Id')
|
|
||||||
# result = block.CheckItem(request=request, parentid=district_id, childname=block_name, storedprocfetch="GetBlockByNameAndDistrict")
|
|
||||||
# self.isSuccess = block.isSuccess
|
|
||||||
# self.resultMessage = block.resultMessage
|
|
||||||
# return result
|
|
||||||
def CheckBlock(self, request):
|
def CheckBlock(self, request):
|
||||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||||
data = request.get_json(silent=True) or request.form
|
data = request.get_json(silent=True) or request.form
|
||||||
@@ -89,24 +53,7 @@ class Block:
|
|||||||
self.resultMessage = block.resultMessage
|
self.resultMessage = block.resultMessage
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# Get Block By ID
|
# Get Block By ID
|
||||||
# ----------------------------------------------------------
|
|
||||||
# def GetBlockByID(self, id):
|
|
||||||
|
|
||||||
# block = ItemCRUD(itemType=ItemCRUDType.Village)
|
|
||||||
# blockdata = block.GetAllData(id=id,storedproc="GetBlockDataByID")
|
|
||||||
# self.isSuccess = block.isSuccess
|
|
||||||
# self.resultMessage = block.resultMessage
|
|
||||||
# print("akash"+blockdata)
|
|
||||||
# return blockdata
|
|
||||||
|
|
||||||
# def GetBlockByID(self,request,id):
|
|
||||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
|
||||||
# blockdata = block.GetDataByID(request=request,id=id,storedproc="GetBlockDataByID")
|
|
||||||
# self.isSuccess = block.isSuccess
|
|
||||||
# self.resultMessage = block.resultMessage
|
|
||||||
# return blockdata
|
|
||||||
def GetBlockByID(self, id):
|
def GetBlockByID(self, id):
|
||||||
|
|
||||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||||
@@ -120,20 +67,8 @@ class Block:
|
|||||||
self.resultMessage = block.resultMessage
|
self.resultMessage = block.resultMessage
|
||||||
|
|
||||||
return blockdata
|
return blockdata
|
||||||
# ----------------------------------------------------------
|
|
||||||
# Update Block
|
# Update Block
|
||||||
# ----------------------------------------------------------
|
|
||||||
# def EditBlock(self, request, block_id):
|
|
||||||
|
|
||||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
|
||||||
|
|
||||||
# district_id = request.form.get('district_Id')
|
|
||||||
# block_name = request.form.get('block_Name', '').strip()
|
|
||||||
|
|
||||||
# block.EditItem(request=request, childid=block_id, parentid=district_id, childname=block_name, storedprocadd="UpdateBlockById" )
|
|
||||||
# self.isSuccess = block.isSuccess
|
|
||||||
# self.resultMessage = block.resultMessage
|
|
||||||
# return
|
|
||||||
def EditBlock(self, request, block_id):
|
def EditBlock(self, request, block_id):
|
||||||
|
|
||||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||||
@@ -151,11 +86,10 @@ class Block:
|
|||||||
|
|
||||||
self.isSuccess = block.isSuccess
|
self.isSuccess = block.isSuccess
|
||||||
self.resultMessage = block.resultMessage
|
self.resultMessage = block.resultMessage
|
||||||
return render_template('add_block.html')
|
return
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# Delete Block
|
# Delete Block
|
||||||
# ---------------------------------------------------------
|
|
||||||
def DeleteBlock(self,request, id):
|
def DeleteBlock(self,request, id):
|
||||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||||
|
|
||||||
|
|||||||
@@ -1,72 +1,60 @@
|
|||||||
import mysql.connector
|
|
||||||
from mysql.connector import Error
|
from mysql.connector import Error
|
||||||
import config
|
import config
|
||||||
import openpyxl
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import ast
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
class ContractorInfo:
|
class ContractorInfo:
|
||||||
ID = ""
|
def __init__(self, contractor_id):
|
||||||
contInfo = None
|
self.ID = contractor_id
|
||||||
def __init__(self, id):
|
self.contInfo = None
|
||||||
self.ID = id
|
|
||||||
print(id)
|
|
||||||
self.fetchData()
|
self.fetchData()
|
||||||
|
|
||||||
def fetchData(self):
|
def fetchData(self):
|
||||||
|
"""Fetch basic contractor info by ID."""
|
||||||
try:
|
try:
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
with connection.cursor(dictionary=True, buffered=True) as cursor:
|
||||||
cursor.callproc('GetContractorInfoById', [self.ID])
|
cursor.callproc('GetContractorInfoById', [self.ID])
|
||||||
for result in cursor.stored_results():
|
# Get the first result set
|
||||||
self.contInfo = result.fetchone()
|
for result in cursor.stored_results():
|
||||||
|
self.contInfo = result.fetchone()
|
||||||
print(self.contInfo,flush=True)
|
except Error as e:
|
||||||
|
print(f"Error fetching contractor info: {e}")
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
if connection.is_connected():
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
def fetchalldata(self):
|
def fetchalldata(self):
|
||||||
|
"""Fetch hold types and invoices for contractor."""
|
||||||
|
data = {}
|
||||||
try:
|
try:
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
with connection.cursor(dictionary=True, buffered=True) as cursor:
|
||||||
print("here", flush=True)
|
# Fetch Hold Types
|
||||||
|
cursor.callproc('GetHoldTypesByContractor', [self.ID])
|
||||||
|
hold_types = []
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
hold_types = result.fetchall()
|
||||||
|
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||||
|
data['hold_types'] = hold_type_map
|
||||||
|
|
||||||
# ---------------- Hold Types ----------------
|
# Fetch Invoices
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor.callproc('GetInvoicesByContractor', [self.ID])
|
||||||
|
invoices = []
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
invoices = result.fetchall()
|
||||||
|
|
||||||
cursor.callproc('GetHoldTypesByContractor', [self.ID])
|
# Remove duplicate invoices
|
||||||
|
seen_ids = set()
|
||||||
hold_types = []
|
unique_invoices = []
|
||||||
for result in cursor.stored_results():
|
for inv in invoices:
|
||||||
hold_types = result.fetchall()
|
if inv['Invoice_Id'] not in seen_ids:
|
||||||
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
seen_ids.add(inv['Invoice_Id'])
|
||||||
|
unique_invoices.append(inv)
|
||||||
# ---------------- Invoices ----------------
|
data['invoices'] = unique_invoices
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
cursor.callproc('GetInvoicesByContractor', [self.ID])
|
|
||||||
|
|
||||||
invoices = []
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
invoices = result.fetchall()
|
|
||||||
|
|
||||||
# Remove duplicate invoices
|
|
||||||
invoice_ids_seen = set()
|
|
||||||
unique_invoices = []
|
|
||||||
for inv in invoices:
|
|
||||||
if inv["Invoice_Id"] not in invoice_ids_seen:
|
|
||||||
invoice_ids_seen.add(inv["Invoice_Id"])
|
|
||||||
unique_invoices.append(inv)
|
|
||||||
invoices = unique_invoices
|
|
||||||
|
|
||||||
|
except Error as e:
|
||||||
|
print(f"Error fetching contractor data: {e}")
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
if connection.is_connected():
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
|
return data
|
||||||
|
|||||||
@@ -1,20 +1,6 @@
|
|||||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
from model.Utilities import ItemCRUDType
|
||||||
from flask import current_app
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
|
||||||
|
|
||||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
|
||||||
from model.Log import LogData, LogHelper
|
|
||||||
|
|
||||||
import os
|
|
||||||
import config
|
|
||||||
import re
|
|
||||||
|
|
||||||
import mysql.connector
|
|
||||||
from mysql.connector import Error
|
|
||||||
|
|
||||||
from model.ItemCRUD import ItemCRUD
|
from model.ItemCRUD import ItemCRUD
|
||||||
|
|
||||||
class District:
|
class District:
|
||||||
|
|
||||||
isSuccess = False
|
isSuccess = False
|
||||||
@@ -24,7 +10,7 @@ class District:
|
|||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = ""
|
self.resultMessage = ""
|
||||||
|
|
||||||
|
# edit district
|
||||||
def EditDistrict(self, request, district_id):
|
def EditDistrict(self, request, district_id):
|
||||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||||
|
|
||||||
@@ -36,7 +22,7 @@ class District:
|
|||||||
self.resultMessage = district.resultMessage
|
self.resultMessage = district.resultMessage
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# add district
|
||||||
def AddDistrict(self, request):
|
def AddDistrict(self, request):
|
||||||
|
|
||||||
district = ItemCRUD(ItemCRUDType.District)
|
district = ItemCRUD(ItemCRUDType.District)
|
||||||
@@ -50,7 +36,7 @@ class District:
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# get all district data
|
||||||
def GetAllDistricts(self, request):
|
def GetAllDistricts(self, request):
|
||||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||||
districtsdata = district.GetAllData(request=request, storedproc="GetAllDistricts")
|
districtsdata = district.GetAllData(request=request, storedproc="GetAllDistricts")
|
||||||
@@ -58,7 +44,7 @@ class District:
|
|||||||
self.resultMessage = district.resultMessage
|
self.resultMessage = district.resultMessage
|
||||||
return districtsdata
|
return districtsdata
|
||||||
|
|
||||||
|
# check district validation
|
||||||
def CheckDistrict(self, request):
|
def CheckDistrict(self, request):
|
||||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||||
district_name = request.json.get('district_Name', '').strip()
|
district_name = request.json.get('district_Name', '').strip()
|
||||||
@@ -68,13 +54,7 @@ class District:
|
|||||||
self.resultMessage = district.resultMessage
|
self.resultMessage = district.resultMessage
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
# get district by district id
|
||||||
# def GetDistrictByID(self, request,district_id):
|
|
||||||
# district = ItemCRUD(itemType=ItemCRUDType.District)
|
|
||||||
# districtdata = district.GetAllData(id=district_id,storedproc="GetDistrictDataByID")
|
|
||||||
# self.isSuccess = district.isSuccess
|
|
||||||
# self.resultMessage = district.resultMessage
|
|
||||||
# return districtdata
|
|
||||||
def GetDistrictByID(self, request, district_id):
|
def GetDistrictByID(self, request, district_id):
|
||||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||||
|
|
||||||
@@ -92,7 +72,7 @@ class District:
|
|||||||
return districtdata
|
return districtdata
|
||||||
|
|
||||||
|
|
||||||
#Delete District
|
# Delete District by district id
|
||||||
def DeleteDistrict(self, request, district_id):
|
def DeleteDistrict(self, request, district_id):
|
||||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||||
district.DeleteItem(request=request,itemID=district_id,storedprocDelete="DeleteDistrict")
|
district.DeleteItem(request=request,itemID=district_id,storedprocDelete="DeleteDistrict")
|
||||||
|
|||||||
@@ -27,13 +27,27 @@ class FolderAndFile:
|
|||||||
os.makedirs(folder, exist_ok=True)
|
os.makedirs(folder, exist_ok=True)
|
||||||
return folder
|
return folder
|
||||||
|
|
||||||
# -----------------------------
|
@staticmethod
|
||||||
# FILE PATH METHODS
|
def get_logs_folder():
|
||||||
# -----------------------------
|
folder = os.path.join(current_app.root_path, "logs")
|
||||||
|
|
||||||
|
if not os.path.exists(folder):
|
||||||
|
os.makedirs(folder)
|
||||||
|
|
||||||
|
os.makedirs(folder, exist_ok=True)
|
||||||
|
return folder
|
||||||
|
|
||||||
|
# FILE PATH METHODS - download
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_download_path(filename):
|
def get_download_path(filename):
|
||||||
return os.path.join(FolderAndFile.get_download_folder(), filename)
|
return os.path.join(FolderAndFile.get_download_folder(), filename)
|
||||||
|
|
||||||
|
# FILE PATH METHODS - upload file
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_upload_path(filename):
|
def get_upload_path(filename):
|
||||||
return os.path.join(FolderAndFile.get_upload_folder(), filename)
|
return os.path.join(FolderAndFile.get_upload_folder(), filename)
|
||||||
|
|
||||||
|
# FILE PATH METHODS - activity log file
|
||||||
|
@staticmethod
|
||||||
|
def get_activity_log_path(filename):
|
||||||
|
return os.path.join(FolderAndFile.get_logs_folder(), filename)
|
||||||
78
model/GST.py
78
model/GST.py
@@ -1,55 +1,51 @@
|
|||||||
import config
|
from model.ItemCRUD import ItemCRUD
|
||||||
|
from model.Utilities import ItemCRUDType
|
||||||
|
|
||||||
class GST:
|
class GST:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_unreleased_gst():
|
def get_unreleased_gst():
|
||||||
|
# Use ItemCRUD for Invoices
|
||||||
|
invoice_crud = ItemCRUD(itemType=ItemCRUDType.Invoice)
|
||||||
|
invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic")
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
if not invoice_crud.isSuccess:
|
||||||
cursor = connection.cursor(dictionary=True)
|
return [] # Could also log invoice_crud.resultMessage
|
||||||
|
|
||||||
try:
|
invoices = [
|
||||||
# ----------- Invoices -----------
|
dict(
|
||||||
cursor.callproc('GetAllInvoicesBasic')
|
Invoice_No=row[1],
|
||||||
invoices = []
|
GST_SD_Amount=float(row[2]) if row[2] is not None else 0
|
||||||
for result in cursor.stored_results():
|
)
|
||||||
invoices = result.fetchall()
|
for row in invoices_rows
|
||||||
|
]
|
||||||
|
|
||||||
|
# Use ItemCRUD for GST Releases
|
||||||
|
gst_crud = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic")
|
||||||
|
|
||||||
# ----------- GST Releases -----------
|
if not gst_crud.isSuccess:
|
||||||
cursor.callproc('GetAllGSTReleasesBasic')
|
return [] # Could also log gst_crud.resultMessage
|
||||||
gst_releases = []
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
gst_releases = result.fetchall()
|
|
||||||
|
|
||||||
gst_invoice_nos = {
|
gst_invoice_nos = {
|
||||||
g['Invoice_No']
|
g[2] # Invoice_No is at index 2
|
||||||
for g in gst_releases
|
for g in gst_rows
|
||||||
if g['Invoice_No']
|
if g[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_basic_amounts = {
|
gst_basic_amounts = {
|
||||||
float(g['Basic_Amount'])
|
float(g[3]) # Basic_Amount at index 3
|
||||||
for g in gst_releases
|
for g in gst_rows
|
||||||
if g['Basic_Amount'] is not None
|
if g[3] is not None
|
||||||
}
|
}
|
||||||
|
|
||||||
unreleased = []
|
# Filter unreleased invoices
|
||||||
|
unreleased = []
|
||||||
|
for inv in invoices:
|
||||||
|
match_by_invoice = inv['Invoice_No'] in gst_invoice_nos
|
||||||
|
match_by_gst_amount = inv['GST_SD_Amount'] in gst_basic_amounts
|
||||||
|
|
||||||
for inv in invoices:
|
if not (match_by_invoice or match_by_gst_amount):
|
||||||
|
unreleased.append(inv)
|
||||||
|
|
||||||
match_by_invoice = inv['Invoice_No'] in gst_invoice_nos
|
return unreleased
|
||||||
|
|
||||||
match_by_gst_amount = float(
|
|
||||||
inv.get('GST_SD_Amount') or 0
|
|
||||||
) in gst_basic_amounts
|
|
||||||
|
|
||||||
if not (match_by_invoice or match_by_gst_amount):
|
|
||||||
unreleased.append(inv)
|
|
||||||
|
|
||||||
return unreleased
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
@@ -3,7 +3,6 @@ from model.ItemCRUD import ItemCRUD
|
|||||||
from model.Utilities import ItemCRUDType
|
from model.Utilities import ItemCRUDType
|
||||||
|
|
||||||
class HoldTypes:
|
class HoldTypes:
|
||||||
"""CRUD operations for Hold Types using ItemCRUD"""
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
@@ -33,7 +32,7 @@ class HoldTypes:
|
|||||||
self.isSuccess = hold.isSuccess
|
self.isSuccess = hold.isSuccess
|
||||||
self.resultMessage = hold.resultMessage
|
self.resultMessage = hold.resultMessage
|
||||||
|
|
||||||
# ✅ Convert tuple → dictionary
|
# Convert tuple → dictionary
|
||||||
data = []
|
data = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
data.append({
|
data.append({
|
||||||
@@ -51,7 +50,7 @@ class HoldTypes:
|
|||||||
self.isSuccess = hold.isSuccess
|
self.isSuccess = hold.isSuccess
|
||||||
self.resultMessage = hold.resultMessage
|
self.resultMessage = hold.resultMessage
|
||||||
|
|
||||||
# ✅ Convert tuple → dictionary
|
# Convert tuple → dictionary
|
||||||
if row:
|
if row:
|
||||||
return {
|
return {
|
||||||
"hold_type_id": row[0],
|
"hold_type_id": row[0],
|
||||||
|
|||||||
510
model/Invoice.py
510
model/Invoice.py
@@ -1,287 +1,151 @@
|
|||||||
|
|
||||||
import config
|
import config
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
|
|
||||||
# ------------------- Helper -------------------
|
# ------------------- Helper Functions -------------------
|
||||||
def clear_results(cursor):
|
def clear_results(cursor):
|
||||||
|
"""Consume all stored results to prevent cursor issues."""
|
||||||
for r in cursor.stored_results():
|
for r in cursor.stored_results():
|
||||||
r.fetchall()
|
r.fetchall()
|
||||||
|
|
||||||
|
def fetch_one(cursor):
|
||||||
|
"""Fetch first row from stored results."""
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
return result.fetchone()
|
||||||
|
return None
|
||||||
|
|
||||||
# ------------------- Get Village Id -------------------
|
def fetch_all(cursor):
|
||||||
def get_village_id(village_name):
|
"""Fetch all rows from stored results."""
|
||||||
|
data = []
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
data.extend(result.fetchall())
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_numeric_values(data):
|
||||||
|
"""Return numeric fields for invoices safely."""
|
||||||
|
return [
|
||||||
|
float(data.get('basic_amount') or 0),
|
||||||
|
float(data.get('debit_amount') or 0),
|
||||||
|
float(data.get('after_debit_amount') or 0),
|
||||||
|
float(data.get('amount') or 0),
|
||||||
|
float(data.get('gst_amount') or 0),
|
||||||
|
float(data.get('tds_amount') or 0),
|
||||||
|
float(data.get('sd_amount') or 0),
|
||||||
|
float(data.get('on_commission') or 0),
|
||||||
|
float(data.get('hydro_testing') or 0),
|
||||||
|
float(data.get('gst_sd_amount') or 0),
|
||||||
|
float(data.get('final_amount') or 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
def execute_db_operation(operation_func):
|
||||||
|
"""General DB operation wrapper with commit/rollback."""
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor = connection.cursor(dictionary=True)
|
||||||
|
|
||||||
cursor.callproc("GetVillageIdByName", (village_name,))
|
|
||||||
village_result = None
|
|
||||||
|
|
||||||
for rs in cursor.stored_results():
|
|
||||||
village_result = rs.fetchone()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return village_result
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Insert Invoice -------------------
|
|
||||||
def insert_invoice(data, village_id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 1. Insert Invoice
|
result = operation_func(cursor)
|
||||||
cursor.callproc('InsertInvoice', [
|
connection.commit()
|
||||||
|
return result
|
||||||
|
except Exception:
|
||||||
|
connection.rollback()
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------- Village Functions -------------------
|
||||||
|
def get_village_id(village_name):
|
||||||
|
def operation(cursor):
|
||||||
|
cursor.callproc("GetVillageIdByName", (village_name,))
|
||||||
|
return fetch_one(cursor)
|
||||||
|
return execute_db_operation(operation)
|
||||||
|
|
||||||
|
def get_all_villages():
|
||||||
|
def operation(cursor):
|
||||||
|
cursor.callproc("GetAllVillages")
|
||||||
|
return fetch_all(cursor)
|
||||||
|
return execute_db_operation(operation)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------- Invoice Functions -------------------
|
||||||
|
def insert_invoice(data, village_id):
|
||||||
|
def operation(cursor):
|
||||||
|
# Insert invoice
|
||||||
|
# cursor.callproc('InsertInvoice', [
|
||||||
|
# data.get('pmc_no'),
|
||||||
|
# village_id,
|
||||||
|
# data.get('work_type'),
|
||||||
|
# data.get('invoice_details'),
|
||||||
|
# data.get('invoice_date'),
|
||||||
|
# data.get('invoice_no'),
|
||||||
|
# *get_numeric_values(data),
|
||||||
|
# data.get('subcontractor_id')
|
||||||
|
|
||||||
|
# ])
|
||||||
|
# invoice_row = fetch_one(cursor)
|
||||||
|
# if not invoice_row:
|
||||||
|
# raise Exception("Invoice ID not returned")
|
||||||
|
# invoice_id = invoice_row.get('invoice_id')
|
||||||
|
cursor.callproc('SaveInvoice', [
|
||||||
data.get('pmc_no'),
|
data.get('pmc_no'),
|
||||||
village_id,
|
village_id,
|
||||||
data.get('work_type'),
|
data.get('work_type'),
|
||||||
data.get('invoice_details'),
|
data.get('invoice_details'),
|
||||||
data.get('invoice_date'),
|
data.get('invoice_date'),
|
||||||
data.get('invoice_no'),
|
data.get('invoice_no'),
|
||||||
float(data.get('basic_amount') or 0),
|
*get_numeric_values(data),
|
||||||
float(data.get('debit_amount') or 0),
|
data.get('subcontractor_id'),
|
||||||
float(data.get('after_debit_amount') or 0),
|
0
|
||||||
float(data.get('amount') or 0),
|
|
||||||
float(data.get('gst_amount') or 0),
|
|
||||||
float(data.get('tds_amount') or 0),
|
|
||||||
float(data.get('sd_amount') or 0),
|
|
||||||
float(data.get('on_commission') or 0),
|
|
||||||
float(data.get('hydro_testing') or 0),
|
|
||||||
float(data.get('gst_sd_amount') or 0),
|
|
||||||
float(data.get('final_amount') or 0)
|
|
||||||
])
|
])
|
||||||
|
|
||||||
invoice_id = None
|
invoice_id = None
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
row = result.fetchone()
|
row = result.fetchone()
|
||||||
if row:
|
if row:
|
||||||
invoice_id = row.get('invoice_id')
|
invoice_id = row['invoice_id']
|
||||||
|
|
||||||
if not invoice_id:
|
# # Insert inpayment
|
||||||
raise Exception("Invoice ID not returned")
|
# cursor.callproc('InsertInpayment', [
|
||||||
|
# data.get('pmc_no'),
|
||||||
# 2. Insert Inpayment
|
# village_id,
|
||||||
cursor.callproc('InsertInpayment', [
|
# data.get('work_type'),
|
||||||
data.get('pmc_no'),
|
# data.get('invoice_details'),
|
||||||
village_id,
|
# data.get('invoice_date'),
|
||||||
data.get('work_type'),
|
# data.get('invoice_no'),
|
||||||
data.get('invoice_details'),
|
# *get_numeric_values(data),
|
||||||
data.get('invoice_date'),
|
# data.get('subcontractor_id')
|
||||||
data.get('invoice_no'),
|
# ])
|
||||||
float(data.get('basic_amount') or 0),
|
# clear_results(cursor)
|
||||||
float(data.get('debit_amount') or 0),
|
|
||||||
float(data.get('after_debit_amount') or 0),
|
|
||||||
float(data.get('amount') or 0),
|
|
||||||
float(data.get('gst_amount') or 0),
|
|
||||||
float(data.get('tds_amount') or 0),
|
|
||||||
float(data.get('sd_amount') or 0),
|
|
||||||
float(data.get('on_commission') or 0),
|
|
||||||
float(data.get('hydro_testing') or 0),
|
|
||||||
float(data.get('gst_sd_amount') or 0),
|
|
||||||
float(data.get('final_amount') or 0),
|
|
||||||
data.get('subcontractor_id')
|
|
||||||
])
|
|
||||||
clear_results(cursor)
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
return invoice_id
|
return invoice_id
|
||||||
|
|
||||||
except Exception as e:
|
return execute_db_operation(operation)
|
||||||
connection.rollback()
|
|
||||||
raise e
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Assign Subcontractor -------------------
|
|
||||||
def assign_subcontractor(data, village_id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor.callproc('AssignSubcontractor', [
|
|
||||||
data.get('pmc_no'),
|
|
||||||
data.get('subcontractor_id'),
|
|
||||||
village_id
|
|
||||||
])
|
|
||||||
clear_results(cursor)
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
connection.rollback()
|
|
||||||
raise e
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Insert Hold Types -------------------
|
|
||||||
def insert_hold_types(data, invoice_id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
hold_types = data.getlist('hold_type[]')
|
|
||||||
hold_amounts = data.getlist('hold_amount[]')
|
|
||||||
|
|
||||||
for hold_type, hold_amount in zip(hold_types, hold_amounts):
|
|
||||||
if not hold_type:
|
|
||||||
continue
|
|
||||||
|
|
||||||
cursor.callproc('GetHoldTypeIdByName', [hold_type])
|
|
||||||
hold_type_result = None
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
hold_type_result = result.fetchone()
|
|
||||||
|
|
||||||
if not hold_type_result:
|
|
||||||
cursor.callproc('InsertHoldType', [hold_type, 0])
|
|
||||||
cursor.execute("SELECT @_InsertHoldType_1")
|
|
||||||
hold_type_id = cursor.fetchone()[0]
|
|
||||||
else:
|
|
||||||
hold_type_id = hold_type_result['hold_type_id']
|
|
||||||
|
|
||||||
hold_amount = float(hold_amount or 0)
|
|
||||||
|
|
||||||
cursor.callproc('InsertInvoiceSubcontractorHold', [
|
|
||||||
data.get('subcontractor_id'),
|
|
||||||
invoice_id,
|
|
||||||
hold_type_id,
|
|
||||||
hold_amount
|
|
||||||
])
|
|
||||||
clear_results(cursor)
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
connection.rollback()
|
|
||||||
raise e
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Get All Invoices -------------------
|
|
||||||
def get_all_invoice_details():
|
def get_all_invoice_details():
|
||||||
connection = config.get_db_connection()
|
def operation(cursor):
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor.callproc('GetAllInvoiceDetails')
|
||||||
|
return fetch_all(cursor)
|
||||||
|
return execute_db_operation(operation)
|
||||||
|
|
||||||
cursor.callproc('GetAllInvoiceDetails')
|
|
||||||
invoices = []
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
invoices = result.fetchall()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return invoices
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Get All Villages -------------------
|
|
||||||
def get_all_villages():
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
cursor.callproc("GetAllVillages")
|
|
||||||
villages = []
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
villages = result.fetchall()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return villages
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Search Contractors -------------------
|
|
||||||
def search_contractors(sub_query):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
cursor.callproc('SearchContractorsByName', [sub_query])
|
|
||||||
results = []
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
results = result.fetchall()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Get All Hold Types -------------------
|
|
||||||
def get_all_hold_types():
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
cursor.callproc("GetAllHoldTypes")
|
|
||||||
hold_types = []
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
hold_types = result.fetchall()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return hold_types
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Get Invoice By Id -------------------
|
|
||||||
def get_invoice_by_id(invoice_id):
|
def get_invoice_by_id(invoice_id):
|
||||||
connection = config.get_db_connection()
|
def operation(cursor):
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor.callproc('GetInvoiceDetailsById', [invoice_id])
|
||||||
|
invoice = fetch_one(cursor)
|
||||||
|
|
||||||
cursor.callproc('GetInvoiceDetailsById', [invoice_id])
|
cursor.callproc('GetHoldAmountsByInvoiceId', [invoice_id])
|
||||||
invoice = None
|
hold_amounts = fetch_all(cursor)
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
if invoice:
|
||||||
invoice = result.fetchone()
|
invoice["hold_amounts"] = hold_amounts
|
||||||
|
return invoice
|
||||||
|
return execute_db_operation(operation)
|
||||||
|
|
||||||
cursor.callproc('GetHoldAmountsByInvoiceId', [invoice_id])
|
|
||||||
hold_amounts = []
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
hold_amounts = result.fetchall()
|
|
||||||
|
|
||||||
if invoice:
|
|
||||||
invoice["hold_amounts"] = hold_amounts
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return invoice
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Update Invoice -------------------
|
|
||||||
def update_invoice(data, invoice_id):
|
def update_invoice(data, invoice_id):
|
||||||
connection = config.get_db_connection()
|
def operation(cursor):
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor.callproc("GetVillageIdByName", (data.get('village'),))
|
cursor.callproc("GetVillageIdByName", (data.get('village'),))
|
||||||
village = None
|
village = fetch_one(cursor)
|
||||||
|
if not village:
|
||||||
for rs in cursor.stored_results():
|
raise Exception("Village not found")
|
||||||
village = rs.fetchone()
|
|
||||||
|
|
||||||
village_id = village['Village_Id']
|
village_id = village['Village_Id']
|
||||||
|
|
||||||
numeric = [
|
|
||||||
float(data.get('basic_amount') or 0),
|
|
||||||
float(data.get('debit_amount') or 0),
|
|
||||||
float(data.get('after_debit_amount') or 0),
|
|
||||||
float(data.get('amount') or 0),
|
|
||||||
float(data.get('gst_amount') or 0),
|
|
||||||
float(data.get('tds_amount') or 0),
|
|
||||||
float(data.get('sd_amount') or 0),
|
|
||||||
float(data.get('on_commission') or 0),
|
|
||||||
float(data.get('hydro_testing') or 0),
|
|
||||||
float(data.get('gst_sd_amount') or 0),
|
|
||||||
float(data.get('final_amount') or 0),
|
|
||||||
]
|
|
||||||
|
|
||||||
cursor.callproc('UpdateInvoice', [
|
cursor.callproc('UpdateInvoice', [
|
||||||
data.get('pmc_no'),
|
data.get('pmc_no'),
|
||||||
village_id,
|
village_id,
|
||||||
@@ -289,91 +153,101 @@ def update_invoice(data, invoice_id):
|
|||||||
data.get('invoice_details'),
|
data.get('invoice_details'),
|
||||||
data.get('invoice_date'),
|
data.get('invoice_date'),
|
||||||
data.get('invoice_no'),
|
data.get('invoice_no'),
|
||||||
*numeric,
|
*get_numeric_values(data),
|
||||||
invoice_id
|
invoice_id
|
||||||
])
|
])
|
||||||
clear_results(cursor)
|
clear_results(cursor)
|
||||||
|
execute_db_operation(operation)
|
||||||
|
|
||||||
connection.commit()
|
# def update_inpayment(data):
|
||||||
|
# def operation(cursor):
|
||||||
|
# cursor.callproc('UpdateInpayment', [
|
||||||
|
# data.get('work_type'),
|
||||||
|
# data.get('invoice_details'),
|
||||||
|
# data.get('invoice_date'),
|
||||||
|
# *get_numeric_values(data),
|
||||||
|
# data.get('pmc_no'),
|
||||||
|
# data.get('invoice_no')
|
||||||
|
# ])
|
||||||
|
# clear_results(cursor)
|
||||||
|
# execute_db_operation(operation)
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
connection.rollback()
|
|
||||||
raise e
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Update Inpayment -------------------
|
|
||||||
def update_inpayment(data):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
numeric = [
|
|
||||||
float(data.get('basic_amount') or 0),
|
|
||||||
float(data.get('debit_amount') or 0),
|
|
||||||
float(data.get('after_debit_amount') or 0),
|
|
||||||
float(data.get('amount') or 0),
|
|
||||||
float(data.get('gst_amount') or 0),
|
|
||||||
float(data.get('tds_amount') or 0),
|
|
||||||
float(data.get('sd_amount') or 0),
|
|
||||||
float(data.get('on_commission') or 0),
|
|
||||||
float(data.get('hydro_testing') or 0),
|
|
||||||
float(data.get('gst_sd_amount') or 0),
|
|
||||||
float(data.get('final_amount') or 0),
|
|
||||||
]
|
|
||||||
|
|
||||||
cursor.callproc('UpdateInpayment', [
|
|
||||||
data.get('work_type'),
|
|
||||||
data.get('invoice_details'),
|
|
||||||
data.get('invoice_date'),
|
|
||||||
*numeric,
|
|
||||||
data.get('pmc_no'),
|
|
||||||
data.get('invoice_no')
|
|
||||||
])
|
|
||||||
clear_results(cursor)
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
connection.rollback()
|
|
||||||
raise e
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Delete Invoice -------------------
|
|
||||||
def delete_invoice_data(invoice_id, user_id):
|
def delete_invoice_data(invoice_id, user_id):
|
||||||
connection = config.get_db_connection()
|
def operation(cursor):
|
||||||
cursor = connection.cursor(dictionary=True)
|
# Fetch PMC and Invoice_No from DB
|
||||||
|
cursor.callproc('GetInvoicePMCById', (invoice_id,))
|
||||||
try:
|
|
||||||
cursor.callproc('GetInvoicePMCById', [invoice_id])
|
|
||||||
|
|
||||||
record = {}
|
record = {}
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
record = result.fetchone() or {}
|
record = result.fetchone() or {}
|
||||||
if not record:
|
if not record:
|
||||||
raise Exception("Invoice not found")
|
raise Exception("Invoice not found")
|
||||||
|
|
||||||
|
# Use exact DB keys
|
||||||
|
pmc_no = record['PMC_No']
|
||||||
|
invoice_no = record['Invoice_No']
|
||||||
|
|
||||||
|
# Delete invoice
|
||||||
cursor.callproc("DeleteInvoice", (invoice_id,))
|
cursor.callproc("DeleteInvoice", (invoice_id,))
|
||||||
clear_results(cursor)
|
clear_results(cursor)
|
||||||
|
|
||||||
cursor.callproc(
|
# Delete inpayment
|
||||||
'DeleteInpaymentByPMCInvoice',
|
# cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no))
|
||||||
[record['PMC_No'], record['invoice_no']]
|
# clear_results(cursor)
|
||||||
)
|
|
||||||
|
|
||||||
connection.commit()
|
execute_db_operation(operation)
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
connection.rollback()
|
|
||||||
raise e
|
|
||||||
|
|
||||||
finally:
|
# ------------------- Subcontractor Functions -------------------
|
||||||
cursor.close()
|
# def assign_subcontractor(data, village_id):
|
||||||
connection.close()
|
# def operation(cursor):
|
||||||
|
# cursor.callproc('AssignSubcontractor', [
|
||||||
|
# data.get('pmc_no'),
|
||||||
|
# data.get('subcontractor_id'),
|
||||||
|
# village_id
|
||||||
|
# ])
|
||||||
|
# clear_results(cursor)
|
||||||
|
# execute_db_operation(operation)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------- Hold Types Functions -------------------
|
||||||
|
def insert_hold_types(data, invoice_id):
|
||||||
|
def operation(cursor):
|
||||||
|
hold_types = data.getlist('hold_type[]')
|
||||||
|
hold_amounts = data.getlist('hold_amount[]')
|
||||||
|
|
||||||
|
for hold_type, hold_amount in zip(hold_types, hold_amounts):
|
||||||
|
if not hold_type:
|
||||||
|
continue
|
||||||
|
|
||||||
|
cursor.callproc('GetHoldTypeIdByName', [hold_type])
|
||||||
|
hold_type_result = fetch_one(cursor)
|
||||||
|
|
||||||
|
if not hold_type_result:
|
||||||
|
cursor.callproc('InsertHoldType', [hold_type, 0])
|
||||||
|
cursor.execute("SELECT @_InsertHoldType_1")
|
||||||
|
hold_type_id = cursor.fetchone()[0]
|
||||||
|
else:
|
||||||
|
hold_type_id = hold_type_result['hold_type_id']
|
||||||
|
|
||||||
|
cursor.callproc('InsertInvoiceSubcontractorHold', [
|
||||||
|
data.get('subcontractor_id'),
|
||||||
|
invoice_id,
|
||||||
|
hold_type_id,
|
||||||
|
float(hold_amount or 0)
|
||||||
|
])
|
||||||
|
clear_results(cursor)
|
||||||
|
execute_db_operation(operation)
|
||||||
|
|
||||||
|
def get_all_hold_types():
|
||||||
|
def operation(cursor):
|
||||||
|
cursor.callproc("GetAllHoldTypes")
|
||||||
|
return fetch_all(cursor)
|
||||||
|
return execute_db_operation(operation)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------- Contractor Functions -------------------
|
||||||
|
def search_contractors(sub_query):
|
||||||
|
def operation(cursor):
|
||||||
|
cursor.callproc('SearchContractorsByName', [sub_query])
|
||||||
|
return fetch_all(cursor)
|
||||||
|
return execute_db_operation(operation)
|
||||||
@@ -6,7 +6,6 @@ import config
|
|||||||
import re
|
import re
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# Mapping Class
|
# Mapping Class
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
@@ -23,10 +22,11 @@ class itemCRUDMapping:
|
|||||||
self.name = "Hold Type"
|
self.name = "Hold Type"
|
||||||
elif itemType is ItemCRUDType.Subcontractor:
|
elif itemType is ItemCRUDType.Subcontractor:
|
||||||
self.name = "Subcontractor"
|
self.name = "Subcontractor"
|
||||||
|
elif itemType.name == "GSTRelease":
|
||||||
|
self.name = "GSTRelease"
|
||||||
else:
|
else:
|
||||||
self.name = "Item"
|
self.name = "Item"
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# Generic CRUD Class
|
# Generic CRUD Class
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
@@ -93,13 +93,47 @@ class ItemCRUD:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# SUBCONTRACTOR (MULTI-FIELD)
|
# GSTRelease MULTI-FIELD
|
||||||
# ======================================================
|
# ======================================================
|
||||||
if data:
|
if self.itemCRUDType.name == "GSTRelease" and data:
|
||||||
|
|
||||||
|
# Duplicate check (PMC_No + Invoice_No)
|
||||||
|
if storedprocfetch:
|
||||||
|
cursor.callproc(storedprocfetch, (data['PMC_No'], data['Invoice_No']))
|
||||||
|
existing_item = None
|
||||||
|
for rs in cursor.stored_results():
|
||||||
|
existing_item = rs.fetchone()
|
||||||
|
if existing_item:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
|
ResponseHandler.already_exists(self.itemCRUDMapping.name), 409
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Insert GSTRelease
|
||||||
|
cursor.callproc(storedprocadd, (
|
||||||
|
data['PMC_No'],
|
||||||
|
data['Invoice_No'],
|
||||||
|
data['Basic_Amount'],
|
||||||
|
data['Final_Amount'],
|
||||||
|
data['Total_Amount'],
|
||||||
|
data['UTR'],
|
||||||
|
data['Contractor_ID']
|
||||||
|
))
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
self.isSuccess = True
|
||||||
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
|
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# ======================================================
|
||||||
|
# SUBCONTRACTOR MULTI-FIELD
|
||||||
|
# ======================================================
|
||||||
|
if self.itemCRUDType.name == "Subcontractor" and data:
|
||||||
|
|
||||||
# Duplicate check
|
|
||||||
cursor.callproc(storedprocfetch, (data['Contractor_Name'],))
|
cursor.callproc(storedprocfetch, (data['Contractor_Name'],))
|
||||||
|
|
||||||
existing_item = None
|
existing_item = None
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
existing_item = rs.fetchone()
|
existing_item = rs.fetchone()
|
||||||
@@ -111,7 +145,6 @@ class ItemCRUD:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Insert
|
|
||||||
cursor.callproc(storedprocadd, (
|
cursor.callproc(storedprocadd, (
|
||||||
data['Contractor_Name'],
|
data['Contractor_Name'],
|
||||||
data['Address'],
|
data['Address'],
|
||||||
@@ -123,26 +156,24 @@ class ItemCRUD:
|
|||||||
data['GST_No'],
|
data['GST_No'],
|
||||||
data['Contractor_password']
|
data['Contractor_password']
|
||||||
))
|
))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# NORMAL (Village / Block / State)
|
# NORMAL SINGLE-FIELD (Village / Block / State)
|
||||||
# ======================================================
|
# ======================================================
|
||||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
if not re.match(RegEx.allPattern, childname):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Duplicate check
|
|
||||||
if parentid is None:
|
if parentid is None:
|
||||||
cursor.callproc(storedprocfetch, (childname,))
|
cursor.callproc(storedprocfetch, (childname,))
|
||||||
else:
|
else:
|
||||||
@@ -159,17 +190,14 @@ class ItemCRUD:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Insert
|
|
||||||
if parentid is None:
|
if parentid is None:
|
||||||
cursor.callproc(storedprocadd, (childname,))
|
cursor.callproc(storedprocadd, (childname,))
|
||||||
else:
|
else:
|
||||||
cursor.callproc(storedprocadd, (childname, parentid))
|
cursor.callproc(storedprocadd, (childname, parentid))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
|
|
||||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -199,9 +227,32 @@ class ItemCRUD:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# SUBCONTRACTOR (MULTI-FIELD)
|
# GSTRelease MULTI-FIELD
|
||||||
# ======================================================
|
# ======================================================
|
||||||
if data:
|
if self.itemCRUDType.name == "GSTRelease" and data:
|
||||||
|
|
||||||
|
cursor.callproc(storedprocupdate, (
|
||||||
|
data['p_pmc_no'], # PMC_No
|
||||||
|
data['p_invoice_no'], # Invoice_No
|
||||||
|
data['p_basic_amount'], # Basic_Amount
|
||||||
|
data['p_final_amount'], # Final_Amount
|
||||||
|
data['p_total_amount'], # Total_Amount
|
||||||
|
data['p_utr'], # UTR
|
||||||
|
data['p_gst_release_id']# GST_Release_Id
|
||||||
|
))
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
self.isSuccess = True
|
||||||
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
|
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# ======================================================
|
||||||
|
# SUBCONTRACTOR MULTI-FIELD
|
||||||
|
# ======================================================
|
||||||
|
if self.itemCRUDType.name == "Subcontractor" and data:
|
||||||
|
|
||||||
cursor.callproc(storedprocupdate, (
|
cursor.callproc(storedprocupdate, (
|
||||||
childid,
|
childid,
|
||||||
data['Contractor_Name'],
|
data['Contractor_Name'],
|
||||||
@@ -214,9 +265,7 @@ class ItemCRUD:
|
|||||||
data['GST_No'],
|
data['GST_No'],
|
||||||
data['Contractor_password']
|
data['Contractor_password']
|
||||||
))
|
))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
||||||
@@ -224,9 +273,9 @@ class ItemCRUD:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# NORMAL
|
# NORMAL SINGLE-FIELD
|
||||||
# ======================================================
|
# ======================================================
|
||||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
if not re.match(RegEx.allPattern, childname):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = ResponseHandler.update_failure(self.itemCRUDMapping.name)['message']
|
self.resultMessage = ResponseHandler.update_failure(self.itemCRUDMapping.name)['message']
|
||||||
return
|
return
|
||||||
@@ -237,7 +286,6 @@ class ItemCRUD:
|
|||||||
cursor.callproc(storedprocupdate, (childid, parentid, childname))
|
cursor.callproc(storedprocupdate, (childid, parentid, childname))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
|
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
|
||||||
|
|
||||||
@@ -259,20 +307,15 @@ class ItemCRUD:
|
|||||||
|
|
||||||
data = []
|
data = []
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
|
|
||||||
if not connection:
|
if not connection:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.callproc(storedproc)
|
cursor.callproc(storedproc)
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
data = result.fetchall()
|
data = result.fetchall()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
@@ -280,7 +323,6 @@ class ItemCRUD:
|
|||||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||||
)
|
)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
@@ -298,13 +340,10 @@ class ItemCRUD:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.callproc(storedproc, (id,))
|
cursor.callproc(storedproc, (id,))
|
||||||
|
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
data = rs.fetchone()
|
data = rs.fetchone()
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
@@ -324,7 +363,7 @@ class ItemCRUD:
|
|||||||
f"User {current_user.id} checked '{childname}'"
|
f"User {current_user.id} checked '{childname}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
if not re.match(RegEx.allPattern, childname):
|
||||||
return HtmlHelper.json_response(
|
return HtmlHelper.json_response(
|
||||||
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
||||||
)
|
)
|
||||||
@@ -353,7 +392,6 @@ class ItemCRUD:
|
|||||||
return HtmlHelper.json_response(
|
return HtmlHelper.json_response(
|
||||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||||
)
|
)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
32
model/Log.py
32
model/Log.py
@@ -1,10 +1,9 @@
|
|||||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
import os
|
||||||
from flask import current_app
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
||||||
|
|
||||||
import os
|
from datetime import datetime
|
||||||
|
|
||||||
|
from model.FolderAndFile import FolderAndFile
|
||||||
|
|
||||||
class LogHelper:
|
class LogHelper:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -14,22 +13,24 @@ class LogHelper:
|
|||||||
logData.WriteLog(action, details="")
|
logData.WriteLog(action, details="")
|
||||||
|
|
||||||
class LogData:
|
class LogData:
|
||||||
|
|
||||||
filepath = ""
|
filepath = ""
|
||||||
timestamp = None
|
timestamp = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.filepath = os.path.join(current_app.root_path, 'activity.log')
|
self.filepath = FolderAndFile.get_activity_log_path('activity.log')
|
||||||
self.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
self.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
self.user = LogData.get_current_user()
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_current_user():
|
||||||
if hasattr(current_user, "cn") and current_user.cn:
|
if hasattr(current_user, "cn") and current_user.cn:
|
||||||
self.user = current_user.cn
|
return current_user.cn
|
||||||
elif hasattr(current_user, "username") and current_user.username:
|
elif hasattr(current_user, "username") and current_user.username:
|
||||||
self.user = current_user.username
|
return current_user.username
|
||||||
elif hasattr(current_user, "sAMAccountName") and current_user.sAMAccountName:
|
elif hasattr(current_user, "sAMAccountName") and current_user.sAMAccountName:
|
||||||
self.user = current_user.sAMAccountName
|
return current_user.sAMAccountName
|
||||||
else:
|
return "Unknown"
|
||||||
self.user = "Unknown"
|
|
||||||
|
|
||||||
def WriteLog(self, action, details=""):
|
def WriteLog(self, action, details=""):
|
||||||
"""Log user actions with timestamp, user, action, and details."""
|
"""Log user actions with timestamp, user, action, and details."""
|
||||||
@@ -42,7 +43,6 @@ class LogData:
|
|||||||
f"Details: {details}\n"
|
f"Details: {details}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def GetActivitiesLog(self):
|
def GetActivitiesLog(self):
|
||||||
logs = []
|
logs = []
|
||||||
|
|
||||||
@@ -60,7 +60,6 @@ class LogData:
|
|||||||
return logs
|
return logs
|
||||||
|
|
||||||
def GetFilteredActivitiesLog(self, startDate, endDate, userName):
|
def GetFilteredActivitiesLog(self, startDate, endDate, userName):
|
||||||
|
|
||||||
filtered_logs = self.GetActivitiesLog()
|
filtered_logs = self.GetActivitiesLog()
|
||||||
|
|
||||||
# Date filter
|
# Date filter
|
||||||
@@ -69,17 +68,14 @@ class LogData:
|
|||||||
start_dt = datetime.strptime(startDate, "%Y-%m-%d") if startDate else datetime.min
|
start_dt = datetime.strptime(startDate, "%Y-%m-%d") if startDate else datetime.min
|
||||||
end_dt = datetime.strptime(endDate, "%Y-%m-%d") if endDate else datetime.max
|
end_dt = datetime.strptime(endDate, "%Y-%m-%d") if endDate else datetime.max
|
||||||
|
|
||||||
|
|
||||||
filtered_logs = [
|
filtered_logs = [
|
||||||
log for log in filtered_logs
|
log for log in filtered_logs
|
||||||
if start_dt <= datetime.strptime(log["timestamp"], "%Y-%m-%d %H:%M:%S") <= end_dt
|
if start_dt <= datetime.strptime(log["timestamp"], "%Y-%m-%d %H:%M:%S") <= end_dt
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Date filter error:", e)
|
print("Date filter error:", e)
|
||||||
#Why catching all exceptions? Need to handle specific exceptions
|
|
||||||
|
|
||||||
# Username filter
|
# Username filter
|
||||||
if userName:
|
if userName:
|
||||||
filtered_logs = [log for log in filtered_logs if userName.lower() in log["user"].lower()]
|
filtered_logs = [log for log in filtered_logs if userName.lower() in log["user"].lower()]
|
||||||
|
|||||||
@@ -1,456 +1,137 @@
|
|||||||
import openpyxl
|
|
||||||
from openpyxl.styles import Font, PatternFill
|
|
||||||
import config
|
import config
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
|
|
||||||
from model.Report import ReportHelper
|
from services.Generalservice import GeneralUse
|
||||||
from model.FolderAndFile import FolderAndFile
|
from model.FolderAndFile import FolderAndFile
|
||||||
|
from model.Report import ReportHelper
|
||||||
|
|
||||||
class PmcReport:
|
class PmcReport:
|
||||||
|
data=[]
|
||||||
|
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def get_pmc_report(pmc_no):
|
# def get_pmc_report(pmc_no):
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
# connection = config.get_db_connection()
|
||||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||||||
|
|
||||||
try:
|
# try:
|
||||||
|
# pmc_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
||||||
|
# cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
||||||
|
# hold_types = next(cursor.stored_results()).fetchall()
|
||||||
|
|
||||||
# cursor.callproc("GetContractorInfoByPmcNo", (pmc_no,))
|
# # Extract hold_type_ids
|
||||||
# pmc_info = next(cursor.stored_results()).fetchone()
|
# hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||||||
pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
|
||||||
|
|
||||||
if not pmc_info:
|
# invoices = []
|
||||||
return None
|
# hold_type_ids_str = ",".join(map(str, hold_type_ids))
|
||||||
|
# cursor.callproc('GetInvoices_WithHold',[pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str])
|
||||||
|
# for result in cursor.stored_results():
|
||||||
|
# invoices = result.fetchall()
|
||||||
|
|
||||||
cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
# gst_rel = GeneralUse.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
||||||
hold_types = next(cursor.stored_results()).fetchall()
|
|
||||||
|
# hold_release = GeneralUse.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
||||||
# Extract hold_type_ids
|
|
||||||
hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
|
||||||
|
|
||||||
invoices = []
|
|
||||||
hold_amount_total = 0
|
|
||||||
if hold_type_ids:
|
|
||||||
hold_type_ids_str = ",".join(map(str, hold_type_ids))
|
|
||||||
cursor.callproc(
|
|
||||||
'GetInvoices_WithHold',
|
|
||||||
[pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
cursor.callproc(
|
|
||||||
'GetInvoices_NoHold',
|
|
||||||
[pmc_no, pmc_info["Contractor_Id"]]
|
|
||||||
)
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
invoices = result.fetchall()
|
|
||||||
|
|
||||||
if hold_type_ids:
|
|
||||||
hold_amount_total = sum(row.get('hold_amount', 0) or 0 for row in invoices)
|
|
||||||
|
|
||||||
total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices)
|
|
||||||
|
|
||||||
|
|
||||||
# GST RELEASE
|
|
||||||
# cursor.callproc('GetGSTReleaseByPMC', [pmc_no])
|
|
||||||
# gst_rel = []
|
|
||||||
# for result in cursor.stored_results():
|
|
||||||
# gst_rel = result.fetchall()
|
|
||||||
|
|
||||||
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
# credit_note = GeneralUse.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
|
||||||
|
|
||||||
total_gst_basic = sum(row.get('basic_amount', 0) or 0 for row in gst_rel)
|
# payments = GeneralUse.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
|
||||||
total_gst_final = sum(row.get('final_amount', 0) or 0 for row in gst_rel)
|
|
||||||
|
# totals = {
|
||||||
|
# "sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_debit_amt": sum(row.get('Debit_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_after_debit_amt": sum(row.get('After_Debit_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_amt": sum(row.get('Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_gst_amt": sum(row.get('GST_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_tds_amt": sum(row.get('TDS_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_ds_amt": sum(row.get('SD_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_on_commission": sum(row.get('On_Commission', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_hydro_test": sum(row.get('Hydro_Testing', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_gst_sd_amt": sum(row.get('GST_SD_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_final_amt": sum(row.get('Final_Amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_invo_hold_amt": sum(row.get('hold_amount', 0) or 0 for row in invoices),
|
||||||
|
# "sum_gst_basic_amt": sum(row.get('basic_amount', 0) or 0 for row in gst_rel),
|
||||||
|
# "sum_gst_final_amt": sum(row.get('final_amount', 0) or 0 for row in gst_rel),
|
||||||
|
# "sum_pay_payment_amt": sum(row.get('Payment_Amount', 0) or 0 for row in payments),
|
||||||
|
# "sum_pay_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments),
|
||||||
|
# "sum_pay_total_amt": sum(row.get('Total_amount', 0) or 0 for row in payments)
|
||||||
|
# }
|
||||||
|
|
||||||
# ---------------- HOLD RELEASE ----------------
|
# return {
|
||||||
# cursor.callproc('GetHoldReleaseByPMC', [pmc_no])
|
# "info": pmc_info,
|
||||||
# hold_release = []
|
# "invoices": invoices,
|
||||||
# for result in cursor.stored_results():
|
# "hold_types": hold_types,
|
||||||
# hold_release = result.fetchall()
|
# "gst_rel": gst_rel,
|
||||||
|
# "payments": payments,
|
||||||
|
# "credit_note": credit_note,
|
||||||
|
# "hold_release": hold_release,
|
||||||
|
# "total": totals
|
||||||
|
# }
|
||||||
|
|
||||||
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
# finally:
|
||||||
|
# cursor.close()
|
||||||
|
# connection.close()
|
||||||
|
|
||||||
# ---------------- CREDIT NOTE ----------------
|
|
||||||
# cursor.callproc('GetCreditNoteByPMC', [pmc_no])
|
|
||||||
# credit_note = []
|
|
||||||
# for result in cursor.stored_results():
|
|
||||||
# credit_note = result.fetchall()
|
|
||||||
|
|
||||||
credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
|
|
||||||
|
|
||||||
payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------- PAYMENTS ----------------
|
|
||||||
# cursor.callproc('GetPaymentsByPMC', [pmc_no])
|
|
||||||
# payments = []
|
|
||||||
# for result in cursor.stored_results():
|
|
||||||
# payments = result.fetchall()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments)
|
|
||||||
total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments)
|
|
||||||
|
|
||||||
totals = {
|
|
||||||
"sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_debit_amt": sum(row.get('Debit_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_after_debit_amt": sum(row.get('After_Debit_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_amt": sum(row.get('Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_gst_amt": sum(row.get('GST_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_tds_amt": sum(row.get('TDS_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_ds_amt": sum(row.get('SD_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_on_commission": sum(row.get('On_Commission', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_hydro_test": sum(row.get('Hydro_Testing', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_gst_sd_amt": sum(row.get('GST_SD_Amount', 0) or 0 for row in invoices),
|
|
||||||
"sum_invo_final_amt": total_invo_final,
|
|
||||||
"sum_invo_hold_amt": hold_amount_total,
|
|
||||||
"sum_gst_basic_amt": total_gst_basic,
|
|
||||||
"sum_gst_final_amt": total_gst_final,
|
|
||||||
"sum_pay_payment_amt": total_pay_amount,
|
|
||||||
"sum_pay_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments),
|
|
||||||
"sum_pay_total_amt": total_pay_total
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"info": pmc_info,
|
|
||||||
"invoices": invoices,
|
|
||||||
"hold_types": hold_types,
|
|
||||||
"gst_rel": gst_rel,
|
|
||||||
"payments": payments,
|
|
||||||
"credit_note": credit_note,
|
|
||||||
"hold_release": hold_release,
|
|
||||||
"total": totals
|
|
||||||
}
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def download_pmc_report(pmc_no):
|
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
if not connection:
|
|
||||||
return None
|
|
||||||
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# filename
|
|
||||||
filename = f"PMC_Report_{pmc_no}.xlsx"
|
|
||||||
|
|
||||||
output_folder = FolderAndFile.get_download_folder()
|
|
||||||
output_file = FolderAndFile.get_download_path(filename)
|
|
||||||
|
|
||||||
# ================= DATA FETCH =================
|
|
||||||
|
|
||||||
contractor_info = ReportHelper.execute_sp(cursor, 'GetContractorDetailsByPMC', [pmc_no], "one")
|
|
||||||
|
|
||||||
if not contractor_info:
|
|
||||||
return None
|
|
||||||
|
|
||||||
hold_types = ReportHelper.execute_sp(cursor, 'GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
|
|
||||||
|
|
||||||
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
|
||||||
|
|
||||||
invoices = ReportHelper.execute_sp(cursor, 'GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
|
||||||
|
|
||||||
credit_notes = ReportHelper.execute_sp(cursor, 'GetCreditNoteByContractor', [contractor_info["Contractor_Id"]])
|
|
||||||
|
|
||||||
hold_amounts = ReportHelper.execute_sp(cursor, 'GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
|
||||||
|
|
||||||
all_payments = ReportHelper.execute_sp(cursor, 'GetAllPaymentsByPMC', [pmc_no])
|
|
||||||
|
|
||||||
gst_releases = ReportHelper.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no])
|
|
||||||
|
|
||||||
# ================= DATA MAPPING =================
|
|
||||||
|
|
||||||
hold_data = {}
|
|
||||||
for h in hold_amounts:
|
|
||||||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
|
||||||
|
|
||||||
payments_map = {}
|
|
||||||
for pay in all_payments:
|
|
||||||
if pay['invoice_no']:
|
|
||||||
payments_map.setdefault(pay['invoice_no'], []).append(pay)
|
|
||||||
|
|
||||||
# ================= LOG =================
|
|
||||||
LogHelper.log_action(
|
|
||||||
"Download PMC Report",
|
|
||||||
f"User {current_user.id} Download PMC Report '{pmc_no}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
# ================= EXCEL =================
|
|
||||||
workbook = openpyxl.Workbook()
|
|
||||||
sheet = workbook.active
|
|
||||||
sheet.title = "PMC Report"
|
|
||||||
|
|
||||||
# HEADER INFO
|
|
||||||
sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD."])
|
|
||||||
sheet.append(["Contractor Name", contractor_info["Contractor_Name"]])
|
|
||||||
sheet.append(["State", contractor_info["State_Name"]])
|
|
||||||
sheet.append(["District", contractor_info["District_Name"]])
|
|
||||||
sheet.append(["Block", contractor_info["Block_Name"]])
|
|
||||||
sheet.append([])
|
|
||||||
|
|
||||||
base_headers = [
|
|
||||||
"PMC No","Village","Work Type","Invoice Details","Invoice Date","Invoice No",
|
|
||||||
"Basic Amount","Debit","After Debit Amount","GST","Amount","TDS",
|
|
||||||
"SD","On Commission","Hydro Testing","GST SD Amount"
|
|
||||||
]
|
|
||||||
|
|
||||||
hold_headers = [ht['hold_type'] for ht in hold_types]
|
|
||||||
|
|
||||||
payment_headers = [
|
|
||||||
"Final Amount","Payment Amount","TDS Payment","Total Paid","UTR"
|
|
||||||
]
|
|
||||||
|
|
||||||
headers = base_headers + hold_headers + payment_headers
|
|
||||||
sheet.append(headers)
|
|
||||||
|
|
||||||
# STYLE
|
|
||||||
for cell in sheet[sheet.max_row]:
|
|
||||||
cell.font = Font(bold=True)
|
|
||||||
|
|
||||||
# DATA
|
|
||||||
seen_invoices = set()
|
|
||||||
|
|
||||||
for inv in invoices:
|
|
||||||
|
|
||||||
invoice_no = inv["Invoice_No"]
|
|
||||||
payments = payments_map.get(invoice_no, [])
|
|
||||||
|
|
||||||
if invoice_no in seen_invoices:
|
|
||||||
continue
|
|
||||||
|
|
||||||
seen_invoices.add(invoice_no)
|
|
||||||
|
|
||||||
first_payment = payments[0] if payments else None
|
|
||||||
|
|
||||||
row = [
|
|
||||||
pmc_no,
|
|
||||||
inv["Village_Name"],
|
|
||||||
inv["Work_Type"],
|
|
||||||
inv["Invoice_Details"],
|
|
||||||
inv["Invoice_Date"],
|
|
||||||
invoice_no,
|
|
||||||
inv["Basic_Amount"],
|
|
||||||
inv["Debit_Amount"],
|
|
||||||
inv["After_Debit_Amount"],
|
|
||||||
inv["GST_Amount"],
|
|
||||||
inv["Amount"],
|
|
||||||
inv["TDS_Amount"],
|
|
||||||
inv["SD_Amount"],
|
|
||||||
inv["On_Commission"],
|
|
||||||
inv["Hydro_Testing"],
|
|
||||||
inv["GST_SD_Amount"]
|
|
||||||
]
|
|
||||||
|
|
||||||
# HOLD DATA
|
|
||||||
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
|
||||||
for ht_id in hold_type_map.keys():
|
|
||||||
row.append(invoice_holds.get(ht_id, ""))
|
|
||||||
|
|
||||||
# PAYMENT DATA
|
|
||||||
row += [
|
|
||||||
inv["Final_Amount"],
|
|
||||||
first_payment["Payment_Amount"] if first_payment else "",
|
|
||||||
first_payment["TDS_Payment_Amount"] if first_payment else "",
|
|
||||||
first_payment["Total_amount"] if first_payment else "",
|
|
||||||
first_payment["UTR"] if first_payment else ""
|
|
||||||
]
|
|
||||||
|
|
||||||
sheet.append(row)
|
|
||||||
|
|
||||||
# AUTO WIDTH
|
|
||||||
for col in sheet.columns:
|
|
||||||
max_len = max((len(str(cell.value)) for cell in col if cell.value), default=0)
|
|
||||||
sheet.column_dimensions[col[0].column_letter].width = max_len + 2
|
|
||||||
|
|
||||||
# SAVE
|
|
||||||
workbook.save(output_file)
|
|
||||||
workbook.close()
|
|
||||||
|
|
||||||
return output_folder, filename
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error generating PMC report: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# @staticmethod
|
# @staticmethod
|
||||||
# def download_pmc_report(pmc_no):
|
# def download_pmc_report(pmc_no):
|
||||||
|
|
||||||
# connection = config.get_db_connection()
|
# connection = config.get_db_connection()
|
||||||
|
# if not connection:
|
||||||
|
# return None
|
||||||
|
|
||||||
# cursor = connection.cursor(dictionary=True)
|
# cursor = connection.cursor(dictionary=True)
|
||||||
|
|
||||||
# # output_folder = "static/download"
|
|
||||||
# # output_file = os.path.join(output_folder, f"PMC_Report_{pmc_no}.xlsx")
|
|
||||||
# output_folder = FolderAndFile.get_download_folder
|
|
||||||
# filename = f"PMC_Report_{pmc_no}.xlsx"
|
|
||||||
# output_file = FolderAndFile.get_download_path(filename)
|
|
||||||
|
|
||||||
# try:
|
# try:
|
||||||
|
# filename = f"PMC_Report_{pmc_no}.xlsx"
|
||||||
|
|
||||||
# cursor.callproc('GetContractorDetailsByPMC', [pmc_no])
|
# output_folder = FolderAndFile.get_download_folder()
|
||||||
# contractor_info = next(cursor.stored_results()).fetchone()
|
# output_file = FolderAndFile.get_download_path(filename)
|
||||||
|
|
||||||
|
# contractor_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no])
|
||||||
|
|
||||||
|
# contractor_info = contractor_info[0] if contractor_info else None
|
||||||
|
# print("contractor_info:::",contractor_info)
|
||||||
|
|
||||||
# if not contractor_info:
|
# if not contractor_info:
|
||||||
# return None
|
# return None
|
||||||
|
|
||||||
# cursor.callproc('GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
|
# hold_types = GeneralUse.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]])
|
||||||
# hold_types = next(cursor.stored_results()).fetchall()
|
|
||||||
|
|
||||||
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||||
|
|
||||||
# cursor.callproc('GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
# invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [None,pmc_no])
|
||||||
# invoices = next(cursor.stored_results()).fetchall()
|
|
||||||
|
|
||||||
# cursor.callproc('GetCreditNoteByContractor',[contractor_info["Contractor_Id"]])
|
|
||||||
|
|
||||||
# credit_notes = []
|
|
||||||
# for result in cursor.stored_results():
|
|
||||||
# credit_notes = result.fetchall()
|
|
||||||
|
|
||||||
|
# credit_notes = GeneralUse.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no])
|
||||||
# credit_note_map = {}
|
# credit_note_map = {}
|
||||||
# for cn in credit_notes:
|
# for cn in credit_notes:
|
||||||
# key = (cn["PMC_No"], cn["Invoice_No"])
|
|
||||||
|
# key = (str(cn['PMC_No']).strip())
|
||||||
# credit_note_map.setdefault(key, []).append(cn)
|
# credit_note_map.setdefault(key, []).append(cn)
|
||||||
|
|
||||||
# cursor.callproc('GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
# hold_amounts = GeneralUse.execute_sp(cursor, 'GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||||||
# hold_amounts = next(cursor.stored_results()).fetchall()
|
|
||||||
|
|
||||||
|
# gst_releases = GeneralUse.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no])
|
||||||
|
# gst_release_map = {}
|
||||||
|
# for gr in gst_releases:
|
||||||
|
# key = (str(gr['PMC_No']).strip())
|
||||||
|
# gst_release_map.setdefault(key, []).append(gr)
|
||||||
|
|
||||||
|
# # ================= DATA MAPPING =================
|
||||||
# hold_data = {}
|
# hold_data = {}
|
||||||
# for h in hold_amounts:
|
# for h in hold_amounts:
|
||||||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||||
|
|
||||||
# cursor.callproc('GetAllPaymentsByPMC', [pmc_no])
|
# # ================= LOG =================
|
||||||
# all_payments = next(cursor.stored_results()).fetchall()
|
# LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'")
|
||||||
|
|
||||||
# payments_map = {}
|
|
||||||
# extra_payments = []
|
|
||||||
|
|
||||||
# for pay in all_payments:
|
|
||||||
# if pay['invoice_no']:
|
|
||||||
# payments_map.setdefault(pay['invoice_no'], []).append(pay)
|
|
||||||
# else:
|
|
||||||
# extra_payments.append(pay)
|
|
||||||
|
|
||||||
# # ---------------- GST RELEASE DETAILS ----------------
|
|
||||||
# cursor.callproc('GetGSTReleaseDetailsByPMC', [pmc_no])
|
|
||||||
|
|
||||||
# gst_releases = []
|
|
||||||
# for result in cursor.stored_results():
|
|
||||||
# gst_releases = result.fetchall()
|
|
||||||
|
|
||||||
# gst_release_map = {}
|
|
||||||
|
|
||||||
# for gr in gst_releases:
|
|
||||||
|
|
||||||
# invoice_nos = []
|
|
||||||
|
|
||||||
# if gr['Invoice_No']:
|
|
||||||
|
|
||||||
# cleaned = gr['Invoice_No'].replace(' ', '')
|
|
||||||
|
|
||||||
# if '&' in cleaned:
|
|
||||||
# invoice_nos = cleaned.split('&')
|
|
||||||
|
|
||||||
# elif ',' in cleaned:
|
|
||||||
# invoice_nos = cleaned.split(',')
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# invoice_nos = [cleaned]
|
|
||||||
|
|
||||||
# for inv_no in invoice_nos:
|
|
||||||
# gst_release_map.setdefault(inv_no, []).append(gr)
|
|
||||||
|
|
||||||
# LogHelper.log_action(
|
|
||||||
# "Download PMC Report",
|
|
||||||
# f"User {current_user.id} Download PMC Report '{pmc_no}'"
|
|
||||||
# )
|
|
||||||
|
|
||||||
# workbook = openpyxl.Workbook()
|
|
||||||
# sheet = workbook.active
|
|
||||||
# sheet.title = "PMC Report"
|
|
||||||
|
|
||||||
# sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD."])
|
|
||||||
# sheet.append(["Contractor Name", contractor_info["Contractor_Name"], "", "GST No", contractor_info["GST_No"], "", "GST Type", contractor_info["GST_Registration_Type"]])
|
|
||||||
# sheet.append(["State", contractor_info["State_Name"], "", "PAN No", contractor_info["PAN_No"], "", "Address", contractor_info["Address"]])
|
|
||||||
# sheet.append(["District", contractor_info["District_Name"], "", "Mobile No", contractor_info["Mobile_No"]])
|
|
||||||
# sheet.append(["Block", contractor_info["Block_Name"], "", "Email", contractor_info["Email"]])
|
|
||||||
# sheet.append([])
|
|
||||||
|
|
||||||
# base_headers = [
|
|
||||||
# "PMC No","Village","Work Type","Invoice Details","Invoice Date","Invoice No",
|
|
||||||
# "Basic Amount","Debit","After Debit Amount","GST (18%)","Amount","TDS (1%)",
|
|
||||||
# "SD (5%)","On Commission","Hydro Testing","GST SD Amount"
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# hold_headers = [ht['hold_type'] for ht in hold_types]
|
|
||||||
|
|
||||||
# payment_headers = [
|
|
||||||
# "Final Amount","Payment Amount","TDS Payment","Total Paid","UTR"
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# sheet.append(base_headers + hold_headers + payment_headers)
|
|
||||||
|
|
||||||
# header_fill = PatternFill(start_color="ADD8E6",end_color="ADD8E6",fill_type="solid")
|
|
||||||
# header_font = Font(bold=True)
|
|
||||||
|
|
||||||
# for cell in sheet[sheet.max_row]:
|
|
||||||
# cell.font = header_font
|
|
||||||
# cell.fill = header_fill
|
|
||||||
|
|
||||||
# seen_invoices = set()
|
|
||||||
# processed_payments = set()
|
|
||||||
|
|
||||||
# for inv in invoices:
|
|
||||||
|
|
||||||
# invoice_no = inv["Invoice_No"]
|
|
||||||
# payments = payments_map.get(invoice_no, [])
|
|
||||||
|
|
||||||
# if invoice_no not in seen_invoices:
|
|
||||||
|
|
||||||
# seen_invoices.add(invoice_no)
|
|
||||||
# first_payment = payments[0] if payments else None
|
|
||||||
|
|
||||||
# row = [
|
|
||||||
# pmc_no, inv["Village_Name"], inv["Work_Type"],
|
|
||||||
# inv["Invoice_Details"], inv["Invoice_Date"], invoice_no,
|
|
||||||
# inv["Basic_Amount"], inv["Debit_Amount"],
|
|
||||||
# inv["After_Debit_Amount"], inv["GST_Amount"],
|
|
||||||
# inv["Amount"], inv["TDS_Amount"], inv["SD_Amount"],
|
|
||||||
# inv["On_Commission"], inv["Hydro_Testing"], inv["GST_SD_Amount"]
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
|
||||||
|
|
||||||
# for ht_id in hold_type_map.keys():
|
|
||||||
# row.append(invoice_holds.get(ht_id, ""))
|
|
||||||
|
|
||||||
# row += [
|
|
||||||
# inv["Final_Amount"],
|
|
||||||
# first_payment["Payment_Amount"] if first_payment else "",
|
|
||||||
# first_payment["TDS_Payment_Amount"] if first_payment else "",
|
|
||||||
# first_payment["Total_amount"] if first_payment else "",
|
|
||||||
# first_payment["UTR"] if first_payment else ""
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# sheet.append(row)
|
|
||||||
|
|
||||||
# workbook.save(output_file)
|
|
||||||
# workbook.close()
|
|
||||||
|
|
||||||
|
# ReportHelper.generate_excel(
|
||||||
|
# 0, contractor_info, invoices, hold_types, hold_data,
|
||||||
|
# credit_note_map,gst_release_map, output_file)
|
||||||
|
|
||||||
# return output_folder, filename
|
# return output_folder, filename
|
||||||
|
|
||||||
# finally:
|
# finally:
|
||||||
|
|
||||||
# cursor.close()
|
# cursor.close()
|
||||||
# connection.close()
|
# connection.close()
|
||||||
|
|
||||||
|
|||||||
335
model/Report.py
335
model/Report.py
@@ -2,9 +2,10 @@ import config
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import send_file
|
from flask import send_file
|
||||||
import openpyxl
|
import openpyxl
|
||||||
from openpyxl.styles import Font
|
from openpyxl.styles import Font, PatternFill
|
||||||
|
|
||||||
from model.FolderAndFile import FolderAndFile
|
from model.FolderAndFile import FolderAndFile
|
||||||
|
from services.Generalservice import GeneralUse
|
||||||
|
|
||||||
class ReportHelper:
|
class ReportHelper:
|
||||||
isSuccess = False
|
isSuccess = False
|
||||||
@@ -16,30 +17,6 @@ class ReportHelper:
|
|||||||
self.resultMessage = ""
|
self.resultMessage = ""
|
||||||
self.data = []
|
self.data = []
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def execute_sp(cursor, proc_name, params=[], fetch_one=False):
|
|
||||||
cursor.callproc(proc_name, params)
|
|
||||||
return (
|
|
||||||
ReportHelper.fetch_one_result(cursor)
|
|
||||||
if fetch_one else
|
|
||||||
ReportHelper.fetch_all_results(cursor)
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fetch_all_results(cursor):
|
|
||||||
data = []
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
data = result.fetchall()
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fetch_one_result(cursor):
|
|
||||||
data = None
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
data = result.fetchone()
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def search_contractor(request):
|
def search_contractor(request):
|
||||||
@@ -59,10 +36,7 @@ class ReportHelper:
|
|||||||
cursor = connection.cursor(dictionary=True)
|
cursor = connection.cursor(dictionary=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = ReportHelper.execute_sp(
|
data = GeneralUse.execute_sp(cursor,"search_contractor_info",[
|
||||||
cursor,
|
|
||||||
"search_contractor_info",
|
|
||||||
[
|
|
||||||
subcontractor_name or None,
|
subcontractor_name or None,
|
||||||
pmc_no or None,
|
pmc_no or None,
|
||||||
state or None,
|
state or None,
|
||||||
@@ -71,8 +45,7 @@ class ReportHelper:
|
|||||||
village or None,
|
village or None,
|
||||||
year_from or None,
|
year_from or None,
|
||||||
year_to or None
|
year_to or None
|
||||||
]
|
])
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error in search_contractor: {e}")
|
print(f"Error in search_contractor: {e}")
|
||||||
@@ -84,192 +57,156 @@ class ReportHelper:
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_contractor_report(contractor_id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Contractor Info (only one fetch)
|
|
||||||
contInfo = ReportHelper.execute_sp(cursor, 'GetContractorInfo', [contractor_id], True)
|
|
||||||
# Hold Types
|
|
||||||
hold_types = ReportHelper.execute_sp(cursor, 'GetContractorHoldTypes', [contractor_id])
|
|
||||||
# Invoices
|
|
||||||
invoices = ReportHelper.execute_sp(cursor, 'GetContractorInvoices', [contractor_id])
|
|
||||||
# GST Release
|
|
||||||
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTRelease', [contractor_id])
|
|
||||||
# Hold Release
|
|
||||||
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldRelease', [contractor_id])
|
|
||||||
# Credit Note
|
|
||||||
credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNote', [contractor_id])
|
|
||||||
# Payments
|
|
||||||
payments = ReportHelper.execute_sp(cursor, 'GetPayments', [contractor_id])
|
|
||||||
|
|
||||||
# Totals
|
|
||||||
total = {
|
|
||||||
"sum_invo_basic_amt": float(sum(row['Basic_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_debit_amt": float(sum(row['Debit_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_after_debit_amt": float(sum(row['After_Debit_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_amt": float(sum(row['Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_gst_amt": float(sum(row['GST_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_tds_amt": float(sum(row['TDS_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_ds_amt": float(sum(row['SD_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_on_commission": float(sum(row['On_Commission'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_hydro_test": float(sum(row['Hydro_Testing'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_gst_sd_amt": float(sum(row['GST_SD_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_final_amt": float(sum(row['Final_Amount'] or 0 for row in invoices)),
|
|
||||||
"sum_invo_hold_amt": float(sum(row['hold_amount'] or 0 for row in invoices)),
|
|
||||||
|
|
||||||
"sum_gst_basic_amt": float(sum(row['basic_amount'] or 0 for row in gst_rel)),
|
|
||||||
"sum_gst_final_amt": float(sum(row['final_amount'] or 0 for row in gst_rel)),
|
|
||||||
|
|
||||||
"sum_pay_payment_amt": float(sum(row['Payment_Amount'] or 0 for row in payments)),
|
|
||||||
"sum_pay_tds_payment_amt": float(sum(row['TDS_Payment_Amount'] or 0 for row in payments)),
|
|
||||||
"sum_pay_total_amt": float(sum(row['Total_amount'] or 0 for row in payments))
|
|
||||||
}
|
|
||||||
|
|
||||||
current_date = datetime.now().strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return {
|
|
||||||
"contInfo": contInfo,
|
|
||||||
"invoices": invoices,
|
|
||||||
"hold_types": hold_types,
|
|
||||||
"gst_rel": gst_rel,
|
|
||||||
"payments": payments,
|
|
||||||
"credit_note": credit_note,
|
|
||||||
"hold_release": hold_release,
|
|
||||||
"total": total,
|
|
||||||
"current_date": current_date
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def download_report(contractor_id):
|
def get_contractor_info(contractor_id):
|
||||||
try:
|
from model.ContractorInfo import ContractorInfo
|
||||||
connection = config.get_db_connection()
|
contractor = ContractorInfo(contractor_id)
|
||||||
cursor = connection.cursor(dictionary=True)
|
return contractor.contInfo if contractor.contInfo else None
|
||||||
|
|
||||||
# -------- Contractor Info --------
|
|
||||||
contInfo = ReportHelper.execute_sp(cursor, 'GetContractorInfo', [contractor_id], True)
|
|
||||||
|
|
||||||
if not contInfo:
|
# call this method for excel formate written
|
||||||
return "No contractor found", 404
|
@staticmethod
|
||||||
|
def generate_excel(contractor_id, contInfo, invoices, hold_types, hold_data,
|
||||||
|
credit_note_map, gst_release_map, output_file):
|
||||||
|
|
||||||
|
workbook = openpyxl.Workbook()
|
||||||
|
sheet = workbook.active
|
||||||
|
sheet.title = "Contractor Report"
|
||||||
|
|
||||||
# -------- Invoice Data --------
|
# Contractor Info
|
||||||
cursor.callproc('FetchInvoicesByContractor', [contractor_id])
|
for field, value in contInfo.items():
|
||||||
|
sheet.append([field.replace("_", " "), value])
|
||||||
|
sheet.append([])
|
||||||
|
|
||||||
invoices = []
|
# Headers
|
||||||
for result in cursor.stored_results():
|
base_headers = ["PMC No", "Village", "Work Type", "Invoice Details", "Invoice Date", "Invoice No",
|
||||||
invoices.extend(result.fetchall())
|
"Basic Amount", "Debit", "After Debit Amount", "GST (18%)", "Amount", "TDS (1%)",
|
||||||
|
"SD (5%)", "On Commission", "Hydro Testing", "GST SD Amount"]
|
||||||
|
|
||||||
if not invoices:
|
hold_headers = [ht['hold_type'] for ht in hold_types]
|
||||||
return "No invoice data found"
|
|
||||||
|
|
||||||
# -------- Create Workbook --------
|
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
||||||
workbook = openpyxl.Workbook()
|
|
||||||
sheet = workbook.active
|
|
||||||
sheet.title = "Contractor Report"
|
|
||||||
|
|
||||||
# ================= CONTRACTOR DETAILS =================
|
all_headers = base_headers + hold_headers + payment_headers
|
||||||
sheet.append(["SUB CONTRACTOR DETAILS"])
|
sheet.append(all_headers)
|
||||||
sheet.cell(row=sheet.max_row, column=1).font = Font(bold=True)
|
|
||||||
sheet.append([])
|
|
||||||
|
|
||||||
sheet.append(["Name", contInfo.get("Contractor_Name") or ""])
|
for cell in sheet[sheet.max_row]:
|
||||||
sheet.append(["Mobile No", contInfo.get("Mobile_No") or ""])
|
cell.font = Font(bold=True)
|
||||||
sheet.append(["Email", contInfo.get("Email") or ""])
|
cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||||||
sheet.append(["Village", contInfo.get("Village_Name") or ""])
|
|
||||||
sheet.append(["Block", contInfo.get("Block_Name") or ""])
|
|
||||||
sheet.append(["District", contInfo.get("District_Name") or ""])
|
|
||||||
sheet.append(["State", contInfo.get("State_Name") or ""])
|
|
||||||
sheet.append(["Address", contInfo.get("Address") or ""])
|
|
||||||
sheet.append(["GST No", contInfo.get("GST_No") or ""])
|
|
||||||
sheet.append(["PAN No", contInfo.get("PAN_No") or ""])
|
|
||||||
sheet.append([])
|
|
||||||
sheet.append([])
|
|
||||||
|
|
||||||
# ================= TABLE HEADERS =================
|
processed_gst_releases = set()
|
||||||
headers = [
|
appended_credit_keys = set()
|
||||||
"PMC No", "Village", "Invoice No", "Invoice Date", "Work Type","Invoice_Details",
|
previous_pmc_no = None
|
||||||
"Basic Amount", "Debit Amount", "After Debit Amount",
|
|
||||||
"Amount", "GST Amount", "TDS Amount", "SD Amount",
|
for inv in invoices:
|
||||||
"On Commission", "Hydro Testing", "Hold Amount",
|
pmc_no = str(inv["PMC_No"]).strip()
|
||||||
"GST SD Amount", "Final Amount",
|
|
||||||
"Payment Amount", "TDS Payment",
|
invoice_no = (
|
||||||
"Total Amount", "UTR"
|
inv["invoice_no"].replace(" ", "") if inv["invoice_no"] else ""
|
||||||
|
if inv["invoice_no"] not in (None, "", 0)
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
key = (pmc_no)
|
||||||
|
|
||||||
|
# Yellow separator
|
||||||
|
if previous_pmc_no and pmc_no != previous_pmc_no:
|
||||||
|
sheet.append([""] * len(all_headers))
|
||||||
|
yellow_fill = PatternFill(start_color="FFFF99", end_color="FFFF99", fill_type="solid")
|
||||||
|
for cell in sheet[sheet.max_row]:
|
||||||
|
cell.fill = yellow_fill
|
||||||
|
|
||||||
|
previous_pmc_no = pmc_no
|
||||||
|
|
||||||
|
# Invoice Row
|
||||||
|
row = [
|
||||||
|
pmc_no,
|
||||||
|
inv.get("Village_Name", ""),
|
||||||
|
inv.get("Work_Type", ""),
|
||||||
|
inv.get("Invoice_Details", ""),
|
||||||
|
inv.get("Invoice_Date", ""),
|
||||||
|
# inv.get("invoice_no",""),
|
||||||
|
invoice_no,
|
||||||
|
inv.get("Basic_Amount", ""),
|
||||||
|
inv.get("Debit_Amount", ""),
|
||||||
|
inv.get("After_Debit_Amount", ""),
|
||||||
|
inv.get("GST_Amount", ""),
|
||||||
|
inv.get("Amount", ""),
|
||||||
|
inv.get("TDS_Amount", ""),
|
||||||
|
inv.get("SD_Amount", ""),
|
||||||
|
inv.get("On_Commission", ""),
|
||||||
|
inv.get("Hydro_Testing", ""),
|
||||||
|
inv.get("GST_SD_Amount", "")
|
||||||
]
|
]
|
||||||
sheet.append(headers)
|
|
||||||
for col in range(1, len(headers) + 1):
|
|
||||||
sheet.cell(row=sheet.max_row, column=col).font = Font(bold=True)
|
|
||||||
|
|
||||||
# ================= DATA =================
|
# Hold values
|
||||||
total_final = 0
|
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||||||
total_payment = 0
|
for ht_id in [ht['hold_type_id'] for ht in hold_types]:
|
||||||
total_amount = 0
|
row.append(invoice_holds.get(ht_id, ""))
|
||||||
|
|
||||||
for inv in invoices:
|
# Payment values
|
||||||
row = [
|
row += [
|
||||||
inv.get("PMC_No"),
|
inv.get("Final_Amount", ""),
|
||||||
inv.get("Village_Name"),
|
inv.get("Payment_Amount", ""),
|
||||||
inv.get("invoice_no"),
|
inv.get("TDS_Payment_Amount", ""),
|
||||||
inv.get("Invoice_Date"),
|
inv.get("Total_Amount", ""),
|
||||||
inv.get("Work_Type"),
|
inv.get("UTR", "")
|
||||||
inv.get("Invoice_Details"),
|
]
|
||||||
inv.get("Basic_Amount"),
|
|
||||||
inv.get("Debit_Amount"),
|
|
||||||
inv.get("After_Debit_Amount"),
|
|
||||||
inv.get("Amount"),
|
|
||||||
inv.get("GST_Amount"),
|
|
||||||
inv.get("TDS_Amount"),
|
|
||||||
inv.get("SD_Amount"),
|
|
||||||
inv.get("On_Commission"),
|
|
||||||
inv.get("Hydro_Testing"),
|
|
||||||
inv.get("Hold_Amount"),
|
|
||||||
inv.get("GST_SD_Amount"),
|
|
||||||
inv.get("Final_Amount"),
|
|
||||||
inv.get("Payment_Amount"),
|
|
||||||
inv.get("TDS_Payment_Amount"),
|
|
||||||
inv.get("Total_Amount"),
|
|
||||||
inv.get("UTR")
|
|
||||||
]
|
|
||||||
|
|
||||||
total_final += float(inv.get("Final_Amount") or 0)
|
sheet.append(row)
|
||||||
total_payment += float(inv.get("Payment_Amount") or 0)
|
|
||||||
total_amount += float(inv.get("Total_Amount") or 0)
|
|
||||||
|
|
||||||
sheet.append(row)
|
# GST Releases
|
||||||
|
if key in gst_release_map and key not in processed_gst_releases:
|
||||||
|
for gr in gst_release_map[key]:
|
||||||
|
gst_row = [
|
||||||
|
pmc_no, "", "", "GST Release Note", "", gr.get("Invoice_No", ""),
|
||||||
|
gr.get("Basic_Amount", ""), "", "", "", "", "", "", "", "", ""
|
||||||
|
]
|
||||||
|
|
||||||
# ================= TOTAL ROW =================
|
gst_row += [""] * len(hold_headers)
|
||||||
sheet.append([])
|
|
||||||
sheet.append([
|
|
||||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
|
||||||
"TOTAL",
|
|
||||||
total_final,
|
|
||||||
total_payment,
|
|
||||||
"",
|
|
||||||
total_amount,
|
|
||||||
""
|
|
||||||
])
|
|
||||||
|
|
||||||
# ================= AUTO WIDTH =================
|
gst_row += [
|
||||||
for column in sheet.columns:
|
gr.get("Final_Amount", ""),
|
||||||
max_length = 0
|
"",
|
||||||
column_letter = column[0].column_letter
|
"",
|
||||||
for cell in column:
|
gr.get("Total_Amount", ""),
|
||||||
if cell.value:
|
gr.get("UTR", "")
|
||||||
max_length = max(max_length, len(str(cell.value)))
|
]
|
||||||
sheet.column_dimensions[column_letter].width = max_length + 2
|
|
||||||
|
sheet.append(gst_row)
|
||||||
|
|
||||||
|
processed_gst_releases.add(key)
|
||||||
|
|
||||||
|
# Credit Notes
|
||||||
|
if key in credit_note_map and key not in appended_credit_keys:
|
||||||
|
for cn in credit_note_map[key]:
|
||||||
|
cn_row = [
|
||||||
|
pmc_no, "", "", cn.get("Invoice_Details", "Credit Note"), "",
|
||||||
|
cn.get("Invoice_No", ""),
|
||||||
|
cn.get("Basic_Amount", ""),
|
||||||
|
cn.get("Debit_Amount", ""),
|
||||||
|
cn.get("After_Debit_Amount", ""),
|
||||||
|
cn.get("GST_Amount", ""),
|
||||||
|
cn.get("Amount", ""),
|
||||||
|
"", "", "", "", ""
|
||||||
|
]
|
||||||
|
|
||||||
|
cn_row += [""] * len(hold_headers)
|
||||||
|
|
||||||
|
cn_row += [
|
||||||
|
cn.get("Final_Amount", ""),
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
cn.get("Total_Amount", ""),
|
||||||
|
cn.get("UTR", "")
|
||||||
|
]
|
||||||
|
|
||||||
|
sheet.append(cn_row)
|
||||||
|
|
||||||
|
appended_credit_keys.add(key)
|
||||||
|
|
||||||
|
# SAVE ONCE AT END
|
||||||
|
workbook.save(output_file)
|
||||||
|
|
||||||
# ================= SAVE FILE =================
|
|
||||||
filename = f"Contractor_Report_{contInfo.get('Contractor_Name')}.xlsx"
|
|
||||||
output_file = FolderAndFile.get_download_path(filename)
|
|
||||||
workbook.save(output_file)
|
|
||||||
|
|
||||||
return send_file(output_file, as_attachment=True)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
from flask import request, redirect, url_for
|
|
||||||
from flask_login import current_user
|
|
||||||
|
|
||||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
|
||||||
from model.Log import LogHelper
|
|
||||||
from model.ItemCRUD import ItemCRUD
|
|
||||||
|
|
||||||
import config
|
import config
|
||||||
import re
|
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
|
from flask import request, redirect, url_for
|
||||||
|
|
||||||
|
from model.Utilities import ResponseHandler, HtmlHelper, ItemCRUDType
|
||||||
|
from model.ItemCRUD import ItemCRUD
|
||||||
|
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
@@ -20,7 +16,6 @@ class State:
|
|||||||
# ADD STATE (USING ITEM CRUD)
|
# ADD STATE (USING ITEM CRUD)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def AddState(self, request):
|
def AddState(self, request):
|
||||||
|
|
||||||
state_name = request.form['state_Name'].strip()
|
state_name = request.form['state_Name'].strip()
|
||||||
|
|
||||||
crud = ItemCRUD(ItemCRUDType.State)
|
crud = ItemCRUD(ItemCRUDType.State)
|
||||||
@@ -42,16 +37,14 @@ class State:
|
|||||||
# GET ALL STATES (NO CHANGE - THIS IS CORRECT)
|
# GET ALL STATES (NO CHANGE - THIS IS CORRECT)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def GetAllStates(self, request):
|
def GetAllStates(self, request):
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
if not connection:
|
if not connection:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
cursor = connection.cursor()
|
||||||
cursor.callproc("GetAllStates")
|
cursor.callproc("GetAllStates")
|
||||||
for res in cursor.stored_results():
|
for res in cursor.stored_results():
|
||||||
data = res.fetchall()
|
data = res.fetchall()
|
||||||
@@ -77,7 +70,6 @@ class State:
|
|||||||
# CHECK STATE (USING ITEM CRUD)
|
# CHECK STATE (USING ITEM CRUD)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def CheckState(self, request):
|
def CheckState(self, request):
|
||||||
|
|
||||||
state_name = request.json.get('state_Name', '').strip()
|
state_name = request.json.get('state_Name', '').strip()
|
||||||
|
|
||||||
crud = ItemCRUD(ItemCRUDType.State)
|
crud = ItemCRUD(ItemCRUDType.State)
|
||||||
@@ -94,7 +86,6 @@ class State:
|
|||||||
# DELETE STATE (USING ITEM CRUD)
|
# DELETE STATE (USING ITEM CRUD)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def DeleteState(self, request, id):
|
def DeleteState(self, request, id):
|
||||||
|
|
||||||
crud = ItemCRUD(ItemCRUDType.State)
|
crud = ItemCRUD(ItemCRUDType.State)
|
||||||
|
|
||||||
crud.DeleteItem(
|
crud.DeleteItem(
|
||||||
@@ -113,7 +104,6 @@ class State:
|
|||||||
# EDIT STATE (USING ITEM CRUD)
|
# EDIT STATE (USING ITEM CRUD)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def EditState(self, request, id):
|
def EditState(self, request, id):
|
||||||
|
|
||||||
state_name = request.form['state_Name'].strip()
|
state_name = request.form['state_Name'].strip()
|
||||||
|
|
||||||
crud = ItemCRUD(ItemCRUDType.State)
|
crud = ItemCRUD(ItemCRUDType.State)
|
||||||
@@ -136,16 +126,14 @@ class State:
|
|||||||
# GET STATE BY ID (KEEP SAME)
|
# GET STATE BY ID (KEEP SAME)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def GetStateByID(self, request, id):
|
def GetStateByID(self, request, id):
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
data = None
|
data = None
|
||||||
|
|
||||||
if not connection:
|
if not connection:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
cursor = connection.cursor()
|
||||||
cursor.callproc("GetStateByID", (id,))
|
cursor.callproc("GetStateByID", (id,))
|
||||||
for res in cursor.stored_results():
|
for res in cursor.stored_results():
|
||||||
data = res.fetchone()
|
data = res.fetchone()
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from model.Utilities import ItemCRUDType
|
from model.Utilities import ItemCRUDType
|
||||||
from model.ItemCRUD import ItemCRUD
|
from model.ItemCRUD import ItemCRUD
|
||||||
|
|
||||||
|
|
||||||
class Subcontractor:
|
class Subcontractor:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ class ItemCRUDType(Enum):
|
|||||||
State = 4
|
State = 4
|
||||||
HoldType = 5
|
HoldType = 5
|
||||||
Subcontractor = 6
|
Subcontractor = 6
|
||||||
|
GSTRelease = 7
|
||||||
|
Invoice = 8
|
||||||
|
|
||||||
class RegEx:
|
class RegEx:
|
||||||
patternAlphabetOnly = "^[A-Za-z ]+$"
|
patternAlphabetOnly = r"^[A-Za-z ]+$"
|
||||||
|
allPattern = r"^(?!\s*$).+"
|
||||||
|
|
||||||
|
|
||||||
class ResponseHandler:
|
class ResponseHandler:
|
||||||
@@ -62,5 +64,5 @@ class HtmlHelper:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def json_response(message_obj, status_code):
|
def json_response(message_obj, status_code):
|
||||||
return jsonify(message_obj), status_code
|
return jsonify(message_obj), status_code
|
||||||
#May need to refactor further
|
|
||||||
|
|
||||||
|
|||||||
211
model/Village.py
211
model/Village.py
@@ -1,17 +1,11 @@
|
|||||||
|
|
||||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
|
||||||
|
|
||||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
|
||||||
from model.Log import LogData, LogHelper
|
|
||||||
|
|
||||||
|
from model.Utilities import ResponseHandler, HtmlHelper, ItemCRUDType
|
||||||
import config
|
import config
|
||||||
|
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
from mysql.connector import Error
|
|
||||||
|
|
||||||
from model.ItemCRUD import ItemCRUD
|
from model.ItemCRUD import ItemCRUD
|
||||||
|
|
||||||
|
|
||||||
class Village:
|
class Village:
|
||||||
isSuccess = False
|
isSuccess = False
|
||||||
resultMessage = ""
|
resultMessage = ""
|
||||||
@@ -19,103 +13,174 @@ class Village:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = ""
|
self.resultMessage = ""
|
||||||
|
self.response = {}
|
||||||
|
self.village = ItemCRUD(itemType=ItemCRUDType.Village)
|
||||||
|
|
||||||
|
# 🔹 Helper: sync status
|
||||||
|
def _set_status(self, village):
|
||||||
|
self.isSuccess = village.isSuccess
|
||||||
|
|
||||||
|
# UPDATED (safe handling)
|
||||||
|
if hasattr(village, "response"):
|
||||||
|
self.response = village.response
|
||||||
|
self.resultMessage = village.response.get("message", "")
|
||||||
|
else:
|
||||||
|
self.resultMessage = village.resultMessage
|
||||||
|
|
||||||
|
# 🔹 Helper: get request data
|
||||||
|
def _get_form_data(self, request):
|
||||||
|
block_id = request.form.get('block_Id')
|
||||||
|
village_name = request.form.get('Village_Name', '').strip()
|
||||||
|
return block_id, village_name
|
||||||
|
|
||||||
def AddVillage(self, request):
|
def AddVillage(self, request):
|
||||||
village = ItemCRUD(itemType=ItemCRUDType.Village)
|
block_id, village_name = self._get_form_data(request)
|
||||||
|
|
||||||
block_id = request.form.get('block_Id')
|
if not village_name:
|
||||||
village_name = request.form.get('Village_Name', '').strip()
|
self.response = ResponseHandler.invalid_name("village")
|
||||||
|
self.resultMessage = self.response["message"]
|
||||||
|
self.isSuccess = False
|
||||||
|
return
|
||||||
|
|
||||||
village.AddItem(request=request, parentid=block_id, childname=village_name, storedprocfetch="GetVillageByNameAndBlock", storedprocadd="SaveVillage" )
|
try:
|
||||||
self.isSuccess = village.isSuccess
|
self.village.AddItem(
|
||||||
self.resultMessage = village.resultMessage
|
request=request,
|
||||||
return
|
parentid=block_id,
|
||||||
#self.isSuccess = False
|
childname=village_name,
|
||||||
|
storedprocfetch="GetVillageByNameAndBlock",
|
||||||
|
storedprocadd="SaveVillage"
|
||||||
|
)
|
||||||
|
self._set_status(self.village)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
|
||||||
def GetAllVillages(self, request):
|
def GetAllVillages(self, request):
|
||||||
village = ItemCRUD(itemType=ItemCRUDType.Village)
|
|
||||||
villagesdata = village.GetAllData(request=request, storedproc="GetAllVillages")
|
|
||||||
self.isSuccess = village.isSuccess
|
|
||||||
self.resultMessage = village.resultMessage
|
|
||||||
return villagesdata
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
villagesdata = self.village.GetAllData(
|
||||||
|
request=request,
|
||||||
|
storedproc="GetAllVillages"
|
||||||
|
)
|
||||||
|
self._set_status(self.village)
|
||||||
|
return villagesdata
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
return []
|
||||||
|
|
||||||
def CheckVillage(self, request):
|
def CheckVillage(self, request):
|
||||||
village = ItemCRUD(itemType=ItemCRUDType.Village)
|
block_id, village_name = self._get_form_data(request)
|
||||||
block_id = request.form.get('block_Id')
|
|
||||||
village_name = request.form.get('Village_Name', '').strip()
|
if not village_name:
|
||||||
result = village.CheckItem(request=request, parentid=block_id, childname=village_name, storedprocfetch="GetVillageByNameAndBlocks")
|
self.response = ResponseHandler.invalid_name("village")
|
||||||
self.isSuccess = village.isSuccess
|
self.resultMessage = self.response["message"]
|
||||||
self.resultMessage = village.resultMessage
|
self.isSuccess = False
|
||||||
return result
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.village.CheckItem(
|
||||||
|
request=request,
|
||||||
|
parentid=block_id,
|
||||||
|
childname=village_name,
|
||||||
|
storedprocfetch="GetVillageByNameAndBlocks"
|
||||||
|
)
|
||||||
|
self._set_status(self.village)
|
||||||
|
return result
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def DeleteVillage(self, request, village_id):
|
def DeleteVillage(self, request, village_id):
|
||||||
|
|
||||||
village = ItemCRUD(itemType=ItemCRUDType.Village)
|
try:
|
||||||
|
self.village.DeleteItem(
|
||||||
|
request=request,
|
||||||
|
itemID=village_id,
|
||||||
|
storedprocDelete="DeleteVillage"
|
||||||
|
)
|
||||||
|
self._set_status(self.village)
|
||||||
|
|
||||||
village.DeleteItem(request=request, itemID=village_id, storedprocDelete="DeleteVillage" )
|
except Exception as e:
|
||||||
self.isSuccess = village.isSuccess
|
self.isSuccess = False
|
||||||
self.resultMessage = village.resultMessage
|
self.resultMessage = str(e)
|
||||||
return
|
|
||||||
|
|
||||||
def EditVillage(self, request, village_id):
|
def EditVillage(self, request, village_id):
|
||||||
corsor=None
|
block_id, village_name = self._get_form_data(request)
|
||||||
village = ItemCRUD(itemType=ItemCRUDType.Village)
|
|
||||||
|
|
||||||
block_id = request.form.get('block_Id')
|
if not village_name:
|
||||||
village_name = request.form.get('Village_Name', '').strip()
|
self.response = ResponseHandler.invalid_name("village")
|
||||||
|
self.resultMessage = self.response["message"]
|
||||||
village.EditItem(request=request,childid=village_id,parentid=block_id,childname=village_name,storedprocupdate="UpdateVillage" )
|
|
||||||
|
|
||||||
self.isSuccess = village.isSuccess
|
|
||||||
self.resultMessage = village.resultMessage
|
|
||||||
return
|
|
||||||
|
|
||||||
# def GetVillageByID(self, request, id):
|
|
||||||
|
|
||||||
# village = ItemCRUD(itemType=ItemCRUDType.Village)
|
|
||||||
# villagedetailsdata = village.GetAllData(request=request, storedproc="GetVillageDetailsById")
|
|
||||||
# self.isSuccess = village.isSuccess
|
|
||||||
# self.resultMessage = village.resultMessage
|
|
||||||
# return villagedetailsdata
|
|
||||||
|
|
||||||
def GetVillageByID(self, request, id):
|
|
||||||
village = ItemCRUD(itemType=ItemCRUDType.Village)
|
|
||||||
villagedetailsdata = village.GetDataByID(id=id,storedproc="GetVillageDetailsById")
|
|
||||||
if villagedetailsdata:
|
|
||||||
self.isSuccess = True
|
|
||||||
else:
|
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = "Village not found"
|
return
|
||||||
|
|
||||||
return villagedetailsdata
|
try:
|
||||||
|
self.village.EditItem(
|
||||||
|
request=request,
|
||||||
|
childid=village_id,
|
||||||
|
parentid=block_id,
|
||||||
|
childname=village_name,
|
||||||
|
storedprocupdate="UpdateVillage"
|
||||||
|
)
|
||||||
|
self._set_status(self.village)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
|
||||||
def GetAllBlocks(self, request):
|
def GetVillageByID(self, id):
|
||||||
|
|
||||||
|
try:
|
||||||
|
villagedetailsdata = self.village.GetDataByID(
|
||||||
|
id=id,
|
||||||
|
storedproc="GetVillageDetailsById"
|
||||||
|
)
|
||||||
|
|
||||||
|
if villagedetailsdata:
|
||||||
|
self.isSuccess = True
|
||||||
|
else:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = "Village not found"
|
||||||
|
|
||||||
|
return villagedetailsdata
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def GetAllBlocks(self):
|
||||||
blocks = []
|
blocks = []
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = ""
|
self.resultMessage = ""
|
||||||
connection = config.get_db_connection()
|
|
||||||
|
|
||||||
|
connection = config.get_db_connection()
|
||||||
if not connection:
|
if not connection:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.callproc('GetAllBlocks')
|
with connection.cursor() as cursor:
|
||||||
for result in cursor.stored_results():
|
cursor.callproc('GetAllBlocks')
|
||||||
blocks = result.fetchall()
|
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
blocks.extend(result.fetchall())
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
|
return blocks
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error fetching blocks: {e}")
|
print(f"Error fetching blocks: {e}")
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.fetch_failure("block"), 500)
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return blocks
|
# FIXED (removed jsonify response)
|
||||||
|
self.response = ResponseHandler.fetch_failure("block")
|
||||||
|
self.resultMessage = self.response["message"]
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
finally:
|
||||||
|
connection.close()
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,150 +1,160 @@
|
|||||||
import config
|
# model/gst_release.py
|
||||||
import mysql.connector
|
from flask import request, jsonify
|
||||||
|
from model.ItemCRUD import ItemCRUD
|
||||||
|
from model.Utilities import ItemCRUDType
|
||||||
|
|
||||||
class GSTReleasemodel:
|
class GSTRelease:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = ""
|
||||||
|
|
||||||
|
# ------------------- Add GST Release -------------------
|
||||||
|
def AddGSTRelease(self, request):
|
||||||
|
try:
|
||||||
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
|
||||||
|
# Print the full form data
|
||||||
|
print("===== DEBUG: FORM DATA =====")
|
||||||
|
for key, value in request.form.items():
|
||||||
|
print(f"{key} : {value}")
|
||||||
|
print("=============================")
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"PMC_No": request.form.get("PMC_No", "").strip(),
|
||||||
|
"Invoice_No": request.form.get("Invoice_No", "").strip(),
|
||||||
|
"Basic_Amount": float(request.form.get("Basic_Amount", 0) or 0),
|
||||||
|
"Final_Amount": float(request.form.get("Final_Amount", 0) or 0),
|
||||||
|
"Total_Amount": float(request.form.get("Total_Amount", 0) or 0),
|
||||||
|
"UTR": request.form.get("UTR", "").strip(),
|
||||||
|
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
print("===== DEBUG: PARSED DATA =====")
|
||||||
|
print(data)
|
||||||
|
print("==============================")
|
||||||
|
|
||||||
|
# Add GST Release
|
||||||
|
gst.AddItem(
|
||||||
|
request=request,
|
||||||
|
data=data,
|
||||||
|
storedprocfetch="CheckGSTReleaseExists",
|
||||||
|
storedprocadd="AddGSTReleaseFromExcel"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"AddItem result: isSuccess={gst.isSuccess}, message={gst.resultMessage}")
|
||||||
|
|
||||||
|
self.isSuccess = gst.isSuccess
|
||||||
|
self.resultMessage = str(gst.resultMessage)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("ERROR in AddGSTRelease:", e)
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
|
||||||
|
return jsonify({"success": self.isSuccess, "message": self.resultMessage})
|
||||||
|
|
||||||
|
def EditGSTRelease(self, request, gst_release_id):
|
||||||
|
try:
|
||||||
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
|
||||||
|
# Map form inputs to stored procedure parameters
|
||||||
|
data = {
|
||||||
|
"p_pmc_no": request.form.get("PMC_No", "").strip(),
|
||||||
|
"p_invoice_no": request.form.get("invoice_no", "").strip(),
|
||||||
|
"p_basic_amount": float(request.form.get("Basic_Amount", 0) or 0),
|
||||||
|
"p_final_amount": float(request.form.get("Final_Amount", 0) or 0),
|
||||||
|
"p_total_amount": float(request.form.get("Total_Amount", 0) or 0),
|
||||||
|
"p_utr": request.form.get("UTR", "").strip(),
|
||||||
|
"p_gst_release_id": gst_release_id
|
||||||
|
}
|
||||||
|
|
||||||
|
print("===== DEBUG: UPDATE DATA =====")
|
||||||
|
print(data)
|
||||||
|
print("==============================")
|
||||||
|
|
||||||
|
# Call your stored procedure
|
||||||
|
gst.EditItem(
|
||||||
|
request=request,
|
||||||
|
childid=gst_release_id,
|
||||||
|
data=data,
|
||||||
|
storedprocupdate="UpdateGSTRelease"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.isSuccess = gst.isSuccess
|
||||||
|
self.resultMessage = str(gst.resultMessage)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("ERROR in EditGSTRelease:", e)
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
|
||||||
|
# ------------------- Delete GST Release -------------------
|
||||||
|
def DeleteGSTRelease(self, gst_release_id):
|
||||||
|
try:
|
||||||
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
|
||||||
|
gst.DeleteItem(
|
||||||
|
request=None,
|
||||||
|
itemID=gst_release_id,
|
||||||
|
storedprocDelete="DeleteGSTReleaseById"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.isSuccess = gst.isSuccess
|
||||||
|
self.resultMessage = str(gst.resultMessage)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("ERROR in DeleteGSTRelease:", e)
|
||||||
|
self.isSuccess = False
|
||||||
|
self.resultMessage = str(e)
|
||||||
|
|
||||||
|
return jsonify({"success": self.isSuccess, "message": self.resultMessage})
|
||||||
|
|
||||||
|
# ------------------- Get All GST Releases -------------------
|
||||||
|
def GetAllGSTReleases(self):
|
||||||
|
try:
|
||||||
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
rows = gst.GetAllData(None, "GetAllGSTReleases")
|
||||||
|
|
||||||
|
data = []
|
||||||
|
for row in rows:
|
||||||
|
data.append({
|
||||||
|
"gst_release_id": row[0],
|
||||||
|
"pmc_no": row[1],
|
||||||
|
"invoice_no": row[2],
|
||||||
|
"basic_amount": row[3],
|
||||||
|
"final_amount": row[4],
|
||||||
|
"total_amount": row[5],
|
||||||
|
"utr": row[6],
|
||||||
|
"contractor_id": row[7]
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("ERROR in GetAllGSTReleases:", e)
|
||||||
|
return []
|
||||||
|
|
||||||
|
# ------------------- Get GST Release By ID -------------------
|
||||||
|
def GetGSTReleaseByID(self, gst_release_id):
|
||||||
|
try:
|
||||||
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
row = gst.GetDataByID(gst_release_id, "GetGSTReleaseById")
|
||||||
|
|
||||||
|
if row:
|
||||||
|
return {
|
||||||
|
"gst_release_id": row[0],
|
||||||
|
"pmc_no": row[1],
|
||||||
|
"invoice_no": row[2],
|
||||||
|
"basic_amount": row[3],
|
||||||
|
"final_amount": row[4],
|
||||||
|
"total_amount": row[5],
|
||||||
|
"utr": row[6],
|
||||||
|
"contractor_id": row[7]
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_connection():
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
if not connection:
|
|
||||||
return None
|
return None
|
||||||
return connection
|
|
||||||
|
|
||||||
@staticmethod
|
except Exception as e:
|
||||||
def fetch_all_gst_releases():
|
print("ERROR in GetGSTReleaseByID:", e)
|
||||||
connection = GSTReleasemodel.get_connection()
|
return None
|
||||||
gst_releases = []
|
|
||||||
if connection:
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor.callproc('GetAllGSTReleases')
|
|
||||||
|
|
||||||
gst_releases = []
|
|
||||||
for result in cursor.stored_results(): # change to procedure
|
|
||||||
gst_releases = result.fetchall()
|
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error fetching GST releases: {e}")
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return gst_releases
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def insert_gst_release(pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id):
|
|
||||||
connection = GSTReleasemodel.get_connection()
|
|
||||||
if not connection:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
# Insert into gst_release
|
|
||||||
cursor.callproc(
|
|
||||||
'InsertGSTReleaseOnly',
|
|
||||||
[pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Insert into inpayment
|
|
||||||
cursor.callproc(
|
|
||||||
'InsertInpaymentOnly',
|
|
||||||
[pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id]
|
|
||||||
)
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
return True
|
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error inserting GST release: {e}")
|
|
||||||
return False
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fetch_gst_release_by_id(gst_release_id):
|
|
||||||
connection = GSTReleasemodel.get_connection()
|
|
||||||
if not connection:
|
|
||||||
return None
|
|
||||||
data = {}
|
|
||||||
try:
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
cursor.callproc('GetGSTReleaseById', [gst_release_id])
|
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
data = result.fetchone()
|
|
||||||
if data:
|
|
||||||
# Convert to array for template
|
|
||||||
data = [
|
|
||||||
data.get('GST_Release_Id'),
|
|
||||||
data.get('PMC_No'),
|
|
||||||
data.get('Invoice_No'),
|
|
||||||
data.get('Basic_Amount'),
|
|
||||||
data.get('Final_Amount'),
|
|
||||||
data.get('Total_Amount'),
|
|
||||||
data.get('UTR')
|
|
||||||
]
|
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error fetching GST release by id: {e}")
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return data
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def update_gst_release(gst_release_id, pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr):
|
|
||||||
connection = GSTReleasemodel.get_connection()
|
|
||||||
if not connection:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
cursor = connection.cursor()
|
|
||||||
# Update gst_release
|
|
||||||
cursor.callproc(
|
|
||||||
'UpdateGSTRelease',
|
|
||||||
[pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, gst_release_id]
|
|
||||||
)
|
|
||||||
# Update inpayment
|
|
||||||
cursor.callproc(
|
|
||||||
'UpdateInpaymentByUTR',
|
|
||||||
[basic_amount, final_amount, total_amount, utr]
|
|
||||||
)
|
|
||||||
connection.commit()
|
|
||||||
return True
|
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error updating GST release: {e}")
|
|
||||||
return False
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def delete_gst_release(gst_release_id):
|
|
||||||
connection = GSTReleasemodel.get_connection()
|
|
||||||
if not connection:
|
|
||||||
return False, None
|
|
||||||
try:
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
cursor.callproc('GetGSTReleaseUTRById', [gst_release_id])
|
|
||||||
record = None
|
|
||||||
for result in cursor.stored_results():
|
|
||||||
record = result.fetchone()
|
|
||||||
|
|
||||||
if not record:
|
|
||||||
return False, None
|
|
||||||
|
|
||||||
utr = record['UTR']
|
|
||||||
|
|
||||||
# Step 1: Delete gst_release
|
|
||||||
cursor.callproc('DeleteGSTReleaseById', [gst_release_id])
|
|
||||||
|
|
||||||
# Step 2: Reset inpayment using UTR
|
|
||||||
cursor.callproc('ResetInpaymentByUTR', [utr])
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
return True, utr
|
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error deleting GST release: {e}")
|
|
||||||
return False, None
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
151
model/payment.py
151
model/payment.py
@@ -1,8 +1,12 @@
|
|||||||
import config
|
import config
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
|
import config
|
||||||
|
import mysql.connector
|
||||||
|
from model.Utilities import ItemCRUDType
|
||||||
|
|
||||||
class Paymentmodel:
|
class Paymentmodel:
|
||||||
|
|
||||||
|
# ---------------- Database Connection ----------------
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_connection():
|
def get_connection():
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
@@ -10,6 +14,7 @@ class Paymentmodel:
|
|||||||
return None
|
return None
|
||||||
return connection
|
return connection
|
||||||
|
|
||||||
|
# ---------------- Payment Methods ----------------
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fetch_all_payments():
|
def fetch_all_payments():
|
||||||
connection = Paymentmodel.get_connection()
|
connection = Paymentmodel.get_connection()
|
||||||
@@ -28,46 +33,44 @@ class Paymentmodel:
|
|||||||
return payments
|
return payments
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def insert_payment(pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
def insert_payment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
||||||
connection = Paymentmodel.get_connection()
|
connection = Paymentmodel.get_connection()
|
||||||
if not connection:
|
if not connection:
|
||||||
return False
|
return False
|
||||||
try:
|
|
||||||
cursor = connection.cursor()
|
|
||||||
cursor.callproc('InsertPayments', [pmc_no, invoice_no, amount, tds_amount, total_amount, utr])
|
|
||||||
connection.commit()
|
|
||||||
return True
|
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error inserting payment: {e}")
|
|
||||||
return False
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
@staticmethod
|
cursor = None
|
||||||
def update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
|
||||||
connection = Paymentmodel.get_connection()
|
|
||||||
if not connection:
|
|
||||||
return False
|
|
||||||
try:
|
try:
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.callproc('UpdateInpaymentRecord', [
|
|
||||||
subcontractor_id,
|
cursor.callproc('GetInvoiceId', [subcontractor_id, pmc_no, invoice_no])
|
||||||
pmc_no,
|
|
||||||
invoice_no,
|
invoice_id = None
|
||||||
amount,
|
for result in cursor.stored_results():
|
||||||
tds_amount,
|
row = result.fetchone()
|
||||||
total_amount,
|
if row:
|
||||||
utr
|
invoice_id = row[0]
|
||||||
])
|
|
||||||
|
if not invoice_id:
|
||||||
|
return False
|
||||||
|
|
||||||
|
cursor.callproc(
|
||||||
|
'InsertPayments',
|
||||||
|
[pmc_no, invoice_no, amount, tds_amount, total_amount, utr, invoice_id]
|
||||||
|
)
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
return True
|
return True
|
||||||
except mysql.connector.Error as e:
|
|
||||||
print(f"Error updating inpayment: {e}")
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
if cursor:
|
||||||
connection.close()
|
cursor.close()
|
||||||
|
if connection:
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fetch_payment_by_id(payment_id):
|
def fetch_payment_by_id(payment_id):
|
||||||
@@ -80,7 +83,6 @@ class Paymentmodel:
|
|||||||
cursor.callproc("GetPaymentById", (payment_id,))
|
cursor.callproc("GetPaymentById", (payment_id,))
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
payment_data = result.fetchone()
|
payment_data = result.fetchone()
|
||||||
# Convert to array for template
|
|
||||||
if payment_data:
|
if payment_data:
|
||||||
payment_data = [
|
payment_data = [
|
||||||
payment_data.get('Payment_Id'),
|
payment_data.get('Payment_Id'),
|
||||||
@@ -117,42 +119,97 @@ class Paymentmodel:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_payment(payment_id):
|
def delete_payment(payment_id):
|
||||||
"""
|
|
||||||
Deletes a payment and resets the related inpayment fields in one go.
|
|
||||||
Returns (success, pmc_no, invoice_no)
|
|
||||||
"""
|
|
||||||
connection = Paymentmodel.get_connection()
|
connection = Paymentmodel.get_connection()
|
||||||
if not connection:
|
if not connection:
|
||||||
return False, None, None
|
return False, None, None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor = connection.cursor(dictionary=True)
|
||||||
|
# Fetch PMC & Invoice before deleting
|
||||||
cursor.callproc('GetPaymentPMCInvoiceById', [payment_id])
|
cursor.callproc('GetPaymentPMCInvoiceById', [payment_id])
|
||||||
|
|
||||||
record = {}
|
record = {}
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
record = result.fetchone() or {}
|
record = result.fetchone() or {}
|
||||||
if not record:
|
if not record:
|
||||||
return False, None, None
|
return False, None, None
|
||||||
|
|
||||||
pmc_no = record['PMC_No']
|
pmc_no = record['PMC_No']
|
||||||
invoice_no = record['Invoice_No']
|
invoice_no = record['Invoice_No']
|
||||||
|
# Delete payment
|
||||||
# Step 2: Delete the payment using the stored procedure
|
|
||||||
cursor.callproc("DeletePayment", (payment_id,))
|
cursor.callproc("DeletePayment", (payment_id,))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
# Step 3: Reset inpayment fields using the stored procedure
|
|
||||||
cursor.callproc("ResetInpayment", [pmc_no, invoice_no])
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
return True, pmc_no, invoice_no
|
return True, pmc_no, invoice_no
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error deleting payment: {e}")
|
print(f"Error deleting payment: {e}")
|
||||||
return False, None, None
|
return False, None, None
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# ---------------- Item CRUD Methods ----------------
|
||||||
|
@staticmethod
|
||||||
|
def fetch_items(item_type: ItemCRUDType):
|
||||||
|
connection = Paymentmodel.get_connection()
|
||||||
|
items = []
|
||||||
|
if connection:
|
||||||
|
cursor = connection.cursor(dictionary=True)
|
||||||
|
try:
|
||||||
|
cursor.callproc('GetItemsByType', [item_type.value])
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
items = result.fetchall()
|
||||||
|
except mysql.connector.Error as e:
|
||||||
|
print(f"Error fetching {item_type.name}: {e}")
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
return items
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def insert_item(item_type: ItemCRUDType, name: str):
|
||||||
|
connection = Paymentmodel.get_connection()
|
||||||
|
if not connection:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.callproc('InsertItem', [item_type.value, name])
|
||||||
|
connection.commit()
|
||||||
|
return True
|
||||||
|
except mysql.connector.Error as e:
|
||||||
|
print(f"Error inserting {item_type.name}: {e}")
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_item(item_type: ItemCRUDType, item_id: int, new_name: str):
|
||||||
|
connection = Paymentmodel.get_connection()
|
||||||
|
if not connection:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.callproc('UpdateItem', [item_type.value, item_id, new_name])
|
||||||
|
connection.commit()
|
||||||
|
return True
|
||||||
|
except mysql.connector.Error as e:
|
||||||
|
print(f"Error updating {item_type.name}: {e}")
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete_item(item_type: ItemCRUDType, item_id: int):
|
||||||
|
connection = Paymentmodel.get_connection()
|
||||||
|
if not connection:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.callproc('DeleteItem', [item_type.value, item_id])
|
||||||
|
connection.commit()
|
||||||
|
return True
|
||||||
|
except mysql.connector.Error as e:
|
||||||
|
print(f"Error deleting {item_type.name}: {e}")
|
||||||
|
return False
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
30
services/Generalservice.py
Normal file
30
services/Generalservice.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class GeneralUse:
|
||||||
|
data=[]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def execute_sp(cursor, proc_name, params=[], fetch_one=False):
|
||||||
|
cursor.callproc(proc_name, params)
|
||||||
|
return (
|
||||||
|
GeneralUse.fetch_one_result(cursor)
|
||||||
|
if fetch_one else
|
||||||
|
GeneralUse.fetch_all_results(cursor)
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fetch_all_results(cursor):
|
||||||
|
data = []
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
data = result.fetchall()
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fetch_one_result(cursor):
|
||||||
|
data = None
|
||||||
|
for result in cursor.stored_results():
|
||||||
|
data = result.fetchone()
|
||||||
|
return data
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user