← Назад
// Claude API Report Generator — freelance template // Typical Upwork project: $800-1,200 // Stack: @anthropic-ai/sdk + csv-parse + nodemailer const Anthropic = require('@anthropic-ai/sdk') const fs = require('fs') const path = require('path') // ---- Config ---- const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || 'your-key' const REPORT_MODEL = 'claude-sonnet-4-20250514' const client = new Anthropic({ apiKey: ANTHROPIC_API_KEY }) // ---- CSV Parser (simple, no deps) ---- function parseCSV(filePath) { const content = fs.readFileSync(filePath, 'utf8') const lines = content.trim().split('\n') const headers = lines[0].split(',').map(h => h.trim()) return lines.slice(1).map(line => { const values = line.split(',').map(v => v.trim()) const row = {} headers.forEach((h, i) => { row[h] = values[i] || '' }) return row }) } // ---- Report Generation ---- async function generateReport(data, config = {}) { const { companyName = 'Company', reportType = 'Weekly Sales Report', period = 'This Week', extraContext = '', } = config // Summarize data for the prompt const dataPreview = JSON.stringify(data.slice(0, 50), null, 2) const totalRows = data.length const prompt = `You are a business analyst generating an executive report. ## Context - Company: ${companyName} - Report Type: ${reportType} - Period: ${period} ${extraContext ? `- Additional: ${extraContext}` : ''} ## Data (${totalRows} rows, showing first 50) \`\`\`json ${dataPreview} \`\`\` ## Instructions Generate a professional executive summary report with: 1. **Key Metrics** — top 3-5 numbers that matter (revenue, growth, etc.) 2. **Trends** — what's going up, what's going down, why 3. **Highlights** — notable wins or concerns 4. **Recommendations** — 2-3 actionable items for next week 5. **Risk Flags** — anything that needs immediate attention Format as clean Markdown. Be concise, data-driven, no fluff. Use bullet points and bold for key numbers.` const response = await client.messages.create({ model: REPORT_MODEL, max_tokens: 2000, messages: [{ role: 'user', content: prompt }], }) return response.content[0].text } // ---- HTML Wrapper ---- function wrapHTML(markdown, title) { // Simple markdown → HTML (bold, headers, bullets) let html = markdown .replace(/^### (.+)$/gm, '<h3>$1</h3>') .replace(/^## (.+)$/gm, '<h2>$1</h2>') .replace(/^# (.+)$/gm, '<h1>$1</h1>') .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>') .replace(/^- (.+)$/gm, '<li>$1</li>') .replace(/(<li>.*<\/li>\n?)+/g, '<ul>$&</ul>') .replace(/\n\n/g, '</p><p>') .replace(/\n/g, '<br>') return `<!DOCTYPE html> <html> <head> <style> body { font-family: -apple-system, Arial, sans-serif; max-width: 700px; margin: 40px auto; color: #333; line-height: 1.6; } h1 { color: #1a1a2e; border-bottom: 2px solid #4361ee; padding-bottom: 8px; } h2 { color: #4361ee; margin-top: 24px; } h3 { color: #555; } strong { color: #1a1a2e; } ul { padding-left: 20px; } li { margin: 4px 0; } .footer { margin-top: 40px; font-size: 12px; color: #999; border-top: 1px solid #eee; padding-top: 12px; } </style> </head> <body> <h1>${title}</h1> <p>${html}</p> <div class="footer">Generated automatically by AI Report Generator · ${new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}</div> </body> </html>` } // ---- Main ---- async function main() { const inputFile = process.argv[2] || 'sample-data.csv' if (!fs.existsSync(inputFile)) { console.log('Creating sample data...') createSampleData(inputFile) } console.log(`[Report] Reading ${inputFile}...`) const data = parseCSV(inputFile) console.log(`[Report] ${data.length} rows loaded`) console.log('[Report] Generating with Claude...') const report = await generateReport(data, { companyName: 'Acme Corp', reportType: 'Weekly Sales Report', period: 'Apr 28 — May 4, 2026', }) // Save Markdown const mdFile = 'report.md' fs.writeFileSync(mdFile, `# Weekly Sales Report\n\n${report}`) console.log(`[Report] Markdown saved: ${mdFile}`) // Save HTML const htmlFile = 'report.html' fs.writeFileSync(htmlFile, wrapHTML(report, 'Weekly Sales Report — Acme Corp')) console.log(`[Report] HTML saved: ${htmlFile}`) console.log('\n--- REPORT PREVIEW ---\n') console.log(report) } // ---- Sample Data Generator ---- function createSampleData(file) { const products = ['Widget A', 'Widget B', 'Pro Plan', 'Enterprise', 'Add-on Pack'] const regions = ['US-West', 'US-East', 'EU', 'APAC'] const lines = ['date,product,region,revenue,units,refunds'] for (let d = 0; d < 7; d++) { const date = new Date(2026, 4, d + 28) // Apr 28 - May 4 for (const product of products) { const region = regions[Math.floor(Math.random() * regions.length)] const units = Math.floor(Math.random() * 50) + 5 const price = product.includes('Enterprise') ? 499 : product.includes('Pro') ? 99 : 29 const revenue = units * price const refunds = Math.floor(Math.random() * 3) lines.push(`${date.toISOString().split('T')[0]},${product},${region},${revenue},${units},${refunds}`) } } fs.writeFileSync(file, lines.join('\n')) console.log(`[Sample] Created ${file} with ${lines.length - 1} rows`) } main().catch(console.error)