📄 Document Workflows
🎯 Mục tiêu bài học
Sau bài học này, bạn sẽ:
✅ Xây dựng multi-level document approval workflows
✅ Tạo documents tự động từ templates
✅ Implement version control cho documents
✅ Thiết kế contract management và report automation
Document management thường involves nhiều manual steps. Bài này hướng dẫn automate document creation, approvals, versioning và distribution.
🔍 Document Automation Overview
Automatable Document Tasks:
Checkpoint
Có mấy loại document tasks có thể automate?
⚡ Workflow 1: Document Approval Process
Multi-Level Approval:
Document Approval
Approval Request Message:
1const doc = $input.item.json;23const approvalRequest = {4 channel: doc.approverSlackId,5 blocks: [6 {7 type: "header",8 text: {9 type: "plain_text",10 text: "📋 Document Approval Required"11 }12 },13 {14 type: "section",15 text: {16 type: "mrkdwn",17 text: `*${doc.title}*\n\nSubmitted by: ${doc.creator}\nType: ${doc.docType}\nPriority: ${doc.priority}`18 }19 },20 {21 type: "section",22 text: {23 type: "mrkdwn",24 text: `*Summary:*\n${doc.summary || 'No summary provided'}`25 }26 },27 {28 type: "actions",29 elements: [30 {31 type: "button",32 text: {33 type: "plain_text",34 text: "📄 View Document"35 },36 url: doc.viewUrl37 },38 {39 type: "button",40 text: {41 type: "plain_text",42 text: "✅ Approve"43 },44 style: "primary",45 action_id: "approve_doc",46 value: doc.id47 },48 {49 type: "button",50 text: {51 type: "plain_text",52 text: "❌ Reject"53 },54 style: "danger",55 action_id: "reject_doc",56 value: doc.id57 }58 ]59 },60 {61 type: "context",62 elements: [63 {64 type: "mrkdwn",65 text: `Request ID: ${doc.id} | Deadline: ${doc.deadline || 'None'}`66 }67 ]68 }69 ]70};7172return approvalRequest;Handle Approval Response:
1const response = $input.item.json;23const updateDoc = {4 id: response.docId,5 status: response.action === 'approve_doc' ? 'approved' : 'rejected',6 approvedBy: response.userId,7 approvalDate: new Date().toISOString(),8 feedback: response.feedback || null9};1011// Determine next step12if (updateDoc.status === 'approved') {13 const doc = $('Get Document').item.json;14 15 if (doc.currentApprovalLevel < doc.requiredApprovals) {16 updateDoc.nextApprover = doc.approvalChain[doc.currentApprovalLevel + 1];17 updateDoc.nextAction = 'request_next_approval';18 } else {19 updateDoc.nextAction = 'finalize';20 }21} else {22 updateDoc.nextAction = 'notify_rejection';23}2425return updateDoc;Checkpoint
Multi-level approval workflow có bao nhiêu steps?
🔧 Workflow 2: Document Generation
Auto-Generate from Template:
Generate Document
Google Docs Template Merge:
1// Replace placeholders in Google Docs2const templateId = 'your-template-id';3const data = $input.item.json;45// Map of placeholders to values6const replacements = {7 '{{CLIENT_NAME}}': data.clientName,8 '{{DATE}}': new Date().toLocaleDateString(),9 '{{CONTRACT_NUMBER}}': data.contractNumber,10 '{{AMOUNT}}': data.amount.toLocaleString('en-US', {style: 'currency', currency: 'USD'}),11 '{{START_DATE}}': data.startDate,12 '{{END_DATE}}': data.endDate,13 '{{TERMS}}': data.terms14};1516return {17 templateId,18 replacements,19 outputName: `Contract_${data.contractNumber}_${data.clientName}.pdf`20};HTML to PDF Generation:
1const data = $input.item.json;23const htmlTemplate = `4<!DOCTYPE html>5<html>6<head>7 <style>8 body { font-family: Arial, sans-serif; margin: 40px; }9 .header { text-align: center; border-bottom: 2px solid #333; padding-bottom: 20px; }10 .logo { max-width: 150px; }11 h1 { color: #333; }12 .content { margin: 30px 0; }13 .signature-line { border-top: 1px solid #333; width: 200px; margin-top: 50px; }14 .footer { text-align: center; font-size: 12px; color: #666; margin-top: 50px; }15 table { width: 100%; border-collapse: collapse; }16 td, th { border: 1px solid #ddd; padding: 10px; }17 th { background: #f5f5f5; }18 </style>19</head>20<body>21 <div class="header">22 <img src="${data.logoUrl}" class="logo" alt="Company Logo">23 <h1>${data.documentType}</h1>24 <p>Document #: ${data.docNumber}</p>25 </div>26 27 <div class="content">28 <p><strong>To:</strong> ${data.recipientName}</p>29 <p><strong>From:</strong> ${data.senderName}</p>30 <p><strong>Date:</strong> ${new Date().toLocaleDateString()}</p>31 32 <h2>Summary</h2>33 <p>${data.summary}</p>34 35 <h2>Details</h2>36 <table>37 <tr>38 <th>Item</th>39 <th>Description</th>40 <th>Amount</th>41 </tr>42 ${data.items.map(item => `43 <tr>44 <td>${item.name}</td>45 <td>${item.description}</td>46 <td>$${item.amount.toFixed(2)}</td>47 </tr>48 `).join('')}49 <tr>50 <td colspan="2"><strong>Total</strong></td>51 <td><strong>$${data.total.toFixed(2)}</strong></td>52 </tr>53 </table>54 55 <div class="signature-line">56 <p>Authorized Signature</p>57 </div>58 </div>59 60 <div class="footer">61 <p>Generated automatically on ${new Date().toLocaleString()}</p>62 </div>63</body>64</html>65`;6667return { html: htmlTemplate, filename: `${data.docNumber}.pdf` };Checkpoint
Document generation từ template sử dụng placeholders format nào?
🏗️ Workflow 3: Version Control
Document Versioning:
Version Control
Version Management Code:
1const doc = $input.item.json;23// Parse current version (e.g., "1.2.3")4const currentVersion = doc.version || '1.0.0';5const [major, minor, patch] = currentVersion.split('.').map(Number);67// Determine version increment type8let newVersion;9const changeType = doc.changeType || 'patch';1011switch (changeType) {12 case 'major':13 newVersion = `${major + 1}.0.0`;14 break;15 case 'minor':16 newVersion = `${major}.${minor + 1}.0`;17 break;18 case 'patch':19 default:20 newVersion = `${major}.${minor}.${patch + 1}`;21}2223// Create archive name24const archiveName = `${doc.name}_v${currentVersion}_${new Date().toISOString().split('T')[0]}`;2526// Generate changelog entry27const changelogEntry = {28 version: newVersion,29 previousVersion: currentVersion,30 date: new Date().toISOString(),31 author: doc.modifiedBy,32 changes: doc.changeDescription || 'No description provided',33 type: changeType34};3536return {37 doc: {38 ...doc,39 version: newVersion,40 lastModified: new Date().toISOString()41 },42 archiveName,43 changelogEntry44};Checkpoint
Version control increment version theo semantic versioning như thế nào?
📊 Workflow 4: Contract Management
Contract Lifecycle Automation:
Contract Lifecycle
DocuSign Integration:
1{2 "name": "Request Signature",3 "type": "n8n-nodes-base.docuSign",4 "parameters": {5 "operation": "createEnvelope",6 "templateId": "your-template-id",7 "emailSubject": "Please sign: {{ $json.contractTitle }}",8 "recipients": {9 "signers": [10 {11 "email": "={{ $json.clientEmail }}",12 "name": "={{ $json.clientName }}",13 "recipientId": "1",14 "routingOrder": "1"15 }16 ]17 }18 }19}Expiration Reminder Setup:
1const contract = $input.item.json;2const expirationDate = new Date(contract.expirationDate);34// Calculate reminder dates5const reminders = [6 { days: 90, type: '3-month' },7 { days: 30, type: '1-month' },8 { days: 7, type: '1-week' }9];1011const scheduledReminders = reminders.map(r => {12 const reminderDate = new Date(expirationDate);13 reminderDate.setDate(reminderDate.getDate() - r.days);14 15 return {16 contractId: contract.id,17 contractTitle: contract.title,18 clientName: contract.clientName,19 expirationDate: contract.expirationDate,20 reminderDate: reminderDate.toISOString(),21 reminderType: r.type,22 status: 'scheduled'23 };24});2526return { reminders: scheduledReminders };Checkpoint
Contract lifecycle automation bao gồm những giai đoạn nào?
💡 Workflow 5: Report Automation
Weekly Report Generator:
Automated Report
Report Generation Code:
1const data = $input.item.json;23// Calculate key metrics4const metrics = {5 totalRevenue: data.sales.reduce((sum, s) => sum + s.amount, 0),6 newCustomers: data.customers.filter(c => c.isNew).length,7 churnRate: (data.churnedCustomers / data.totalCustomers * 100).toFixed(2),8 avgOrderValue: data.sales.reduce((sum, s) => sum + s.amount, 0) / data.sales.length9};1011// Compare with previous period12const comparison = {13 revenueChange: ((metrics.totalRevenue - data.previousRevenue) / data.previousRevenue * 100).toFixed(1),14 customerChange: metrics.newCustomers - data.previousNewCustomers15};1617// Generate insights18const insights = [];19if (parseFloat(comparison.revenueChange) > 10) {20 insights.push('🎉 Revenue increased significantly this week');21}22if (parseFloat(metrics.churnRate) > 5) {23 insights.push('⚠️ Churn rate is above target - investigation needed');24}2526const report = `27# Weekly Performance Report28*${new Date().toLocaleDateString()} - Week ${getWeekNumber(new Date())}*2930## Executive Summary31${insights.join('\n') || 'Performance is tracking to expectations.'}3233## Key Metrics3435| Metric | This Week | Change |36|--------|-----------|--------|37| Total Revenue | $${metrics.totalRevenue.toLocaleString()} | ${comparison.revenueChange}% |38| New Customers | ${metrics.newCustomers} | ${comparison.customerChange > 0 ? '+' : ''}${comparison.customerChange} |39| Churn Rate | ${metrics.churnRate}% | -- |40| Avg Order Value | $${metrics.avgOrderValue.toFixed(2)} | -- |4142## Top Performers43${data.topProducts.slice(0, 5).map((p, i) => `${i + 1}. ${p.name} - $${p.revenue.toLocaleString()}`).join('\n')}4445## Action Items46- [ ] Review churn drivers47- [ ] Follow up with top opportunities48- [ ] Update forecast4950*Auto-generated report*51`;5253return { report, metrics };5455function getWeekNumber(d) {56 const onejan = new Date(d.getFullYear(), 0, 1);57 return Math.ceil((((d - onejan) / 86400000) + onejan.getDay() + 1) / 7);58}Checkpoint
Report automation generate reports từ những data sources nào?
🌟 Workflow 6: Document Organization
Auto-Organize Documents:
Document Organization
Document Classification:
1const doc = $input.item.json;2const content = doc.text.toLowerCase();3const filename = doc.name.toLowerCase();45// Classification rules6const rules = [7 { 8 type: 'Invoice',9 folder: 'Finance/Invoices',10 patterns: ['invoice', 'bill', 'amount due', 'payment'],11 namePrefix: 'INV'12 },13 {14 type: 'Contract',15 folder: 'Legal/Contracts',16 patterns: ['agreement', 'contract', 'terms and conditions', 'hereby agree'],17 namePrefix: 'CON'18 },19 {20 type: 'Receipt',21 folder: 'Finance/Receipts',22 patterns: ['receipt', 'paid', 'transaction', 'thank you for your purchase'],23 namePrefix: 'REC'24 },25 {26 type: 'Report',27 folder: 'Reports',28 patterns: ['report', 'analysis', 'summary', 'findings'],29 namePrefix: 'RPT'30 }31];3233// Find matching rule34let classification = {35 type: 'Other',36 folder: 'Inbox/Uncategorized',37 namePrefix: 'DOC'38};3940for (const rule of rules) {41 const hasMatch = rule.patterns.some(p => 42 content.includes(p) || filename.includes(p)43 );44 45 if (hasMatch) {46 classification = rule;47 break;48 }49}5051// Generate new name52const date = new Date().toISOString().split('T')[0];53const newName = `${classification.namePrefix}_${date}_${doc.name}`;5455return {56 originalName: doc.name,57 newName,58 destinationFolder: classification.folder,59 documentType: classification.type,60 confidence: 'high'61};Checkpoint
Document classification sử dụng patterns matching cho những loại nào?
📋 Best Practices
DO:
- ✅ Maintain clear naming conventions
- ✅ Always version documents
- ✅ Include audit trails
- ✅ Backup before processing
- ✅ Validate before distribution
DON'T:
- ❌ Overwrite without archiving
- ❌ Skip approval steps
- ❌ Lose original documents
- ❌ Ignore access permissions
Checkpoint
Tại sao cần maintain clear naming conventions?
📝 Bài Tập Thực Hành
Build document system:
- Create approval workflow (2-level)
- Build document generator from template
- Implement version control system
- Set up contract expiration reminders
- Design auto-organization for incoming docs
Master document automation! 📄
Checkpoint
Bạn đã hoàn thành những challenges nào trong bài tập?
🧠 Key Takeaways
- 📝 Templates save time - Invest in good templates
- ✅ Approvals matter - Don't skip the process
- 📁 Organize consistently - Naming conventions are key
- 🔄 Version everything - Never lose history
- 📧 Automate distribution - Right doc, right person
Checkpoint
Tại sao Templates save time là nguyên tắc quan trọng?
🚀 Bài tiếp theo
Meeting Automation — Scheduling, prep, và follow-up automation.
