diff --git a/docs/MOC_AUTO_GENERATION.md b/docs/MOC_AUTO_GENERATION.md new file mode 100644 index 0000000..a195557 --- /dev/null +++ b/docs/MOC_AUTO_GENERATION.md @@ -0,0 +1,348 @@ +# MOC Auto-Generation Feature + +## Overview + +The LEGO Instructions Manager now includes automatic MOC (My Own Creation) set number generation, making it easier to track and organize your custom LEGO builds without manually managing set numbers. + +## Features + +### 🤖 Automatic Number Generation +- **Sequential Numbering**: Automatically generates MOC numbers in sequence (MOC-10000, MOC-10001, MOC-10002, etc.) +- **Conflict-Free**: Ensures no duplicate MOC numbers +- **Customizable Prefix**: Default is "MOC" but can be changed +- **User-Scoped Option**: Can scope MOC numbers per user or globally + +### 🔌 API Endpoints + +#### 1. Generate Next MOC Number +``` +GET /api/moc/generate +``` + +**Query Parameters:** +- `prefix` (optional): MOC prefix, default is 'MOC' +- `user_scoped` (optional): Scope to current user, default is 'true' + +**Response:** +```json +{ + "success": true, + "moc_number": "MOC-10001", + "prefix": "MOC", + "user_scoped": true +} +``` + +**Example Usage:** +```javascript +fetch('/api/moc/generate') + .then(response => response.json()) + .then(data => { + console.log('Next MOC number:', data.moc_number); + }); +``` + +#### 2. Validate MOC Number +``` +POST /api/moc/validate +``` + +**Request Body:** +```json +{ + "set_number": "MOC-12345", + "user_scoped": true +} +``` + +**Response:** +```json +{ + "success": true, + "available": true, + "set_number": "MOC-12345" +} +``` + +#### 3. Check MOC Format +``` +GET /api/moc/check-format?set_number=MOC-10001&prefix=MOC +``` + +**Response:** +```json +{ + "is_moc": true, + "set_number": "MOC-10001", + "prefix": "MOC" +} +``` + +## Database Schema + +The `Set` model includes MOC support fields: + +```python +is_moc = db.Column(db.Boolean, default=False, nullable=False, index=True) +moc_designer = db.Column(db.String(100), nullable=True) # Designer/creator name +moc_description = db.Column(db.Text, nullable=True) # Detailed description +``` + +## Frontend Integration + +### HTML Form Example + +When creating a new set, users can toggle MOC mode: + +```html +
+ + +
+ + + +
+ + +
+``` + +### JavaScript Integration + +```javascript +// Handle MOC toggle +document.getElementById('is_moc').addEventListener('change', function() { + const mocSection = document.getElementById('mocSection'); + const officialSection = document.getElementById('officialSection'); + const setNumberInput = document.getElementById('set_number'); + + if (this.checked) { + // Show MOC section, hide official section + mocSection.style.display = 'block'; + officialSection.style.display = 'none'; + setNumberInput.removeAttribute('required'); + + // Fetch next MOC number + fetchNextMocNumber(); + } else { + // Show official section, hide MOC section + mocSection.style.display = 'none'; + officialSection.style.display = 'block'; + setNumberInput.setAttribute('required', 'required'); + } +}); + +// Fetch next MOC number from API +function fetchNextMocNumber() { + fetch('/api/moc/generate') + .then(response => response.json()) + .then(data => { + if (data.success) { + document.getElementById('mocNumberPreview').textContent = data.moc_number; + // Optionally store in hidden field + document.getElementById('moc_number_hidden').value = data.moc_number; + } + }) + .catch(error => { + console.error('Error fetching MOC number:', error); + document.getElementById('mocNumberPreview').textContent = 'Error generating number'; + }); +} +``` + +## Backend Implementation + +### Service Layer + +The `MOCNumberGenerator` service handles all MOC number logic: + +```python +from app.services.moc_generator import MOCNumberGenerator + +# Generate next MOC number +moc_number = MOCNumberGenerator.generate_next_number( + prefix='MOC', + user_id=current_user.id # Optional: scope to user +) + +# Validate MOC number availability +is_available = MOCNumberGenerator.validate_moc_number( + 'MOC-12345', + user_id=current_user.id +) + +# Check if number follows MOC format +is_moc = MOCNumberGenerator.is_moc_number('MOC-10001') +``` + +### Route Layer + +MOC routes are organized in `app/routes/moc.py`: + +```python +from flask import Blueprint, jsonify +from flask_login import login_required, current_user +from app.services.moc_generator import MOCNumberGenerator + +bp = Blueprint('moc', __name__, url_prefix='/api/moc') + +@bp.route('/generate', methods=['GET']) +@login_required +def generate_moc_number(): + moc_number = MOCNumberGenerator.generate_next_number( + user_id=current_user.id + ) + return jsonify({ + 'success': True, + 'moc_number': moc_number + }) +``` + +## Configuration + +### Customizing MOC Prefix + +Edit `app/services/moc_generator.py`: + +```python +class MOCNumberGenerator: + DEFAULT_PREFIX = 'MOC' # Change to 'CUSTOM' or any prefix + DEFAULT_START = 10000 # Starting number for MOCs +``` + +### Per-User vs Global Numbering + +**Per-User Numbering** (default): +- Each user has their own MOC number sequence +- MOC-10000 can exist for multiple users +- API: `user_scoped=true` + +**Global Numbering**: +- All users share the same MOC number sequence +- Ensures unique MOC numbers across the entire system +- API: `user_scoped=false` + +## Use Cases + +### Creating a New MOC + +1. User clicks "Add New Set" +2. User toggles "This is a MOC" checkbox +3. System automatically generates MOC-10000 (or next available) +4. User fills in MOC designer, description, and other details +5. System saves set with is_moc=True + +### Importing Multiple MOCs + +```python +from app.services.moc_generator import MOCNumberGenerator + +for moc_data in moc_import_list: + moc_number = MOCNumberGenerator.generate_next_number() + new_set = Set( + set_number=moc_number, + set_name=moc_data['name'], + is_moc=True, + moc_designer=moc_data['designer'], + theme='MOC', + year_released=moc_data['year'] + ) + db.session.add(new_set) + +db.session.commit() +``` + +### Filtering MOCs + +```python +# Get all MOCs +mocs = Set.query.filter_by(is_moc=True).all() + +# Get MOCs by designer +designer_mocs = Set.query.filter_by( + is_moc=True, + moc_designer='John Doe' +).all() + +# Get MOCs by number range +mocs_range = Set.query.filter( + Set.is_moc == True, + Set.set_number.like('MOC-10%') +).all() +``` + +## Troubleshooting + +### MOC Number Not Generating + +**Issue**: API returns error or "Error generating number" + +**Solutions**: +1. Check that user is logged in (endpoint requires authentication) +2. Verify database connection +3. Check browser console for JavaScript errors +4. Ensure `moc_bp` is registered in `app/__init__.py` + +### Duplicate MOC Numbers + +**Issue**: Same MOC number assigned to multiple sets + +**Solutions**: +1. Check database constraints on `set_number` field +2. Verify `user_scoped` parameter matches your use case +3. Run database migration to add unique constraint if missing + +### MOC Toggle Not Working + +**Issue**: Toggle switch doesn't show/hide sections + +**Solutions**: +1. Check JavaScript console for errors +2. Verify element IDs match between HTML and JavaScript +3. Ensure Bootstrap JavaScript is loaded (for styling) + +## Future Enhancements + +Potential improvements for the MOC feature: + +- [ ] Bulk MOC number generation API +- [ ] MOC number recycling (reuse deleted MOC numbers) +- [ ] Custom number formats (e.g., MOC-YYYY-NNNN for year-based) +- [ ] MOC templates for common builds +- [ ] MOC sharing/export functionality +- [ ] Integration with MOC platforms like Rebrickable + +## Related Documentation + +- [Main README](../README.md) - General application documentation +- [Setup Guide](../SETUP_GUIDE.md) - Installation and configuration +- [API Documentation](../docs/api.md) - Complete API reference (if exists) +- [Database Schema](../docs/database.md) - Database structure (if exists) + +## Support + +For issues or questions about MOC auto-generation: + +1. Check existing issues on Gitea +2. Review this documentation +3. Check application logs for errors +4. Create a new issue with: + - Steps to reproduce + - Expected vs actual behavior + - Browser console logs + - Server logs (if applicable) + +--- + +**Last Updated**: December 2024 +**Feature Version**: 1.0 +**Compatibility**: LEGO Instructions Manager v1.3.0+