admin_url('admin-ajax.php'), 'nonce' => $ajax_nonce )); // Get quote ID if present in URL $quote_id = isset($_GET['id']) ? intval($_GET['id']) : 0; if ($quote_id) { $post = get_post($quote_id); if (!$post || $post->post_type !== \EasyInvoice\Constants\PostTypes::EASY_INVOICE_QUOTE_POST_TYPE) { wp_die(__('Invalid post type. This builder can only be used for quotes.', 'easy-invoice'), __('Invalid Post Type', 'easy-invoice'), array('back_link' => true)); } } $quote = null; // Check if this is a new quote (no ID) $is_new_quote = ($quote_id === 0); // Default values for new quote $quote_number_service = function_exists('easy_invoice_get_quote_number_service') ? easy_invoice_get_quote_number_service() : null; // Get global quote settings $settings_controller = new \EasyInvoice\Controllers\SettingsController(); $quote_prefix = $settings_controller::getQuotePrefix(); $quote_terms = $settings_controller::getQuoteTermsConditions(); $quote_footer = $settings_controller::getQuoteFooterText(); $quote_accept_button = get_option('easy_invoice_quote_accept_button', 'yes'); $quote_accept_action = get_option('easy_invoice_quote_accept_action', 'email'); $quote_accept_text = get_option('easy_invoice_quote_accept_text', __('Accept Quote', 'easy-invoice')); $quote_accepted_message = get_option('easy_invoice_quote_accepted_message', __('Thank you for accepting our quote!', 'easy-invoice')); $quote_declined_message = get_option('easy_invoice_quote_declined_message', __('Thank you for your consideration.', 'easy-invoice')); $quote_data = array( 'number' => $quote_number_service ? $quote_number_service->getNextNumber() : 'QT-1', 'date' => date('Y-m-d'), 'expiry_date' => date('Y-m-d', strtotime('+30 days')), 'client_id' => 0, 'client_name' => '', 'client_email' => '', 'client_phone' => '', 'client_address' => '', 'items' => array(), 'notes' => '', 'internal_notes' => '', 'discount' => 0, 'discount_type' => 'percentage', 'calculation_method' => 'before_tax', 'tax_rate' => easy_invoice_get_tax_rate(), 'prices_include_tax' => 'no', 'status' => 'draft', 'currency' => 'USD', 'currency_symbol' => '$', 'title' => '', 'description' => '', 'terms' => $quote_terms, // Use global terms setting 'footer_text' => $quote_footer, // Use global footer setting 'accept_button' => $quote_accept_button, // Use global accept button setting 'accept_action' => $quote_accept_action, // Use global accept action setting 'accept_text' => $quote_accept_text, // Use global accept text setting 'accepted_message' => $quote_accepted_message, // Use global accepted message setting 'declined_message' => $quote_declined_message, // Use global declined message setting ); // Get clients from repository $client_repository = ClientServiceProvider::getClientRepository(); $clients = $client_repository->all(); // Load client data directly in PHP if quote has a client $client_data = null; if ($quote && $quote->getClientId()) { $client = $client_repository->find($quote->getClientId()); if ($client) { $client_data = array( 'id' => $client->getId(), 'name' => $client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName()), 'email' => $client->getEmail() ?: '', 'phone' => $client->getExtraInfo() ?: '', 'company' => $client->getBusinessClientName() ?: '', 'address' => $client->getAddress() ?: '', 'website' => $client->getWebsite() ?: '', ); } } // If editing an existing quote, load its data if ($quote_id > 0) { // Get the quote from repository $quote_repository = QuoteServiceProvider::getQuoteRepository(); $quote = $quote_repository->find($quote_id); if ($quote && $quote->getId()) { // Quote loaded successfully } else { // Failed to load quote } } else { // Create a temporary WP_Post object for new quote $empty_post = new WP_Post((object) array( 'ID' => 0, 'post_author' => get_current_user_id(), 'post_date' => current_time('mysql'), 'post_date_gmt' => current_time('mysql', 1), 'post_title' => $quote_data['number'], 'post_status' => 'auto-draft', 'comment_status' => 'closed', 'ping_status' => 'closed', 'post_name' => '', 'post_modified' => current_time('mysql'), 'post_modified_gmt' => current_time('mysql', 1), 'post_parent' => 0, 'guid' => '', 'menu_order' => 0, 'post_type' => \EasyInvoice\Constants\PostTypes::EASY_INVOICE_QUOTE_POST_TYPE, 'post_mime_type' => '', 'comment_count' => 0, 'filter' => 'raw', )); $quote = new \EasyInvoice\Models\Quote($empty_post); // Set default values on the quote object foreach ($quote_data as $key => $value) { $setter = 'set' . easy_invoice_str_replace('_', '', ucwords($key, '_')); if (method_exists($quote, $setter)) { // Handle type-specific setters switch ($setter) { case 'setClientId': $quote->setClientId((int) $value); break; case 'setItems': $quote->setItems((array) $value); break; case 'setSubtotal': case 'setTaxAmount': case 'setDiscountAmount': case 'setTotal': case 'setDiscountValue': case 'setTaxRate': $quote->$setter((float) $value); break; case 'setPricesIncludeTax': $quote->$setter((bool) $value); break; default: $quote->$setter((string) $value); break; } } } // Initialize empty items array $quote->setItems([]); } // Only load custom meta that's not handled by Quote object if ($quote) { // These are still accessed from meta as they don't have model methods yet $quote_data['terms'] = $quote_id > 0 ? get_post_meta($quote_id, '_easy_invoice_terms', true) : $quote_data['terms']; $quote_data['internal_notes'] = $quote_id > 0 ? get_post_meta($quote_id, '_easy_invoice_internal_notes', true) : $quote_data['internal_notes']; $quote_data['currency'] = $quote_id > 0 ? get_post_meta($quote_id, '_easy_invoice_currency_code', true) : $quote_data['currency']; $quote_data['currency_symbol'] = $quote_id > 0 ? get_post_meta($quote_id, '_easy_invoice_currency_position', true) : $quote_data['currency_symbol']; $quote_data['calculation_method'] = $quote_id > 0 ? get_post_meta($quote_id, '_easy_invoice_calculation_method', true) : $quote_data['calculation_method']; } // Prepare quote items JSON for JavaScript $quote_items_json = json_encode($quote ? $quote->getItems() : []); // Create nonce for AJAX calls $admin_nonce = wp_create_nonce('easy_invoice_admin_nonce'); // Initialize quote form manager for field configuration $quote_form_manager = new \EasyInvoice\Forms\Quote\QuoteFormManager(); $quote_field_config = $quote_form_manager->getFieldConfigForJavaScript(); // Remove the following code that preloads all templates into JS // $templates = $quote_form_manager->getTemplates(); // $template_htmls = []; // $formatter = new \EasyInvoice\Helpers\QuoteFormatter($quote); // foreach ($templates as $template_id => $template_config) { // $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/' . $template_id . '.php'; // if (file_exists($template_file)) { // ob_start(); // include $template_file; // $template_htmls[$template_id] = ob_get_clean(); // } else { // $template_htmls[$template_id] = '
The template "' . esc_html($template_id) . '" does not exist.