Creation logic!
This commit is contained in:
parent
2502375d32
commit
21a3399ecd
6 changed files with 45 additions and 10 deletions
|
|
@ -653,9 +653,13 @@ class CRUDService(Generic[T]):
|
||||||
session = self.session
|
session = self.session
|
||||||
obj = self.model(**data)
|
obj = self.model(**data)
|
||||||
session.add(obj)
|
session.add(obj)
|
||||||
|
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
self._log_version("create", obj, actor, commit=commit)
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
session.commit()
|
session.commit()
|
||||||
self._log_version("create", obj, actor, commit=commit)
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def update(self, id: int, data: dict, actor=None, *, commit: bool = True) -> T:
|
def update(self, id: int, data: dict, actor=None, *, commit: bool = True) -> T:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from typing import List, Optional
|
||||||
|
|
||||||
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Unicode, case, cast, func
|
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Unicode, case, cast, func
|
||||||
from sqlalchemy.ext.hybrid import hybrid_property
|
from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
from sqlalchemy.orm import Mapped, mapped_column, relationship, synonym
|
||||||
from sqlalchemy.sql import expression as sql
|
from sqlalchemy.sql import expression as sql
|
||||||
|
|
||||||
from crudkit.core.base import Base, CRUDMixin
|
from crudkit.core.base import Base, CRUDMixin
|
||||||
|
|
@ -21,13 +21,14 @@ class Inventory(Base, CRUDMixin):
|
||||||
model: Mapped[Optional[str]] = mapped_column(Unicode(255))
|
model: Mapped[Optional[str]] = mapped_column(Unicode(255))
|
||||||
notes: Mapped[Optional[str]] = mapped_column(Unicode(255))
|
notes: Mapped[Optional[str]] = mapped_column(Unicode(255))
|
||||||
shared: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false())
|
shared: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false())
|
||||||
timestamp: Mapped[DateTime] = mapped_column(DateTime)
|
timestamp: Mapped[DateTime] = mapped_column(DateTime, default=func.now(), nullable=False)
|
||||||
|
|
||||||
brand: Mapped[Optional['Brand']] = relationship('Brand', back_populates='inventory')
|
brand: Mapped[Optional['Brand']] = relationship('Brand', back_populates='inventory')
|
||||||
brand_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey('brand.id'), nullable=True, index=True)
|
brand_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey('brand.id'), nullable=True, index=True)
|
||||||
|
|
||||||
device_type: Mapped[Optional['DeviceType']] = relationship('DeviceType', back_populates='inventory')
|
device_type: Mapped[Optional['DeviceType']] = relationship('DeviceType', back_populates='inventory')
|
||||||
type_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("item.id"), nullable=True, index=True)
|
type_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("item.id"), nullable=True, index=True)
|
||||||
|
device_type_id = synonym("type_id")
|
||||||
|
|
||||||
image: Mapped[Optional['Image']] = relationship('Image', back_populates='inventory', passive_deletes=True)
|
image: Mapped[Optional['Image']] = relationship('Image', back_populates='inventory', passive_deletes=True)
|
||||||
image_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey('images.id', ondelete='SET NULL'), nullable=True, index=True)
|
image_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey('images.id', ondelete='SET NULL'), nullable=True, index=True)
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,14 @@ def init_entry_routes(app):
|
||||||
updates = payload.pop("updates", []) or []
|
updates = payload.pop("updates", []) or []
|
||||||
payload.pop("delete_update_ids", None) # irrelevant on create
|
payload.pop("delete_update_ids", None) # irrelevant on create
|
||||||
|
|
||||||
|
if model == "inventory":
|
||||||
|
if "device_type_id" in payload and "type_id" not in payload:
|
||||||
|
payload["type_id"] = payload.pop("device_type_id")
|
||||||
|
for k in ("brand_id", "type_id", "owner_id", "location_id", "image_id"):
|
||||||
|
if payload.get(k) == "":
|
||||||
|
payload[k] = None
|
||||||
|
# payload["timestamp"] = datetime.now()
|
||||||
|
|
||||||
if model == "worklog":
|
if model == "worklog":
|
||||||
if "contact" in payload and "contact_id" not in payload:
|
if "contact" in payload and "contact_id" not in payload:
|
||||||
payload["contact_id"] = payload.pop("contact")
|
payload["contact_id"] = payload.pop("contact")
|
||||||
|
|
@ -279,7 +287,28 @@ def init_entry_routes(app):
|
||||||
|
|
||||||
params = {}
|
params = {}
|
||||||
if model == "inventory":
|
if model == "inventory":
|
||||||
pass
|
if "device_type_id" in payload:
|
||||||
|
payload["type_id"] = payload.pop("device_type_id")
|
||||||
|
for k in ("brand_id", "type_id", "owner_id", "location_id", "image_id"):
|
||||||
|
if payload.get(k) == "":
|
||||||
|
payload[k] = None
|
||||||
|
params = {
|
||||||
|
"fields": [
|
||||||
|
"barcode",
|
||||||
|
"name",
|
||||||
|
"serial",
|
||||||
|
"condition",
|
||||||
|
"model",
|
||||||
|
"notes",
|
||||||
|
"shared",
|
||||||
|
"timestamp",
|
||||||
|
"brand_id",
|
||||||
|
"type_id",
|
||||||
|
"image_id",
|
||||||
|
"location_id",
|
||||||
|
"owner_id",
|
||||||
|
]
|
||||||
|
}
|
||||||
elif model == "user":
|
elif model == "user":
|
||||||
params = {
|
params = {
|
||||||
"fields": [
|
"fields": [
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<label class="form-label">Notes</label>
|
<label class="form-label">Notes</label>
|
||||||
<div class="d-flex justify-content-between align-items-start">
|
<div class="d-flex justify-content-between align-items-start">
|
||||||
<div class="me-3 w-100 markdown-body" id="editContainer"></div>
|
<div class="me-3 w-100 markdown-body" id="editContainer"></div>
|
||||||
<script type="application/json" id="noteContent">{{ field['template_ctx']['values']['notes'] | tojson }}</script>
|
<script type="application/json" id="noteContent">{{ (field['template_ctx']['values']['notes'] if field['template_ctx']['values']['notes'] else '') | tojson }}</script>
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input type="checkbox" class="form-check-input" id="editSwitch" onchange="changeMode()" role="switch"
|
<input type="checkbox" class="form-check-input" id="editSwitch" onchange="changeMode()" role="switch"
|
||||||
aria-label="Edit mode switch for inventory notes.">
|
aria-label="Edit mode switch for inventory notes.">
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (field-sizing: content) {
|
@supports (field-sizing: content) {
|
||||||
text-area.auto-md {
|
textarea.auto-md {
|
||||||
field-sizing: content;
|
field-sizing: content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
function getMarkdown() {
|
function getMarkdown() {
|
||||||
const el = document.getElementById('noteContent');
|
const el = document.getElementById('noteContent');
|
||||||
return el ? JSON.parse(el.textContent) : "";
|
return el ? (JSON.parse(el.textContent) || "") : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMarkdown(md) {
|
function setMarkdown(md) {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,8 @@
|
||||||
const json = formToJson(formEl);
|
const json = formToJson(formEl);
|
||||||
|
|
||||||
if (model === 'inventory' && typeof getMarkdown === 'function') {
|
if (model === 'inventory' && typeof getMarkdown === 'function') {
|
||||||
json.notes = getMarkdown().trim();
|
const md = getMarkdown();
|
||||||
|
json.notes = (typeof md === 'string') ? getMarkdown().trim() : '';
|
||||||
} else if (model === 'worklog') {
|
} else if (model === 'worklog') {
|
||||||
json.updates = collectEditedUpdates();
|
json.updates = collectEditedUpdates();
|
||||||
json.delete_update_ids = collectDeletedIds();
|
json.delete_update_ids = collectDeletedIds();
|
||||||
|
|
@ -85,7 +86,7 @@
|
||||||
window.newDrafts = [];
|
window.newDrafts = [];
|
||||||
window.deletedIds = [];
|
window.deletedIds = [];
|
||||||
if (!hasId && reply.id) {
|
if (!hasId && reply.id) {
|
||||||
window.location.href = `/entry/${model}/${reply.id}?pretty=1`;
|
window.location.href = `/entry/${model}/${reply.id}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toastMessage(`Unable to save entry: ${reply.error}`, 'danger');
|
toastMessage(`Unable to save entry: ${reply.error}`, 'danger');
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (field-sizing: content) {
|
@supports (field-sizing: content) {
|
||||||
text-area.auto-md {
|
textarea.auto-md {
|
||||||
field-sizing: content;
|
field-sizing: content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue