Major restructure: Remove Confluence, add V2 data structure, organize for dev/prod
- Import real data from PDF (35 Bambu Lab filaments) - Remove all Confluence integration and dependencies - Implement new V2 data structure with proper inventory tracking - Add backwards compatibility for existing data - Create enhanced UI components (ColorSwatch, InventoryBadge, MaterialBadge) - Add advanced filtering with quick filters and multi-criteria search - Organize codebase for dev/prod environments - Update Lambda functions to support both V1/V2 formats - Add inventory summary dashboard - Clean up project structure and documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
255
docs/DATA_STRUCTURE_PROPOSAL.md
Normal file
255
docs/DATA_STRUCTURE_PROPOSAL.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Improved Data Structure Proposal
|
||||
|
||||
## Current Issues
|
||||
1. Mixed languages (English/Serbian)
|
||||
2. String fields for numeric/boolean values
|
||||
3. Inconsistent status representation
|
||||
4. No proper inventory tracking
|
||||
5. Missing important metadata
|
||||
|
||||
## Proposed Structure
|
||||
|
||||
```typescript
|
||||
interface Filament {
|
||||
// Identifiers
|
||||
id: string;
|
||||
sku?: string; // For internal tracking
|
||||
|
||||
// Product Info
|
||||
brand: string;
|
||||
type: 'PLA' | 'PETG' | 'ABS' | 'TPU' | 'SILK' | 'CF' | 'WOOD';
|
||||
material: {
|
||||
base: 'PLA' | 'PETG' | 'ABS' | 'TPU';
|
||||
modifier?: 'Silk' | 'Matte' | 'Glow' | 'Wood' | 'CF';
|
||||
};
|
||||
color: {
|
||||
name: string;
|
||||
hex?: string; // Color code for UI display
|
||||
pantone?: string; // For color matching
|
||||
};
|
||||
|
||||
// Physical Properties
|
||||
weight: {
|
||||
value: number; // 1000 for 1kg, 500 for 0.5kg
|
||||
unit: 'g' | 'kg';
|
||||
};
|
||||
diameter: number; // 1.75 or 2.85
|
||||
|
||||
// Inventory Status
|
||||
inventory: {
|
||||
total: number; // Total spools
|
||||
available: number; // Available for use
|
||||
inUse: number; // Currently being used
|
||||
locations: {
|
||||
vacuum: number; // In vacuum storage
|
||||
opened: number; // Opened but usable
|
||||
printer: number; // Loaded in printer
|
||||
};
|
||||
};
|
||||
|
||||
// Purchase Info
|
||||
pricing: {
|
||||
purchasePrice?: number;
|
||||
currency: 'RSD' | 'EUR' | 'USD';
|
||||
supplier?: string;
|
||||
purchaseDate?: string;
|
||||
};
|
||||
|
||||
// Condition
|
||||
condition: {
|
||||
isRefill: boolean;
|
||||
openedDate?: string;
|
||||
expiryDate?: string;
|
||||
storageCondition: 'vacuum' | 'sealed' | 'opened' | 'desiccant';
|
||||
humidity?: number; // Last measured
|
||||
};
|
||||
|
||||
// Metadata
|
||||
tags: string[]; // ['premium', 'engineering', 'easy-print']
|
||||
notes?: string; // Special handling instructions
|
||||
images?: string[]; // S3 URLs for photos
|
||||
|
||||
// Timestamps
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
lastUsed?: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### 1. **Better Filtering**
|
||||
```typescript
|
||||
// Find all sealed PLA under 1kg
|
||||
filaments.filter(f =>
|
||||
f.material.base === 'PLA' &&
|
||||
f.weight.value <= 1000 &&
|
||||
f.condition.storageCondition === 'vacuum'
|
||||
)
|
||||
```
|
||||
|
||||
### 2. **Inventory Management**
|
||||
```typescript
|
||||
// Get total available filament weight
|
||||
const totalWeight = filaments.reduce((sum, f) =>
|
||||
sum + (f.inventory.available * f.weight.value), 0
|
||||
);
|
||||
|
||||
// Find low stock items
|
||||
const lowStock = filaments.filter(f =>
|
||||
f.inventory.available <= 1 && f.inventory.total > 0
|
||||
);
|
||||
```
|
||||
|
||||
### 3. **Color Management**
|
||||
```typescript
|
||||
// Group by color for visualization
|
||||
const colorGroups = filaments.reduce((groups, f) => {
|
||||
const color = f.color.name;
|
||||
groups[color] = groups[color] || [];
|
||||
groups[color].push(f);
|
||||
return groups;
|
||||
}, {});
|
||||
```
|
||||
|
||||
### 4. **Usage Tracking**
|
||||
```typescript
|
||||
// Find most used filaments
|
||||
const mostUsed = filaments
|
||||
.filter(f => f.lastUsed)
|
||||
.sort((a, b) => new Date(b.lastUsed) - new Date(a.lastUsed))
|
||||
.slice(0, 10);
|
||||
```
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: Add New Fields (Non-breaking)
|
||||
```javascript
|
||||
// Update Lambda to handle both old and new structure
|
||||
const migrateFilament = (old) => ({
|
||||
...old,
|
||||
material: {
|
||||
base: old.tip || 'PLA',
|
||||
modifier: old.finish !== 'Basic' ? old.finish : undefined
|
||||
},
|
||||
color: {
|
||||
name: old.boja
|
||||
},
|
||||
weight: {
|
||||
value: 1000, // Default 1kg
|
||||
unit: 'g'
|
||||
},
|
||||
inventory: {
|
||||
total: parseInt(old.kolicina) || 1,
|
||||
available: old.otvoreno ? 0 : 1,
|
||||
inUse: 0,
|
||||
locations: {
|
||||
vacuum: old.vakum ? 1 : 0,
|
||||
opened: old.otvoreno ? 1 : 0,
|
||||
printer: 0
|
||||
}
|
||||
},
|
||||
condition: {
|
||||
isRefill: old.refill === 'Da',
|
||||
storageCondition: old.vakum ? 'vacuum' : (old.otvoreno ? 'opened' : 'sealed')
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Phase 2: Update UI Components
|
||||
- Create new filter components for material type
|
||||
- Add inventory status indicators
|
||||
- Color preview badges
|
||||
- Storage condition icons
|
||||
|
||||
### Phase 3: Enhanced Features
|
||||
1. **Barcode/QR Integration**: Generate QR codes for each spool
|
||||
2. **Usage History**: Track which prints used which filament
|
||||
3. **Alerts**: Low stock, expiry warnings
|
||||
4. **Analytics**: Cost per print, filament usage trends
|
||||
|
||||
## DynamoDB Optimization
|
||||
|
||||
### Current Indexes
|
||||
- brand-index
|
||||
- tip-index
|
||||
- status-index
|
||||
|
||||
### Proposed Indexes
|
||||
```terraform
|
||||
global_secondary_index {
|
||||
name = "material-color-index"
|
||||
hash_key = "material.base"
|
||||
range_key = "color.name"
|
||||
}
|
||||
|
||||
global_secondary_index {
|
||||
name = "inventory-status-index"
|
||||
hash_key = "condition.storageCondition"
|
||||
range_key = "inventory.available"
|
||||
}
|
||||
|
||||
global_secondary_index {
|
||||
name = "brand-type-index"
|
||||
hash_key = "brand"
|
||||
range_key = "material.base"
|
||||
}
|
||||
```
|
||||
|
||||
## Example Queries
|
||||
|
||||
### Find all available green filaments
|
||||
```javascript
|
||||
const greenFilaments = await dynamodb.query({
|
||||
IndexName: 'material-color-index',
|
||||
FilterExpression: 'contains(color.name, :green) AND inventory.available > :zero',
|
||||
ExpressionAttributeValues: {
|
||||
':green': 'Green',
|
||||
':zero': 0
|
||||
}
|
||||
}).promise();
|
||||
```
|
||||
|
||||
### Get inventory summary
|
||||
```javascript
|
||||
const summary = await dynamodb.scan({
|
||||
TableName: TABLE_NAME,
|
||||
ProjectionExpression: 'brand, material.base, inventory'
|
||||
}).promise();
|
||||
|
||||
const report = summary.Items.reduce((acc, item) => {
|
||||
const key = `${item.brand}-${item.material.base}`;
|
||||
acc[key] = (acc[key] || 0) + item.inventory.total;
|
||||
return acc;
|
||||
}, {});
|
||||
```
|
||||
|
||||
## UI Improvements
|
||||
|
||||
### 1. **Visual Inventory Status**
|
||||
```tsx
|
||||
<div className="flex gap-2">
|
||||
{filament.inventory.locations.vacuum > 0 && (
|
||||
<Badge icon="vacuum" count={filament.inventory.locations.vacuum} />
|
||||
)}
|
||||
{filament.inventory.locations.opened > 0 && (
|
||||
<Badge icon="box-open" count={filament.inventory.locations.opened} />
|
||||
)}
|
||||
</div>
|
||||
```
|
||||
|
||||
### 2. **Color Swatches**
|
||||
```tsx
|
||||
<div
|
||||
className="w-8 h-8 rounded-full border-2"
|
||||
style={{ backgroundColor: filament.color.hex || getColorFromName(filament.color.name) }}
|
||||
title={filament.color.name}
|
||||
/>
|
||||
```
|
||||
|
||||
### 3. **Smart Filters**
|
||||
- Quick filters: "Ready to use", "Low stock", "Refills only"
|
||||
- Material groups: "Standard PLA", "Engineering", "Specialty"
|
||||
- Storage status: "Vacuum sealed", "Open spools", "In printer"
|
||||
|
||||
Would you like me to implement this improved structure?
|
||||
Reference in New Issue
Block a user