fix: resolve migration multiple heads and flake8 F821/F823

- Add merge migration 116_merge_three_heads to join heads
  090_add_push_subscriptions, 100_gantt_colors_modules, and
  115_add_exclude_weekends so 'flask db upgrade' runs cleanly.

- Fix undefined-name and scope issues for CI code-quality:
  - api_v1: import InvalidOperation in amount_paid Decimal block
  - custom_reports, invoice_approvals, reports, scheduled_reports,
    tasks: add current_app to Flask imports
  - integrations: set user_integration before POST branches so
    update_config path can use it
  - invoices: use _ign for unpacking in export_invoice_ubl to avoid
    shadowing gettext _ (F823)
  - data_import, excel_export: add module logger (logging.getLogger)
This commit is contained in:
Dries Peeters
2026-01-25 08:59:47 +01:00
parent 8d3469d741
commit 5d4099422c
11 changed files with 45 additions and 8 deletions
+1 -1
View File
@@ -1536,7 +1536,7 @@ def update_invoice(invoice_id):
current_app.logger.warning(f"Invalid tax_rate value in invoice update: {data.get('tax_rate')} - {e}")
if "amount_paid" in data:
try:
from decimal import Decimal
from decimal import Decimal, InvalidOperation
update_kwargs["amount_paid"] = Decimal(str(data["amount_paid"]))
except (ValueError, TypeError, InvalidOperation) as e:
+1 -1
View File
@@ -2,7 +2,7 @@
Routes for custom report builder.
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_babel import gettext as _
from flask_login import login_required, current_user
from app import db
+2
View File
@@ -317,6 +317,8 @@ def manage_integration(provider):
# Per-user integration
integration = Integration.query.filter_by(provider=provider, user_id=current_user.id, is_global=False).first()
user_integration = None if is_global else integration
# Handle POST (OAuth credential updates - admin only for global integrations)
if request.method == "POST":
if is_global and not current_user.is_admin:
+1 -1
View File
@@ -2,7 +2,7 @@
Routes for invoice approval workflow.
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_babel import gettext as _
from flask_login import login_required, current_user
from app.models import Invoice, InvoiceApproval, User
+2 -2
View File
@@ -1073,8 +1073,8 @@ def export_invoice_ubl(invoice_id):
svc = PeppolService()
sender = svc._get_sender_party()
recipient_party, _, _ = svc._get_recipient_party(invoice)
ubl_xml, _ = build_peppol_ubl_invoice_xml(invoice=invoice, supplier=sender, customer=recipient_party)
recipient_party, _ign, _ign = svc._get_recipient_party(invoice)
ubl_xml, _ign = build_peppol_ubl_invoice_xml(invoice=invoice, supplier=sender, customer=recipient_party)
fn = f"invoice_{invoice.invoice_number}.xml"
return Response(ubl_xml, mimetype="application/xml", headers={"Content-Disposition": f"attachment; filename={fn}"})
except ValueError as e:
+1 -1
View File
@@ -1,4 +1,4 @@
from flask import Blueprint, render_template, request, redirect, url_for, flash, send_file, jsonify
from flask import Blueprint, render_template, request, redirect, url_for, flash, send_file, jsonify, current_app
from flask_login import login_required, current_user
from flask_babel import _
from app import db, log_event, track_event
+1 -1
View File
@@ -2,7 +2,7 @@
Routes for scheduled reports management.
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_babel import gettext as _
from flask_login import login_required, current_user
from app.models import SavedReportView, ReportEmailSchedule
+1 -1
View File
@@ -1,6 +1,6 @@
import re
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, make_response, Response
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, make_response, Response, current_app
from flask_babel import gettext as _
from flask_login import login_required, current_user
import app as app_module
+3
View File
@@ -4,6 +4,7 @@ Data import utilities for importing time tracking data from various sources
import json
import csv
import logging
import requests
from datetime import datetime, timedelta
from io import StringIO
@@ -12,6 +13,8 @@ from app import db
from app.models import User, Project, TimeEntry, Task, Client, Expense, ExpenseCategory, Contact
from app.utils.db import safe_commit
logger = logging.getLogger(__name__)
class ImportError(Exception):
"""Custom exception for import errors"""
+3
View File
@@ -1,12 +1,15 @@
"""Excel export utilities for reports and data export"""
import io
import logging
from datetime import datetime
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
from app.utils.timezone import convert_app_datetime_to_user
logger = logging.getLogger(__name__)
def create_time_entries_excel(entries, filename_prefix="timetracker_export"):
"""Create Excel file from time entries
@@ -0,0 +1,29 @@
"""Merge three migration heads into one
Revision ID: 116_merge_three_heads
Revises: 090_add_push_subscriptions, 100_gantt_colors_modules, 115_add_exclude_weekends
Create Date: 2026-01-25
Merge revision to resolve multiple heads:
- 090_add_push_subscriptions
- 100_gantt_colors_modules
- 115_add_exclude_weekends
"""
from alembic import op
# revision identifiers, used by Alembic.
revision = '116_merge_three_heads'
down_revision = ('090_add_push_subscriptions', '100_gantt_colors_modules', '115_add_exclude_weekends')
branch_labels = None
depends_on = None
def upgrade():
"""No schema changes - merge only."""
pass
def downgrade():
"""No schema changes - merge only."""
pass