diff --git a/app.py b/app.py
index 29c745f..81082a3 100644
--- a/app.py
+++ b/app.py
@@ -1139,7 +1139,15 @@ def create_app(config_object="config"):
return redirect(url_for("device_detail", device_id=device_id))
increment = 1 if request.form.get("increment_cycles") else 0
notes = request.form.get("notes", "").strip() or None
- installed = [b for b in device.batteries if b.status == "installed"]
+ if device.has_children():
+ installed = [
+ b
+ for child in device.children
+ for b in child.batteries
+ if b.status == "installed"
+ ]
+ else:
+ installed = [b for b in device.batteries if b.status == "installed"]
if not installed:
flash("No installed batteries to log.", "warning")
return redirect(url_for("device_detail", device_id=device_id))
diff --git a/templates/device_detail.html b/templates/device_detail.html
index 57a9969..1975d32 100644
--- a/templates/device_detail.html
+++ b/templates/device_detail.html
@@ -232,6 +232,32 @@
{% endif %}
+{% if device.has_children() and flat_installed %}
+
+
Charge All Installed Batteries
+
+
+{% endif %}
+
{% if not device.has_children() %}
Install Batteries
diff --git a/tests/test_acceptance.py b/tests/test_acceptance.py
index 5f8d82d..2455cc0 100644
--- a/tests/test_acceptance.py
+++ b/tests/test_acceptance.py
@@ -1066,5 +1066,32 @@ def test_parent_battery_summary_flat(client):
# Both child names linked in the component column
assert b"Sensor A" in resp.data
assert b"Sensor B" in resp.data
- # Only one "Installed Batteries" heading
- assert resp.data.count(b"Installed Batteries") == 1
+ # Flat table heading appears once (not duplicated per sub-component)
+ assert resp.data.count(b"Installed Batteries
") == 1
+
+
+def test_device_charge_all_parent(client):
+ _setup_parent_with_two_children(client)
+ client.post("/battery/add", data={"brand": "Eneloop", "label": "E001", "size": "AA"})
+ client.post("/battery/add", data={"brand": "Eneloop", "label": "E002", "size": "AA"})
+ client.post("/device/2/install-one", data={"battery_id": "1"})
+ client.post("/device/3/install-one", data={"battery_id": "2"})
+ resp = client.post(
+ "/device/1/charge-all",
+ data={"charged_date": "2025-06-01", "increment_cycles": "1"},
+ follow_redirects=True,
+ )
+ assert resp.status_code == 200
+ assert b"Logged charge for 2 batteri" in resp.data
+ assert b"+cycles" in resp.data
+
+
+def test_device_charge_all_parent_no_installed(client):
+ _setup_parent_with_two_children(client)
+ resp = client.post(
+ "/device/1/charge-all",
+ data={"charged_date": "2025-06-01"},
+ follow_redirects=True,
+ )
+ assert resp.status_code == 200
+ assert b"No installed batteries" in resp.data