Refactor brand and item models to introduce 'identifier' property for consistency; update dropdown rendering in templates to utilize new properties and improve input handling.
This commit is contained in:
parent
8631e4082c
commit
9242ce6eab
5 changed files with 52 additions and 58 deletions
|
@ -23,13 +23,13 @@ class Brand(ValidatableMixin, db.Model):
|
|||
|
||||
def __repr__(self):
|
||||
return f"<Brand(id={self.id}, name={repr(self.name)})>"
|
||||
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name
|
||||
}
|
||||
|
||||
|
||||
@classmethod
|
||||
def sync_from_state(cls, submitted_items: list[dict]) -> dict[str, int]:
|
||||
submitted_clean = []
|
||||
|
@ -93,7 +93,7 @@ class Brand(ValidatableMixin, db.Model):
|
|||
if not isinstance(item, dict):
|
||||
errors.append(f"Area entry #{index + 1} is not a valid object.")
|
||||
continue
|
||||
|
||||
|
||||
name = item.get('name')
|
||||
if not name or not str(name).strip():
|
||||
errors.append(f"Area entry #{index + 1} is missing a name.")
|
||||
|
@ -107,3 +107,7 @@ class Brand(ValidatableMixin, db.Model):
|
|||
errors.append(f"Area entry #{index + 1} has invalid ID: {raw_id}")
|
||||
|
||||
return errors
|
||||
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
return self.name if self.name else f"ID: {self.id}"
|
||||
|
|
|
@ -42,6 +42,7 @@ class Inventory(db.Model, ImageAttachable):
|
|||
item: Mapped['Item'] = relationship('Item', back_populates='inventory')
|
||||
work_logs: Mapped[List['WorkLog']] = relationship('WorkLog', back_populates='work_item')
|
||||
image: Mapped[Optional['Image']] = relationship('Image', back_populates='inventory', passive_deletes=True)
|
||||
type: Mapped[Optional['Item']] = relationship('Item', back_populates='inventory')
|
||||
|
||||
def __init__(self, timestamp: datetime.datetime, condition: str, type_id: Optional[int] = None,
|
||||
name: Optional[str] = None, serial: Optional[str] = None,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from typing import List, Optional, TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from .inventory import Inventory
|
||||
from .inventory import Inventory
|
||||
|
||||
from sqlalchemy import Identity, Integer, Unicode
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
@ -20,18 +20,21 @@ class Item(ValidatableMixin, db.Model):
|
|||
|
||||
def __init__(self, description: Optional[str] = None, category: Optional[str] = None):
|
||||
self.description = description
|
||||
self.category = category
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Item(id={self.id}, description={repr(self.description)}, category={repr(self.category)})>"
|
||||
|
||||
return f"<Item(id={self.id}, description={repr(self.description)})>"
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.description,
|
||||
'category': self.category
|
||||
}
|
||||
|
||||
|
||||
@property
|
||||
def identifier(self):
|
||||
return self.description if self.description else f"Item {self.id}"
|
||||
|
||||
@classmethod
|
||||
def sync_from_state(cls, submitted_items: list[dict]) -> dict[str, int]:
|
||||
submitted_clean = []
|
||||
|
@ -84,7 +87,7 @@ class Item(ValidatableMixin, db.Model):
|
|||
**{str(temp): real for temp, real in temp_id_map.items()}
|
||||
}
|
||||
return id_map
|
||||
|
||||
|
||||
@classmethod
|
||||
def validate_state(cls, submitted_items: list[dict]) -> list[str]:
|
||||
errors = []
|
||||
|
@ -93,7 +96,7 @@ class Item(ValidatableMixin, db.Model):
|
|||
if not isinstance(item, dict):
|
||||
errors.append(f"Area entry #{index + 1} is not a valid object.")
|
||||
continue
|
||||
|
||||
|
||||
name = item.get('name')
|
||||
if not name or not str(name).strip():
|
||||
errors.append(f"Area entry #{index + 1} is missing a name.")
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<div class="dropdown">
|
||||
<button class="btn btn-outline-dark dropdown-toggle w-100" type="button" data-bs-toggle="dropdown"
|
||||
data-inv-value="{{ current_item.id if current_item else '' }}" id="{{ id }}Button"{% if not enabled %} disabled{% endif %}
|
||||
style="border-color: rgb(222, 226, 230);{% if not enabled %}background-color: rgb(233, 236, 239); color: rgb(0, 0, 0);{% endif %}">
|
||||
style="border-color: rgb(222, 226, 230);{% if not enabled %} background-color: rgb(233, 236, 239); color: rgb(0, 0, 0);{% endif %}">
|
||||
{{ current_item.identifier if current_item else '-' }}
|
||||
</button>
|
||||
<input type="hidden" name="{{ id }}" id="{{ id }}" value="{{ current_item.id if current_item else '' }}">
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
const payload = {
|
||||
timestamp: document.querySelector("input[name='timestamp']").value,
|
||||
condition: document.querySelector("select[name='condition']").value,
|
||||
type_id: parseInt(document.querySelector("select[name='type']").value),
|
||||
type_id: parseInt(document.querySelector("input[name='type']").value),
|
||||
name: document.querySelector("input[name='name']").value || null,
|
||||
serial: document.querySelector("input[name='serial']").value || null,
|
||||
model: document.querySelector("input[name='model']").value || null,
|
||||
notes: document.querySelector("textarea[name='editornotes']").value || null,
|
||||
owner_id: parseInt(document.querySelector("select#userList").value) || null,
|
||||
brand_id: parseInt(document.querySelector("select[name='brand']").value) || null,
|
||||
location_id: parseInt(document.querySelector("select#room").value) || null,
|
||||
owner_id: parseInt(document.querySelector("input[name='owner']").value) || null,
|
||||
brand_id: parseInt(document.querySelector("input[name='brand']").value) || null,
|
||||
location_id: parseInt(document.querySelector("input[name='room']").value) || null,
|
||||
barcode: document.querySelector("input[name='barcode']").value || null,
|
||||
shared: document.querySelector("input[name='shared']").checked
|
||||
};
|
||||
|
@ -167,16 +167,13 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<label for="brand" class="form-label">Brand</label>
|
||||
<select class="form-select" id="brand" name="brand" {% if item.condition in ["Removed", "Disposed" ]
|
||||
%} disabled{% endif %}>
|
||||
<option>-</option>
|
||||
{% for brand in brands %}
|
||||
<option value="{{ brand.id }}" {% if brand.id==item.brand_id %} selected{% endif %}>{{
|
||||
brand.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ dropdowns.render_dropdown(
|
||||
id='brand',
|
||||
list=brands,
|
||||
label='Brand',
|
||||
current_item=item.brand,
|
||||
enabled=item.condition not in ["Removed", "Disposed"]
|
||||
) }}
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label for="model" class="form-label">Model</label>
|
||||
|
@ -185,45 +182,34 @@
|
|||
%} disabled{% endif %}>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label for="type" class="form-label">Category</label>
|
||||
<select name="type" id="type" class="form-select" {% if item.condition in ["Removed", "Disposed" ]
|
||||
%} disabled{% endif %}>
|
||||
<option>-</option>
|
||||
{% for t in types %}
|
||||
<option value="{{ t.id }}" {% if t.id==item.type_id %} selected{% endif %}>{{ t.description }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ dropdowns.render_dropdown(
|
||||
id='type',
|
||||
list=types,
|
||||
label='Category',
|
||||
current_item=item.type,
|
||||
enabled=item.condition not in ["Removed", "Disposed"]
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<label for="owner" class="form-label">
|
||||
Contact
|
||||
{% if item.owner %}
|
||||
{{ links.entry_link('user', item.owner_id) }}
|
||||
{% endif %}
|
||||
</label>
|
||||
<select class="form-select" id="userList" {% if item.condition in ["Removed", "Disposed" ] %}
|
||||
disabled{% endif %}>
|
||||
<option>-</option>
|
||||
{% for user in users %}
|
||||
<option value="{{ user.id }}" {% if user.id==item.owner_id %} selected{% endif %}>{{
|
||||
user.identifier
|
||||
}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ dropdowns.render_dropdown(
|
||||
id='owner',
|
||||
list=users,
|
||||
label='Contact',
|
||||
current_item=item.owner,
|
||||
entry_link='user',
|
||||
enabled=item.condition not in ["Removed", "Disposed"]
|
||||
) }}
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label for="location" class="form-label">Location</label>
|
||||
<select class="form-select" id="room" {% if item.condition in ["Removed", "Disposed" ] %} disabled{%
|
||||
endif %}>
|
||||
<option>-</option>
|
||||
{% for room in rooms %}
|
||||
<option value="{{ room.id }}" {% if room.id==item.location_id %} selected{% endif %}>{{
|
||||
room.identifier }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ dropdowns.render_dropdown(
|
||||
id='room',
|
||||
list=rooms,
|
||||
label='Location',
|
||||
current_item=item.location,
|
||||
enabled=item.condition not in ["Removed", "Disposed"]
|
||||
) }}
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<label for="condition" class="form-label">Condition</label>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue