Invoice.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. class Invoice {
  3. private $conn;
  4. private $table_name = "invoices";
  5. public $id;
  6. public $client_id;
  7. public $invoice_number;
  8. public $issue_date;
  9. public $due_date;
  10. public $status;
  11. public $subtotal;
  12. public $tax_amount;
  13. public $total_amount;
  14. public $notes;
  15. public $created_at;
  16. public $updated_at;
  17. public function __construct($db) {
  18. $this->conn = $db;
  19. }
  20. public function create() {
  21. $query = "INSERT INTO " . $this->table_name . " SET client_id=:client_id, invoice_number=:invoice_number, issue_date=:issue_date, due_date=:due_date, status=:status, subtotal=:subtotal, tax_amount=:tax_amount, total_amount=:total_amount, notes=:notes, created_at=:created_at, updated_at=:updated_at";
  22. $stmt = $this->conn->prepare($query);
  23. $this->client_id = htmlspecialchars(strip_tags($this->client_id));
  24. $this->invoice_number = htmlspecialchars(strip_tags($this->invoice_number));
  25. $this->issue_date = htmlspecialchars(strip_tags($this->issue_date));
  26. $this->due_date = htmlspecialchars(strip_tags($this->due_date));
  27. $this->status = htmlspecialchars(strip_tags($this->status));
  28. $this->subtotal = htmlspecialchars(strip_tags($this->subtotal));
  29. $this->tax_amount = htmlspecialchars(strip_tags($this->tax_amount));
  30. $this->total_amount = htmlspecialchars(strip_tags($this->total_amount));
  31. $this->notes = htmlspecialchars(strip_tags($this->notes));
  32. $this->created_at = date('Y-m-d H:i:s');
  33. $this->updated_at = date('Y-m-d H:i:s');
  34. $stmt->bindParam(":client_id", $this->client_id);
  35. $stmt->bindParam(":invoice_number", $this->invoice_number);
  36. $stmt->bindParam(":issue_date", $this->issue_date);
  37. $stmt->bindParam(":due_date", $this->due_date);
  38. $stmt->bindParam(":status", $this->status);
  39. $stmt->bindParam(":subtotal", $this->subtotal);
  40. $stmt->bindParam(":tax_amount", $this->tax_amount);
  41. $stmt->bindParam(":total_amount", $this->total_amount);
  42. $stmt->bindParam(":notes", $this->notes);
  43. $stmt->bindParam(":created_at", $this->created_at);
  44. $stmt->bindParam(":updated_at", $this->updated_at);
  45. if($stmt->execute()) {
  46. return true;
  47. }
  48. return false;
  49. }
  50. public function read() {
  51. $query = "SELECT i.*, c.first_name, c.last_name, c.company_name FROM " . $this->table_name . " i LEFT JOIN clients c ON i.client_id = c.id ORDER BY i.issue_date DESC, i.created_at DESC";
  52. $stmt = $this->conn->prepare($query);
  53. $stmt->execute();
  54. return $stmt;
  55. }
  56. public function readOne() {
  57. $query = "SELECT i.*, c.first_name, c.last_name, c.company_name FROM " . $this->table_name . " i LEFT JOIN clients c ON i.client_id = c.id WHERE i.id = ? LIMIT 0,1";
  58. $stmt = $this->conn->prepare($query);
  59. $stmt->bindParam(1, $this->id);
  60. $stmt->execute();
  61. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  62. $this->client_id = $row['client_id'];
  63. $this->invoice_number = $row['invoice_number'];
  64. $this->issue_date = $row['issue_date'];
  65. $this->due_date = $row['due_date'];
  66. $this->status = $row['status'];
  67. $this->subtotal = $row['subtotal'];
  68. $this->tax_amount = $row['tax_amount'];
  69. $this->total_amount = $row['total_amount'];
  70. $this->notes = $row['notes'];
  71. $this->created_at = $row['created_at'];
  72. $this->updated_at = $row['updated_at'];
  73. }
  74. public function update() {
  75. $query = "UPDATE " . $this->table_name . " SET client_id=:client_id, invoice_number=:invoice_number, issue_date=:issue_date, due_date=:due_date, status=:status, subtotal=:subtotal, tax_amount=:tax_amount, total_amount=:total_amount, notes=:notes, updated_at=:updated_at WHERE id=:id";
  76. $stmt = $this->conn->prepare($query);
  77. $this->client_id = htmlspecialchars(strip_tags($this->client_id));
  78. $this->invoice_number = htmlspecialchars(strip_tags($this->invoice_number));
  79. $this->issue_date = htmlspecialchars(strip_tags($this->issue_date));
  80. $this->due_date = htmlspecialchars(strip_tags($this->due_date));
  81. $this->status = htmlspecialchars(strip_tags($this->status));
  82. $this->subtotal = htmlspecialchars(strip_tags($this->subtotal));
  83. $this->tax_amount = htmlspecialchars(strip_tags($this->tax_amount));
  84. $this->total_amount = htmlspecialchars(strip_tags($this->total_amount));
  85. $this->notes = htmlspecialchars(strip_tags($this->notes));
  86. $this->updated_at = date('Y-m-d H:i:s');
  87. $stmt->bindParam(":client_id", $this->client_id);
  88. $stmt->bindParam(":invoice_number", $this->invoice_number);
  89. $stmt->bindParam(":issue_date", $this->issue_date);
  90. $stmt->bindParam(":due_date", $this->due_date);
  91. $stmt->bindParam(":status", $this->status);
  92. $stmt->bindParam(":subtotal", $this->subtotal);
  93. $stmt->bindParam(":tax_amount", $this->tax_amount);
  94. $stmt->bindParam(":total_amount", $this->total_amount);
  95. $stmt->bindParam(":notes", $this->notes);
  96. $stmt->bindParam(":updated_at", $this->updated_at);
  97. $stmt->bindParam(":id", $this->id);
  98. if($stmt->execute()) {
  99. return true;
  100. }
  101. return false;
  102. }
  103. public function delete() {
  104. $query = "DELETE FROM " . $this->table_name . " WHERE id = ?";
  105. $stmt = $this->conn->prepare($query);
  106. $stmt->bindParam(1, $this->id);
  107. if($stmt->execute()) {
  108. return true;
  109. }
  110. return false;
  111. }
  112. public function search($search_term) {
  113. $query = "SELECT i.*, c.first_name, c.last_name, c.company_name FROM " . $this->table_name . " i LEFT JOIN clients c ON i.client_id = c.id WHERE
  114. i.invoice_number LIKE ? OR
  115. c.first_name LIKE ? OR
  116. c.last_name LIKE ? OR
  117. c.company_name LIKE ?
  118. i.notes LIKE ?
  119. ORDER BY i.issue_date DESC, i.created_at DESC";
  120. $stmt = $this->conn->prepare($query);
  121. $search_term = "%{$search_term}%";
  122. $stmt->bindParam(1, $search_term);
  123. $stmt->bindParam(2, $search_term);
  124. $stmt->bindParam(3, $search_term);
  125. $stmt->bindParam(4, $search_term);
  126. $stmt->bindParam(5, $search_term);
  127. $stmt->execute();
  128. return $stmt;
  129. }
  130. public function getInvoiceItems($invoice_id) {
  131. $query = "SELECT ii.*, i.name as item_name FROM invoice_items ii LEFT JOIN items i ON ii.item_id = i.id WHERE ii.invoice_id = ? ORDER BY ii.id";
  132. $stmt = $this->conn->prepare($query);
  133. $stmt->bindParam(1, $invoice_id);
  134. $stmt->execute();
  135. return $stmt;
  136. }
  137. public function getPayments($invoice_id) {
  138. $query = "SELECT * FROM payments WHERE invoice_id = ? ORDER BY payment_date DESC";
  139. $stmt = $this->conn->prepare($query);
  140. $stmt->bindParam(1, $invoice_id);
  141. $stmt->execute();
  142. return $stmt;
  143. }
  144. public function getDisplayName() {
  145. return $this->invoice_number . ' - ' . $this->getClientName();
  146. }
  147. public function getClientName() {
  148. $query = "SELECT CONCAT(first_name, ' ', last_name) as client_name FROM clients WHERE id = ?";
  149. $stmt = $this->conn->prepare($query);
  150. $stmt->bindParam(1, $this->client_id);
  151. $stmt->execute();
  152. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  153. return $row['client_name'];
  154. }
  155. public function getStatusBadge() {
  156. $badges = [
  157. 'draft' => '<span style="background-color: #6c757d; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px;">Draft</span>',
  158. 'sent' => '<span style="background-color: #17a2b8; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px;">Sent</span>',
  159. 'paid' => '<span style="background-color: #28a745; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px;">Paid</span>',
  160. 'overdue' => '<span style="background-color: #dc3545; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px;">Overdue</span>',
  161. 'cancelled' => '<span style="background-color: #6c757d; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px;">Cancelled</span>'
  162. ];
  163. return $badges[$this->status] ?? $this->status;
  164. }
  165. public function calculateTotalFromItems($items) {
  166. $total = 0;
  167. foreach ($items as $item) {
  168. $total += $item['line_total'];
  169. }
  170. return $total;
  171. }
  172. }
  173. ?>