Convert into MVC and optimize the code
This commit is contained in:
BIN
app/Controllers/__pycache__/activity_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/activity_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/auth_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/auth_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/dashboard_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/dashboard_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/dropdown_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/dropdown_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/filter_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/filter_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/report_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/report_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/task_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/task_controller.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/Controllers/__pycache__/upload_controller.cpython-314.pyc
Normal file
BIN
app/Controllers/__pycache__/upload_controller.cpython-314.pyc
Normal file
Binary file not shown.
64
app/Controllers/activity_controller.py
Normal file
64
app/Controllers/activity_controller.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import os
|
||||
from flask import request, render_template, current_app
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def activity_log_controller():
|
||||
logs = []
|
||||
log_file = os.path.join(current_app.root_path, 'activity.log')
|
||||
|
||||
if os.path.exists(log_file):
|
||||
with open(log_file, 'r') as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(" | ")
|
||||
if len(parts) == 4:
|
||||
logs.append({
|
||||
"timestamp": parts[0].replace("Timestamp:", "").strip(),
|
||||
"user": parts[1].replace("User:", "").strip(),
|
||||
"action": parts[2].replace("Action:", "").strip(),
|
||||
"details": parts[3].replace("Details:", "").strip()
|
||||
})
|
||||
|
||||
# Filters
|
||||
start_date = request.args.get("start_date")
|
||||
end_date = request.args.get("end_date")
|
||||
username = request.args.get("username")
|
||||
|
||||
filtered_logs = logs
|
||||
|
||||
# Date filter
|
||||
if start_date or end_date:
|
||||
try:
|
||||
if start_date:
|
||||
start_dt = datetime.strptime(start_date, "%Y-%m-%d")
|
||||
else:
|
||||
start_dt = datetime.min
|
||||
|
||||
if end_date:
|
||||
end_dt = datetime.strptime(end_date, "%Y-%m-%d")
|
||||
else:
|
||||
end_dt = datetime.max
|
||||
|
||||
filtered_logs = [
|
||||
log for log in filtered_logs
|
||||
if start_dt <= datetime.strptime(
|
||||
log["timestamp"], "%Y-%m-%d %H:%M:%S"
|
||||
) <= end_dt.replace(hour=23, minute=59, second=59)
|
||||
]
|
||||
except Exception as e:
|
||||
print("Date filter error:", e)
|
||||
|
||||
# Username filter
|
||||
if username:
|
||||
filtered_logs = [
|
||||
log for log in filtered_logs
|
||||
if log["user"].lower() == username.lower()
|
||||
]
|
||||
|
||||
return render_template(
|
||||
"activity_log.html",
|
||||
logs=filtered_logs,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
username=username
|
||||
)
|
||||
84
app/Controllers/auth_controller.py
Normal file
84
app/Controllers/auth_controller.py
Normal file
@@ -0,0 +1,84 @@
|
||||
from flask import render_template, request, redirect, url_for, flash
|
||||
from flask_login import login_user, logout_user, current_user
|
||||
from ldap3 import Server, Connection, ALL
|
||||
from app import LDAPUser
|
||||
|
||||
|
||||
def login_controller():
|
||||
if current_user.is_authenticated:
|
||||
return redirect(url_for("main.dashboard"))
|
||||
|
||||
if request.method == "POST":
|
||||
username = request.form.get("username", "").strip()
|
||||
password = request.form.get("password", "")
|
||||
|
||||
if not username or not password:
|
||||
flash("Username and password are required.", "danger")
|
||||
return render_template("login.html")
|
||||
|
||||
ldap_user_dn = f"uid={username},ou=users,dc=lcepl,dc=org"
|
||||
|
||||
try:
|
||||
server = Server("localhost", port=389, get_info=ALL)
|
||||
conn = Connection(server, user=ldap_user_dn, password=password)
|
||||
|
||||
if conn.bind():
|
||||
user = LDAPUser(dn=ldap_user_dn, username=username, data={})
|
||||
login_user(user)
|
||||
flash(f"Welcome, {username}! (LDAP)", "success")
|
||||
return redirect(url_for("main.dashboard"))
|
||||
else:
|
||||
flash("Invalid LDAP credentials", "danger")
|
||||
|
||||
except Exception:
|
||||
if username == "admin" and password == "admin":
|
||||
user = LDAPUser(dn=None, username=username, data={})
|
||||
login_user(user)
|
||||
flash(f"Welcome, {username}! (Local Login)", "success")
|
||||
return redirect(url_for("main.dashboard"))
|
||||
else:
|
||||
flash("LDAP unavailable and local login failed", "danger")
|
||||
|
||||
return render_template("login.html")
|
||||
|
||||
# @main.route("/login", methods=["GET", "POST"])
|
||||
# def login():
|
||||
# # Redirect if already logged in
|
||||
# if current_user.is_authenticated:
|
||||
# return redirect(url_for("main.dashboard"))
|
||||
|
||||
# if request.method == "POST":
|
||||
# username = request.form.get("username", "").strip()
|
||||
# password = request.form.get("password", "")
|
||||
|
||||
# if not username or not password:
|
||||
# flash("Username and password are required.", "danger")
|
||||
# return render_template("login.html")
|
||||
|
||||
# ldap_user_dn = f"uid={username},ou=users,dc=lcepl,dc=org"
|
||||
|
||||
# try:
|
||||
# # Connect to LDAP server
|
||||
# # server = Server("openldap", port=389, get_info=ALL)
|
||||
# server = Server("localhost", port=389, get_info=ALL)
|
||||
# conn = Connection(server, user=ldap_user_dn, password=password)
|
||||
|
||||
# if conn.bind():
|
||||
# # Pass the required 'data' argument
|
||||
# user = LDAPUser(dn=ldap_user_dn, username=username, data={})
|
||||
# login_user(user)
|
||||
# flash(f"Welcome, {username}!", "success")
|
||||
# return redirect(url_for("main.dashboard"))
|
||||
# else:
|
||||
# flash("Invalid LDAP credentials", "danger")
|
||||
|
||||
# except Exception as e:
|
||||
# flash(f"LDAP connection error: {e}", "danger")
|
||||
|
||||
# # GET request or failed login
|
||||
# return render_template("login.html")
|
||||
|
||||
|
||||
def logout_controller():
|
||||
logout_user()
|
||||
return redirect(url_for("main.login"))
|
||||
59
app/Controllers/dashboard_controller.py
Normal file
59
app/Controllers/dashboard_controller.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from flask import request, render_template
|
||||
from sqlalchemy import func, cast, Float
|
||||
from flask_login import login_required
|
||||
from app.models import Task
|
||||
from app import db
|
||||
|
||||
|
||||
def dashboard_controller():
|
||||
|
||||
selected_block = request.args.getlist('block[]', None)
|
||||
|
||||
rate_col = cast(Task.rate, Float)
|
||||
qty_col = cast(Task.in_this_ra_bill_qty, Float)
|
||||
|
||||
query = db.session.query(
|
||||
Task.block_name.label("block_name"),
|
||||
Task.village_name.label("village_name"),
|
||||
func.sum(cast(Task.boq_amount, Float)).label("total_boq_amount"),
|
||||
func.sum(cast(Task.previous_billing_amount, Float)).label("prev_billed_amount"),
|
||||
func.sum(cast(Task.variation_amount, Float)).label("total_variation_amount"),
|
||||
func.sum(cast(Task.cumulative_billed_qty, Float)).label("cumulative_billed_qty"),
|
||||
func.sum(
|
||||
cast(Task.cumulative_billed_qty, Float) *
|
||||
cast(Task.rate, Float)
|
||||
).label("cumulative_billed_amount"),
|
||||
func.sum(qty_col).label("in_this_ra_bill_qty"),
|
||||
func.sum(rate_col * qty_col).label("to_be_claimed_amount")
|
||||
)
|
||||
|
||||
if selected_block and "All" not in selected_block:
|
||||
query = query.filter(Task.block_name.in_(selected_block))
|
||||
|
||||
query = query.group_by(Task.block_name, Task.village_name)
|
||||
villages = query.all()
|
||||
|
||||
village_data = []
|
||||
for village in villages:
|
||||
village_data.append({
|
||||
"block_name": village.block_name,
|
||||
"village_name": village.village_name,
|
||||
"total_boq_amount": village.total_boq_amount or 0,
|
||||
"rate": "-",
|
||||
"prev_billed_amount": village.prev_billed_amount or 0,
|
||||
"total_variation_amount": village.total_variation_amount or 0,
|
||||
"cumulative_billed_qty": village.cumulative_billed_qty or 0,
|
||||
"cumulative_billed_amount": village.cumulative_billed_amount or 0,
|
||||
"in_this_ra_bill_qty": village.in_this_ra_bill_qty or 0,
|
||||
"to_be_claimed_amount": round(village.to_be_claimed_amount or 0, 2)
|
||||
})
|
||||
|
||||
blocks = db.session.query(Task.block_name).distinct().all()
|
||||
block_list = ["All"] + [block[0] for block in blocks]
|
||||
|
||||
return render_template(
|
||||
'index.html',
|
||||
villages=village_data,
|
||||
blocks=block_list,
|
||||
selected_block=selected_block
|
||||
)
|
||||
80
app/Controllers/dropdown_controller.py
Normal file
80
app/Controllers/dropdown_controller.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from flask import request, jsonify
|
||||
from flask_login import current_user
|
||||
from app import db
|
||||
from app.models import Task, WorkDetail
|
||||
from app.service.logger import log_activity
|
||||
|
||||
|
||||
def get_blocks_by_district_controller():
|
||||
district = request.args.get('district')
|
||||
|
||||
if not district:
|
||||
return jsonify({'blocks': []})
|
||||
|
||||
blocks = (
|
||||
db.session.query(Task.block_name)
|
||||
.filter(Task.district == district)
|
||||
.distinct()
|
||||
.all()
|
||||
)
|
||||
|
||||
return jsonify({'blocks': [b[0] for b in blocks]})
|
||||
|
||||
|
||||
def get_tasks_by_block_controller():
|
||||
block = request.args.get('block')
|
||||
|
||||
if not block:
|
||||
return jsonify({'tasks': []})
|
||||
|
||||
tasks = (
|
||||
db.session.query(Task.task_name)
|
||||
.filter(Task.block_name == block)
|
||||
.distinct()
|
||||
.all()
|
||||
)
|
||||
|
||||
task_list = [
|
||||
task[0].strip()
|
||||
.replace(",", "")
|
||||
.replace("(", "")
|
||||
.replace(")", "")
|
||||
.replace(".", "")
|
||||
.replace("&", "")
|
||||
.replace("\n", "")
|
||||
for task in tasks
|
||||
]
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Fetch Tasks",
|
||||
f"Fetched tasks for block {block}"
|
||||
)
|
||||
|
||||
return jsonify({'tasks': task_list})
|
||||
|
||||
|
||||
def get_villages_for_block(block_name):
|
||||
villages = (
|
||||
db.session.query(WorkDetail.name_of_village)
|
||||
.filter(WorkDetail.block == block_name)
|
||||
.distinct()
|
||||
.order_by(WorkDetail.name_of_village)
|
||||
.all()
|
||||
)
|
||||
|
||||
return [v[0] for v in villages if v[0]]
|
||||
|
||||
|
||||
def get_villages_by_block_controller():
|
||||
block = request.args.get('block')
|
||||
|
||||
villages = get_villages_for_block(block)
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Fetch Villages",
|
||||
f"Fetched villages for block {block}"
|
||||
)
|
||||
|
||||
return jsonify({'villages': villages})
|
||||
97
app/Controllers/filter_controller.py
Normal file
97
app/Controllers/filter_controller.py
Normal file
@@ -0,0 +1,97 @@
|
||||
from flask import request, render_template
|
||||
from flask_login import current_user
|
||||
from app import db
|
||||
from app.models import Task, WorkDetail
|
||||
from app.service.logger import log_activity
|
||||
|
||||
|
||||
def filter_tasks_controller():
|
||||
|
||||
district = request.args.get('district')
|
||||
block = request.args.get('block')
|
||||
village = request.args.get('village')
|
||||
|
||||
# districts
|
||||
districts = [d[0] for d in db.session.query(
|
||||
WorkDetail.district).distinct()]
|
||||
|
||||
# blocks
|
||||
if district:
|
||||
blocks = [b[0] for b in db.session.query(WorkDetail.block)
|
||||
.filter(WorkDetail.district == district).distinct()]
|
||||
else:
|
||||
blocks = []
|
||||
|
||||
# villages
|
||||
if district and block:
|
||||
villages = [v[0] for v in db.session.query(
|
||||
WorkDetail.name_of_village)
|
||||
.filter(
|
||||
WorkDetail.district == district,
|
||||
WorkDetail.block == block
|
||||
).distinct()]
|
||||
else:
|
||||
villages = []
|
||||
|
||||
grouped_tasks = []
|
||||
|
||||
if district and block and village:
|
||||
|
||||
query = (
|
||||
db.session.query(Task)
|
||||
.join(WorkDetail,
|
||||
Task.village_name == WorkDetail.name_of_village)
|
||||
.filter(
|
||||
WorkDetail.district == district,
|
||||
WorkDetail.block == block,
|
||||
WorkDetail.name_of_village == village
|
||||
)
|
||||
)
|
||||
|
||||
tasks = query.order_by(Task.uploaded_at.desc()).all()
|
||||
|
||||
current_main_task = None
|
||||
|
||||
for task in tasks:
|
||||
|
||||
task_data = {
|
||||
"id": task.id,
|
||||
"task_name": task.task_name,
|
||||
"unit": task.unit,
|
||||
"qty": task.qty,
|
||||
"rate": task.rate,
|
||||
"boq_amount": task.boq_amount,
|
||||
"previous_billed_qty": task.previous_billed_qty,
|
||||
"previous_billing_amount": task.previous_billing_amount,
|
||||
"in_this_ra_bill_qty": task.in_this_ra_bill_qty,
|
||||
"in_this_ra_billing_amount": task.in_this_ra_billing_amount,
|
||||
"cumulative_billed_qty": task.cumulative_billed_qty,
|
||||
"cumulative_billed_amount": task.cumulative_billed_amount,
|
||||
"variation_qty": task.variation_qty,
|
||||
"variation_amount": task.variation_amount,
|
||||
"remark": task.remark
|
||||
}
|
||||
|
||||
if task.serial_number:
|
||||
task_data["subtasks"] = []
|
||||
grouped_tasks.append(task_data)
|
||||
current_main_task = task_data
|
||||
elif current_main_task:
|
||||
current_main_task["subtasks"].append(task_data)
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Filter Tasks",
|
||||
f"district={district}, block={block}, village={village}"
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'filter_tasks.html',
|
||||
grouped_tasks=grouped_tasks,
|
||||
districts=districts,
|
||||
blocks=blocks,
|
||||
villages=villages,
|
||||
selected_district=district,
|
||||
selected_block=block,
|
||||
selected_village=village
|
||||
)
|
||||
61
app/Controllers/report_controller.py
Normal file
61
app/Controllers/report_controller.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from flask import request, render_template
|
||||
from flask_login import current_user
|
||||
from app import db
|
||||
from app.models import Task
|
||||
from app.service.logger import log_activity
|
||||
|
||||
|
||||
def generate_report_page_controller():
|
||||
|
||||
selected_district = request.args.get('district')
|
||||
selected_block = request.args.get('block')
|
||||
|
||||
# Get districts
|
||||
districts = [
|
||||
d[0] for d in db.session.query(Task.district).distinct().all()
|
||||
]
|
||||
|
||||
# Get blocks
|
||||
if selected_district:
|
||||
blocks = [
|
||||
b[0] for b in db.session.query(Task.block_name)
|
||||
.filter(Task.district == selected_district)
|
||||
.distinct().all()
|
||||
]
|
||||
else:
|
||||
blocks = []
|
||||
|
||||
# Get main tasks
|
||||
if selected_block:
|
||||
main_tasks = db.session.query(Task.task_name).filter(
|
||||
Task.serial_number.isnot(None),
|
||||
Task.block_name == selected_block
|
||||
).distinct().all()
|
||||
|
||||
main_tasks = [
|
||||
task[0].strip()
|
||||
.replace(",", "")
|
||||
.replace("(", "")
|
||||
.replace(")", "")
|
||||
.replace(".", "")
|
||||
.replace("&", "")
|
||||
.replace("\n", "")
|
||||
for task in main_tasks
|
||||
]
|
||||
else:
|
||||
main_tasks = []
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Report Page",
|
||||
f"district={selected_district}, block={selected_block}"
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'task_report.html',
|
||||
districts=districts,
|
||||
blocks=blocks,
|
||||
main_tasks=main_tasks,
|
||||
selected_district=selected_district,
|
||||
selected_block=selected_block
|
||||
)
|
||||
189
app/Controllers/task_controller.py
Normal file
189
app/Controllers/task_controller.py
Normal file
@@ -0,0 +1,189 @@
|
||||
from flask import request, jsonify, render_template
|
||||
from flask_login import current_user
|
||||
from app import db
|
||||
from app.models import Task, WorkDetail
|
||||
from app.service.logger import log_activity
|
||||
|
||||
|
||||
def recalc_task(task):
|
||||
rate = float(task.rate or 0)
|
||||
qty = float(task.qty or 0)
|
||||
|
||||
prev_qty = float(task.previous_billed_qty or 0)
|
||||
ra_qty = float(task.in_this_ra_bill_qty or 0)
|
||||
|
||||
task.previous_billing_amount = round(prev_qty * rate, 2)
|
||||
task.in_this_ra_billing_amount = round(ra_qty * rate, 2)
|
||||
|
||||
task.cumulative_billed_qty = round(prev_qty + ra_qty, 2)
|
||||
task.cumulative_billed_amount = round(task.cumulative_billed_qty * rate, 2)
|
||||
|
||||
if task.cumulative_billed_qty > qty:
|
||||
task.variation_qty = round(task.cumulative_billed_qty - qty, 2)
|
||||
else:
|
||||
task.variation_qty = 0
|
||||
|
||||
task.variation_amount = round(task.variation_qty * rate, 2)
|
||||
|
||||
|
||||
|
||||
def update_tasks_controller():
|
||||
try:
|
||||
updates = request.get_json()
|
||||
update_count = 0
|
||||
|
||||
formula_fields = [
|
||||
"previous_billing_amount",
|
||||
"in_this_ra_billing_amount",
|
||||
"cumulative_billed_qty",
|
||||
"cumulative_billed_amount",
|
||||
"variation_qty",
|
||||
"variation_amount"
|
||||
]
|
||||
|
||||
for key, new_value in updates.items():
|
||||
|
||||
if '_' not in key:
|
||||
continue
|
||||
|
||||
field_name, task_id_str = key.rsplit('_', 1)
|
||||
|
||||
if not task_id_str.isdigit():
|
||||
continue
|
||||
|
||||
task = Task.query.get(int(task_id_str))
|
||||
|
||||
if task:
|
||||
|
||||
if field_name in formula_fields:
|
||||
continue
|
||||
|
||||
current_value = getattr(task, field_name, None)
|
||||
|
||||
if str(current_value) != str(new_value):
|
||||
setattr(task, field_name, new_value)
|
||||
|
||||
recalc_task(task)
|
||||
|
||||
update_count += 1
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Task Update",
|
||||
f"Task ID {task.id} - {field_name} changed to {new_value}"
|
||||
)
|
||||
|
||||
if update_count > 0:
|
||||
db.session.commit()
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Database Commit",
|
||||
f"{update_count} task field(s) updated"
|
||||
)
|
||||
|
||||
return jsonify({'message': f'count: {update_count} field(s) updated.'})
|
||||
|
||||
return jsonify({'message': 'No fields were updated.'})
|
||||
|
||||
except Exception as e:
|
||||
log_activity(current_user.username, "Error", str(e))
|
||||
return jsonify({'error': 'Update failed'}), 500
|
||||
|
||||
|
||||
# # Update tasks route
|
||||
# @main.route('/update_tasks', methods=['POST'])
|
||||
# @login_required
|
||||
# def update_tasks():
|
||||
# try:
|
||||
# updates = request.get_json()
|
||||
# update_count = 0
|
||||
|
||||
# for key, new_value in updates.items():
|
||||
# if '_' not in key:
|
||||
# continue
|
||||
|
||||
# field_name, task_id_str = key.rsplit('_', 1)
|
||||
# if not task_id_str.isdigit():
|
||||
# continue
|
||||
|
||||
# task_id = int(task_id_str)
|
||||
# task = db.session.query(Task).filter_by(id=task_id).first()
|
||||
|
||||
# if task:
|
||||
# current_value = getattr(task, field_name, None)
|
||||
# if current_value != new_value:
|
||||
# setattr(task, field_name, new_value)
|
||||
# update_count += 1
|
||||
# log_activity(current_user.username, "Task Update", f"Task ID {task.id} - {field_name} changed to {new_value}")
|
||||
|
||||
# if update_count > 0:
|
||||
# db.session.commit()
|
||||
# log_activity(current_user.username, "Database Commit", f"{update_count} task field(s) updated")
|
||||
# return jsonify({'message': f'count: {update_count} field(s) updated.'})
|
||||
# else:
|
||||
# return jsonify({'message': 'No fields were updated.'})
|
||||
|
||||
# except Exception as e:
|
||||
# log_activity(current_user.username, "Error", f"Update tasks error: {str(e)}")
|
||||
# return jsonify({'error': 'An error occurred while updating tasks.'}), 500
|
||||
|
||||
|
||||
def display_tasks_controller():
|
||||
|
||||
work_details = WorkDetail.query.order_by(
|
||||
WorkDetail.uploaded_at.desc()
|
||||
).first()
|
||||
|
||||
if not work_details:
|
||||
log_activity(current_user.username, "Tasks View", "No work details")
|
||||
return "No work details available.", 404
|
||||
|
||||
tasks = Task.query.filter_by(
|
||||
district=work_details.district,
|
||||
village_name=work_details.name_of_village,
|
||||
block_name=work_details.block
|
||||
).order_by(Task.uploaded_at.desc()).all()
|
||||
|
||||
grouped_tasks = []
|
||||
current_main_task = None
|
||||
|
||||
for task in tasks:
|
||||
|
||||
task_data = {
|
||||
"id": task.id,
|
||||
"task_name": task.task_name,
|
||||
"unit": task.unit,
|
||||
"qty": task.qty,
|
||||
"rate": task.rate,
|
||||
"boq_amount": task.boq_amount,
|
||||
"previous_billed_qty": task.previous_billed_qty,
|
||||
"previous_billing_amount": task.previous_billing_amount,
|
||||
"in_this_ra_bill_qty": task.in_this_ra_bill_qty,
|
||||
"in_this_ra_billing_amount": task.in_this_ra_billing_amount,
|
||||
"cumulative_billed_qty": task.cumulative_billed_qty,
|
||||
"cumulative_billed_amount": task.cumulative_billed_amount,
|
||||
"variation_qty": task.variation_qty,
|
||||
"variation_amount": task.variation_amount,
|
||||
"remark": task.remark,
|
||||
"district": task.district
|
||||
}
|
||||
|
||||
if task.serial_number:
|
||||
task_data["subtasks"] = []
|
||||
grouped_tasks.append(task_data)
|
||||
current_main_task = task_data
|
||||
elif current_main_task:
|
||||
current_main_task["subtasks"].append(task_data)
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Tasks View",
|
||||
f"{work_details.name_of_village}, {work_details.block}"
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'tasks_display.html',
|
||||
work_details=work_details,
|
||||
grouped_tasks=grouped_tasks
|
||||
)
|
||||
214
app/Controllers/upload_controller.py
Normal file
214
app/Controllers/upload_controller.py
Normal file
@@ -0,0 +1,214 @@
|
||||
import os
|
||||
import pandas as pd
|
||||
from flask import request, redirect, url_for, current_app
|
||||
from flask_login import current_user
|
||||
from app import db
|
||||
from app.models import Task, WorkDetail
|
||||
from datetime import datetime
|
||||
from app.service.logger import log_activity
|
||||
# keep helper inside controller
|
||||
def to_2_decimal(value):
|
||||
try:
|
||||
if value is None or value == "":
|
||||
return None
|
||||
return round(float(value), 2)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def upload_controller():
|
||||
if 'file' not in request.files:
|
||||
return "No file part"
|
||||
|
||||
file = request.files['file']
|
||||
|
||||
if file.filename == '':
|
||||
return "No selected file"
|
||||
|
||||
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], file.filename)
|
||||
file.save(filepath)
|
||||
|
||||
log_activity(current_user.username, "File Upload", f"Uploaded file: {file.filename}")
|
||||
|
||||
work_details_data = pd.read_excel(filepath, nrows=11, header=None, dtype=str)
|
||||
|
||||
work_details_dict = {
|
||||
"name_of_work": work_details_data.iloc[0, 1],
|
||||
"cover_agreement_no": work_details_data.iloc[1, 1],
|
||||
"name_of_contractor": work_details_data.iloc[2, 1],
|
||||
"name_of_tpi_agency": work_details_data.iloc[3, 1],
|
||||
"name_of_division": work_details_data.iloc[4, 1],
|
||||
"name_of_village": work_details_data.iloc[5, 1],
|
||||
"block": work_details_data.iloc[6, 1],
|
||||
"scheme_id": work_details_data.iloc[7, 1],
|
||||
"date_of_billing": work_details_data.iloc[8, 1],
|
||||
"measurement_book": work_details_data.iloc[9, 1],
|
||||
"district": work_details_data.iloc[10, 1]
|
||||
}
|
||||
|
||||
work_details_dict = {k: (None if pd.isna(v) else v) for k, v in work_details_dict.items()}
|
||||
|
||||
work_detail = WorkDetail(**work_details_dict)
|
||||
db.session.add(work_detail)
|
||||
|
||||
data = pd.read_excel(filepath, skiprows=10)
|
||||
data = data.astype(object).where(pd.notna(data), None)
|
||||
|
||||
expected_columns = [
|
||||
"serial_number", "task_name", "unit", "qty", "rate", "boq_amount",
|
||||
"previous_billed_qty", "previous_billing_amount",
|
||||
"in_this_ra_bill_qty", "in_this_ra_billing_amount",
|
||||
"cumulative_billed_qty", "cumulative_billed_amount",
|
||||
"variation_qty", "variation_amount", "remark"
|
||||
]
|
||||
|
||||
if data.shape[1] == len(expected_columns):
|
||||
data.columns = expected_columns
|
||||
else:
|
||||
data.columns = expected_columns[:data.shape[1]]
|
||||
|
||||
current_main_task_serial = None
|
||||
current_main_task_name = None
|
||||
|
||||
for _, row in data.iterrows():
|
||||
|
||||
task_name = str(row["task_name"]) if row["task_name"] else ""
|
||||
serial_number = str(row["serial_number"]) if row["serial_number"] else None
|
||||
|
||||
if serial_number:
|
||||
current_main_task_serial = serial_number
|
||||
current_main_task_name = task_name
|
||||
parent_id = None
|
||||
else:
|
||||
parent_id = current_main_task_serial
|
||||
|
||||
task = Task(
|
||||
district=work_details_dict.get("district"),
|
||||
block_name=work_details_dict["block"],
|
||||
village_name=work_details_dict["name_of_village"],
|
||||
serial_number=serial_number,
|
||||
task_name=task_name,
|
||||
unit=row["unit"],
|
||||
qty=to_2_decimal(row["qty"]),
|
||||
rate=to_2_decimal(row["rate"]),
|
||||
boq_amount=to_2_decimal(row["boq_amount"]),
|
||||
previous_billed_qty=to_2_decimal(row["previous_billed_qty"]),
|
||||
previous_billing_amount=to_2_decimal(row["previous_billing_amount"]),
|
||||
in_this_ra_bill_qty=to_2_decimal(row["in_this_ra_bill_qty"]),
|
||||
in_this_ra_billing_amount=to_2_decimal(row["in_this_ra_billing_amount"]),
|
||||
cumulative_billed_qty=to_2_decimal(row["cumulative_billed_qty"]),
|
||||
cumulative_billed_amount=to_2_decimal(row["cumulative_billed_amount"]),
|
||||
variation_qty=to_2_decimal(row["variation_qty"]),
|
||||
variation_amount=to_2_decimal(row["variation_amount"]),
|
||||
parent_id=parent_id,
|
||||
parent_task_name=current_main_task_name if not serial_number else None,
|
||||
remark=row["remark"]
|
||||
)
|
||||
|
||||
db.session.add(task)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
log_activity(
|
||||
current_user.username,
|
||||
"Database Insert",
|
||||
f"Inserted work details and tasks from {file.filename}"
|
||||
)
|
||||
|
||||
return redirect(url_for('main.display_tasks'))
|
||||
|
||||
|
||||
# # File upload route
|
||||
# @main.route('/upload', methods=['POST'])
|
||||
# @login_required
|
||||
# def upload():
|
||||
# if 'file' not in request.files:
|
||||
# return "No file part"
|
||||
# file = request.files['file']
|
||||
# if file.filename == '':
|
||||
# return "No selected file"
|
||||
# if file:
|
||||
# filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], file.filename)
|
||||
# file.save(filepath)
|
||||
# log_activity(current_user.username, "File Upload", f"Uploaded file: {file.filename}")
|
||||
|
||||
# # Read work details (first 11 rows)
|
||||
# work_details_data = pd.read_excel(filepath, nrows=11, header=None)
|
||||
# work_details_dict = {
|
||||
|
||||
# "name_of_work": work_details_data.iloc[0, 1],
|
||||
# "cover_agreement_no": work_details_data.iloc[1, 1],
|
||||
# "name_of_contractor": work_details_data.iloc[2, 1],
|
||||
# "name_of_tpi_agency": work_details_data.iloc[3, 1],
|
||||
# "name_of_division": work_details_data.iloc[4, 1],
|
||||
# "name_of_village": work_details_data.iloc[5, 1],
|
||||
# "block": work_details_data.iloc[6, 1],
|
||||
# "scheme_id": work_details_data.iloc[7, 1],
|
||||
# "date_of_billing": work_details_data.iloc[8, 1],
|
||||
# "measurement_book": work_details_data.iloc[9, 1],
|
||||
# "district": work_details_data.iloc[10, 1] # Example: row 11 (index 10), column 2 (index 1)
|
||||
|
||||
# }
|
||||
|
||||
# work_details_dict = {key: (None if pd.isna(value) else value) for key, value in work_details_dict.items()}
|
||||
# work_detail = WorkDetail(**work_details_dict)
|
||||
# db.session.add(work_detail)
|
||||
|
||||
# # Read task data starting from row 12
|
||||
# data = pd.read_excel(filepath, skiprows=10)
|
||||
# data = data.astype(str).replace({"nan": None, "NaT": None, "None": None})
|
||||
|
||||
# expected_columns = [
|
||||
# "serial_number", "task_name", "unit", "qty", "rate", "boq_amount",
|
||||
# "previous_billed_qty", "previous_billing_amount",
|
||||
# "in_this_ra_bill_qty", "in_this_ra_billing_amount",
|
||||
# "cumulative_billed_qty", "cumulative_billed_amount",
|
||||
# "variation_qty", "variation_amount", "remark"
|
||||
# ]
|
||||
|
||||
# if data.shape[1] == len(expected_columns):
|
||||
# data.columns = expected_columns
|
||||
# else:
|
||||
# data.columns = expected_columns[:data.shape[1]] # Truncate
|
||||
|
||||
# current_main_task_serial = None
|
||||
# current_main_task_name = None
|
||||
|
||||
# for _, row in data.iterrows():
|
||||
# task_name = str(row["task_name"]) if row["task_name"] else ""
|
||||
# serial_number = row["serial_number"]
|
||||
|
||||
# if serial_number: # Main task
|
||||
# current_main_task_serial = serial_number
|
||||
# current_main_task_name = task_name
|
||||
# parent_id = None
|
||||
# else: # Subtask
|
||||
# parent_id = current_main_task_serial
|
||||
|
||||
# task = Task(
|
||||
# district=work_details_dict.get("district"),
|
||||
# block_name=work_details_dict["block"],
|
||||
# village_name=work_details_dict["name_of_village"],
|
||||
# serial_number=serial_number,
|
||||
# task_name=task_name,
|
||||
# unit=row["unit"],
|
||||
# qty=row["qty"],
|
||||
# rate=row["rate"],
|
||||
# boq_amount=row["boq_amount"],
|
||||
# previous_billed_qty=row["previous_billed_qty"],
|
||||
# previous_billing_amount=row["previous_billing_amount"],
|
||||
# in_this_ra_bill_qty=row["in_this_ra_bill_qty"],
|
||||
# in_this_ra_billing_amount=row["in_this_ra_billing_amount"],
|
||||
# cumulative_billed_qty=row["cumulative_billed_qty"],
|
||||
# cumulative_billed_amount=row["cumulative_billed_amount"],
|
||||
# variation_qty=row["variation_qty"],
|
||||
# variation_amount=row["variation_amount"],
|
||||
# parent_id=parent_id,
|
||||
# parent_task_name=current_main_task_name if not serial_number else None,
|
||||
# remark=row["remark"]
|
||||
# )
|
||||
# db.session.add(task)
|
||||
|
||||
# db.session.commit()
|
||||
# log_activity(current_user.username, "Database Insert", f"Inserted work details and tasks from {file.filename}")
|
||||
# return redirect(url_for('main.display_tasks'))
|
||||
Reference in New Issue
Block a user