|
|
|
@ -23,6 +23,27 @@ from app.services import ( |
|
|
|
quick_entry_bp = Blueprint("quick_entry", __name__, url_prefix="/quick-entry") |
|
|
|
|
|
|
|
|
|
|
|
def _include_bride_side_param(source: object) -> bool: |
|
|
|
if not hasattr(source, "get"): |
|
|
|
return False |
|
|
|
|
|
|
|
value = getattr(source, "get")("include_bride_side", "") |
|
|
|
if not isinstance(value, str): |
|
|
|
return False |
|
|
|
|
|
|
|
return value.strip() == "1" |
|
|
|
|
|
|
|
|
|
|
|
def _quick_entry_search_url(*, search_term: str = "", include_bride_side: bool = False) -> str: |
|
|
|
params: dict[str, str] = {} |
|
|
|
normalized_search_term = search_term.strip() |
|
|
|
if normalized_search_term: |
|
|
|
params["q"] = normalized_search_term |
|
|
|
if include_bride_side: |
|
|
|
params["include_bride_side"] = "1" |
|
|
|
return url_for("quick_entry.index", **params) |
|
|
|
|
|
|
|
|
|
|
|
def _option_id_by_code(options: list[object], code: str) -> int | None: |
|
|
|
for option in options: |
|
|
|
if getattr(option, "option_code", None) == code: |
|
|
|
@ -34,13 +55,17 @@ def _option_id_by_code(options: list[object], code: str) -> int | None: |
|
|
|
|
|
|
|
def _quick_entry_index_context() -> dict[str, object]: |
|
|
|
search_term = request.args.get("q", "").strip() |
|
|
|
include_bride_side = _include_bride_side_param(request.args) |
|
|
|
households = list_households(search_term=search_term, limit=20) if normalize_search_term(search_term) else [] |
|
|
|
if not include_bride_side: |
|
|
|
households = [household for household in households if household.side != "bride_side"] |
|
|
|
households = sorted( |
|
|
|
households, |
|
|
|
key=lambda household: household.total_gift_amount > Decimal("0.00"), |
|
|
|
) |
|
|
|
return { |
|
|
|
"search_term": search_term, |
|
|
|
"include_bride_side": include_bride_side, |
|
|
|
"households": households, |
|
|
|
} |
|
|
|
|
|
|
|
@ -52,7 +77,7 @@ def _is_partial_request(expected_partial: str) -> bool: |
|
|
|
|
|
|
|
|
|
|
|
@quick_entry_bp.get("/") |
|
|
|
@role_required("admin", "editor", "entry_only") |
|
|
|
@role_required("admin", "editor", "entry_only", "quick_editor") |
|
|
|
def index() -> str: |
|
|
|
context = _quick_entry_index_context() |
|
|
|
if _is_partial_request("search-results"): |
|
|
|
@ -61,21 +86,23 @@ def index() -> str: |
|
|
|
|
|
|
|
|
|
|
|
@quick_entry_bp.get("/households/new") |
|
|
|
@role_required("admin", "editor", "entry_only") |
|
|
|
@role_required("admin", "editor", "entry_only", "quick_editor") |
|
|
|
def new_household() -> str: |
|
|
|
search_term = request.args.get("q", "").strip() |
|
|
|
include_bride_side = _include_bride_side_param(request.args) |
|
|
|
gift_method_options = list_enabled_options("gift_method") |
|
|
|
gift_scene_options = list_enabled_options("gift_scene") |
|
|
|
return render_template( |
|
|
|
"quick_entry/new.html", |
|
|
|
search_term=search_term, |
|
|
|
include_bride_side=include_bride_side, |
|
|
|
default_gift_method_id=_option_id_by_code(gift_method_options, "cash"), |
|
|
|
default_gift_scene_id=_option_id_by_code(gift_scene_options, "wedding_day"), |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@quick_entry_bp.get("/households/<int:household_id>/edit") |
|
|
|
@role_required("admin", "editor", "entry_only") |
|
|
|
@role_required("admin", "editor", "entry_only", "quick_editor") |
|
|
|
def edit_household(household_id: int): |
|
|
|
household = get_household_or_none(household_id) |
|
|
|
if household is None: |
|
|
|
@ -87,6 +114,7 @@ def edit_household(household_id: int): |
|
|
|
context = { |
|
|
|
"household": household, |
|
|
|
"search_term": request.args.get("q", "").strip(), |
|
|
|
"include_bride_side": _include_bride_side_param(request.args), |
|
|
|
"gift_method_options": gift_method_options, |
|
|
|
"gift_scene_options": gift_scene_options, |
|
|
|
"default_gift_method_id": _option_id_by_code(gift_method_options, "cash"), |
|
|
|
@ -98,7 +126,7 @@ def edit_household(household_id: int): |
|
|
|
|
|
|
|
|
|
|
|
@quick_entry_bp.post("/households/<int:household_id>/edit") |
|
|
|
@role_required("admin", "editor", "entry_only") |
|
|
|
@role_required("admin", "editor", "entry_only", "quick_editor") |
|
|
|
def update_household(household_id: int): |
|
|
|
household = get_household_or_none(household_id) |
|
|
|
if household is None: |
|
|
|
@ -106,11 +134,13 @@ def update_household(household_id: int): |
|
|
|
return redirect(url_for("quick_entry.index")) |
|
|
|
|
|
|
|
search_term = request.form.get("q", "").strip() |
|
|
|
redirect_to_search = url_for("quick_entry.index", q=search_term) if search_term else url_for("quick_entry.index") |
|
|
|
redirect_to_self = ( |
|
|
|
url_for("quick_entry.edit_household", household_id=household_id, q=search_term) |
|
|
|
if search_term |
|
|
|
else url_for("quick_entry.edit_household", household_id=household_id) |
|
|
|
include_bride_side = _include_bride_side_param(request.form) |
|
|
|
redirect_to_search = _quick_entry_search_url(search_term=search_term, include_bride_side=include_bride_side) |
|
|
|
redirect_to_self = url_for( |
|
|
|
"quick_entry.edit_household", |
|
|
|
household_id=household_id, |
|
|
|
q=search_term, |
|
|
|
**({"include_bride_side": "1"} if include_bride_side else {}), |
|
|
|
) |
|
|
|
|
|
|
|
submitted_version = request.form.get("version", "").strip() |
|
|
|
@ -131,12 +161,18 @@ def update_household(household_id: int): |
|
|
|
valid_method_ids={option.id for option in gift_method_options}, |
|
|
|
valid_scene_ids={option.id for option in gift_scene_options}, |
|
|
|
) |
|
|
|
head_name = request.form.get("head_name", "").strip() |
|
|
|
if not head_name: |
|
|
|
errors.append("户主姓名不能为空。") |
|
|
|
elif is_head_name_taken(head_name, excluding_household_id=household_id): |
|
|
|
errors.append("该户主姓名已存在,请换一个名字或直接录入现有户。") |
|
|
|
if errors: |
|
|
|
for error in errors: |
|
|
|
flash(error, "error") |
|
|
|
return redirect(redirect_to_self) |
|
|
|
|
|
|
|
before_snapshot = serialize_entry_edit_snapshot(household) |
|
|
|
household.head_name = head_name |
|
|
|
for field_name, value in payload.items(): |
|
|
|
setattr(household, field_name, value) |
|
|
|
|
|
|
|
@ -167,11 +203,16 @@ def update_household(household_id: int): |
|
|
|
|
|
|
|
|
|
|
|
@quick_entry_bp.post("/households") |
|
|
|
@role_required("admin", "editor", "entry_only") |
|
|
|
@role_required("admin", "editor", "entry_only", "quick_editor") |
|
|
|
def create_household(): |
|
|
|
search_term = request.form.get("head_name", "").strip() |
|
|
|
redirect_to_search = url_for("quick_entry.index", q=search_term) if search_term else url_for("quick_entry.index") |
|
|
|
redirect_to_self = url_for("quick_entry.new_household", q=search_term) if search_term else url_for("quick_entry.new_household") |
|
|
|
search_term = request.form.get("q", "").strip() or request.form.get("head_name", "").strip() |
|
|
|
include_bride_side = _include_bride_side_param(request.form) |
|
|
|
redirect_to_search = _quick_entry_search_url(search_term=search_term, include_bride_side=include_bride_side) |
|
|
|
redirect_to_self = url_for( |
|
|
|
"quick_entry.new_household", |
|
|
|
q=search_term, |
|
|
|
**({"include_bride_side": "1"} if include_bride_side else {}), |
|
|
|
) |
|
|
|
|
|
|
|
gift_method_options = list_enabled_options("gift_method") |
|
|
|
gift_scene_options = list_enabled_options("gift_scene") |
|
|
|
@ -188,7 +229,7 @@ def create_household(): |
|
|
|
head_name = request.form.get("head_name", "").strip() |
|
|
|
if not head_name: |
|
|
|
flash("户主姓名不能为空。", "error") |
|
|
|
return redirect(url_for("quick_entry.new_household")) |
|
|
|
return redirect(redirect_to_self) |
|
|
|
|
|
|
|
if is_head_name_taken(head_name): |
|
|
|
flash("该户主姓名已存在,请先搜索现有户后直接录入礼金。", "error") |
|
|
|
|