remove files

This commit is contained in:
admin.suherdy 2025-11-27 10:08:15 +07:00
parent 16e8155c23
commit 2ee5a11d1a
2 changed files with 0 additions and 689 deletions

View File

@ -1,402 +0,0 @@
# Architecture and Flow Diagrams
## System Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ Product Configuration │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ product.template │ │
│ │ - lot_sequence_id (Many2one to ir.sequence) │ │
│ │ - serial_prefix_format (Char, computed) │ │
│ │ - next_serial (Char, computed) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Lot Generation Triggers │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Incoming │ │ Manufacturing│ │ Inventory │ │
│ │ Receipts │ │ Orders │ │ Adjustments │ │
│ │ (stock.move) │ │(mrp.production)│ │ (stock.quant) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Optimization Layer │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Smart Threshold Detection │ │
│ │ if count > 10: │ │
│ │ use batch optimization │ │
│ │ else: │ │
│ │ use standard generation │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Batch Processing Engine │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. Group lots by product │ │
│ │ 2. Allocate sequences in batch (PostgreSQL) │ │
│ │ 3. Format lot names │ │
│ │ 4. Create lot records in batch │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Database Layer │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL │ │
│ │ - ir_sequence (sequence numbers) │ │
│ │ - stock_lot (lot records) │ │
│ │ - generate_series() for batch allocation │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Batch Sequence Allocation Flow
### Old Method (Slow)
```
┌──────────────┐
│ Need 500 lots│
└──────┬───────┘
┌──────────────────────────────────────┐
│ Loop 500 times: │
│ ┌────────────────────────────────┐ │
│ │ 1. Call seq.next_by_id() │ │ ◄── 500 DB queries
│ │ 2. Wait for DB response │ │
│ │ 3. Format lot name │ │
│ │ 4. Create single lot record │ │ ◄── 500 DB inserts
│ └────────────────────────────────┘ │
└──────────────────────────────────────┘
┌──────────────┐
│ 500 lots │
│ Time: ~60s │
└──────────────┘
```
### New Method (Fast)
```
┌──────────────┐
│ Need 500 lots│
└──────┬───────┘
┌──────────────────────────────────────┐
│ Batch Allocation: │
│ ┌────────────────────────────────┐ │
│ │ 1. Single DB query: │ │ ◄── 1 DB query
│ │ SELECT nextval(seq) │ │
│ │ FROM generate_series(1,500) │ │
│ │ 2. Format all 500 names │ │
│ │ 3. Batch create 500 records │ │ ◄── 1 DB insert
│ └────────────────────────────────┘ │
└──────────────────────────────────────┘
┌──────────────┐
│ 500 lots │
│ Time: ~8s │
└──────────────┘
```
## Inventory Adjustment Flow
### Without Auto-Generation (Old)
```
┌─────────────────────┐
│ User creates │
│ inventory adjustment│
│ for 100 units │
└──────────┬──────────┘
┌─────────────────────┐
│ User must manually │
│ create 100 lots: │
│ - Enter each name │
│ - One by one │
│ - Time: ~10 min │
└──────────┬──────────┘
┌─────────────────────┐
│ Apply inventory │
└─────────────────────┘
```
### With Auto-Generation (New)
```
┌─────────────────────┐
│ User creates │
│ inventory adjustment│
│ for 100 units │
└──────────┬──────────┘
┌─────────────────────┐
│ System detects: │
│ - Product tracked │
│ - No lot assigned │
│ - Custom sequence │
└──────────┬──────────┘
┌─────────────────────┐
│ Auto-generate 100 │
│ lots using batch │
│ optimization │
│ Time: ~3s │
└──────────┬──────────┘
┌─────────────────────┐
│ Apply inventory │
│ (lots already ready)│
└─────────────────────┘
```
## Code Flow Diagram
### Incoming Receipt with 500 Serials
```
User clicks "Generate Serials"
stock.move.action_generate_lot_line_vals()
├─► Check: count > 10? ──► YES
│ │
│ ▼
│ _allocate_sequence_batch(seq, 500)
│ │
│ ├─► Execute SQL:
│ │ SELECT nextval(seq)
│ │ FROM generate_series(1, 500)
│ │
│ ├─► Format 500 lot names
│ │ (prefix + number + suffix)
│ │
│ └─► Return 500 lot names
stock.move._create_lot_ids_from_move_line_vals()
├─► Group by product
├─► Prepare 500 lot values
│ [{'name': 'SN-0001', ...}, ...]
stock.lot.create([500 lot values])
├─► Single batch insert
└─► Return 500 lot records
Lots assigned to move lines
User validates receipt
```
## Performance Comparison
### Database Operations
#### Old Method (500 lots)
```
┌─────────────────────────────────────┐
│ Sequence Allocation │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ Q1 │ │ Q2 │ ... │ Q500│ │ 500 queries
│ └─────┘ └─────┘ └─────┘ │
│ │
│ Lot Creation │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ C1 │ │ C2 │ ... │ C500│ │ 500 creates
│ └─────┘ └─────┘ └─────┘ │
│ │
│ Total: 1000 DB operations │
│ Time: ~60 seconds │
└─────────────────────────────────────┘
```
#### New Method (500 lots)
```
┌─────────────────────────────────────┐
│ Sequence Allocation │
│ ┌───────────────────────────────┐ │
│ │ Single Query (generate_series)│ │ 1 query
│ └───────────────────────────────┘ │
│ │
│ Lot Creation │
│ ┌───────────────────────────────┐ │
│ │ Batch Create (500 records) │ │ 1 create
│ └───────────────────────────────┘ │
│ │
│ Total: 2 DB operations │
│ Time: ~8 seconds │
└─────────────────────────────────────┘
```
### Speedup Factor
```
Old: 1000 operations / 60 seconds = 16.7 ops/sec
New: 2 operations / 8 seconds = 0.25 ops/sec
But creates 500 lots in both cases:
Old: 500 lots / 60 sec = 8.3 lots/sec
New: 500 lots / 8 sec = 62.5 lots/sec
Speedup: 62.5 / 8.3 = 7.5x faster
```
## Module Dependencies
```
┌─────────────────────────────────────────────────────────┐
│ product_lot_sequence_per_product │
│ │
│ Depends on: │
│ ┌──────────┐ ┌──────────┐ │
│ │ stock │ │ mrp │ │
│ │ (core) │ │ (core) │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ ├─► stock.move ├─► mrp.production │
│ ├─► stock.move.line │ │
│ ├─► stock.lot │ │
│ ├─► stock.quant │ │
│ └─► stock.picking │ │
│ │ │
└────────────────────────────┴───────────────────────────┘
```
## Data Model
```
┌─────────────────────────────────────────────────────────┐
│ product.template │
│ ┌─────────────────────────────────────────────────────┐│
│ │ id : Integer ││
│ │ name : Char ││
│ │ tracking : Selection (none/lot/serial) ││
│ │ lot_sequence_id : Many2one(ir.sequence) ││
│ │ serial_prefix_format : Char (computed) ││
│ │ next_serial : Char (computed) ││
│ └─────────────────────────────────────────────────────┘│
└────────────────────┬────────────────────────────────────┘
│ Many2one
┌─────────────────────────────────────────────────────────┐
│ ir.sequence │
│ ┌─────────────────────────────────────────────────────┐│
│ │ id : Integer ││
│ │ name : Char ││
│ │ code : Char ('stock.lot.serial') ││
│ │ prefix : Char (e.g., 'SN-') ││
│ │ suffix : Char ││
│ │ padding : Integer (e.g., 7) ││
│ │ number_next_actual: Integer ││
│ └─────────────────────────────────────────────────────┘│
└────────────────────┬────────────────────────────────────┘
│ Used by
┌─────────────────────────────────────────────────────────┐
│ stock.lot │
│ ┌─────────────────────────────────────────────────────┐│
│ │ id : Integer ││
│ │ name : Char (e.g., 'SN-0000001') ││
│ │ product_id : Many2one(product.product) ││
│ │ company_id : Many2one(res.company) ││
│ └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
```
## Optimization Decision Tree
```
┌─────────────────┐
│ Need to generate│
│ N lot numbers │
└────────┬────────┘
┌─────────────────┐
│ Is N > 10? │
└────────┬────────┘
┌────────────┴────────────┐
│ │
YES NO
│ │
▼ ▼
┌───────────────────────┐ ┌──────────────────┐
│ Use Batch Optimization│ │ Use Standard │
│ │ │ Generation │
│ - Single DB query │ │ │
│ - generate_series() │ │ - Loop N times │
│ - Batch create │ │ - seq.next_by_id()│
│ │ │ - Individual │
│ Time: O(1) │ │ creates │
│ Fast for large N │ │ │
└───────────────────────┘ │ Time: O(N) │
│ Fine for small N │
└──────────────────┘
```
## Concurrency Handling
```
┌─────────────────────────────────────────────────────────┐
│ Multiple Users Generating Lots Simultaneously │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ PostgreSQL Sequence (ir_sequence_XXX) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ User A │ │ User B │ │ User C │ │
│ │ nextval()│ │ nextval()│ │ nextval()│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ├─────────────┼─────────────┤ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ Atomic sequence increment │ │
│ │ (Database-level locking) │ │
│ └────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ 1001 1002 1003 │
│ │
│ No conflicts - each gets unique number │
└─────────────────────────────────────────────────────────┘
```
## Summary
The architecture provides:
1. **Layered Design**: Clear separation between configuration, triggers, optimization, and database
2. **Smart Optimization**: Automatic detection and application of batch processing
3. **Scalability**: Handles from 1 to 500,000+ lots efficiently
4. **Concurrency Safety**: Database-level sequence management prevents conflicts
5. **Backward Compatibility**: Works with existing Odoo infrastructure
6. **Extensibility**: Easy to add new triggers or optimization strategies
The key innovation is the **batch processing layer** that intercepts lot generation requests and optimizes them transparently, providing massive performance improvements without changing the user experience.

View File

@ -1,287 +0,0 @@
# Date Format Code Fix - Summary
## Issue
The batch sequence allocation optimization was not properly handling date format codes like `%(y)s`, `%(month)s`, `%(day)s` in the sequence prefix/suffix. This resulted in literal strings being used instead of actual date values.
**Example Problem**:
- Configuration: `%(y)s%(month)s%(day)s`
- Expected: `2411200000001` (for Nov 20, 2024)
- Actual: `%(y)s%(month)s%(day)s0000001` (literal string)
## Root Cause
The `_allocate_sequence_batch()` method was directly using `sequence.prefix` and `sequence.suffix` without interpolating the date format codes. The standard `seq.next_by_id()` method handles this interpolation automatically, but our optimized batch method bypassed it.
## Solution
Updated three methods to properly handle date format codes:
### 1. `stock_lot._allocate_sequence_batch()`
Added date interpolation logic before formatting lot names:
```python
from datetime import datetime
now = datetime.now()
# Build interpolation dictionary (same as Odoo's ir.sequence)
interpolation_dict = {
'year': now.strftime('%Y'),
'y': now.strftime('%y'),
'month': now.strftime('%m'),
'day': now.strftime('%d'),
'doy': now.strftime('%j'),
'woy': now.strftime('%W'),
'weekday': now.strftime('%w'),
'h24': now.strftime('%H'),
'h12': now.strftime('%I'),
'min': now.strftime('%M'),
'sec': now.strftime('%S'),
}
# Format prefix and suffix with date codes
prefix = (sequence.prefix or '') % interpolation_dict if sequence.prefix else ''
suffix = (sequence.suffix or '') % interpolation_dict if sequence.suffix else ''
# Then format lot names with interpolated prefix/suffix
lot_name = '{}{:0{}d}{}'.format(prefix, seq_num, sequence.padding, suffix)
```
### 2. `stock_move._allocate_sequence_batch()`
Applied the same fix to the duplicate method in `stock_move.py`.
### 3. `product_template._compute_next_serial()`
Updated to show correct preview of next lot number with date codes:
```python
# Format prefix and suffix with date codes
prefix = (seq.prefix or '') % interpolation_dict if seq.prefix else ''
suffix = (seq.suffix or '') % interpolation_dict if seq.suffix else ''
template.next_serial = '{}{:0{}d}{}'.format(
prefix,
seq.number_next_actual,
seq.padding,
suffix
)
```
## Files Modified
1. **customaddons/product_lot_sequence_per_product/models/stock_lot.py**
- Enhanced `_allocate_sequence_batch()` with date interpolation
2. **customaddons/product_lot_sequence_per_product/models/stock_move.py**
- Enhanced `_allocate_sequence_batch()` with date interpolation
3. **customaddons/product_lot_sequence_per_product/models/product_template.py**
- Enhanced `_compute_next_serial()` with date interpolation
4. **customaddons/product_lot_sequence_per_product/tests/test_date_format.py** (new)
- Comprehensive test suite for date format codes
5. **customaddons/product_lot_sequence_per_product/DATE_FORMAT_GUIDE.md** (new)
- Complete guide for using date format codes
6. **customaddons/product_lot_sequence_per_product/CHANGELOG.md**
- Added version 1.1.1 with fix details
7. **customaddons/product_lot_sequence_per_product/__manifest__.py**
- Updated version to 1.1.1
## Supported Date Format Codes
| Code | Description | Example |
|------|-------------|---------|
| `%(year)s` | Full year (4 digits) | 2024 |
| `%(y)s` | Short year (2 digits) | 24 |
| `%(month)s` | Month (2 digits) | 11 |
| `%(day)s` | Day of month (2 digits) | 20 |
| `%(doy)s` | Day of year (3 digits) | 325 |
| `%(woy)s` | Week of year (2 digits) | 47 |
| `%(weekday)s` | Day of week | 4 |
| `%(h24)s` | Hour (24-hour) | 14 |
| `%(h12)s` | Hour (12-hour) | 02 |
| `%(min)s` | Minute | 30 |
| `%(sec)s` | Second | 45 |
## Testing
### Test Suite Added
**File**: `tests/test_date_format.py`
**Tests**:
1. `test_date_format_year_month_day` - Tests `%(y)s%(month)s%(day)s` format
2. `test_date_format_full_year` - Tests `%(year)s` format
3. `test_date_format_batch_generation` - Tests batch generation with date codes
4. `test_date_format_complex` - Tests complex multi-code formats
5. `test_date_format_with_suffix` - Tests date codes with suffix
6. `test_date_format_inventory_adjustment` - Tests inventory adjustments
7. `test_date_format_all_codes` - Tests all available format codes
### Running Tests
```bash
# Run all date format tests
odoo-bin -c odoo.conf -d test_db --test-tags product_lot_sequence_per_product.test_date_format
# Run all module tests
odoo-bin -c odoo.conf -d test_db --test-tags product_lot_sequence_per_product
```
## Usage Examples
### Example 1: Year-Month-Day
**Configuration**: `%(y)s%(month)s%(day)s`
**Result**: `2411200000001` (for Nov 20, 2024)
### Example 2: Full Date with Separators
**Configuration**: `LOT-%(year)s-%(month)s-%(day)s-`
**Result**: `LOT-2024-11-20-0000001`
### Example 3: Week-Based
**Configuration**: `WK%(y)s%(woy)s-`
**Result**: `WK2447-0000001` (Week 47 of 2024)
## Performance Impact
**No performance degradation**:
- Date interpolation happens once per batch (not per lot)
- Adds ~0.001 seconds to batch generation
- Negligible compared to database operations
- Batch optimization still provides 8-10x speedup
## Verification
### Before Fix
```
Configuration: %(y)s%(month)s%(day)s
Generated: %(y)s%(month)s%(day)s0000001 ❌ Wrong
```
### After Fix
```
Configuration: %(y)s%(month)s%(day)s
Generated: 2411200000001 ✓ Correct
```
## Backward Compatibility
✓ Fully backward compatible
✓ No breaking changes
✓ Existing sequences without date codes work as before
✓ Only affects sequences using date format codes
## Upgrade Instructions
### For Existing Installations
1. **Backup database**:
```bash
pg_dump your_database > backup_before_1.1.1.sql
```
2. **Update module files**:
```bash
cp -r product_lot_sequence_per_product /path/to/odoo/customaddons/
```
3. **Upgrade module**:
```bash
odoo-bin -c odoo.conf -d your_database -u product_lot_sequence_per_product --stop-after-init
```
4. **Verify**:
- Check a product with date format codes
- Verify "Next Number" field shows correct date
- Generate a test lot to confirm
### For New Installations
Simply install version 1.1.1 - date format codes work out of the box.
## Documentation
### New Documentation Added
1. **DATE_FORMAT_GUIDE.md**
- Complete guide for date format codes
- Usage examples
- Best practices
- Troubleshooting
2. **Test Suite**
- Comprehensive tests for all date codes
- Batch generation tests
- Integration tests
3. **Updated CHANGELOG.md**
- Version 1.1.1 details
- Fix description
- Changed files list
## Common Use Cases
### Daily Production Batches
```
Format: %(y)s%(month)s%(day)s
Result: 2411200000001, 2411200000002, ...
Next day: 2411210000001, 2411210000002, ...
```
### Monthly Inventory Cycles
```
Format: LOT-%(year)s-%(month)s-
Result: LOT-2024-11-0000001, LOT-2024-11-0000002, ...
Next month: LOT-2024-12-0000001, ...
```
### Weekly Production Runs
```
Format: WK%(woy)s-%(year)s-
Result: WK47-2024-0000001, WK47-2024-0000002, ...
Next week: WK48-2024-0000001, ...
```
## Troubleshooting
### Issue: Still seeing literal `%(y)s`
**Solution**:
1. Verify you're on version 1.1.1 or later
2. Restart Odoo after upgrade
3. Clear browser cache
4. Check sequence configuration
### Issue: Wrong date values
**Solution**:
1. Check server timezone
2. Verify Odoo timezone configuration
3. Check PostgreSQL timezone
### Issue: Different dates in same batch
**Explanation**: If batch generation crosses midnight, some lots may have different dates. This is expected behavior.
**Solution**: Generate batches earlier in the day to avoid midnight crossover.
## Summary
The fix ensures that date format codes work correctly in all scenarios:
✓ Single lot creation
✓ Batch generation (10+ lots)
✓ Very large batches (1000+ lots)
✓ Incoming receipts
✓ Manufacturing orders
✓ Inventory adjustments
✓ Manual lot creation
All while maintaining the 8-10x performance improvement from batch optimization.
**Version**: 1.1.1
**Status**: Production Ready
**Testing**: Comprehensive test suite included
**Documentation**: Complete guide available