| ← Back to Main Documentation | Core Systems Index |
Set Object Scanning Workflows
This document defines the scanning workflows for managing Set Objects through component scanning, addressing the fundamental constraint that sets cannot have physical identifiers.
Core Constraint: No Direct Set Scanning
Set objects cannot have PlingsIdentifiers because they are logical groupings, not physical objects. Only individual components can have QR codes, NFC tags, or other physical identifiers.
Implication: All set operations must be accessed through component scanning workflows.
Scanning Workflow Patterns
1. Component Scan Detection
When a component with a PlingsIdentifier is scanned:
// Component scan detection
MATCH (identifier:PlingsIdentifier {key: $scannedKey})-[:IDENTIFIES]->(component:ObjectInstance)
OPTIONAL MATCH (component)-[:PART_OF]->(setObject:ObjectInstance)
RETURN {
component: component,
parentSet: setObject,
hasSet: setObject IS NOT NULL,
availableActions: CASE
WHEN setObject IS NOT NULL THEN ["WORK_WITH_COMPONENT", "WORK_WITH_SET"]
ELSE ["WORK_WITH_COMPONENT"]
END
}
2. User Choice Prompt
If component is part of a set:
┌─────────────────────────────────────────────┐
│ Scanned: Left Ski Glove │
│ Part of: My Ski Gloves │
│ │
│ Choose operation scope: │
│ ○ Work with Left Ski Glove only │
│ ● Work with entire My Ski Gloves set │
│ │
│ [Continue] [Cancel] │
└─────────────────────────────────────────────┘
If component is not part of a set:
┌─────────────────────────────────────────────┐
│ Scanned: Standalone Wrench │
│ │
│ Proceeding with individual object... │
└─────────────────────────────────────────────┘
3. Operation Execution
3a. Component-Only Operations
Move Component Only:
// Update only the scanned component
MATCH (component:ObjectInstance {id: $componentId})
MATCH (newLocation:ObjectInstance {id: $newLocationId})
// Remove old spatial relationship
OPTIONAL MATCH (component)-[old:CURRENT_IN|CURRENT_ON|CURRENT_ATTACHED_TO]-()
DELETE old
// Create new spatial relationship
CREATE (component)-[:CURRENT_IN]->(newLocation)
RETURN component, newLocation
3b. Set-Level Operations
Move Entire Set:
// Update all components in the set
MATCH (setObject:ObjectInstance {id: $setId})<-[:PART_OF]-(component:ObjectInstance)
MATCH (newLocation:ObjectInstance {id: $newLocationId})
// Remove old spatial relationships for all components
OPTIONAL MATCH (component)-[old:CURRENT_IN|CURRENT_ON|CURRENT_ATTACHED_TO]-()
DELETE old
// Create new spatial relationships for all components
CREATE (component)-[:CURRENT_IN]->(newLocation)
RETURN COUNT(component) as movedComponents
Detailed Workflow Examples
Example 1: Moving Ski Gloves
Step 1: Scan Component
User scans QR code on left ski glove
System identifies: "Left Ski Glove" (part of "My Ski Gloves" set)
Step 2: Choose Scope
UI presents choice:
- Work with "Left Ski Glove" only
- Work with entire "My Ski Gloves" set
User selects: "Work with entire set"
Step 3: Scan Target Location
UI prompts: "Scan location where My Ski Gloves should be moved"
User scans: Gear bag QR code
System identifies: "Main Gear Bag"
Step 4: Confirm and Execute
UI shows confirmation:
"Move My Ski Gloves (2 items) to Main Gear Bag?"
- Left Ski Glove → Main Gear Bag
- Right Ski Glove → Main Gear Bag
User confirms: Yes
System executes:
- Updates both gloves' CURRENT_IN relationships to gear bag
- Records movement timestamp
- Updates spatial hierarchy for both components
Step 5: Result
// After move operation
(:LeftSkiGlove)-[:CURRENT_IN]->(:MainGearBag)
(:RightSkiGlove)-[:CURRENT_IN]->(:MainGearBag)
// Set maintains logical relationship
(:MySkiGloves)<-[:PART_OF]-(:LeftSkiGlove)
(:MySkiGloves)<-[:PART_OF]-(:RightSkiGlove)
Example 2: Individual Component Operation
Scenario: Taking one glove for repair while leaving other in set location
Step 1: Scan Component
User scans right ski glove
System identifies: "Right Ski Glove" (part of "My Ski Gloves" set)
Step 2: Choose Scope
User selects: "Work with Right Ski Glove only"
Step 3: Scan Target Location
User scans: Repair shop location
System identifies: "Equipment Repair Station"
Step 4: Execute Individual Move
// Only right glove moves
(:RightSkiGlove)-[:CURRENT_IN]->(:RepairStation)
// Left glove remains in original location
(:LeftSkiGlove)-[:CURRENT_IN]->(:MainGearBag)
// Set relationship unchanged
(:MySkiGloves)<-[:PART_OF]-(:LeftSkiGlove)
(:MySkiGloves)<-[:PART_OF]-(:RightSkiGlove)
Example 3: Distributed Set Status
Scenario: Checking location of distributed set components
Query Set Status:
MATCH (set:ObjectInstance {name: "My Ski Gloves"})<-[:PART_OF]-(component:ObjectInstance)
OPTIONAL MATCH (component)-[:CURRENT_IN|CURRENT_ON]->(location:ObjectInstance)
RETURN {
setName: set.name,
components: COLLECT({
componentName: component.name,
currentLocation: location.name,
locationId: location.id
}),
isUnified: COUNT(DISTINCT location.id) = 1,
locationCount: COUNT(DISTINCT location.id)
}
Example Result:
{
"setName": "My Ski Gloves",
"components": [
{
"componentName": "Left Ski Glove",
"currentLocation": "Main Gear Bag",
"locationId": "gear-bag-1"
},
{
"componentName": "Right Ski Glove",
"currentLocation": "Equipment Repair Station",
"locationId": "repair-station-1"
}
],
"isUnified": false,
"locationCount": 2
}
GraphQL API Integration
Scan Result Type
type ScanResult {
component: ObjectInstance!
parentSet: ObjectInstance
hasSet: Boolean!
availableActions: [ScanAction!]!
}
enum ScanAction {
WORK_WITH_COMPONENT
WORK_WITH_SET
}
Movement Mutations
type Mutation {
# Scan identifier and get context
scanIdentifier(identifierKey: String!): ScanResult!
# Move individual component
moveComponent(
componentId: ID!
newLocationId: ID!
relationshipType: SpatialRelationshipType = CURRENT_IN
): ComponentMoveResult!
# Move entire set via component scan
moveSet(
setId: ID!
newLocationId: ID!
relationshipType: SpatialRelationshipType = CURRENT_IN
): SetMoveResult!
}
type ComponentMoveResult {
component: ObjectInstance!
newLocation: ObjectInstance!
updatedAt: DateTime!
}
type SetMoveResult {
set: ObjectInstance!
components: [ObjectInstance!]!
newLocation: ObjectInstance!
movedCount: Int!
updatedAt: DateTime!
}
Query Set Status
type ObjectInstance {
# ... existing fields
# Set-specific fields
isSet: Boolean!
componentLocations: [ComponentLocation!]
isLocationUnified: Boolean
locationSummary: String
}
type ComponentLocation {
component: ObjectInstance!
currentLocation: ObjectInstance
spatialHierarchy: [SpatialReference!]
}
UI Implementation Guidelines
1. Scan Flow Components
ScanResultModal Component:
- Shows scanned component details
- Displays parent set information if applicable
- Provides action selection (component vs set)
SetActionSelector Component:
- Radio button selection for operation scope
- Clear labeling of what will be affected
- Preview of components that will be moved
2. Confirmation Workflows
MoveConfirmationDialog:
- Lists all objects that will be affected
- Shows source and target locations
- Provides clear “Cancel” option before execution
3. Status Displays
SetStatusCard:
- Shows unified vs distributed status
- Lists component locations when distributed
- Provides quick actions for reunifying set
4. Error Handling
Common Error Scenarios:
- Component not found
- Set has missing components
- Location not accessible
- Permission denied for set operations
Performance Considerations
1. Query Optimization
- Index on
PART_OFrelationships for fast set membership checks - Cache set component lists for frequently accessed sets
- Batch location updates for set operations
2. UI Responsiveness
- Progressive loading for large sets
- Optimistic UI updates with rollback on failure
- Background status updates for distributed sets
3. Scanning Performance
- Fast identifier lookup with proper indexing
- Minimal query complexity for scan detection
- Efficient component counting for large sets
Related Documentation
- Relationship Decision Guide - When to use Set Objects
- PlingsIdentifier System - Physical identifier constraints
- Spatial Relationships System - Spatial relationship mechanics
Implementation Checklist
Backend Requirements
- Scan detection query with set membership
- Component vs set operation mutations
- Set status aggregation queries
- Validation for set operation permissions
Frontend Requirements
- Scan result modal with action selection
- Set vs component choice UI
- Move confirmation with affected items list
- Set status display components
Database Requirements
- Proper indexing on PART_OF relationships
- Performance testing with large sets
- Transaction handling for set operations