fix: prevent duplicate item creation with barcode conflict detection
Backend: - Added UNIQUE constraint check on barcode before item creation - Returns 409 Conflict with user-friendly message if duplicate exists - Prevents sqlite3.IntegrityError crashes Frontend: - Improved error handling for cloud sync failures - Detects 409 status code (duplicate barcode) - Shows specific error message to user - Gracefully falls back to local-only save Example error message: 'Item already exists. Item with barcode P66093-002 already exists (ID: 42). Update it instead or use a different barcode.'
This commit is contained in:
@@ -97,6 +97,15 @@ def create_item(
|
|||||||
current_user: auth.TokenData = Depends(auth.get_current_user)
|
current_user: auth.TokenData = Depends(auth.get_current_user)
|
||||||
):
|
):
|
||||||
"""[C-01] Create item — only for authenticated users. [M-02] user_id from token."""
|
"""[C-01] Create item — only for authenticated users. [M-02] user_id from token."""
|
||||||
|
# [DUPLICATE CHECK] Prevent duplicate barcodes (part numbers)
|
||||||
|
if item.barcode:
|
||||||
|
existing = db.query(models.Item).filter(models.Item.barcode == item.barcode).first()
|
||||||
|
if existing:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=409,
|
||||||
|
detail=f"Item with barcode '{item.barcode}' already exists (ID: {existing.id}). Update it instead or use a different barcode."
|
||||||
|
)
|
||||||
|
|
||||||
# [AUTO-PERSIST] Create Category/Color if not exists
|
# [AUTO-PERSIST] Create Category/Color if not exists
|
||||||
if item.category:
|
if item.category:
|
||||||
cat = db.query(models.Category).filter(models.Category.name == item.category).first()
|
cat = db.query(models.Category).filter(models.Category.name == item.category).first()
|
||||||
|
|||||||
@@ -170,9 +170,16 @@ export default function Home() {
|
|||||||
await inventoryApi.createItem(currentUser.id, itemData);
|
await inventoryApi.createItem(currentUser.id, itemData);
|
||||||
toast.success("Item saved to cloud catalog!");
|
toast.success("Item saved to cloud catalog!");
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Cloud sync failed:", err.message);
|
const status = err.response?.status;
|
||||||
|
const detail = err.response?.data?.detail || err.message;
|
||||||
|
console.error("Cloud sync failed:", detail);
|
||||||
|
|
||||||
|
if (status === 409) {
|
||||||
|
toast.error(`Item already exists. ${detail}`);
|
||||||
|
} else {
|
||||||
toast.error("Item saved locally. Cloud sync failed.");
|
toast.error("Item saved locally. Cloud sync failed.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (!isOnline) {
|
} else if (!isOnline) {
|
||||||
toast.success("Item saved locally. Will sync when online.");
|
toast.success("Item saved locally. Will sync when online.");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user