Support for damaged parts
This commit is contained in:
parent
5ffea66de0
commit
271effd5d2
@ -107,9 +107,10 @@
|
||||
# Default: false
|
||||
# BK_HIDE_ALL_SETS=true
|
||||
|
||||
# Optional: Hide the 'Missing' entry from the menu. Does not disable the route.
|
||||
# Optional: Hide the 'Problems' entry from the menu. Does not disable the route.
|
||||
# Default: false
|
||||
# BK_HIDE_MISSING_PARTS=true
|
||||
# Legacy name: BK_HIDE_MISSING_PARTS
|
||||
# BK_HIDE_PROBLEMS_PARTS=true
|
||||
|
||||
# Optional: Hide the 'Instructions' entry in a Set card
|
||||
# Default: false
|
||||
|
@ -29,7 +29,7 @@ CONFIG: Final[list[dict[str, Any]]] = [
|
||||
{'n': 'HIDE_ALL_MINIFIGURES', 'c': bool},
|
||||
{'n': 'HIDE_ALL_PARTS', 'c': bool},
|
||||
{'n': 'HIDE_ALL_SETS', 'c': bool},
|
||||
{'n': 'HIDE_MISSING_PARTS', 'c': bool},
|
||||
{'n': 'HIDE_PROBLEMS_PARTS', 'e': 'BK_HIDE_MISSING_PARTS', 'c': bool},
|
||||
{'n': 'HIDE_SET_INSTRUCTIONS', 'c': bool},
|
||||
{'n': 'HIDE_WISHES', 'c': bool},
|
||||
{'n': 'MINIFIGURES_DEFAULT_ORDER', 'd': '"rebrickable_minifigures"."name" ASC'}, # noqa: E501
|
||||
|
@ -21,10 +21,11 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]):
|
||||
|
||||
# Queries
|
||||
all_query: str = 'minifigure/list/all'
|
||||
damaged_part_query: str = 'minifigure/list/damaged_part'
|
||||
last_query: str = 'minifigure/list/last'
|
||||
missing_part_query: str = 'minifigure/list/missing_part'
|
||||
select_query: str = 'minifigure/list/from_set'
|
||||
using_part_query: str = 'minifigure/list/using_part'
|
||||
missing_part_query: str = 'minifigure/list/missing_part'
|
||||
|
||||
def __init__(self, /):
|
||||
super().__init__()
|
||||
@ -47,6 +48,23 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]):
|
||||
|
||||
return self
|
||||
|
||||
# Minifigures with a part damaged part
|
||||
def damaged_part(self, part: str, color: int, /) -> Self:
|
||||
# Save the parameters to the fields
|
||||
self.fields.part = part
|
||||
self.fields.color = color
|
||||
|
||||
# Load the minifigures from the database
|
||||
for record in self.select(
|
||||
override_query=self.damaged_part_query,
|
||||
order=self.order
|
||||
):
|
||||
minifigure = BrickMinifigure(record=record)
|
||||
|
||||
self.records.append(minifigure)
|
||||
|
||||
return self
|
||||
|
||||
# Last added minifigure
|
||||
def last(self, /, *, limit: int = 6) -> Self:
|
||||
# Randomize
|
||||
@ -80,12 +98,7 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]):
|
||||
return self
|
||||
|
||||
# Minifigures missing a part
|
||||
def missing_part(
|
||||
self,
|
||||
part: str,
|
||||
color: int,
|
||||
/,
|
||||
) -> Self:
|
||||
def missing_part(self, part: str, color: int, /) -> Self:
|
||||
# Save the parameters to the fields
|
||||
self.fields.part = part
|
||||
self.fields.color = color
|
||||
@ -102,12 +115,7 @@ class BrickMinifigureList(BrickRecordList[BrickMinifigure]):
|
||||
return self
|
||||
|
||||
# Minifigure using a part
|
||||
def using_part(
|
||||
self,
|
||||
part: str,
|
||||
color: int,
|
||||
/,
|
||||
) -> Self:
|
||||
def using_part(self, part: str, color: int, /) -> Self:
|
||||
# Save the parameters to the fields
|
||||
self.fields.part = part
|
||||
self.fields.color = color
|
||||
|
@ -11,7 +11,7 @@ NAVBAR: Final[list[dict[str, Any]]] = [
|
||||
{'e': 'set.list', 't': 'Sets', 'i': 'grid-line', 'f': 'HIDE_ALL_SETS'}, # noqa: E501
|
||||
{'e': 'add.add', 't': 'Add', 'i': 'add-circle-line', 'f': 'HIDE_ADD_SET'}, # noqa: E501
|
||||
{'e': 'part.list', 't': 'Parts', 'i': 'shapes-line', 'f': 'HIDE_ALL_PARTS'}, # noqa: E501
|
||||
{'e': 'part.missing', 't': 'Missing', 'i': 'error-warning-line', 'f': 'HIDE_MISSING_PARTS'}, # noqa: E501
|
||||
{'e': 'part.problem', 't': 'Problems', 'i': 'error-warning-line', 'f': 'HIDE_PROBLEMS_PARTS'}, # noqa: E501
|
||||
{'e': 'minifigure.list', 't': 'Minifigures', 'i': 'group-line', 'f': 'HIDE_ALL_MINIFIGURES'}, # noqa: E501
|
||||
{'e': 'instructions.list', 't': 'Instructions', 'i': 'file-line', 'f': 'HIDE_ALL_INSTRUCTIONS'}, # noqa: E501
|
||||
{'e': 'wish.list', 't': 'Wishlist', 'i': 'gift-line', 'f': 'HIDE_WISHES'},
|
||||
|
@ -74,9 +74,12 @@ class BrickPart(RebrickablePart):
|
||||
return True
|
||||
|
||||
# A identifier for HTML component
|
||||
def html_id(self, /) -> str:
|
||||
def html_id(self, prefix: str | None = None, /) -> str:
|
||||
components: list[str] = ['part']
|
||||
|
||||
if prefix is not None:
|
||||
components.append(prefix)
|
||||
|
||||
if self.fields.figure is not None:
|
||||
components.append(self.fields.figure)
|
||||
|
||||
@ -144,36 +147,38 @@ class BrickPart(RebrickablePart):
|
||||
|
||||
return self
|
||||
|
||||
# Update the missing part
|
||||
def update_missing(self, json: Any | None, /) -> None:
|
||||
missing: str | int = json.get('value', '') # type: ignore
|
||||
# Update a problematic part
|
||||
def update_problem(self, problem: str, json: Any | None, /) -> int:
|
||||
amount: str | int = json.get('value', '') # type: ignore
|
||||
|
||||
# We need a positive integer
|
||||
try:
|
||||
if missing == '':
|
||||
missing = 0
|
||||
if amount == '':
|
||||
amount = 0
|
||||
|
||||
missing = int(missing)
|
||||
amount = int(amount)
|
||||
|
||||
if missing < 0:
|
||||
missing = 0
|
||||
if amount < 0:
|
||||
amount = 0
|
||||
except Exception:
|
||||
raise ErrorException('"{missing}" is not a valid integer'.format(
|
||||
missing=missing
|
||||
raise ErrorException('"{amount}" is not a valid integer'.format(
|
||||
amount=amount
|
||||
))
|
||||
|
||||
if missing < 0:
|
||||
raise ErrorException('Cannot set a negative missing value')
|
||||
if amount < 0:
|
||||
raise ErrorException('Cannot set a negative amount')
|
||||
|
||||
self.fields.missing = missing
|
||||
setattr(self.fields, problem, amount)
|
||||
|
||||
BrickSQL().execute_and_commit(
|
||||
'part/update/missing',
|
||||
'part/update/{problem}'.format(problem=problem),
|
||||
parameters=self.sql_parameters()
|
||||
)
|
||||
|
||||
# Compute the url for missing part
|
||||
def url_for_missing(self, /) -> str:
|
||||
return amount
|
||||
|
||||
# Compute the url for problematic part
|
||||
def url_for_problem(self, problem: str, /) -> str:
|
||||
# Different URL for a minifigure part
|
||||
if self.minifigure is not None:
|
||||
figure = self.minifigure.fields.figure
|
||||
@ -181,10 +186,11 @@ class BrickPart(RebrickablePart):
|
||||
figure = None
|
||||
|
||||
return url_for(
|
||||
'set.missing_part',
|
||||
'set.problem_part',
|
||||
id=self.fields.id,
|
||||
figure=figure,
|
||||
part=self.fields.part,
|
||||
color=self.fields.color,
|
||||
spare=self.fields.spare,
|
||||
problem=problem,
|
||||
)
|
||||
|
@ -25,7 +25,7 @@ class BrickPartList(BrickRecordList[BrickPart]):
|
||||
all_query: str = 'part/list/all'
|
||||
last_query: str = 'part/list/last'
|
||||
minifigure_query: str = 'part/list/from_minifigure'
|
||||
missing_query: str = 'part/list/missing'
|
||||
problem_query: str = 'part/list/problem'
|
||||
print_query: str = 'part/list/from_print'
|
||||
select_query: str = 'part/list/specific'
|
||||
|
||||
@ -138,10 +138,10 @@ class BrickPartList(BrickRecordList[BrickPart]):
|
||||
|
||||
return self
|
||||
|
||||
# Load missing parts
|
||||
def missing(self, /) -> Self:
|
||||
# Load problematic parts
|
||||
def problem(self, /) -> Self:
|
||||
for record in self.select(
|
||||
override_query=self.missing_query,
|
||||
override_query=self.problem_query,
|
||||
order=self.order
|
||||
):
|
||||
part = BrickPart(record=record)
|
||||
|
@ -18,6 +18,8 @@ class BrickSetList(BrickRecordList[BrickSet]):
|
||||
order: str
|
||||
|
||||
# Queries
|
||||
damaged_minifigure_query: str = 'set/list/damaged_minifigure'
|
||||
damaged_part_query: str = 'set/list/damaged_part'
|
||||
generic_query: str = 'set/list/generic'
|
||||
light_query: str = 'set/list/light'
|
||||
missing_minifigure_query: str = 'set/list/missing_minifigure'
|
||||
@ -57,6 +59,39 @@ class BrickSetList(BrickRecordList[BrickSet]):
|
||||
|
||||
return self
|
||||
|
||||
# Sets with a minifigure part damaged
|
||||
def damaged_minifigure(self, figure: str, /) -> Self:
|
||||
# Save the parameters to the fields
|
||||
self.fields.figure = figure
|
||||
|
||||
# Load the sets from the database
|
||||
for record in self.select(
|
||||
override_query=self.damaged_minifigure_query,
|
||||
order=self.order
|
||||
):
|
||||
brickset = BrickSet(record=record)
|
||||
|
||||
self.records.append(brickset)
|
||||
|
||||
return self
|
||||
|
||||
# Sets with a part damaged
|
||||
def damaged_part(self, part: str, color: int, /) -> Self:
|
||||
# Save the parameters to the fields
|
||||
self.fields.part = part
|
||||
self.fields.color = color
|
||||
|
||||
# Load the sets from the database
|
||||
for record in self.select(
|
||||
override_query=self.damaged_part_query,
|
||||
order=self.order
|
||||
):
|
||||
brickset = BrickSet(record=record)
|
||||
|
||||
self.records.append(brickset)
|
||||
|
||||
return self
|
||||
|
||||
# A generic list of the different sets
|
||||
def generic(self, /) -> Self:
|
||||
for record in self.select(
|
||||
@ -90,7 +125,7 @@ class BrickSetList(BrickRecordList[BrickSet]):
|
||||
|
||||
return self
|
||||
|
||||
# Sets missing a minifigure
|
||||
# Sets missing a minifigure part
|
||||
def missing_minifigure(self, figure: str, /) -> Self:
|
||||
# Save the parameters to the fields
|
||||
self.fields.figure = figure
|
||||
|
@ -7,6 +7,9 @@ SELECT
|
||||
{% block total_missing %}
|
||||
NULL AS "total_missing", -- dummy for order: total_missing
|
||||
{% endblock %}
|
||||
{% block total_damaged %}
|
||||
NULL AS "total_damaged", -- dummy for order: total_damaged
|
||||
{% endblock %}
|
||||
{% block total_quantity %}
|
||||
NULL AS "total_quantity", -- dummy for order: total_quantity
|
||||
{% endblock %}
|
||||
|
@ -1,7 +1,11 @@
|
||||
{% extends 'minifigure/base/base.sql' %}
|
||||
|
||||
{% block total_missing %}
|
||||
SUM(IFNULL("missing_join"."total", 0)) AS "total_missing",
|
||||
SUM(IFNULL("problem_join"."total_missing", 0)) AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM(IFNULL("problem_join"."total_damaged", 0)) AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_quantity %}
|
||||
@ -18,15 +22,16 @@ LEFT JOIN (
|
||||
SELECT
|
||||
"bricktracker_parts"."id",
|
||||
"bricktracker_parts"."figure",
|
||||
SUM("bricktracker_parts"."missing") AS total
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged"
|
||||
FROM "bricktracker_parts"
|
||||
WHERE "bricktracker_parts"."figure" IS NOT NULL
|
||||
GROUP BY
|
||||
"bricktracker_parts"."id",
|
||||
"bricktracker_parts"."figure"
|
||||
) "missing_join"
|
||||
ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "missing_join"."id"
|
||||
AND "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "missing_join"."figure"
|
||||
) "problem_join"
|
||||
ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "problem_join"."id"
|
||||
AND "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "problem_join"."figure"
|
||||
{% endblock %}
|
||||
|
||||
{% block group %}
|
||||
|
28
bricktracker/sql/minifigure/list/damaged_part.sql
Normal file
28
bricktracker/sql/minifigure/list/damaged_part.sql
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends 'minifigure/base/base.sql' %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block join %}
|
||||
LEFT JOIN "bricktracker_parts"
|
||||
ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "bricktracker_parts"."id"
|
||||
AND "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "bricktracker_parts"."figure"
|
||||
{% endblock %}
|
||||
|
||||
{% block where %}
|
||||
WHERE "rebrickable_minifigures"."figure" IN (
|
||||
SELECT "bricktracker_parts"."figure"
|
||||
FROM "bricktracker_parts"
|
||||
WHERE "bricktracker_parts"."part" IS NOT DISTINCT FROM :part
|
||||
AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color
|
||||
AND "bricktracker_parts"."figure" IS NOT NULL
|
||||
AND "bricktracker_parts"."damaged" > 0
|
||||
GROUP BY "bricktracker_parts"."figure"
|
||||
)
|
||||
{% endblock %}
|
||||
|
||||
{% block group %}
|
||||
GROUP BY
|
||||
"rebrickable_minifigures"."figure"
|
||||
{% endblock %}
|
@ -4,6 +4,10 @@
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block join %}
|
||||
LEFT JOIN "bricktracker_parts"
|
||||
ON "bricktracker_minifigures"."id" IS NOT DISTINCT FROM "bricktracker_parts"."id"
|
||||
|
@ -1,7 +1,11 @@
|
||||
{% extends 'minifigure/base/base.sql' %}
|
||||
|
||||
{% block total_missing %}
|
||||
IFNULL("missing_join"."total", 0) AS "total_missing",
|
||||
IFNULL("problem_join"."total_missing", 0) AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
IFNULL("problem_join"."total_damaged", 0) AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_quantity %}
|
||||
@ -17,12 +21,13 @@ COUNT(DISTINCT "bricktracker_minifigures"."id") AS "total_sets"
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
"bricktracker_parts"."figure",
|
||||
SUM("bricktracker_parts"."missing") AS "total"
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged"
|
||||
FROM "bricktracker_parts"
|
||||
WHERE "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure
|
||||
GROUP BY "bricktracker_parts"."figure"
|
||||
) "missing_join"
|
||||
ON "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "missing_join"."figure"
|
||||
) "problem_join"
|
||||
ON "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM "problem_join"."figure"
|
||||
{% endblock %}
|
||||
|
||||
{% block where %}
|
||||
|
@ -23,6 +23,9 @@ SELECT
|
||||
{% block total_missing %}
|
||||
NULL AS "total_missing", -- dummy for order: total_missing
|
||||
{% endblock %}
|
||||
{% block total_damaged %}
|
||||
NULL AS "total_damaged", -- dummy for order: total_damaged
|
||||
{% endblock %}
|
||||
{% block total_quantity %}
|
||||
NULL AS "total_quantity", -- dummy for order: total_quantity
|
||||
{% endblock %}
|
||||
|
@ -4,6 +4,10 @@
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_quantity %}
|
||||
SUM("bricktracker_parts"."quantity" * IFNULL("bricktracker_minifigures"."quantity", 1)) AS "total_quantity",
|
||||
{% endblock %}
|
||||
|
@ -5,6 +5,10 @@
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block where %}
|
||||
WHERE "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure
|
||||
{% endblock %}
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
{% extends 'part/base/base.sql' %}
|
||||
|
||||
{% block total_missing %}
|
||||
{% endblock %}
|
||||
{% block total_missing %}{% endblock %}
|
||||
|
||||
{% block total_damaged %}{% endblock %}
|
||||
|
||||
{% block where %}
|
||||
WHERE "rebrickable_parts"."print" IS NOT DISTINCT FROM :print
|
||||
|
@ -4,6 +4,10 @@
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_sets %}
|
||||
COUNT("bricktracker_parts"."id") - COUNT("bricktracker_parts"."figure") AS "total_sets",
|
||||
{% endblock %}
|
||||
@ -20,6 +24,7 @@ AND "bricktracker_parts"."figure" IS NOT DISTINCT FROM "bricktracker_minifigures
|
||||
|
||||
{% block where %}
|
||||
WHERE "bricktracker_parts"."missing" > 0
|
||||
OR "bricktracker_parts"."damaged" > 0
|
||||
{% endblock %}
|
||||
|
||||
{% block group %}
|
@ -5,6 +5,10 @@
|
||||
IFNULL("bricktracker_parts"."missing", 0) AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
IFNULL("bricktracker_parts"."damaged", 0) AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block where %}
|
||||
WHERE "bricktracker_parts"."id" IS NOT DISTINCT FROM :id
|
||||
AND "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure
|
||||
|
@ -4,6 +4,10 @@
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_quantity %}
|
||||
SUM((NOT "bricktracker_parts"."spare") * "bricktracker_parts"."quantity" * IFNULL("bricktracker_minifigures"."quantity", 1)) AS "total_quantity",
|
||||
{% endblock %}
|
||||
|
7
bricktracker/sql/part/update/damaged.sql
Normal file
7
bricktracker/sql/part/update/damaged.sql
Normal file
@ -0,0 +1,7 @@
|
||||
UPDATE "bricktracker_parts"
|
||||
SET "damaged" = :damaged
|
||||
WHERE "bricktracker_parts"."id" IS NOT DISTINCT FROM :id
|
||||
AND "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure
|
||||
AND "bricktracker_parts"."part" IS NOT DISTINCT FROM :part
|
||||
AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color
|
||||
AND "bricktracker_parts"."spare" IS NOT DISTINCT FROM :spare
|
@ -21,6 +21,9 @@ SELECT
|
||||
{% block total_missing %}
|
||||
NULL AS "total_missing", -- dummy for order: total_missing
|
||||
{% endblock %}
|
||||
{% block total_damaged %}
|
||||
NULL AS "total_damaged", -- dummy for order: total_damaged
|
||||
{% endblock %}
|
||||
{% block total_quantity %}
|
||||
NULL AS "total_quantity", -- dummy for order: total_quantity
|
||||
{% endblock %}
|
||||
|
@ -5,7 +5,11 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block total_missing %}
|
||||
IFNULL("missing_join"."total", 0) AS "total_missing",
|
||||
IFNULL("problem_join"."total_missing", 0) AS "total_missing",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_damaged %}
|
||||
IFNULL("problem_join"."total_damaged", 0) AS "total_damaged",
|
||||
{% endblock %}
|
||||
|
||||
{% block total_quantity %}
|
||||
@ -32,12 +36,13 @@ ON "bricktracker_sets"."id" IS NOT DISTINCT FROM "bricktracker_set_tags"."id"
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
"bricktracker_parts"."id",
|
||||
SUM("bricktracker_parts"."missing") AS "total"
|
||||
SUM("bricktracker_parts"."missing") AS "total_missing",
|
||||
SUM("bricktracker_parts"."damaged") AS "total_damaged"
|
||||
FROM "bricktracker_parts"
|
||||
{% block where_missing %}{% endblock %}
|
||||
GROUP BY "bricktracker_parts"."id"
|
||||
) "missing_join"
|
||||
ON "bricktracker_sets"."id" IS NOT DISTINCT FROM "missing_join"."id"
|
||||
) "problem_join"
|
||||
ON "bricktracker_sets"."id" IS NOT DISTINCT FROM "problem_join"."id"
|
||||
|
||||
-- LEFT JOIN + SELECT to avoid messing the total
|
||||
LEFT JOIN (
|
||||
|
11
bricktracker/sql/set/list/damaged_minifigure.sql
Normal file
11
bricktracker/sql/set/list/damaged_minifigure.sql
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends 'set/base/full.sql' %}
|
||||
|
||||
{% block where %}
|
||||
WHERE "bricktracker_sets"."id" IN (
|
||||
SELECT "bricktracker_parts"."id"
|
||||
FROM "bricktracker_parts"
|
||||
WHERE "bricktracker_parts"."figure" IS NOT DISTINCT FROM :figure
|
||||
AND "bricktracker_parts"."missing" > 0
|
||||
GROUP BY "bricktracker_parts"."id"
|
||||
)
|
||||
{% endblock %}
|
12
bricktracker/sql/set/list/damaged_part.sql
Normal file
12
bricktracker/sql/set/list/damaged_part.sql
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends 'set/base/full.sql' %}
|
||||
|
||||
{% block where %}
|
||||
WHERE "bricktracker_sets"."id" IN (
|
||||
SELECT "bricktracker_parts"."id"
|
||||
FROM "bricktracker_parts"
|
||||
WHERE "bricktracker_parts"."part" IS NOT DISTINCT FROM :part
|
||||
AND "bricktracker_parts"."color" IS NOT DISTINCT FROM :color
|
||||
AND "bricktracker_parts"."damaged" > 0
|
||||
GROUP BY "bricktracker_parts"."id"
|
||||
)
|
||||
{% endblock %}
|
@ -27,4 +27,5 @@ def details(*, figure: str) -> str:
|
||||
item=BrickMinifigure().select_generic(figure),
|
||||
using=BrickSetList().using_minifigure(figure),
|
||||
missing=BrickSetList().missing_minifigure(figure),
|
||||
damaged=BrickSetList().damaged_minifigure(figure),
|
||||
)
|
||||
|
@ -19,13 +19,13 @@ def list() -> str:
|
||||
)
|
||||
|
||||
|
||||
# Missing
|
||||
@part_page.route('/missing', methods=['GET'])
|
||||
# Problem
|
||||
@part_page.route('/problem', methods=['GET'])
|
||||
@exception_handler(__file__)
|
||||
def missing() -> str:
|
||||
def problem() -> str:
|
||||
return render_template(
|
||||
'missing.html',
|
||||
table_collection=BrickPartList().missing()
|
||||
'problem.html',
|
||||
table_collection=BrickPartList().problem()
|
||||
)
|
||||
|
||||
|
||||
@ -46,6 +46,10 @@ def details(*, part: str, color: int) -> str:
|
||||
part,
|
||||
color
|
||||
),
|
||||
sets_damaged=BrickSetList().damaged_part(
|
||||
part,
|
||||
color
|
||||
),
|
||||
minifigures_using=BrickMinifigureList().using_part(
|
||||
part,
|
||||
color
|
||||
@ -54,5 +58,9 @@ def details(*, part: str, color: int) -> str:
|
||||
part,
|
||||
color
|
||||
),
|
||||
minifigures_damaged=BrickMinifigureList().damaged_part(
|
||||
part,
|
||||
color
|
||||
),
|
||||
similar_prints=BrickPartList().from_print(brickpart)
|
||||
)
|
||||
|
@ -136,18 +136,19 @@ def details(*, id: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
# Update the missing pieces of a part
|
||||
@set_page.route('/<id>/parts/<part>/<int:color>/<int:spare>/missing', defaults={'figure': None}, methods=['POST']) # noqa: E501
|
||||
@set_page.route('/<id>/minifigures/<figure>/parts/<part>/<int:color>/<int:spare>/missing', methods=['POST']) # noqa: E501
|
||||
# Update problematic pieces of a set
|
||||
@set_page.route('/<id>/parts/<part>/<int:color>/<int:spare>/<problem>', defaults={'figure': None}, methods=['POST']) # noqa: E501
|
||||
@set_page.route('/<id>/minifigures/<figure>/parts/<part>/<int:color>/<int:spare>/<problem>', methods=['POST']) # noqa: E501
|
||||
@login_required
|
||||
@exception_handler(__file__, json=True)
|
||||
def missing_part(
|
||||
def problem_part(
|
||||
*,
|
||||
id: str,
|
||||
figure: str | None,
|
||||
part: str,
|
||||
color: int,
|
||||
spare: int,
|
||||
problem: str,
|
||||
) -> Response:
|
||||
brickset = BrickSet().select_specific(id)
|
||||
|
||||
@ -164,20 +165,21 @@ def missing_part(
|
||||
minifigure=brickminifigure,
|
||||
)
|
||||
|
||||
brickpart.update_missing(request.json)
|
||||
amount = brickpart.update_problem(problem, request.json)
|
||||
|
||||
# Info
|
||||
logger.info('Set {set} ({id}): updated part ({part} color: {color}, spare: {spare}, minifigure: {figure}) missing count to {missing}'.format( # noqa: E501
|
||||
logger.info('Set {set} ({id}): updated part ({part} color: {color}, spare: {spare}, minifigure: {figure}) {problem} count to {amount}'.format( # noqa: E501
|
||||
set=brickset.fields.set,
|
||||
id=brickset.fields.id,
|
||||
figure=figure,
|
||||
part=brickpart.fields.part,
|
||||
color=brickpart.fields.color,
|
||||
spare=brickpart.fields.spare,
|
||||
missing=brickpart.fields.missing,
|
||||
problem=problem,
|
||||
amount=amount
|
||||
))
|
||||
|
||||
return jsonify({'missing': brickpart.fields.missing})
|
||||
return jsonify({problem: amount})
|
||||
|
||||
|
||||
# Refresh a set
|
||||
|
@ -43,7 +43,7 @@
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro table(table_collection, title, id, parent, target, quantity=none, icon=none, image=none, alt=none, details=none, no_missing=none, read_only=none) %}
|
||||
{% macro table(table_collection, title, id, parent, target, quantity=none, icon=none, image=none, alt=none, details=none, read_only=none) %}
|
||||
{% set size=table_collection | length %}
|
||||
{% if size %}
|
||||
{{ header(title, id, parent, quantity=quantity, icon=icon, class='p-0', image=image, alt=alt) }}
|
||||
|
@ -90,6 +90,10 @@
|
||||
{{ badge(check=theme, solo=solo, last=last, color='primary', icon='price-tag-3-line', text=text, alt='Theme', tooltip=tooltip) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro total_damaged(damaged, solo=false, last=false) %}
|
||||
{{ badge(check=damaged, solo=solo, last=last, color='danger', icon='error-warning-line', collapsible='Damaged:', text=damaged, alt='Damaged') }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro total_quantity(quantity, solo=false, last=false) %}
|
||||
{{ badge(check=quantity, solo=solo, last=last, color='success', icon='functions', collapsible='Quantity:', text=quantity, alt='Quantity') }}
|
||||
{% endmacro %}
|
||||
@ -99,7 +103,7 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro total_missing(missing, solo=false, last=false) %}
|
||||
{{ badge(check=missing, solo=solo, last=last, color='danger', icon='error-warning-line', collapsible='Missing:', text=missing, alt='Missing') }}
|
||||
{{ badge(check=missing, solo=solo, last=last, color='light text-danger-emphasis bg-danger-subtle border border-danger-subtle', icon='question-line', collapsible='Missing:', text=missing, alt='Missing') }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro total_sets(sets, solo=false, last=false) %}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% macro header(color=false, quantity=false, missing=false, missing_parts=false, sets=false, minifigures=false) %}
|
||||
{% macro header(color=false, quantity=false, missing_parts=false, damaged_parts=false, sets=false, minifigures=false) %}
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
|
||||
@ -9,12 +9,8 @@
|
||||
{% if quantity %}
|
||||
<th data-table-number="true" scope="col"><i class="ri-functions fw-normal"></i> Quantity</th>
|
||||
{% endif %}
|
||||
{% if missing %}
|
||||
<th data-table-number="true" scope="col"><i class="ri-error-warning-line fw-normal"></i> Missing</th>
|
||||
{% endif %}
|
||||
{% if missing_parts %}
|
||||
<th data-table-number="true" scope="col"><i class="ri-error-warning-line fw-normal"></i> Missing parts</th>
|
||||
{% endif %}
|
||||
<th data-table-number="true" scope="col"><i class="ri-question-line fw-normal"></i> Missing{% if missing_parts %} parts{% endif %}</th>
|
||||
<th data-table-number="true" scope="col"><i class="ri-error-warning-line fw-normal"></i> Damaged{% if damaged_parts %} parts{% endif %}</th>
|
||||
{% if sets %}
|
||||
<th data-table-number="true" scope="col"><i class="ri-hashtag fw-normal"></i> Sets</th>
|
||||
{% endif %}
|
||||
|
@ -13,6 +13,7 @@
|
||||
{{ badge.quantity(item.fields.total_quantity, solo=solo, last=last) }}
|
||||
{{ badge.total_sets(using | length, solo=solo, last=last) }}
|
||||
{{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }}
|
||||
{{ badge.total_damaged(item.fields.total_damaged, solo=solo, last=last) }}
|
||||
{% if not last %}
|
||||
{{ badge.rebrickable(item, solo=solo, last=last) }}
|
||||
{% endif %}
|
||||
@ -21,7 +22,8 @@
|
||||
<div class="accordion accordion-flush" id="minifigure-details">
|
||||
{{ accordion.table(item.generic_parts(), 'Parts', item.fields.figure, 'minifigure-details', 'part/table.html', icon='shapes-line', alt=item.fields.figure, read_only=read_only)}}
|
||||
{{ accordion.cards(using, 'Sets using this minifigure', 'using-inventory', 'minifigure-details', 'set/card.html', icon='hashtag') }}
|
||||
{{ accordion.cards(missing, 'Sets missing parts of this minifigure', 'missing-inventory', 'minifigure-details', 'set/card.html', icon='error-warning-line') }}
|
||||
{{ accordion.cards(missing, 'Sets missing parts for this minifigure', 'missing-inventory', 'minifigure-details', 'set/card.html', icon='question-line') }}
|
||||
{{ accordion.cards(damaged, 'Sets with damaged parts for this minifigure', 'damaged-inventory', 'minifigure-details', 'set/card.html', icon='error-warning-line') }}
|
||||
</div>
|
||||
<div class="card-footer"></div>
|
||||
{% endif %}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle" id="minifigures">
|
||||
{{ table.header(quantity=true, missing_parts=true, sets=true) }}
|
||||
{{ table.header(quantity=true, missing_parts=true, damaged_parts=true, sets=true) }}
|
||||
<tbody>
|
||||
{% for item in table_collection %}
|
||||
<tr>
|
||||
@ -15,6 +15,7 @@
|
||||
</td>
|
||||
<td>{{ item.fields.total_quantity }}</td>
|
||||
<td>{{ item.fields.total_missing }}</td>
|
||||
<td>{{ item.fields.total_damaged }}</td>
|
||||
<td>{{ item.fields.total_sets }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -15,6 +15,7 @@
|
||||
{{ badge.total_quantity(item.fields.total_quantity, solo=solo, last=last) }}
|
||||
{{ badge.total_spare(item.fields.total_spare, solo=solo, last=last) }}
|
||||
{{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }}
|
||||
{{ badge.total_damaged(item.fields.total_damaged, solo=solo, last=last) }}
|
||||
{% if not last %}
|
||||
{{ badge.rebrickable(item, solo=solo, last=last) }}
|
||||
{{ badge.bricklink(item, solo=solo, last=last) }}
|
||||
@ -23,9 +24,11 @@
|
||||
{% if solo %}
|
||||
<div class="accordion accordion-flush border-top" id="part-details">
|
||||
{{ accordion.cards(sets_using, 'Sets using this part', 'sets-using-inventory', 'part-details', 'set/card.html', icon='hashtag') }}
|
||||
{{ accordion.cards(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/card.html', icon='error-warning-line') }}
|
||||
{{ accordion.cards(sets_missing, 'Sets missing this part', 'sets-missing-inventory', 'part-details', 'set/card.html', icon='question-line') }}
|
||||
{{ accordion.cards(sets_damaged, 'Sets with this part damaged', 'sets-damaged-inventory', 'part-details', 'set/card.html', icon='error-warning-line') }}
|
||||
{{ accordion.cards(minifigures_using, 'Minifigures using this part', 'minifigures-using-inventory', 'part-details', 'minifigure/card.html', icon='group-line') }}
|
||||
{{ accordion.cards(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='error-warning-line') }}
|
||||
{{ accordion.cards(minifigures_missing, 'Minifigures missing this part', 'minifigures-missing-inventory', 'part-details', 'minifigure/card.html', icon='question-line') }}
|
||||
{{ accordion.cards(minifigures_damaged, 'Minifigures with this part damaged', 'minifigures-damaged-inventory', 'part-details', 'minifigure/card.html', icon='error-warning-line') }}
|
||||
{{ accordion.cards(similar_prints, 'Prints using the same base', 'similar-prints', 'part-details', 'part/card.html', icon='paint-brush-line') }}
|
||||
</div>
|
||||
<div class="card-footer"></div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle {% if not all %}sortable mb-0{% endif %}" {% if all %}id="parts"{% endif %}>
|
||||
{{ table.header(color=true, quantity=not no_quantity, missing=not no_missing, sets=all, minifigures=all) }}
|
||||
{{ table.header(color=true, quantity=not no_quantity, sets=all, minifigures=all) }}
|
||||
<tbody>
|
||||
{% for item in table_collection %}
|
||||
<tr>
|
||||
@ -27,11 +27,12 @@
|
||||
<td>{% if quantity %}{{ item.fields.quantity * quantity }}{% else %}{{ item.fields.quantity }}{% endif %}</td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if not no_missing %}
|
||||
<td data-sort="{{ item.fields.total_missing }}" class="table-td-input">
|
||||
{{ form.input('Missing', item.fields.id, item.html_id(), item.url_for_missing(), item.fields.total_missing, all=all, read_only=read_only) }}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td data-sort="{{ item.fields.total_missing }}" class="table-td-input">
|
||||
{{ form.input('Missing', item.fields.id, item.html_id('missing'), item.url_for_problem('missing'), item.fields.total_missing, all=all, read_only=read_only) }}
|
||||
</td>
|
||||
<td data-sort="{{ item.fields.total_damaged }}" class="table-td-input">
|
||||
{{ form.input('Damaged', item.fields.id, item.html_id('damaged'), item.url_for_problem('damaged'), item.fields.total_damaged, all=all, read_only=read_only) }}
|
||||
</td>
|
||||
{% if all %}
|
||||
<td>{{ item.fields.total_sets }}</td>
|
||||
<td>{{ item.fields.total_minifigures }}</td>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %} - Missing parts{% endblock %}
|
||||
{% block title %} - Problematic parts{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="container-fluid px-0">
|
@ -6,8 +6,11 @@
|
||||
<div {% if not solo %}id="set-{{ item.fields.id }}"{% endif %} class="card mb-3 flex-fill {% if solo %}card-solo{% endif %}"
|
||||
{% if not solo %}
|
||||
data-index="{{ index }}" data-number="{{ item.fields.set }}" data-name="{{ item.fields.name | lower }}" data-parts="{{ item.fields.number_of_parts }}"
|
||||
data-year="{{ item.fields.year }}" data-theme="{{ item.theme.name | lower }}" data-minifigures="{{ item.fields.total_minifigures }}" data-has-minifigures="{{ (item.fields.total_minifigures > 0) | int }}"
|
||||
data-has-missing="{{ (item.fields.total_missing > 0) | int }}" data-has-missing-instructions="{{ (not (item.instructions | length)) | int }}" data-missing="{{ item.fields.total_missing }}"
|
||||
data-year="{{ item.fields.year }}" data-theme="{{ item.theme.name | lower }}"
|
||||
data-has-missing-instructions="{{ (not (item.instructions | length)) | int }}"
|
||||
data-has-minifigures="{{ (item.fields.total_minifigures > 0) | int }}" data-minifigures="{{ item.fields.total_minifigures }}"
|
||||
data-has-missing="{{ (item.fields.total_missing > 0) | int }}" data-missing="{{ item.fields.total_missing }}"
|
||||
data-has-damaged="{{ (item.fields.total_damaged > 0) | int }}" data-damaged="{{ item.fields.total_damaged }}"
|
||||
{% for status in brickset_statuses %}
|
||||
{% with checked=item.fields[status.as_column()] %}
|
||||
{% if checked %}
|
||||
@ -42,6 +45,7 @@
|
||||
{{ badge.parts(item.fields.number_of_parts, solo=solo, last=last) }}
|
||||
{{ badge.total_minifigures(item.fields.total_minifigures, solo=solo, last=last) }}
|
||||
{{ badge.total_missing(item.fields.total_missing, solo=solo, last=last) }}
|
||||
{{ badge.total_damaged(item.fields.total_damaged, solo=solo, last=last) }}
|
||||
{% for owner in brickset_owners %}
|
||||
{{ badge.owner(item, owner, solo=solo, last=last) }}
|
||||
{% endfor %}
|
||||
|
@ -29,7 +29,9 @@
|
||||
<button id="sort-parts" type="button" class="btn btn-outline-primary"
|
||||
data-sort-attribute="parts" data-sort-desc="true"><i class="ri-shapes-line"></i><span class="d-none d-xxl-inline"> Parts</span></button>
|
||||
<button id="sort-missing" type="button" class="btn btn-outline-primary"
|
||||
data-sort-attribute="missing" data-sort-desc="true"><i class="ri-error-warning-line"></i><span class="d-none d-xxl-inline"> Missing</span></button>
|
||||
data-sort-attribute="missing" data-sort-desc="true"><i class="ri-question-line"></i><span class="d-none d-xxl-inline"> Missing</span></button>
|
||||
<button id="sort-damaged" type="button" class="btn btn-outline-primary"
|
||||
data-sort-attribute="damaged" data-sort-desc="true"><i class="ri-error-warning-line"></i><span class="d-none d-xxl-inline"> Damaged</span></button>
|
||||
<button id="sort-clear" type="button" class="btn btn-outline-dark"
|
||||
data-sort-clear="true"><i class="ri-close-circle-line"></i><span class="d-none d-xxl-inline"> Clear</span></button>
|
||||
</div>
|
||||
@ -53,6 +55,7 @@
|
||||
<option value="" selected>All</option>
|
||||
<option value="-has-missing">Set is complete</option>
|
||||
<option value="has-missing">Set has missing pieces</option>
|
||||
<option value="has-damaged">Set has damaged pieces</option>
|
||||
<option value="has-missing-instructions">Set has missing instructions</option>
|
||||
{% for status in brickset_statuses %}
|
||||
<option value="{{ status.as_dataset() }}">{{ status.fields.name }}</option>
|
||||
|
Loading…
Reference in New Issue
Block a user