151 lines
5.5 KiB
Markdown
151 lines
5.5 KiB
Markdown
# Duplicate Report Feature
|
|
|
|
## Overview
|
|
Added a duplicate functionality for reports/shifts that allows users to create a complementary shift (day ↔ night) based on an existing report, but only when the report sheet is not complete.
|
|
|
|
## Feature Details
|
|
|
|
### ✅ **Functionality**
|
|
- **Duplicate Button**: Available next to "View" for each report
|
|
- **Opposite Shift**: Automatically creates the opposite shift (day → night, night → day)
|
|
- **Data Copying**: Copies all report data EXCEPT stoppages
|
|
- **User Assignment**: Assigns the duplicate to the current user
|
|
- **Sheet Management**: Automatically manages the report sheet relationships
|
|
|
|
### ✅ **Validation Rules**
|
|
1. **Date Restriction**: Cannot duplicate reports older than the day before current date (for all auth levels)
|
|
2. **Universal Access**: All users (auth level 1+) can duplicate any report
|
|
3. **Sheet Completeness**: Cannot duplicate if the sheet already has both day and night shifts
|
|
4. **Shift Existence**: Cannot duplicate if the opposite shift already exists for the same date/location
|
|
5. **User Confirmation**: Requires confirmation before duplicating
|
|
|
|
### ✅ **What Gets Copied**
|
|
- ✅ Area, Dredger Location, Reclamation Location
|
|
- ✅ Dredger Line Length, Shore Connection
|
|
- ✅ Reclamation Height (base + extra)
|
|
- ✅ Pipeline Length (main, ext1, reserve, ext2)
|
|
- ✅ Equipment Statistics (Dozers, Exc, Loaders, Foreman, Laborer)
|
|
- ✅ Time Sheet entries
|
|
- ✅ Notes
|
|
|
|
### ❌ **What Gets Excluded**
|
|
- ❌ Stoppages (empty array)
|
|
- ❌ Original shift type (automatically inverted)
|
|
- ❌ Original employee assignment (assigned to current user)
|
|
|
|
## Technical Implementation
|
|
|
|
### **Database Logic**
|
|
```typescript
|
|
// Check if report is too old (before day before current date)
|
|
const reportDate = new Date(originalReport.createdDate);
|
|
const dayBeforeToday = new Date();
|
|
dayBeforeToday.setDate(dayBeforeToday.getDate() - 1);
|
|
dayBeforeToday.setHours(0, 0, 0, 0);
|
|
|
|
if (reportDate < dayBeforeToday) {
|
|
return error("Cannot duplicate reports older than yesterday");
|
|
}
|
|
|
|
// Check if sheet is complete (has both shifts)
|
|
const existingSheet = await prisma.sheet.findUnique({
|
|
where: {
|
|
areaId_dredgerLocationId_reclamationLocationId_date: {
|
|
areaId: originalReport.areaId,
|
|
dredgerLocationId: originalReport.dredgerLocationId,
|
|
reclamationLocationId: originalReport.reclamationLocationId,
|
|
date: dateString
|
|
}
|
|
}
|
|
});
|
|
|
|
// Prevent duplication if sheet is complete
|
|
if (existingSheet && existingSheet.dayShiftId && existingSheet.nightShiftId) {
|
|
return error("Cannot duplicate - sheet is complete");
|
|
}
|
|
```
|
|
|
|
### **Shift Inversion**
|
|
```typescript
|
|
const newShift = originalReport.shift === 'day' ? 'night' : 'day';
|
|
```
|
|
|
|
### **Data Duplication**
|
|
```typescript
|
|
const duplicateReport = await prisma.report.create({
|
|
data: {
|
|
employeeId: user.id, // Current user
|
|
shift: newShift, // Opposite shift
|
|
// ... all other fields copied
|
|
stoppages: [], // Empty stoppages
|
|
}
|
|
});
|
|
```
|
|
|
|
## User Interface
|
|
|
|
### **Desktop View**
|
|
- **Location**: Next to "View" button in the actions column
|
|
- **Button**: Green "Duplicate" button with hover tooltip
|
|
- **Confirmation**: Shows which shift will be created
|
|
|
|
### **Mobile View**
|
|
- **Location**: Below "View Details" button
|
|
- **Button**: Full-width green button with descriptive text
|
|
- **Text**: "Duplicate as Night Shift" or "Duplicate as Day Shift"
|
|
|
|
### **Confirmation Dialog**
|
|
```
|
|
"Are you sure you want to duplicate this day shift as a night shift?
|
|
Stoppages will not be copied."
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
### **Validation Errors**
|
|
1. **Date Restriction**: "Cannot duplicate reports older than yesterday"
|
|
2. **Sheet Complete**: "Cannot duplicate report - sheet is already complete with both day and night shifts"
|
|
3. **Shift Exists**: "Cannot duplicate report - night shift already exists for this date and location"
|
|
4. **General Error**: "Failed to duplicate report"
|
|
|
|
### **Success Message**
|
|
```
|
|
"Report duplicated successfully as night shift!"
|
|
```
|
|
|
|
## Use Cases
|
|
|
|
### **Primary Use Case**
|
|
1. User creates a day shift report
|
|
2. Realizes they need a night shift for the same location/date
|
|
3. Clicks "Duplicate" on the day shift
|
|
4. System creates a night shift with same operational data
|
|
5. User can then edit the night shift to add specific stoppages and time sheet adjustments
|
|
|
|
### **Business Logic**
|
|
- **Operational Continuity**: Same equipment, locations, and basic setup
|
|
- **Shift-Specific Data**: Stoppages are shift-specific and not copied
|
|
- **User Ownership**: Each user owns their duplicated reports
|
|
- **Sheet Completion**: Helps complete report sheets efficiently
|
|
|
|
## Security & Permissions
|
|
|
|
### **Access Control**
|
|
- **All Users (Level 1+)**: Can duplicate any report within the allowed date range
|
|
- **Date Restriction**: Reports older than the day before current date cannot be duplicated
|
|
- **Sheet Validation**: Server-side validation prevents invalid duplications
|
|
|
|
### **Data Integrity**
|
|
- **Sheet Management**: Automatically updates sheet relationships
|
|
- **Unique Constraints**: Prevents duplicate shifts for same date/location
|
|
- **Transaction Safety**: Uses database transactions for consistency
|
|
|
|
## Benefits
|
|
|
|
1. **Efficiency**: Quickly create complementary shifts
|
|
2. **Consistency**: Maintains operational data consistency
|
|
3. **Flexibility**: Allows shift-specific customizations
|
|
4. **User-Friendly**: Simple one-click duplication with clear feedback
|
|
5. **Data Integrity**: Maintains proper sheet relationships and validation
|
|
|
|
The duplicate feature streamlines the process of creating complementary shifts while maintaining data integrity and proper validation rules. |