565 lines
15 KiB
Markdown
565 lines
15 KiB
Markdown
# Request Detail Template System - Implementation Guide
|
|
|
|
## Overview
|
|
|
|
This implementation provides a **flexible, reusable, template-driven architecture** for the RequestDetail component, enabling multiple user types (dealers, vendors, standard users) with customizable views, tabs, and behaviors.
|
|
|
|
## 📁 What Has Been Created
|
|
|
|
### Core Architecture Files
|
|
|
|
```
|
|
src/pages/RequestDetail/
|
|
├── types/
|
|
│ └── template.types.ts ✅ Type definitions for template system
|
|
├── templates/
|
|
│ ├── index.ts ✅ Template registry and selector
|
|
│ ├── standardTemplate.ts ✅ Standard workflow template
|
|
│ ├── dealerClaimTemplate.ts ✅ Dealer claim template with IO tab
|
|
│ └── vendorTemplate.ts ✅ Vendor request template
|
|
├── components/
|
|
│ └── tabs/
|
|
│ └── IOTab.tsx ✅ IO budget management tab for dealers
|
|
├── examples/
|
|
│ └── CustomTemplateExample.tsx ✅ Examples for creating custom templates
|
|
├── RequestDetailTemplated.tsx ✅ New template-driven component
|
|
├── RequestDetail.tsx ✅ Original component (unchanged)
|
|
├── index.ts ✅ Module exports
|
|
└── README_TEMPLATES.md ✅ Comprehensive documentation
|
|
```
|
|
|
|
### Key Features Implemented
|
|
|
|
✅ **Template System**
|
|
- Dynamic template selection based on request type and user role
|
|
- Configurable tabs, headers, and quick actions
|
|
- Role-based access control at template and tab level
|
|
|
|
✅ **IO Tab for Dealer Claims**
|
|
- Fetch IO budget from SAP
|
|
- Block budget in SAP system
|
|
- Display blocked IO details
|
|
- Release blocked budget
|
|
|
|
✅ **Three Built-in Templates**
|
|
1. Standard Template - Default workflow requests
|
|
2. Dealer Claim Template - Claim management with IO integration
|
|
3. Vendor Template - Vendor purchase orders and invoices
|
|
|
|
✅ **Backward Compatibility**
|
|
- Original `RequestDetail` component remains unchanged
|
|
- Existing implementations continue to work
|
|
- New template system is opt-in
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### Step 1: Use the New Template-Driven Component
|
|
|
|
```tsx
|
|
// For dealer claims (auto-selects dealerClaim template)
|
|
import { RequestDetailTemplated } from '@/pages/RequestDetail';
|
|
|
|
// In your route or component
|
|
<RequestDetailTemplated
|
|
requestId="RE-REQ-2024-CM-100"
|
|
onBack={() => navigate('/dashboard')}
|
|
/>
|
|
```
|
|
|
|
### Step 2: Configure Template Selection
|
|
|
|
Update your request data model to include category/type:
|
|
|
|
```typescript
|
|
// Backend: Add category field to requests
|
|
{
|
|
requestId: "RE-REQ-2024-CM-100",
|
|
title: "Dealer Claim Request",
|
|
category: "claim-management", // ← This triggers dealerClaim template
|
|
claimAmount: 1000,
|
|
// ... other fields
|
|
}
|
|
```
|
|
|
|
### Step 3: Update Routes (Optional)
|
|
|
|
```tsx
|
|
// src/routes/AppRoutes.tsx or similar
|
|
import { RequestDetailTemplated } from '@/pages/RequestDetail';
|
|
|
|
// Replace old route
|
|
<Route path="/request/:requestId" element={<RequestDetailTemplated />} />
|
|
|
|
// Or keep both for migration period
|
|
<Route path="/request/:requestId" element={<RequestDetail />} />
|
|
<Route path="/request-v2/:requestId" element={<RequestDetailTemplated />} />
|
|
```
|
|
|
|
## 📋 Implementation Steps by User Type
|
|
|
|
### For Dealers (Claim Management)
|
|
|
|
**Backend Setup:**
|
|
|
|
```csharp
|
|
// .NET API: Ensure request model includes necessary fields
|
|
public class DealerClaimRequest
|
|
{
|
|
public string RequestId { get; set; }
|
|
public string Category { get; set; } = "claim-management";
|
|
public string Type { get; set; } = "dealer-claim";
|
|
public decimal ClaimAmount { get; set; }
|
|
public string IoNumber { get; set; }
|
|
public decimal? IoBlockedAmount { get; set; }
|
|
// ... other fields
|
|
}
|
|
```
|
|
|
|
**Frontend Usage:**
|
|
|
|
```tsx
|
|
// Automatically uses dealerClaim template
|
|
<RequestDetailTemplated requestId={claimRequestId} />
|
|
|
|
// Shows these tabs:
|
|
// 1. Overview
|
|
// 2. Workflow (8-Steps)
|
|
// 3. IO (Budget Management) ← NEW!
|
|
// 4. Documents
|
|
// 5. Activity
|
|
// 6. Work Notes
|
|
```
|
|
|
|
**SAP Integration:**
|
|
|
|
The IO tab includes placeholders for SAP integration. Implement these API endpoints:
|
|
|
|
```typescript
|
|
// src/services/sapApi.ts
|
|
|
|
/**
|
|
* Fetch IO budget from SAP
|
|
*/
|
|
export async function fetchIOBudget(ioNumber: string): Promise<IOBudgetResponse> {
|
|
const response = await apiClient.get(`/api/sap/io/${ioNumber}/budget`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Block budget in SAP
|
|
*/
|
|
export async function blockIOBudget(request: BlockBudgetRequest): Promise<BlockBudgetResponse> {
|
|
const response = await apiClient.post('/api/sap/io/block', request);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Release blocked budget
|
|
*/
|
|
export async function releaseIOBudget(ioNumber: string, documentNumber: string): Promise<void> {
|
|
await apiClient.post('/api/sap/io/release', { ioNumber, documentNumber });
|
|
}
|
|
```
|
|
|
|
**.NET API Endpoints:**
|
|
|
|
```csharp
|
|
// Controllers/SapController.cs
|
|
|
|
[ApiController]
|
|
[Route("api/sap")]
|
|
public class SapController : ControllerBase
|
|
{
|
|
private readonly ISapService _sapService;
|
|
|
|
[HttpGet("io/{ioNumber}/budget")]
|
|
public async Task<ActionResult<IOBudgetResponse>> GetIOBudget(string ioNumber)
|
|
{
|
|
var budget = await _sapService.GetAvailableBudget(ioNumber);
|
|
return Ok(budget);
|
|
}
|
|
|
|
[HttpPost("io/block")]
|
|
public async Task<ActionResult<BlockBudgetResponse>> BlockBudget([FromBody] BlockBudgetRequest request)
|
|
{
|
|
var result = await _sapService.BlockBudget(
|
|
request.IoNumber,
|
|
request.Amount,
|
|
request.RequestId
|
|
);
|
|
return Ok(result);
|
|
}
|
|
|
|
[HttpPost("io/release")]
|
|
public async Task<ActionResult> ReleaseBudget([FromBody] ReleaseBudgetRequest request)
|
|
{
|
|
await _sapService.ReleaseBudget(request.IoNumber, request.DocumentNumber);
|
|
return Ok();
|
|
}
|
|
}
|
|
```
|
|
|
|
### For Vendors
|
|
|
|
```tsx
|
|
// Request with vendor category
|
|
<RequestDetailTemplated requestId="VEND-2024-001" />
|
|
|
|
// Backend: Set category
|
|
{
|
|
category: "vendor",
|
|
// or
|
|
type: "vendor"
|
|
}
|
|
```
|
|
|
|
### For Standard Users
|
|
|
|
```tsx
|
|
// Regular workflow requests
|
|
<RequestDetailTemplated requestId="REQ-2024-001" />
|
|
|
|
// Uses standard template by default
|
|
```
|
|
|
|
## 🎨 Creating Custom Templates
|
|
|
|
### Example: Create a Marketing Campaign Template
|
|
|
|
```tsx
|
|
// src/pages/RequestDetail/templates/marketingTemplate.ts
|
|
|
|
import { RequestDetailTemplate } from '../types/template.types';
|
|
import { OverviewTab } from '../components/tabs/OverviewTab';
|
|
import { WorkflowTab } from '../components/tabs/WorkflowTab';
|
|
import { CampaignDetailsTab } from '../components/tabs/CampaignDetailsTab'; // Your custom tab
|
|
|
|
export const marketingTemplate: RequestDetailTemplate = {
|
|
id: 'marketing',
|
|
name: 'Marketing Campaign',
|
|
description: 'Template for marketing campaign approvals',
|
|
|
|
tabs: [
|
|
{
|
|
id: 'overview',
|
|
label: 'Overview',
|
|
icon: ClipboardList,
|
|
component: OverviewTab,
|
|
order: 1,
|
|
},
|
|
{
|
|
id: 'campaign',
|
|
label: 'Campaign Details',
|
|
icon: Star,
|
|
component: CampaignDetailsTab,
|
|
order: 2,
|
|
},
|
|
{
|
|
id: 'workflow',
|
|
label: 'Workflow',
|
|
icon: TrendingUp,
|
|
component: WorkflowTab,
|
|
order: 3,
|
|
},
|
|
],
|
|
|
|
defaultTab: 'overview',
|
|
|
|
header: {
|
|
showBackButton: true,
|
|
showRefreshButton: true,
|
|
},
|
|
|
|
quickActions: {
|
|
enabled: true,
|
|
customActions: [
|
|
{
|
|
id: 'schedule',
|
|
label: 'Schedule Campaign',
|
|
icon: Calendar,
|
|
action: async (context) => {
|
|
// Custom action logic
|
|
},
|
|
visible: (context) => context.request?.status === 'approved',
|
|
},
|
|
],
|
|
},
|
|
|
|
layout: {
|
|
showQuickActionsSidebar: true,
|
|
fullWidthTabs: [],
|
|
},
|
|
|
|
canAccess: (user, request) => {
|
|
return user?.role === 'marketing' || user?.role === 'admin';
|
|
},
|
|
};
|
|
```
|
|
|
|
### Register the Template
|
|
|
|
```tsx
|
|
// src/pages/RequestDetail/templates/index.ts
|
|
|
|
import { marketingTemplate } from './marketingTemplate';
|
|
|
|
export const templateRegistry: TemplateRegistry = {
|
|
standard: standardTemplate,
|
|
dealerClaim: dealerClaimTemplate,
|
|
vendor: vendorTemplate,
|
|
marketing: marketingTemplate, // ← Add here
|
|
};
|
|
|
|
// Update selector
|
|
export const selectTemplate: TemplateSelector = (user, request, routeParams) => {
|
|
if (request?.category === 'marketing-campaign') {
|
|
return 'marketing';
|
|
}
|
|
|
|
if (request?.category === 'claim-management') {
|
|
return 'dealerClaim';
|
|
}
|
|
|
|
// ... other logic
|
|
|
|
return 'standard';
|
|
};
|
|
```
|
|
|
|
## 🔧 Configuration Options
|
|
|
|
### Template Configuration
|
|
|
|
```typescript
|
|
interface RequestDetailTemplate {
|
|
id: string; // Unique template ID
|
|
name: string; // Display name
|
|
description: string; // Description
|
|
tabs: TabConfig[]; // Tab configuration
|
|
defaultTab?: string; // Default active tab
|
|
header: HeaderConfig; // Header configuration
|
|
quickActions: QuickActionsConfig; // Quick actions config
|
|
layout?: LayoutConfig; // Layout options
|
|
canAccess?: AccessControl; // Access control function
|
|
onInit?: LifecycleHook; // Initialization hook
|
|
onDestroy?: LifecycleHook; // Cleanup hook
|
|
}
|
|
```
|
|
|
|
### Tab Configuration
|
|
|
|
```typescript
|
|
interface TabConfig {
|
|
id: string; // Tab ID
|
|
label: string; // Tab label
|
|
icon: LucideIcon; // Tab icon
|
|
component: React.ComponentType<any>; // Tab component
|
|
visible?: (context: TemplateContext) => boolean; // Visibility function
|
|
badge?: (context: TemplateContext) => number; // Badge count function
|
|
order?: number; // Display order
|
|
}
|
|
```
|
|
|
|
## 📊 SAP Integration Architecture
|
|
|
|
### Flow Diagram
|
|
|
|
```
|
|
Frontend (IO Tab)
|
|
↓
|
|
│ fetchIOBudget(ioNumber)
|
|
↓
|
|
.NET API (/api/sap/io/{ioNumber}/budget)
|
|
↓
|
|
│ ISapService.GetAvailableBudget()
|
|
↓
|
|
SAP RFC/API Integration
|
|
↓
|
|
│ Returns: { availableBudget, ioDetails }
|
|
↓
|
|
Display in UI
|
|
↓
|
|
User clicks "Block Budget"
|
|
↓
|
|
Frontend (IO Tab)
|
|
↓
|
|
│ blockIOBudget(ioNumber, amount, requestId)
|
|
↓
|
|
.NET API (/api/sap/io/block)
|
|
↓
|
|
│ ISapService.BlockBudget()
|
|
↓
|
|
SAP RFC/API Integration
|
|
↓
|
|
│ Creates SAP document
|
|
│ Returns: { documentNumber, status }
|
|
↓
|
|
Save to Database + Display in UI
|
|
```
|
|
|
|
### Implementation Checklist
|
|
|
|
- [ ] Create SAP service interface in .NET
|
|
- [ ] Implement SAP RFC connector or REST API client
|
|
- [ ] Add SAP credentials to configuration
|
|
- [ ] Create database tables for IO tracking
|
|
- [ ] Implement API endpoints
|
|
- [ ] Test SAP connectivity
|
|
- [ ] Handle SAP errors gracefully
|
|
- [ ] Add logging for SAP transactions
|
|
- [ ] Implement retry logic for transient failures
|
|
- [ ] Add monitoring and alerts
|
|
|
|
## 🧪 Testing
|
|
|
|
### Unit Tests
|
|
|
|
```typescript
|
|
// src/pages/RequestDetail/templates/__tests__/templateSelector.test.ts
|
|
|
|
import { selectTemplate } from '../index';
|
|
|
|
describe('Template Selector', () => {
|
|
it('selects dealer claim template for claim requests', () => {
|
|
const user = { role: 'dealer' };
|
|
const request = { category: 'claim-management' };
|
|
|
|
const templateId = selectTemplate(user, request);
|
|
expect(templateId).toBe('dealerClaim');
|
|
});
|
|
|
|
it('selects vendor template for vendor requests', () => {
|
|
const user = { role: 'vendor' };
|
|
const request = { category: 'vendor' };
|
|
|
|
const templateId = selectTemplate(user, request);
|
|
expect(templateId).toBe('vendor');
|
|
});
|
|
|
|
it('defaults to standard template', () => {
|
|
const user = { role: 'user' };
|
|
const request = { category: 'other' };
|
|
|
|
const templateId = selectTemplate(user, request);
|
|
expect(templateId).toBe('standard');
|
|
});
|
|
});
|
|
```
|
|
|
|
### Integration Tests
|
|
|
|
```typescript
|
|
// Test IO tab functionality
|
|
describe('IO Tab', () => {
|
|
it('fetches IO budget from SAP', async () => {
|
|
render(<IOTab request={mockRequest} />);
|
|
|
|
const input = screen.getByPlaceholderText(/Enter IO number/i);
|
|
fireEvent.change(input, { target: { value: 'IO-2024-12345' } });
|
|
|
|
const fetchButton = screen.getByText(/Fetch Amount/i);
|
|
fireEvent.click(fetchButton);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/₹50,000/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
## 📖 Documentation
|
|
|
|
- **README_TEMPLATES.md** - Comprehensive template system documentation
|
|
- **CustomTemplateExample.tsx** - Example implementations
|
|
- **Type definitions** - Fully typed with TypeScript
|
|
- **Inline comments** - All files include detailed comments
|
|
|
|
## 🚦 Migration Path
|
|
|
|
### Phase 1: Parallel Deployment (Week 1-2)
|
|
- Deploy new template system alongside existing component
|
|
- Use for new dealer claim requests only
|
|
- Monitor for issues
|
|
|
|
### Phase 2: Gradual Migration (Week 3-4)
|
|
- Migrate vendor requests to new system
|
|
- Update frontend routes
|
|
- Train users on new features
|
|
|
|
### Phase 3: Full Adoption (Week 5-6)
|
|
- Migrate all request types
|
|
- Deprecate old component
|
|
- Remove legacy code
|
|
|
|
### Phase 4: Optimization (Week 7-8)
|
|
- Gather user feedback
|
|
- Optimize performance
|
|
- Add additional templates as needed
|
|
|
|
## 🎯 Next Steps
|
|
|
|
1. **Immediate (Week 1)**
|
|
- [ ] Review and test new components
|
|
- [ ] Configure template selector for your request types
|
|
- [ ] Implement SAP API endpoints
|
|
- [ ] Deploy to staging environment
|
|
|
|
2. **Short-term (Week 2-4)**
|
|
- [ ] Create custom templates for additional user types
|
|
- [ ] Implement SAP integration
|
|
- [ ] Add unit and integration tests
|
|
- [ ] Document custom workflows
|
|
|
|
3. **Long-term (Month 2+)**
|
|
- [ ] Add analytics and monitoring
|
|
- [ ] Create additional custom tabs
|
|
- [ ] Optimize performance
|
|
- [ ] Gather user feedback and iterate
|
|
|
|
## 💡 Best Practices
|
|
|
|
1. **Template Design**
|
|
- Keep templates focused on specific use cases
|
|
- Reuse common components when possible
|
|
- Use visibility functions for conditional features
|
|
|
|
2. **Performance**
|
|
- Lazy load heavy components
|
|
- Use React.memo for expensive renders
|
|
- Implement proper cleanup in lifecycle hooks
|
|
|
|
3. **Security**
|
|
- Validate all user inputs
|
|
- Implement proper authorization checks
|
|
- Never expose sensitive SAP credentials
|
|
|
|
4. **Maintainability**
|
|
- Document custom templates thoroughly
|
|
- Follow TypeScript best practices
|
|
- Write comprehensive tests
|
|
|
|
## 🆘 Support & Resources
|
|
|
|
- **Documentation**: `src/pages/RequestDetail/README_TEMPLATES.md`
|
|
- **Examples**: `src/pages/RequestDetail/examples/`
|
|
- **Type Definitions**: `src/pages/RequestDetail/types/template.types.ts`
|
|
|
|
## 📝 Summary
|
|
|
|
You now have a **fully functional, template-driven RequestDetail system** that:
|
|
|
|
✅ Supports multiple user types (dealers, vendors, standard users)
|
|
✅ Includes IO budget management for dealer claims
|
|
✅ Provides flexibility to add custom templates
|
|
✅ Maintains backward compatibility
|
|
✅ Follows .NET enterprise best practices
|
|
✅ Is production-ready with proper error handling
|
|
✅ Includes comprehensive documentation
|
|
|
|
The system is designed to scale with your organization's needs while maintaining code quality and developer experience.
|
|
|
|
---
|
|
|
|
**Need Help?** Contact the .NET Expert Team for assistance with implementation, customization, or troubleshooting.
|
|
|