PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.3.4
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.3.4
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / includes / Services / InvoiceNumberService.php

InvoiceNumberService.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.3.4, at includes/Services/InvoiceNumberService.php

177 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Invoice Number Service
4 *
5 * @package Easy_Invoice
6 * @subpackage Services
7 */
8
9 namespace EasyInvoice\Services;
10
11 /**
12 * InvoiceNumberService Class
13 *
14 * Handles automatic generation of invoice numbers based on settings.
15 */
16 class InvoiceNumberService {
17
18 /**
19 * Generate the next invoice number
20 *
21 * @return string The generated invoice number
22 */
23 public function generateNextNumber(): string {
24 // Get settings
25 $prefix = get_option('easy_invoice_invoice_prefix', 'INV-');
26
27 // Get the next number to use
28 $next_number = get_option('easy_invoice_next_invoice_number', 1);
29
30 // Find the next unique number
31 $unique_number = $this->findNextUniqueNumber($next_number, $prefix);
32
33 // Update the counter to the number we actually used + 1 for next time
34 update_option('easy_invoice_next_invoice_number', $unique_number + 1);
35
36 return $prefix . str_pad($unique_number, 6, '0', STR_PAD_LEFT);
37 }
38
39 /**
40 * Get the next invoice number without incrementing
41 *
42 * @return string The next invoice number
43 */
44 public function getNextNumber(): string {
45 $prefix = get_option('easy_invoice_invoice_prefix', 'INV-');
46 $next_number = get_option('easy_invoice_next_invoice_number', 1);
47
48 // Find what the next unique number would be
49 $unique_number = $this->findNextUniqueNumber($next_number, $prefix);
50
51 return $prefix . str_pad($unique_number, 6, '0', STR_PAD_LEFT);
52 }
53
54 /**
55 * Reset the invoice number counter
56 *
57 * @param int $new_starting_number The new starting number
58 * @return void
59 */
60 public function resetCounter(int $new_starting_number = 1): void {
61 update_option('easy_invoice_next_invoice_number', $new_starting_number);
62 }
63
64 /**
65 * Check if an invoice number already exists
66 *
67 * @param string $invoice_number The invoice number to check
68 * @return bool True if the number exists, false otherwise
69 */
70 public function numberExists(string $invoice_number): bool {
71 global $wpdb;
72
73 $result = $wpdb->get_var($wpdb->prepare(
74 "SELECT COUNT(*) FROM {$wpdb->postmeta}
75 WHERE meta_key = '_easy_invoice_number'
76 AND meta_value = %s",
77 $invoice_number
78 ));
79
80 return intval($result) > 0;
81 }
82
83 /**
84 * Generate a unique invoice number (handles duplicates)
85 *
86 * @return string A unique invoice number
87 */
88 public function generateUniqueNumber(): string {
89 // Get settings
90 $prefix = get_option('easy_invoice_invoice_prefix', 'INV-');
91
92 // Get the next number to use from the current settings
93 $next_number = get_option('easy_invoice_next_invoice_number', 1);
94
95 // Find the next unique number
96 $unique_number = $this->findNextUniqueNumber($next_number, $prefix);
97
98 // Update the counter to the number we actually used + 1 for next time
99 update_option('easy_invoice_next_invoice_number', $unique_number + 1);
100
101 $final_number = $prefix . str_pad($unique_number, 6, '0', STR_PAD_LEFT);
102
103 return $final_number;
104 }
105
106 /**
107 * Find the next unique number starting from the given number
108 *
109 * @param int $start_number The number to start checking from
110 * @param string $prefix The prefix to use for checking
111 * @return int The next unique number
112 */
113 private function findNextUniqueNumber(int $start_number, string $prefix): int {
114 $current_number = $start_number;
115 $max_attempts = 1000; // Prevent infinite loops
116 $attempts = 0;
117
118 while ($attempts < $max_attempts) {
119 $invoice_number = $prefix . str_pad($current_number, 6, '0', STR_PAD_LEFT);
120
121 if (!$this->numberExists($invoice_number)) {
122 return $current_number;
123 }
124
125 $current_number++;
126 $attempts++;
127 }
128
129 // If we can't find a unique number, add timestamp to ensure uniqueness
130 return $current_number + time();
131 }
132
133 /**
134 * Get the highest invoice number from existing invoices
135 *
136 * @return int The highest invoice number found
137 */
138 public function getHighestInvoiceNumber(): int {
139 global $wpdb;
140
141 $prefix = get_option('easy_invoice_invoice_prefix', 'INV-');
142
143 // Get all invoice numbers from the database
144 $results = $wpdb->get_results($wpdb->prepare(
145 "SELECT meta_value FROM {$wpdb->postmeta}
146 WHERE meta_key = '_easy_invoice_number'
147 AND meta_value LIKE %s
148 ORDER BY meta_value DESC
149 LIMIT 1",
150 $prefix . '%'
151 ));
152
153 if (empty($results)) {
154 return 0;
155 }
156
157 $highest_number = $results[0]->meta_value;
158
159 // Extract the number part (remove prefix and padding)
160 $number_part = str_replace($prefix, '', $highest_number);
161 $number_part = ltrim($number_part, '0');
162
163 return intval($number_part);
164 }
165
166 /**
167 * Format an invoice number with custom formatting
168 *
169 * @param int $number The number to format
170 * @param string $prefix The prefix to use
171 * @param int $padding The number of digits to pad to
172 * @return string The formatted invoice number
173 */
174 public function formatNumber(int $number, string $prefix = 'INV-', int $padding = 6): string {
175 return $prefix . str_pad($number, $padding, '0', STR_PAD_LEFT);
176 }
177 }