fix(individual-parts): bulk add image download and storage deletion validation

This commit is contained in:
FrederikBaerentsen
2026-01-31 11:08:32 +01:00
parent beb09641b9
commit a2883cafe9
5 changed files with 74 additions and 3 deletions
+14 -1
View File
@@ -803,6 +803,19 @@ class IndividualPart(BrickRecord):
}
)
# Download part image if available
image_url = color_info.get('part_img_url', '')
if image_url:
try:
self.download_image(image_url)
except Exception as e:
# Don't fail the whole operation if image download fails
logger.warning('Could not download image for part {part_num} color {color_id}: {error}'.format(
part_num=part_num,
color_id=color_id,
error=e
))
parts_added += 1
# Commit all changes
@@ -816,7 +829,7 @@ class IndividualPart(BrickRecord):
# Generate link to individual parts list
from flask import url_for
parts_url = url_for('individual_part.list_all')
parts_url = url_for('individual_part.list')
# Send completion with message and link
socket.complete(
+52
View File
@@ -1,4 +1,6 @@
from .metadata import BrickMetadata
from .exceptions import ErrorException
from .sql import BrickSQL
from flask import url_for
@@ -13,6 +15,7 @@ class BrickSetStorage(BrickMetadata):
select_query: str = 'set/metadata/storage/select'
update_field_query: str = 'set/metadata/storage/update/field'
update_set_value_query: str = 'set/metadata/storage/update/value'
count_usage_query: str = 'set/metadata/storage/count_usage'
# Self url
def url(self, /) -> str:
@@ -20,3 +23,52 @@ class BrickSetStorage(BrickMetadata):
'storage.details',
id=self.fields.id,
)
# Delete from database - check if storage is in use first
def delete(self, /) -> None:
# Check if storage is being used
sql = BrickSQL()
result = sql.fetchone(self.count_usage_query, parameters={'id': self.fields.id})
if result:
sets_count = result[0]
minifigures_count = result[1]
parts_count = result[2]
lots_count = result[3]
total_count = sets_count + minifigures_count + parts_count + lots_count
if total_count > 0:
# Build error message with counts and link
error_parts = []
if sets_count > 0:
error_parts.append('{count} set{plural}'.format(
count=sets_count,
plural='s' if sets_count != 1 else ''
))
if minifigures_count > 0:
error_parts.append('{count} individual minifigure{plural}'.format(
count=minifigures_count,
plural='s' if minifigures_count != 1 else ''
))
if parts_count > 0:
error_parts.append('{count} individual part{plural}'.format(
count=parts_count,
plural='s' if parts_count != 1 else ''
))
if lots_count > 0:
error_parts.append('{count} part lot{plural}'.format(
count=lots_count,
plural='s' if lots_count != 1 else ''
))
error_message = 'Cannot delete storage location "{name}". You need to remove {items} from this storage before it can be deleted. <a href="{url}">View storage details</a>'.format(
name=self.fields.name,
items=', '.join(error_parts),
url=self.url()
)
raise ErrorException(error_message)
# If not in use, proceed with deletion
super().delete()
@@ -0,0 +1,6 @@
-- Count how many items are using this storage location
SELECT
(SELECT COUNT(*) FROM bricktracker_sets WHERE storage = :id) as sets_count,
(SELECT COUNT(*) FROM bricktracker_individual_minifigures WHERE storage = :id) as minifigures_count,
(SELECT COUNT(*) FROM bricktracker_individual_parts WHERE storage = :id) as parts_count,
(SELECT COUNT(*) FROM bricktracker_individual_part_lots WHERE storage = :id) as lots_count
+1 -1
View File
@@ -45,7 +45,7 @@ def delete(*, id: str) -> str:
'admin.html',
delete_storage=True,
storage=BrickSetStorage().select_specific(id),
error=request.args.get('storage_error')
storage_error=request.args.get('storage_error')
)
+1 -1
View File
@@ -2,7 +2,7 @@
{{ accordion.header('Set storages danger zone', 'storage-danger', 'admin', expanded=true, danger=true, class='text-end') }}
<form action="{{ url_for('admin_storage.do_delete', id=storage.fields.id) }}" method="post">
{% if storage_error %}<div class="alert alert-danger text-start" role="alert"><strong>Error:</strong> {{ storage_error }}.</div>{% endif %}
{% if storage_error %}<div class="alert alert-danger text-start" role="alert"><strong>Error:</strong> {{ storage_error|safe }}</div>{% endif %}
<div class="alert alert-danger text-center" role="alert">You are about to <strong>delete a set storage</strong>. This action is irreversible.</div>
<div class="row row-cols-lg-auto g-3 align-items-center">
<div class="col-12 flex-grow-1">