Install AyurERP Pro
Get quick access to your ERP system
`; this.showModal('๐Ÿ“Š Advanced Report Generator', content); } updateReportFields() { const reportType = document.getElementById('reportType').value; const gstinField = document.getElementById('gstinField'); if (reportType === 'gstr1' || reportType === 'gstr3b') { gstinField.style.display = 'block'; } else { gstinField.style.display = 'none'; } } async previewReport() { const reportType = document.getElementById('reportType').value; const period = document.getElementById('reportPeriod').value; if (!reportType) { this.showNotification('Please select a report type', 'error'); return; } this.showNotification('Generating preview...', 'info'); // Simulate report generation setTimeout(() => { const previewDiv = document.getElementById('reportPreview'); const contentDiv = document.getElementById('previewContent'); let previewContent = ''; switch (reportType) { case 'gstr1': previewContent = this.generateGSTR1Preview(); break; case 'profit_loss': previewContent = this.generatePLPreview(); break; case 'balance_sheet': previewContent = this.generateBalanceSheetPreview(); break; default: previewContent = `

Preview for ${reportType} report will be generated here.

`; } contentDiv.innerHTML = previewContent; previewDiv.style.display = 'block'; this.showNotification('Preview generated successfully!', 'success'); }, 1500); } generateGSTR1Preview() { return `

GSTR-1 Summary

Nature of Supplies Taxable Value CGST SGST Total Tax
B2B Supplies โ‚น2,50,000 โ‚น22,500 โ‚น22,500 โ‚น45,000
B2C Supplies โ‚น1,50,000 โ‚น13,500 โ‚น13,500 โ‚น27,000
Total โ‚น4,00,000 โ‚น36,000 โ‚น36,000 โ‚น72,000
`; } generatePLPreview() { return `

Profit & Loss Statement

INCOME
Sales Revenue โ‚น4,72,000
Other Income โ‚น5,000
Total Income โ‚น4,77,000
EXPENSES
Cost of Goods Sold โ‚น2,40,000
Operating Expenses โ‚น1,20,000
Total Expenses โ‚น3,60,000
NET PROFIT โ‚น1,17,000
`; } generateBalanceSheetPreview() { return `

Balance Sheet

ASSETS
Current Assets
Cash & Bankโ‚น4,80,000
Inventoryโ‚น3,00,000
Receivablesโ‚น1,20,000
Fixed Assets
Equipmentโ‚น6,50,000
TOTAL ASSETS โ‚น15,50,000
LIABILITIES & EQUITY
Current Liabilities
Payablesโ‚น80,000
GST Payableโ‚น25,000
Equity
Capitalโ‚น12,00,000
Retained Earningsโ‚น2,45,000
TOTAL LIAB. & EQUITY โ‚น15,50,000
`; } async generateReportFile() { const reportType = document.getElementById('reportType').value; const format = document.getElementById('reportFormat').value; if (!reportType) { this.showNotification('Please select a report type', 'error'); return; } this.showNotification(`Generating ${reportType} report in ${format} format...`, 'info'); // Simulate report generation and download setTimeout(() => { if (format === 'html') { this.previewReport(); } else { // Simulate file download const filename = `${reportType}_${new Date().toISOString().split('T')[0]}.${format}`; this.showNotification(`Report "${filename}" generated successfully!`, 'success'); // Create dummy download const element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent('Report content would be here')); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } }, 2000); } // ================================================================================================ // ADVANCED INVENTORY FEATURES // ================================================================================================ async showStockAdjustment() { const products = await this.db.getAll('products'); const content = `

โš ๏ธ Stock Adjustment

This will permanently adjust stock levels. Please ensure all information is accurate before proceeding.

๐Ÿ“ฆ Products to Adjust

Total Adjustments: 0
`; this.showModal('๐Ÿ”„ Stock Adjustment', content); } updateAdjustmentProductInfo(select, itemIndex) { const option = select.selectedOptions[0]; if (!option || !option.value) return; const currentStock = option.getAttribute('data-current'); const currentStockInput = document.querySelector(`[name="items[${itemIndex}][current_stock]"]`); if (currentStockInput) { currentStockInput.value = currentStock; } } calculateAdjustment(itemIndex) { const currentStockInput = document.querySelector(`[name="items[${itemIndex}][current_stock]"]`); const newStockInput = document.querySelector(`[name="items[${itemIndex}][new_stock]"]`); const adjustmentInput = document.querySelector(`[name="items[${itemIndex}][adjustment]"]`); if (currentStockInput && newStockInput && adjustmentInput) { const currentStock = parseFloat(currentStockInput.value) || 0; const newStock = parseFloat(newStockInput.value) || 0; const adjustment = newStock - currentStock; adjustmentInput.value = adjustment > 0 ? `+${adjustment}` : adjustment.toString(); adjustmentInput.style.color = adjustment >= 0 ? 'var(--success)' : 'var(--danger)'; this.updateTotalAdjustments(); } } updateTotalAdjustments() { const adjustmentInputs = document.querySelectorAll('[name*="[adjustment]"]'); let totalItems = 0; adjustmentInputs.forEach(input => { if (input.value && input.value !== '0') { totalItems++; } }); document.getElementById('totalAdjustments').textContent = totalItems; } addAdjustmentItem() { const container = document.getElementById('adjustmentItems'); const itemCount = container.children.length + 1; const products = this.db.cache.products || []; const newItem = document.createElement('div'); newItem.className = 'form-section'; newItem.style.marginBottom = '1rem'; newItem.innerHTML = `
`; container.appendChild(newItem); } async saveStockAdjustment() { const form = document.getElementById('stockAdjustmentForm'); const formData = new FormData(form); const adjustmentType = formData.get('adjustment_type'); if (!adjustmentType) { this.showNotification('Please select an adjustment type', 'error'); return; } // Collect adjustment items const items = []; const adjustmentInputs = document.querySelectorAll('[name*="[adjustment]"]'); for (let i = 0; i < adjustmentInputs.length; i++) { const itemIndex = i + 1; const productSelect = document.querySelector(`[name="items[${itemIndex}][product_id]"]`); const currentStockInput = document.querySelector(`[name="items[${itemIndex}][current_stock]"]`); const newStockInput = document.querySelector(`[name="items[${itemIndex}][new_stock]"]`); const reasonInput = document.querySelector(`[name="items[${itemIndex}][reason]"]`); if (productSelect && productSelect.value && newStockInput && newStockInput.value !== '') { const product = await this.db.getById('products', productSelect.value); const currentStock = parseInt(currentStockInput.value); const newStock = parseInt(newStockInput.value); const adjustment = newStock - currentStock; if (adjustment !== 0) { items.push({ product_id: productSelect.value, product_name: product.name, current_stock: currentStock, new_stock: newStock, adjustment: adjustment, reason: reasonInput.value }); } } } if (items.length === 0) { this.showNotification('Please add at least one adjustment', 'error'); return; } try { // Create adjustment record const adjustmentRecord = { reference: formData.get('reference'), adjustment_type: adjustmentType, adjustment_date: formData.get('adjustment_date'), approved_by: formData.get('approved_by'), items: items, total_items: items.length, status: 'completed' }; await this.db.create('stock_adjustments', adjustmentRecord); // Update product stocks and create movement records for (const item of items) { await this.db.update('products', item.product_id, { stock: item.new_stock }); // Create movement record await this.db.create('inventory_movements', { product_id: item.product_id, product_name: item.product_name, type: item.adjustment > 0 ? 'in' : 'out', quantity: Math.abs(item.adjustment), reason: `Stock Adjustment - ${adjustmentType}`, reference: adjustmentRecord.reference, notes: item.reason, previous_stock: item.current_stock, new_stock: item.new_stock, created_by: this.currentUser.name }); } this.showNotification('Stock adjustment completed successfully!', 'success'); this.closeModal(); this.loadPage('inventory'); } catch (error) { console.error('Error processing stock adjustment:', error); this.showNotification('Failed to process stock adjustment', 'error'); } } // ================================================================================================ // ERROR HANDLING & VALIDATION // ================================================================================================ handleError(error, context = 'Application') { console.error(`${context} Error:`, error); let userMessage = 'An unexpected error occurred. Please try again.'; if (error.name === 'NetworkError') { userMessage = 'Network connection issue. Operating in offline mode.'; } else if (error.name === 'ValidationError') { userMessage = error.message || 'Please check your input and try again.'; } else if (error.name === 'PermissionError') { userMessage = 'You do not have permission to perform this action.'; } this.showNotification(userMessage, 'error'); // Log error for debugging this.logError(error, context); } logError(error, context) { const errorLog = { timestamp: new Date().toISOString(), context: context, error: { name: error.name, message: error.message, stack: error.stack }, user: this.currentUser?.username || 'anonymous', page: this.currentPage, userAgent: navigator.userAgent }; // Store error log locally const logs = JSON.parse(localStorage.getItem('ayurerp_error_logs') || '[]'); logs.push(errorLog); // Keep only last 100 errors if (logs.length > 100) { logs.splice(0, logs.length - 100); } localStorage.setItem('ayurerp_error_logs', JSON.stringify(logs)); } validateGSTNumber(gstin) { if (!gstin) return true; // Optional field const gstinRegex = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/; return gstinRegex.test(gstin); } validateEmail(email) { if (!email) return true; // Optional field const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } validatePhone(phone) { if (!phone) return false; // Required field const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/; return phoneRegex.test(phone.replace(/[\s\-\(\)]/g, '')); } // ================================================================================================ // USER PROFILE & PREFERENCES // ================================================================================================ showProfile() { const content = `
${this.currentUser.name.charAt(0)}

${this.currentUser.name}

${this.currentUser.email}

${this.currentUser.role}

๐Ÿ” Security Settings

Enable 2FA for enhanced security
`; this.showModal('๐Ÿ‘ค User Profile', content); this.closeModal(); // Close user menu modal first } showPreferences() { const content = `

๐ŸŽจ Display Preferences

๐Ÿ”” Notification Preferences

Low stock alerts
New order notifications
Payment due reminders
System update notifications
Email notifications

๐Ÿ“Š Data & Reports

`; this.showModal('โš™๏ธ Preferences', content); this.closeModal(); // Close user menu modal first } showHelp() { const content = `

โ“ Help & Support

Get help with AyurERP Pro

๐Ÿš€ Getting Started

Learn the basics of using AyurERP Pro

๐Ÿ“– User Guide

Detailed documentation for all features

๐ŸŽฅ Video Tutorials

Step-by-step video guides

โ“ Frequently Asked Questions

Quick answers to common questions

๐Ÿ“ž Contact Support

Email Support
support@ayurerp.com
Phone Support
+91-831-123-4567
Live Chat
Available 9 AM - 6 PM IST

๐Ÿ’ก Quick Tips

`; this.showModal('โ“ Help & Support', content); this.closeModal(); // Close user menu modal first } saveProfile() { this.showNotification('Profile updated successfully!', 'success'); this.closeModal(); } savePreferences() { this.showNotification('Preferences saved successfully!', 'success'); this.closeModal(); } resetPreferences() { if (confirm('Are you sure you want to reset all preferences to default?')) { this.showNotification('Preferences reset to default!', 'success'); } } showHelpSection(section) { this.showNotification(`Loading ${section} documentation...`, 'info'); } } // ================================================================================================ // APPLICATION INITIALIZATION // ================================================================================================ // Initialize the application const app = new AyurERP_App(); // Service Worker Registration for PWA if ('serviceWorker' in navigator) { window.addEventListener('load', () => { const swScript = ` const CACHE_NAME = 'ayurerp-v1'; const urlsToCache = [ '/', '/manifest.json' ]; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll(urlsToCache)) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { return response || fetch(event.request); } ) ); }); `; const blob = new Blob([swScript], { type: 'application/javascript' }); const swUrl = URL.createObjectURL(blob); navigator.serviceWorker.register(swUrl) .then(registration => { console.log('SW registered: ', registration); }) .catch(registrationError => { console.log('SW registration failed: ', registrationError); }); }); }