config_cache = null;
// Also clear any WordPress object cache
wp_cache_delete('easy_invoice_settings_config', 'easy_invoice');
// Force clear any other caches
if (function_exists('wp_cache_flush')) {
wp_cache_flush();
}
}
/**
* Initialize the controller
*
* @return void
*/
public function init() {
// Add AJAX handlers
add_action('wp_ajax_easy_invoice_save_settings', [$this, 'saveSettings']);
add_action('wp_ajax_easy_invoice_test_email', [$this, 'testEmail']);
add_action('wp_ajax_easy_invoice_test_template_email', [$this, 'testTemplateEmail']);
add_action('wp_ajax_easy_invoice_test_payment_reminder_email', [$this, 'testPaymentReminderEmail']);
add_action('wp_ajax_regenerate_invoice_numbers', [$this, 'ajaxRegenerateInvoiceNumbers']);
add_action('wp_ajax_regenerate_quote_numbers', [$this, 'ajaxRegenerateQuoteNumbers']);
// Clear cache on admin init to ensure new fields are recognized
add_action('admin_init', [$this, 'clearCache']);
// Enqueue admin scripts
add_action('admin_enqueue_scripts', [$this, 'enqueueAdminScripts']);
// Initialize settings
$this->initializeSettings();
}
/**
* Enqueue admin scripts and styles for the settings page.
*
* @param string $hook_suffix The current admin page.
* @return void
*/
public function enqueueAdminScripts($hook_suffix) {
// Check if we are on the Easy Invoice settings page.
if (empty($hook_suffix) || strpos($hook_suffix, PagesSlugs::SETTINGS) === false) {
return;
}
wp_enqueue_script('jquery-ui-sortable');
wp_enqueue_media(); // For the logo uploader
// Enqueue Select2 for enhancing multiselect fields
wp_enqueue_style(
'select2',
'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css',
[],
'4.0.13'
);
wp_enqueue_script(
'select2',
'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js',
['jquery'],
'4.0.13',
true
);
// Enqueue confirmation modal for premium features
wp_enqueue_script(
'easy-invoice-confirmation-modal',
EASY_INVOICE_URL . 'assets/js/confirmation-modal.js',
['jquery'],
EASY_INVOICE_VERSION,
true
);
// Enqueue toast notification system
wp_enqueue_script(
'easy-invoice-toast',
EASY_INVOICE_URL . 'assets/js/easy-invoice-toast.js',
['jquery'],
EASY_INVOICE_VERSION,
true
);
$script_handle = 'easy-invoice-settings';
wp_enqueue_script(
$script_handle,
EASY_INVOICE_URL . 'assets/js/settings.js',
['jquery', 'jquery-ui-sortable', 'wp-util', 'select2', 'easy-invoice-confirmation-modal', 'media-views'],
EASY_INVOICE_VERSION,
true
);
// Enqueue the new settings.css only on the settings page
wp_enqueue_style(
'easy-invoice-settings',
EASY_INVOICE_URL . 'assets/css/settings.css',
[],
EASY_INVOICE_VERSION
);
$localize_data = apply_filters('easy_invoice_settings_js_data', [
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('easy_invoice_settings'),
'saveSuccess' => __('Settings saved successfully', 'easy-invoice'),
'saveError' => __('Error saving settings', 'easy-invoice'),
]);
wp_localize_script($script_handle, 'easyInvoiceSettings', $localize_data);
do_action('easy_invoice_after_admin_scripts', $hook_suffix);
}
/**
* Check if Easy Invoice Pro is active
*
* @return bool
*/
private function isProActive(): bool {
return easy_invoice_has_pro();
}
/**
* Get settings fields configuration
*
* @return array
*/
public function get_settings_fields_config() {
// Use cached config if available
if (is_array($this->config_cache)) {
return $this->config_cache;
}
$config = [
'company' => [
'title' => __('Company Information', 'easy-invoice'),
'description' => __('Set up your company details', 'easy-invoice'),
'icon' => 'fas fa-building',
'fields' => [
'easy_invoice_company_name' => ['label' => __('Company Name', 'easy-invoice'), 'type' => 'text', 'default' => '', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_company_email' => ['label' => __('Email', 'easy-invoice'), 'type' => 'email', 'default' => '', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_company_phone' => ['label' => __('Phone Number', 'easy-invoice'), 'type' => 'tel', 'default' => '', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_company_website' => ['label' => __('Website', 'easy-invoice'), 'type' => 'url', 'default' => '', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_company_address' => ['label' => __('Address', 'easy-invoice'), 'type' => 'textarea', 'default' => '', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_tax_number' => ['label' => __('Tax ID / VAT Number', 'easy-invoice'), 'type' => 'text', 'default' => '', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_company_logo' => ['label' => __('Company Logo', 'easy-invoice'), 'type' => 'image', 'default' => '', 'col_span' => 'sm:col-span-6' ],
]
],
'invoice' => [
'title' => __('Invoice Settings', 'easy-invoice'),
'description' => __('Configure invoice-specific settings and preferences', 'easy-invoice'),
'icon' => 'fas fa-file-invoice',
'fields' => [
'easy_invoice_invoice_prefix' => [
'label' => __('Invoice Prefix', 'easy-invoice'),
'type' => 'text',
'default' => 'EIIN_',
'description' => __('Prefix for invoice numbers (e.g., EIIN_, INV-)', 'easy-invoice'),
'col_span' => 'sm:col-span-2'
],
'easy_invoice_next_invoice_number' => [
'label' => __('Next Invoice Number', 'easy-invoice'),
'type' => 'number',
'default' => '1',
'description' => __('Set the next invoice number to be generated. This will be the number of the next invoice created.', 'easy-invoice'),
'col_span' => 'sm:col-span-2',
],
'easy_invoice_regenerate_invoice_numbers' => [
'label' => __('Regenerate Invoice Numbers', 'easy-invoice'),
'type' => 'button',
'button_text' => __('Regenerate All Invoice Numbers', 'easy-invoice'),
'button_class' => 'button button-secondary',
'description' => __('Click to regenerate all invoice numbers starting from the Last Invoice Number. This will update all existing invoices with new sequential numbers.', 'easy-invoice'),
'col_span' => 'sm:col-span-2',
'ajax_action' => 'regenerate_invoice_numbers'
],
'easy_invoice_invoice_show_adjust_field' => [
'label' => __('Show/Hide Adjust Field', 'easy-invoice'),
'type' => 'checkbox',
'default' => 'yes',
'description' => __('Enable/Disable Adjust field. Tick this to show adjust field', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_invoice_terms_conditions' => [
'label' => __('Terms & Conditions', 'easy-invoice'),
'type' => 'wp_editor',
'default' => __('Payment is due within 30 days from date of invoice', 'easy-invoice'),
'description' => __('Terms and conditions that will be displayed on your invoice', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_invoice_footer_text' => [
'label' => __('Footer Text', 'easy-invoice'),
'type' => 'wp_editor',
'default' => '',
'description' => __('You can modify your invoice footer text from here. HTML tags supports: a, br, em, strong, hr, p, h1 to h4', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
],
],
'quote' => [
'title' => __('Quote Settings', 'easy-invoice'),
'description' => __('Configure quote-specific settings and preferences', 'easy-invoice'),
'icon' => 'fas fa-file-contract',
'fields' => [
'easy_invoice_quote_prefix' => [
'label' => __('Quote Prefix', 'easy-invoice'),
'type' => 'text',
'default' => 'EIQN_',
'description' => __('Prefix for quote numbers (e.g., EIQN_, QT-)', 'easy-invoice'),
'col_span' => 'sm:col-span-2'
],
'easy_invoice_next_quote_number' => [
'label' => __('Next Quote Number', 'easy-invoice'),
'type' => 'number',
'default' => '1',
'description' => __('Set the next quote number to be generated. This will be the number of the next quote created.', 'easy-invoice'),
'col_span' => 'sm:col-span-2',
],
'easy_invoice_regenerate_quote_numbers' => [
'label' => __('Regenerate Quote Numbers', 'easy-invoice'),
'type' => 'button',
'button_text' => __('Regenerate All Quote Numbers', 'easy-invoice'),
'button_class' => 'button button-secondary',
'description' => __('Click to regenerate all quote numbers starting from the Next Quote Number. This will update all existing quotes with new sequential numbers.', 'easy-invoice'),
'col_span' => 'sm:col-span-2',
'ajax_action' => 'regenerate_quote_numbers'
],
'easy_invoice_quote_show_adjust_field' => [
'label' => __('Show/Hide Adjust Field', 'easy-invoice'),
'type' => 'checkbox',
'default' => 'yes',
'description' => __('Enable/Disable Adjust field. Tick this to show adjust field', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_terms_conditions' => [
'label' => __('Terms & Conditions', 'easy-invoice'),
'type' => 'wp_editor',
'default' => __('This quote has a fixed price. Upon acceptance, we kindly ask for a 25% deposit prior to initiating the work.', 'easy-invoice'),
'description' => __('Terms and conditions that will be displayed on your quote!', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_footer_text' => [
'label' => __('Footer Text', 'easy-invoice'),
'type' => 'wp_editor',
'default' => __('Thanks for choosing Easy Invoice', 'easy-invoice'),
'description' => __('You can modify your quote footer text from here. HTML tags supports: a, br, em, strong, hr, p, h1 to h4', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_accept_button' => [
'label' => __('Accept quote button', 'easy-invoice'),
'type' => 'checkbox',
'default' => 'yes',
'description' => __('Show/hide accept quote button on quotes.', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_accept_action' => [
'label' => __('Accept quote button action', 'easy-invoice'),
'type' => 'select',
'default' => 'convert',
'options' => [
'convert' => __('Convert quote to invoice - Draft', 'easy-invoice'),
'convert_available' => __('Convert quote to invoice - Available', 'easy-invoice'),
'convert_send' => __('Convert quote to invoice and send to client - Available', 'easy-invoice'),
'duplicate' => __('Create new invoice, keep quote as-is - Draft', 'easy-invoice'),
'duplicate_send' => __('Create new invoice and send to client, keep quote as-is - Available', 'easy-invoice'),
'do_nothing' => __('Do nothing', 'easy-invoice'),
],
'description' => __('Upon the client clicking the "accept quote" button, the subsequent action will be activated.', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_accept_text' => [
'label' => __('Accept Quote Text', 'easy-invoice'),
'type' => 'wp_editor',
'default' => __('Important: When you accept this Quote, an Invoice will be created automatically. This will form a legally binding contract.', 'easy-invoice'),
'description' => __('This information tells your client what happens once they accept the Quote', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_accepted_message' => [
'label' => __('Accepted Quote Message', 'easy-invoice'),
'type' => 'wp_editor',
'default' => __('You\'ve confirmed the Quote.
We\'ll get in touch with you shortly.', 'easy-invoice'),
'description' => __('If the client accepts the Quote, display this message.', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_decline_reason_required' => [
'label' => __('Decline Reason Required', 'easy-invoice'),
'type' => 'checkbox',
'default' => 'no',
'description' => __('Make the \'Reason for declining\' field mandatory when rejecting.', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_quote_declined_message' => [
'label' => __('Declined Quote Message', 'easy-invoice'),
'type' => 'wp_editor',
'default' => '',
'description' => __('Message to display if client declines the Quote', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
],
],
'currency' => [
'title' => __('Currency Settings', 'easy-invoice'),
'description' => __('Configure currency display preferences', 'easy-invoice'),
'icon' => 'fas fa-dollar-sign',
'fields' => [
'easy_invoice_currency_code' => [
'label' => __('Currency & Symbol', 'easy-invoice'),
'type' => 'select',
'default' => 'USD',
'options' => CurrencyHelper::getCurrencyOptions(),
'col_span' => 'sm:col-span-6',
'description' => __('Select your preferred currency. The symbol will be automatically set.', 'easy-invoice')
],
'easy_invoice_currency_position' => [
'label' => __('Symbol Position', 'easy-invoice'),
'type' => 'select',
'default' => 'left',
'options' => [
'left' => __('Left', 'easy-invoice'),
'right' => __('Right', 'easy-invoice'),
'left_space' => __('Left with space', 'easy-invoice'),
'right_space' => __('Right with space', 'easy-invoice'),
],
'col_span' => 'sm:col-span-3'
],
'easy_invoice_currency_symbol_type' => [
'label' => __('Currency Symbol Type', 'easy-invoice'),
'type' => 'select',
'default' => 'symbol',
'options' => [
'code' => __('Currency Code', 'easy-invoice'),
'symbol' => __('Currency Symbol', 'easy-invoice'),
],
'description' => __('Choose whether to display currency code (USD) or currency symbol ($)', 'easy-invoice'),
'col_span' => 'sm:col-span-3'
],
'easy_invoice_thousands_separator' => ['label' => __('Thousands Separator', 'easy-invoice'), 'type' => 'text', 'default' => ',', 'col_span' => 'sm:col-span-3' ],
'easy_invoice_decimal_separator' => ['label' => __('Decimal Separator', 'easy-invoice'), 'type' => 'text', 'default' => '.', 'col_span' => 'sm:col-span-3' ],
'easy_invoice_decimal_precision' => ['label' => __('Decimal Places', 'easy-invoice'), 'type' => 'number', 'default' => '2', 'min' => 0, 'max' => 4, 'col_span' => 'sm:col-span-3' ],
]
],
'tax' => [
'title' => __('Tax Settings', 'easy-invoice'),
'description' => __('Configure tax rates and preferences', 'easy-invoice'),
'icon' => 'fas fa-percent',
'fields' => [
'easy_invoice_tax_enabled' => ['label' => __('Enable Tax', 'easy-invoice'), 'type' => 'checkbox', 'default' => 'no', 'col_span' => 'sm:col-span-6' ],
'easy_invoice_tax_entry_method' => [
'label' => __('How do you enter tax?', 'easy-invoice'),
'type' => 'select',
'default' => 'exclusive',
'options' => [
'inclusive' => __('I will enter price inclusive of tax', 'easy-invoice'),
'exclusive' => __('I will enter price exclusive of tax', 'easy-invoice'),
],
'description' => __('Choose how you want to enter prices - with or without tax included', 'easy-invoice'),
'col_span' => 'sm:col-span-6'
],
'easy_invoice_tax_rate' => ['label' => __('Default Tax Rate (%)', 'easy-invoice'), 'type' => 'number', 'default' => '0', 'step' => '0.01', 'min' => '0', 'max' => '100', 'col_span' => 'sm:col-span-3' ],
'easy_invoice_tax_name' => ['label' => __('Tax Name', 'easy-invoice'), 'type' => 'text', 'default' => __('Tax', 'easy-invoice'), 'col_span' => 'sm:col-span-3' ],
]
],
'payment' => [
'title' => __('Payment Methods', 'easy-invoice'),
'description' => __('Configure and order available payment methods.', 'easy-invoice'),
'icon' => 'fas fa-credit-card',
'is_special_section' => true,
'gateways' => $this->getGatewaySettingsConfigs(),
],
'email' => [
'title' => __('Email Settings', 'easy-invoice'),
'description' => __('Configure email sending options and templates', 'easy-invoice'),
'icon' => 'fas fa-envelope',
'subsections' => [
'general' => [
'title' => __('General Email Settings', 'easy-invoice'),
'description' => __('Configure general email sending options', 'easy-invoice'),
'fields' => [
'easy_invoice_email_from_name' => ['label' => __('From Name', 'easy-invoice'), 'type' => 'text', 'default' => get_bloginfo('name') ?: 'Easy Invoice', 'col_span' => 'sm:col-span-3'],
'easy_invoice_email_from_address' => ['label' => __('From Email Address', 'easy-invoice'), 'type' => 'email', 'default' => get_bloginfo('admin_email') ?: get_option('admin_email', ''), 'col_span' => 'sm:col-span-3'],
'easy_invoice_email_reply_to' => ['label' => __('Reply-To Email', 'easy-invoice'), 'type' => 'email', 'default' => '', 'col_span' => 'sm:col-span-3'],
'easy_invoice_email_reply_to_name' => ['label' => __('Reply-To Name', 'easy-invoice'), 'type' => 'text', 'default' => '', 'col_span' => 'sm:col-span-3'],
'easy_invoice_enable_email_styling' => ['label' => __('Enable HTML Emails', 'easy-invoice'), 'type' => 'checkbox', 'default' => 'yes', 'col_span' => 'sm:col-span-6'],
'easy_invoice_bcc_admin' => ['label' => __('BCC Admin on All Emails', 'easy-invoice'), 'type' => 'checkbox', 'default' => 'no', 'col_span' => 'sm:col-span-6'],
'easy_invoice_admin_email' => ['label' => __('Admin Email for BCC', 'easy-invoice'), 'type' => 'email', 'default' => get_option('admin_email', ''), 'col_span' => 'sm:col-span-6'],
'easy_invoice_email_logo' => ['label' => __('Email Logo URL', 'easy-invoice'), 'type' => 'url', 'default' => '', 'col_span' => 'sm:col-span-6'],
'easy_invoice_email_footer_text' => ['label' => __('Email Footer Text', 'easy-invoice'), 'type' => 'textarea', 'default' => '', 'col_span' => 'sm:col-span-6'],
'easy_invoice_test_email' => [
'label' => __('Test Email', 'easy-invoice'),
'type' => 'test_email',
'default' => '',
'col_span' => 'sm:col-span-6',
'description' => __('Send a test email to verify your email configuration is working correctly.', 'easy-invoice')
],
]
],
'invoice_available' => [
'title' => __('Invoice Available Email', 'easy-invoice'),
'description' => __('Configure email sent when an invoice is available for the client', 'easy-invoice'),
'fields' => [
'easy_invoice_invoice_email_enabled' => ['label' => __('Enable Invoice Available Email', 'easy-invoice'), 'type' => 'checkbox', 'default' => 'yes', 'col_span' => 'sm:col-span-6'],
'easy_invoice_invoice_email_subject' => ['label' => __('Subject', 'easy-invoice'), 'type' => 'text', 'default' => __('Your Invoice #{{invoice_number}} from {{company_name}}', 'easy-invoice'), 'col_span' => 'sm:col-span-6'],
'easy_invoice_invoice_email_body' => ['label' => __('Email Body', 'easy-invoice'), 'type' => 'wp_editor', 'default' => __('
Dear {{client_name}},
Invoice #{{invoice_number}}
{{total_amount}}
Due Date: {{due_date}}
Your invoice has been prepared and is ready for payment. You can view and download the complete invoice from the attachment.
📋 Payment Details:
• Invoice Number: {{invoice_number}}
• Total Amount: {{total_amount}}
• Due Date: {{due_date}}
• Payment Terms: {{payment_terms}}
⚠️ Important: Please ensure payment is received by the due date to avoid any late fees or service interruptions.
If you have any questions about this invoice, please don\'t hesitate to contact us.
Thank you for your business!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Quote #{{quote_number}}
{{total_amount}}
Valid Until: {{expiry_date}}
We have prepared a detailed quote for your project. You can view and download the complete quote from the attachment or visit the link below.
📋 Quote Summary:
• Quote Number: {{quote_number}}
• Total Amount: {{total_amount}}
• Valid Until: {{expiry_date}}
• Terms: {{payment_terms}}
🔗 View Quote Online:
{{quote_url}}
Shortcode: [easy_quote_url number="{{quote_number}}" text="View Quote"]
⏰ Time Sensitive: This quote is valid until {{expiry_date}}. Please review and respond within this timeframe.
If you have any questions or would like to discuss any aspects of this quote, please contact us.
We look forward to working with you!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Payment Confirmation
Invoice #{{invoice_number}}
{{payment_amount}}
Payment Date: {{payment_date}}
Payment Method: {{payment_method}}
We have successfully received your payment. Thank you for your prompt payment!
📊 Payment Details:
• Invoice Number: {{invoice_number}}
• Amount Paid: {{payment_amount}}
• Payment Date: {{payment_date}}
• Payment Method: {{payment_method}}
• Transaction ID: {{transaction_id}}
🎉 Status: PAID
Your payment has been processed and your account is now up to date. We appreciate your business!
If you have any questions about this payment or need a receipt, please don\'t hesitate to contact us.
Thank you for choosing our services!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Invoice #{{invoice_number}}
{{total_amount}}
Due Date: {{due_date}}
Your invoice has been prepared and is ready for payment. You can view and download the complete invoice from the attachment or visit the link below.
📋 Payment Details:
• Invoice Number: {{invoice_number}}
• Total Amount: {{total_amount}}
• Due Date: {{due_date}}
• Payment Terms: {{payment_terms}}
🔗 View Invoice Online:
{{invoice_url}}
Shortcode: [easy_invoice_url number="{{invoice_number}}" text="View Invoice"]
⚠️ Important: Please ensure payment is received by the due date to avoid any late fees or service interruptions.
If you have any questions about this invoice, please don\'t hesitate to contact us.
Thank you for your business!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Quote #{{quote_number}}
Total Amount: {{total_amount}}
Valid Until: {{expiry_date}}
We have prepared a detailed quote for your project. You can view and download the complete quote from the attachment or visit the link below.
Quote Summary:
• Quote Number: {{quote_number}}
• Total Amount: {{total_amount}}
• Valid Until: {{expiry_date}}
• Terms: {{payment_terms}}
🔗 View Quote Online:
{{quote_url}}
Shortcode: [easy_quote_url number="{{quote_number}}" text="View Quote"]
This quote is valid until {{expiry_date}}. If you have any questions or would like to discuss any aspects of this quote, please contact us.
We look forward to working with you!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Payment Confirmation
Invoice #{{invoice_number}}
{{payment_amount}}
Payment Date: {{payment_date}}
Payment Method: {{payment_method}}
We have successfully received your payment. Thank you for your prompt payment!
📊 Payment Details:
• Invoice Number: {{invoice_number}}
• Amount Paid: {{payment_amount}}
• Payment Date: {{payment_date}}
• Payment Method: {{payment_method}}
• Transaction ID: {{transaction_id}}
🎉 Status: PAID
Your payment has been processed and your account is now up to date. We appreciate your business!
If you have any questions about this payment or need a receipt, please don\'t hesitate to contact us.
Thank you for choosing our services!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Invoice #{{invoice_number}}
{{total_amount}}
Due Date: {{due_date}}
Your invoice has been prepared and is ready for payment. You can view and download the complete invoice from the attachment.
📋 Payment Details:
• Invoice Number: {{invoice_number}}
• Total Amount: {{total_amount}}
• Due Date: {{due_date}}
• Payment Terms: {{payment_terms}}
⚠️ Important: Please ensure payment is received by the due date to avoid any late fees or service interruptions.
If you have any questions about this invoice, please do not hesitate to contact us.
Thank you for your business!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Quote #{{quote_number}}
{{total_amount}}
Valid Until: {{expiry_date}}
We have prepared a detailed quote for your project. You can view and download the complete quote from the attachment.
📋 Quote Summary:
• Quote Number: {{quote_number}}
• Total Amount: {{total_amount}}
• Valid Until: {{expiry_date}}
• Terms: {{payment_terms}}
⏰ Time Sensitive: This quote is valid until {{expiry_date}}. Please review and respond within this timeframe.
If you have any questions or would like to discuss any aspects of this quote, please contact us.
We look forward to working with you!
Best regards,
{{company_name}}
{{company_email}}
Dear {{client_name}},
Payment Confirmation
Invoice #{{invoice_number}}
{{payment_amount}}
Payment Date: {{payment_date}}
Payment Method: {{payment_method}}
We have successfully received your payment. Thank you for your prompt payment!
📊 Payment Details:
• Invoice Number: {{invoice_number}}
• Amount Paid: {{payment_amount}}
• Payment Date: {{payment_date}}
• Payment Method: {{payment_method}}
• Transaction ID: {{transaction_id}}
🎉 Status: PAID
Your payment has been processed and your account is now up to date. We appreciate your business!
If you have any questions about this payment or need a receipt, please do not hesitate to contact us.
Thank you for choosing our services!
Best regards,
{{company_name}}
{{company_email}}
echo \EasyInvoice\Controllers\SettingsController::getTextFrom(); : echo $company_name;
//echo \EasyInvoice\Controllers\SettingsController::getTextTo(); : echo $client_name;
// /** * Get custom text setting with fallback to default * * @param string $key Text setting key * @param string $default Default text * @return string Custom text or default */ public static function getTextSetting(string $key, string $default): string { $option_key = 'easy_invoice_text_' . $key; return get_option($option_key, $default); } // Invoice Text Settings public static function getTextInvoice(): string { return self::getTextSetting('invoice', __('Invoice', 'easy-invoice')); } public static function getTextInvoices(): string { return self::getTextSetting('invoices', __('Invoices', 'easy-invoice')); } public static function getTextTo(): string { return self::getTextSetting('to', __('To', 'easy-invoice')); } public static function getTextInvoiceNumber(): string { return self::getTextSetting('invoice_number', __('Invoice Number', 'easy-invoice')); } public static function getTextInvoiceDate(): string { return self::getTextSetting('invoice_date', __('Invoice Date', 'easy-invoice')); } public static function getTextDueDate(): string { return self::getTextSetting('due_date', __('Due Date', 'easy-invoice')); } public static function getTextTotalDue(): string { return self::getTextSetting('total_due', __('Total Due', 'easy-invoice')); } public static function getTextQty(): string { return self::getTextSetting('qty', __('Qty', 'easy-invoice')); } public static function getTextService(): string { return self::getTextSetting('service', __('Service', 'easy-invoice')); } public static function getTextRatePrice(): string { return self::getTextSetting('rate_price', __('Rate', 'easy-invoice')); } public static function getTextAdjust(): string { return self::getTextSetting('adjust', __('Adjust', 'easy-invoice')); } public static function getTextSubTotal(): string { return self::getTextSetting('sub_total', __('Sub Total', 'easy-invoice')); } public static function getTextTotal(): string { return self::getTextSetting('total', __('Total', 'easy-invoice')); } public static function getTextTax(): string { return self::getTextSetting('tax', __('Tax', 'easy-invoice')); } public static function getTextDiscount(): string { return self::getTextSetting('discount', __('Discount', 'easy-invoice')); } public static function getTextPrint(): string { return self::getTextSetting('print', __('Print', 'easy-invoice')); } public static function getTextDownloadPdf(): string { return self::getTextSetting('download_pdf', __('Download as PDF', 'easy-invoice')); } public static function getTextSendEmail(): string { return self::getTextSetting('send_email', __('Send Email', 'easy-invoice')); } public static function getTextPayNow(): string { return self::getTextSetting('pay_now', __('Pay Now', 'easy-invoice')); } // Quote Text Settings public static function getTextQuote(): string { return self::getTextSetting('quote', __('Quote', 'easy-invoice')); } public static function getTextQuoteNumber(): string { return self::getTextSetting('quote_number', __('Quote Number', 'easy-invoice')); } public static function getTextAcceptQuote(): string { return self::getTextSetting('accept_quote', __('Accept Quote', 'easy-invoice')); } public static function getTextDeclineQuote(): string { return self::getTextSetting('decline_quote', __('Decline Quote', 'easy-invoice')); } public static function getTextDeclineReason(): string { return self::getTextSetting('decline_reason', __('Reason for declining', 'easy-invoice')); } public static function getTextValidUntil(): string { return self::getTextSetting('valid_until', __('Valid Until Date', 'easy-invoice')); } public static function getTextQuoteDate(): string { return self::getTextSetting('quote_date', __('Quote Date', 'easy-invoice')); } public static function getTextFrom(): string { return self::getTextSetting('from', __('From', 'easy-invoice')); } /** * Get the actual date format string from the stored format identifier * * @param string $format_identifier The format identifier (us, uk, iso) * @return string The actual date format string */ public static function getDateFormatString($format_identifier = null): string { if ($format_identifier === null) { $format_identifier = get_option('easy_invoice_date_format', 'us'); } switch ($format_identifier) { case 'uk': return 'd/m/Y'; case 'iso': return 'Y-m-d'; case 'us': default: return 'm/d/Y'; } } /** * Get the current date format string * * @return string The current date format string */ public static function getCurrentDateFormat(): string { return self::getDateFormatString(); } /** * Format a date using the Easy Invoice date format setting * * @param string|int $date The date to format (timestamp or date string) * @return string The formatted date */ public static function formatDate($date): string { $format = self::getCurrentDateFormat(); $timestamp = is_numeric($date) ? $date : strtotime($date); return date_i18n($format, $timestamp); } /** * AJAX handler for regenerating invoice numbers */ public function ajaxRegenerateInvoiceNumbers() { // Verify nonce $nonce = $_POST['nonce'] ?? $_POST['easy_invoice_settings_nonce'] ?? ''; if (!wp_verify_nonce($nonce, 'easy_invoice_settings')) { wp_send_json_error(['message' => __('Security check failed', 'easy-invoice')]); } // Check permissions if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('You do not have permission to perform this action', 'easy-invoice')]); } try { // Get the current next invoice number $current_next_number = intval(get_option('easy_invoice_next_invoice_number', 1)); $prefix = get_option('easy_invoice_invoice_prefix', 'EIIN_'); // Start regeneration from the current next number $starting_number = $current_next_number; // Get all invoices ordered by creation date $invoices = get_posts([ 'post_type' => 'easy_invoice', 'post_status' => 'publish', 'numberposts' => -1, 'orderby' => 'date', 'order' => 'ASC' ]); if (empty($invoices)) { wp_send_json_success([ 'message' => __('No invoices found to regenerate', 'easy-invoice'), 'regenerated_count' => 0 ]); } $regenerated_count = 0; $current_number = $starting_number; foreach ($invoices as $invoice) { // Generate new invoice number $new_invoice_number = $prefix . str_pad($current_number, 6, '0', STR_PAD_LEFT); // Update the invoice number update_post_meta($invoice->ID, '_easy_invoice_number', $new_invoice_number); $regenerated_count++; $current_number++; } // Update the next invoice number counter to continue from the last regenerated number + 1 update_option('easy_invoice_next_invoice_number', $current_number); wp_send_json_success([ 'message' => sprintf(__('Successfully regenerated %d invoice numbers', 'easy-invoice'), $regenerated_count), 'regenerated_count' => $regenerated_count, 'next_number' => $current_number ]); } catch (Exception $e) { wp_send_json_error(['message' => __('Failed to regenerate invoice numbers', 'easy-invoice')]); } } /** * AJAX handler for regenerating quote numbers */ public function ajaxRegenerateQuoteNumbers() { // Verify nonce $nonce = $_POST['nonce'] ?? $_POST['easy_invoice_settings_nonce'] ?? ''; if (!wp_verify_nonce($nonce, 'easy_invoice_settings')) { wp_send_json_error(['message' => __('Security check failed', 'easy-invoice')]); } // Check permissions if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('You do not have permission to perform this action', 'easy-invoice')]); } try { $current_next_number = intval(get_option('easy_invoice_next_quote_number', 1)); $prefix = get_option('easy_invoice_quote_prefix', 'QT-'); $starting_number = $current_next_number; $quotes = get_posts([ 'post_type' => 'easy_invoice_quote', 'post_status' => 'publish', 'numberposts' => -1, 'orderby' => 'date', 'order' => 'ASC', 'meta_query' => [ [ 'key' => '_easy_invoice_quote_number', 'compare' => 'EXISTS' ] ] ]); $regenerated_count = 0; $current_number = $starting_number; foreach ($quotes as $quote_post) { $new_quote_number = $prefix . str_pad($current_number, 6, '0', STR_PAD_LEFT); update_post_meta($quote_post->ID, '_easy_invoice_quote_number', $new_quote_number); $regenerated_count++; $current_number++; } update_option('easy_invoice_next_quote_number', $current_number); wp_send_json_success([ 'message' => sprintf(__('Successfully regenerated %d quote numbers', 'easy-invoice'), $regenerated_count), 'regenerated_count' => $regenerated_count, 'next_number' => $current_number ]); } catch (Exception $e) { wp_send_json_error(['message' => __('Failed to regenerate quote numbers', 'easy-invoice')]); } } }