11 KiB
11 KiB
Enhanced Approval Actions - Practical Usage Guide
🎯 Overview
Panduan praktis untuk menggunakan Enhanced Approval Actions API yang mendukung 3 jenis action: Approve, Revision, dan Reject.
🔄 Action Types & Behavior
| Action | Behavior | Use Case | Result |
|---|---|---|---|
approve |
Naik ke step berikutnya | Content sudah sesuai | Workflow berlanjut |
revision |
Mundur 1 step | Content perlu diperbaiki | Workflow mundur 1 step |
reject |
Balik ke Draft | Content tidak sesuai | Workflow dihentikan, artikel jadi draft |
🧪 Practical Examples
Scenario 1: Normal Approval Flow
Step 1: Editor Review
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/10/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer EDITOR_TOKEN" \
-d '{
"action": "approve",
"message": "Content is well-written and follows our guidelines"
}'
Response:
{
"success": true,
"messages": ["Article successfully approve through active approval flow"],
"data": {
"article_id": 10,
"flow_id": 1,
"action": "approve",
"current_step": 2,
"current_branch": "Final_Approval",
"workflow_id": 1
}
}
Step 2: Senior Editor Review
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/10/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SENIOR_EDITOR_TOKEN" \
-d '{
"action": "approve",
"message": "Final approval granted. Ready for publication."
}'
Result: Article published successfully! 🎉
Scenario 2: Request Update Flow
Step 1: Editor Review
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/11/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer EDITOR_TOKEN" \
-d '{
"action": "approve",
"message": "Content is good, moving to next level"
}'
Step 2: Senior Editor Review (Request Revision)
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/11/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SENIOR_EDITOR_TOKEN" \
-d '{
"action": "revision",
"message": "Please add more examples in section 3 and improve the conclusion"
}'
Response:
{
"success": true,
"messages": ["Article successfully revision through active approval flow"],
"data": {
"article_id": 11,
"flow_id": 2,
"action": "revision",
"current_step": 1,
"current_branch": "Branch_A",
"workflow_id": 1
}
}
Result: Article kembali ke step 1 untuk revisi! 📝
Step 3: After Revision, Approve Again
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/11/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer EDITOR_TOKEN" \
-d '{
"action": "approve",
"message": "Revisions completed, content improved significantly"
}'
Scenario 3: Reject Flow
Step 1: Editor Review (Reject)
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/12/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer EDITOR_TOKEN" \
-d '{
"action": "reject",
"message": "Content does not meet our quality standards. Please rewrite with better research and clearer structure."
}'
Response:
{
"success": true,
"messages": ["Article successfully reject through active approval flow"],
"data": {
"article_id": 12,
"flow_id": 3,
"action": "reject",
"current_step": 1,
"current_branch": "Branch_A",
"workflow_id": 1
}
}
Result: Article dikembalikan ke status Draft! ❌
🔍 Database State Changes
After Approve:
-- Article Approval Flows
UPDATE article_approval_flows
SET current_step = 2,
updated_at = NOW()
WHERE id = 1;
-- Article Approval Step Logs
INSERT INTO article_approval_step_logs
(approval_flow_id, step_order, action, action_by_id, message, created_at)
VALUES (1, 1, 'approve', 5, 'Content is well-written', NOW());
After Revision:
-- Article Approval Flows
UPDATE article_approval_flows
SET current_step = 1,
revision_requested = true,
revision_message = 'Please add more examples',
updated_at = NOW()
WHERE id = 2;
-- Article Approval Step Logs
INSERT INTO article_approval_step_logs
(approval_flow_id, step_order, action, action_by_id, message, created_at)
VALUES (2, 2, 'revision', 6, 'Please add more examples', NOW());
After Reject:
-- Article Approval Flows
UPDATE article_approval_flows
SET status_id = 3,
rejection_reason = 'Content does not meet quality standards',
completed_at = NOW(),
updated_at = NOW()
WHERE id = 3;
-- Articles
UPDATE articles
SET status_id = 1,
is_draft = true,
workflow_id = NULL,
current_approval_step = NULL,
updated_at = NOW()
WHERE id = 12;
-- Article Approval Step Logs
INSERT INTO article_approval_step_logs
(approval_flow_id, step_order, action, action_by_id, message, created_at)
VALUES (3, 1, 'reject', 5, 'Content does not meet quality standards', NOW());
🎯 Frontend Integration Examples
React Component:
import React, { useState } from 'react';
const ApprovalActions = ({ articleId, onActionComplete }) => {
const [action, setAction] = useState('approve');
const [message, setMessage] = useState('');
const handleSubmit = async () => {
try {
const response = await fetch(`/api/article-approval-flows/articles/${articleId}/approve`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ action, message })
});
const result = await response.json();
if (result.success) {
onActionComplete(result.data);
alert(`Article ${action} successfully!`);
} else {
alert(`Error: ${result.messages[0]}`);
}
} catch (error) {
alert('Failed to process approval action');
}
};
return (
<div className="approval-actions">
<h3>Approval Actions</h3>
<div className="action-buttons">
<button
className={action === 'approve' ? 'active' : ''}
onClick={() => setAction('approve')}
>
✅ Approve
</button>
<button
className={action === 'revision' ? 'active' : ''}
onClick={() => setAction('revision')}
>
📝 Revision
</button>
<button
className={action === 'reject' ? 'active' : ''}
onClick={() => setAction('reject')}
>
❌ Reject
</button>
</div>
<textarea
placeholder="Enter your message..."
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button onClick={handleSubmit}>
Submit {action}
</button>
</div>
);
};
Vue.js Component:
<template>
<div class="approval-actions">
<h3>Approval Actions</h3>
<div class="action-buttons">
<button
v-for="actionType in actions"
:key="actionType.value"
:class="{ active: selectedAction === actionType.value }"
@click="selectedAction = actionType.value"
>
{{ actionType.icon }} {{ actionType.label }}
</button>
</div>
<textarea
v-model="message"
placeholder="Enter your message..."
/>
<button @click="submitAction" :disabled="!selectedAction">
Submit {{ selectedAction }}
</button>
</div>
</template>
<script>
export default {
data() {
return {
selectedAction: 'approve',
message: '',
actions: [
{ value: 'approve', label: 'Approve', icon: '✅' },
{ value: 'revision', label: 'Revision', icon: '📝' },
{ value: 'reject', label: 'Reject', icon: '❌' }
]
}
},
methods: {
async submitAction() {
try {
const response = await fetch(`/api/article-approval-flows/articles/${this.articleId}/approve`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
},
body: JSON.stringify({
action: this.selectedAction,
message: this.message
})
});
const result = await response.json();
if (result.success) {
this.$emit('action-complete', result.data);
alert(`Article ${this.selectedAction} successfully!`);
} else {
alert(`Error: ${result.messages[0]}`);
}
} catch (error) {
alert('Failed to process approval action');
}
}
}
}
</script>
🚨 Error Handling Examples
Invalid Action:
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/123/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"action": "invalid_action",
"message": "Test"
}'
Response:
{
"success": false,
"messages": ["Validation failed: [Action must be one of: approve, revision, reject]"]
}
Missing Action:
curl -X POST "http://localhost:8080/api/article-approval-flows/articles/123/approve" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"message": "Test"
}'
Response:
{
"success": false,
"messages": ["Validation failed: [Action is required]"]
}
📊 Testing Scenarios
Test Case 1: Complete Approval Flow
- Create article dengan user level 5
- Editor (level 3) approve → step 2
- Senior Editor (level 2) approve → published
Test Case 2: Revision Flow
- Create article dengan user level 5
- Editor (level 3) approve → step 2
- Senior Editor (level 2) revision → step 1
- Editor (level 3) approve again → step 2
- Senior Editor (level 2) approve → published
Test Case 3: Reject Flow
- Create article dengan user level 5
- Editor (level 3) reject → article jadi draft
- Workflow dihentikan
🎉 Summary
Enhanced Approval Actions API memberikan:
- ✅ 3 Action Types: Approve, Revision, Reject
- ✅ Flexible Workflow: Support untuk berbagai skenario
- ✅ Better UX: User bisa memberikan feedback yang spesifik
- ✅ Quality Control: Reject option untuk content yang tidak sesuai
- ✅ Revision Support: Revision untuk perbaikan tanpa menghentikan workflow
- ✅ Audit Trail: Semua action dicatat dalam logs
Sekarang approver memiliki kontrol penuh atas workflow dengan 3 pilihan action yang berbeda! 🚀