alv_laskenta.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <?php
  2. header('Content-Type: application/json');
  3. header('Access-Control-Allow-Origin: *');
  4. header('Access-Control-Allow-Methods: GET, OPTIONS');
  5. header('Access-Control-Allow-Headers: Content-Type, Authorization');
  6. require_once __DIR__ . '/../config/database.php';
  7. require_once __DIR__ . '/../models/AccountingEntry.php';
  8. // Handle preflight requests
  9. if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
  10. exit(0);
  11. }
  12. try {
  13. $database = new Database();
  14. $conn = $database->getConnection();
  15. if (!$conn) {
  16. throw new Exception('Database connection failed');
  17. }
  18. // Get query parameters
  19. $period = $_GET['period'] ?? 'current';
  20. $month = $_GET['month'] ?? null;
  21. $year = $_GET['year'] ?? null;
  22. // Determine date range based on period
  23. $dateConditions = getDateConditions($period, $month, $year);
  24. // Fetch accounting entries for VAT calculation
  25. $sql = "SELECT
  26. ae.*,
  27. ac.category_name,
  28. ac.category_type,
  29. ac.vat_percentage as category_vat
  30. FROM accounting_entries ae
  31. LEFT JOIN accounting_categories ac ON ae.category = ac.category_code
  32. WHERE ae.entry_date BETWEEN :start_date AND :end_date
  33. ORDER BY ae.entry_date";
  34. $stmt = $conn->prepare($sql);
  35. $stmt->bindParam(':start_date', $dateConditions['start_date']);
  36. $stmt->bindParam(':end_date', $dateConditions['end_date']);
  37. $stmt->execute();
  38. $entries = $stmt->fetchAll(PDO::FETCH_ASSOC);
  39. // Calculate VAT breakdown
  40. $vatBreakdown = calculateVATBreakdown($entries);
  41. // Get previous period data for comparison
  42. $previousDateConditions = getPreviousDateConditions($period, $month, $year);
  43. $previousData = getPreviousPeriodVATData($conn, $previousDateConditions);
  44. // Combine current and previous data
  45. $result = [
  46. 'period' => $period,
  47. 'date_range' => $dateConditions,
  48. 'vat_breakdown' => $vatBreakdown,
  49. 'previous_period' => $previousData,
  50. 'totals' => calculateVATTotals($vatBreakdown)
  51. ];
  52. echo json_encode([
  53. 'success' => true,
  54. 'data' => $result
  55. ]);
  56. } catch (Exception $e) {
  57. http_response_code(500);
  58. echo json_encode([
  59. 'success' => false,
  60. 'message' => $e->getMessage()
  61. ]);
  62. }
  63. function getDateConditions($period, $month, $year) {
  64. $currentYear = $year ?: date('Y');
  65. $currentMonth = $month ? date('m', strtotime($month)) : date('m');
  66. switch ($period) {
  67. case 'month':
  68. return [
  69. 'start_date' => "$currentYear-$currentMonth-01",
  70. 'end_date' => date('Y-m-t', strtotime("$currentYear-$currentMonth-01"))
  71. ];
  72. case 'quarter':
  73. $quarter = ceil($currentMonth / 3);
  74. $startMonth = ($quarter - 1) * 3 + 1;
  75. $endMonth = $quarter * 3;
  76. return [
  77. 'start_date' => "$currentYear-" . str_pad($startMonth, 2, '0', STR_PAD_LEFT) . "-01",
  78. 'end_date' => "$currentYear-" . str_pad($endMonth, 2, '0', STR_PAD_LEFT) . "-" . date('t', strtotime("$currentYear-$endMonth-01"))
  79. ];
  80. case 'year':
  81. return [
  82. 'start_date' => "$currentYear-01-01",
  83. 'end_date' => "$currentYear-12-31"
  84. ];
  85. case 'current':
  86. default:
  87. return [
  88. 'start_date' => date('Y-01-01'),
  89. 'end_date' => date('Y-m-d')
  90. ];
  91. }
  92. }
  93. function getPreviousDateConditions($period, $month, $year) {
  94. $currentYear = $year ?: date('Y');
  95. $currentMonth = $month ? date('m', strtotime($month)) : date('m');
  96. switch ($period) {
  97. case 'month':
  98. $previousDate = date('Y-m', strtotime("$currentYear-$currentMonth-01 -1 month"));
  99. $prevYear = date('Y', strtotime($previousDate));
  100. $prevMonth = date('m', strtotime($previousDate));
  101. return [
  102. 'start_date' => "$prevYear-$prevMonth-01",
  103. 'end_date' => "$prevYear-$prevMonth-" . date('t', strtotime("$prevYear-$prevMonth-01"))
  104. ];
  105. case 'quarter':
  106. $quarter = ceil($currentMonth / 3);
  107. if ($quarter == 1) {
  108. $prevYear = $currentYear - 1;
  109. $prevQuarter = 4;
  110. } else {
  111. $prevYear = $currentYear;
  112. $prevQuarter = $quarter - 1;
  113. }
  114. $startMonth = ($prevQuarter - 1) * 3 + 1;
  115. $endMonth = $prevQuarter * 3;
  116. return [
  117. 'start_date' => "$prevYear-" . str_pad($startMonth, 2, '0', STR_PAD_LEFT) . "-01",
  118. 'end_date' => "$prevYear-" . str_pad($endMonth, 2, '0', STR_PAD_LEFT) . "-" . date('t', strtotime("$prevYear-$endMonth-01"))
  119. ];
  120. case 'year':
  121. return [
  122. 'start_date' => ($currentYear - 1) . "-01-01",
  123. 'end_date' => ($currentYear - 1) . "-12-31"
  124. ];
  125. case 'current':
  126. default:
  127. return [
  128. 'start_date' => (date('Y') - 1) . "-01-01",
  129. 'end_date' => (date('Y') - 1) . "-12-31"
  130. ];
  131. }
  132. }
  133. function calculateVATBreakdown($entries) {
  134. $vatData = [
  135. '0' => [
  136. 'taxable_sales' => 0,
  137. 'taxable_purchases' => 0,
  138. 'payable_vat' => 0,
  139. 'deductible_vat' => 0,
  140. 'net_vat' => 0
  141. ],
  142. '10' => [
  143. 'taxable_sales' => 0,
  144. 'taxable_purchases' => 0,
  145. 'payable_vat' => 0,
  146. 'deductible_vat' => 0,
  147. 'net_vat' => 0
  148. ],
  149. '14' => [
  150. 'taxable_sales' => 0,
  151. 'taxable_purchases' => 0,
  152. 'payable_vat' => 0,
  153. 'deductible_vat' => 0,
  154. 'net_vat' => 0
  155. ],
  156. '24' => [
  157. 'taxable_sales' => 0,
  158. 'taxable_purchases' => 0,
  159. 'payable_vat' => 0,
  160. 'deductible_vat' => 0,
  161. 'net_vat' => 0
  162. ],
  163. '25.5' => [
  164. 'taxable_sales' => 0,
  165. 'taxable_purchases' => 0,
  166. 'payable_vat' => 0,
  167. 'deductible_vat' => 0,
  168. 'net_vat' => 0
  169. ]
  170. ];
  171. foreach ($entries as $entry) {
  172. $vatRate = floatval($entry['vat_percentage']);
  173. $vatKey = normalizeVatRate($vatRate);
  174. if (!isset($vatData[$vatKey])) {
  175. $vatData[$vatKey] = [
  176. 'taxable_sales' => 0,
  177. 'taxable_purchases' => 0,
  178. 'payable_vat' => 0,
  179. 'deductible_vat' => 0,
  180. 'net_vat' => 0
  181. ];
  182. }
  183. $taxFreeAmount = floatval($entry['tax_free_amount']);
  184. $vatAmount = floatval($entry['vat_amount']);
  185. if ($entry['entry_type'] === 'Tulo') {
  186. // Sales - VAT is payable
  187. $vatData[$vatKey]['taxable_sales'] += $taxFreeAmount;
  188. $vatData[$vatKey]['payable_vat'] += $vatAmount;
  189. } else {
  190. // Purchases - VAT is deductible
  191. $vatData[$vatKey]['taxable_purchases'] += $taxFreeAmount;
  192. $vatData[$vatKey]['deductible_vat'] += $vatAmount;
  193. }
  194. }
  195. // Calculate net VAT for each rate
  196. foreach ($vatData as $rate => &$data) {
  197. $data['net_vat'] = $data['payable_vat'] - $data['deductible_vat'];
  198. }
  199. return $vatData;
  200. }
  201. function normalizeVatRate($rate) {
  202. // Normalize VAT rates to standard keys
  203. if ($rate == 0) return '0';
  204. if ($rate == 10) return '10';
  205. if ($rate == 14) return '14';
  206. if ($rate == 24) return '24';
  207. if ($rate == 25.5) return '25.5';
  208. // Handle edge cases
  209. if ($rate > 24 && $rate <= 26) return '25.5';
  210. if ($rate > 14 && $rate <= 15) return '14';
  211. if ($rate > 9 && $rate <= 11) return '10';
  212. return '0'; // Default to 0% if unknown
  213. }
  214. function calculateVATTotals($vatBreakdown) {
  215. $totals = [
  216. 'taxable_sales' => 0,
  217. 'taxable_purchases' => 0,
  218. 'payable_vat' => 0,
  219. 'deductible_vat' => 0,
  220. 'net_vat' => 0
  221. ];
  222. foreach ($vatBreakdown as $data) {
  223. $totals['taxable_sales'] += $data['taxable_sales'];
  224. $totals['taxable_purchases'] += $data['taxable_purchases'];
  225. $totals['payable_vat'] += $data['payable_vat'];
  226. $totals['deductible_vat'] += $data['deductible_vat'];
  227. $totals['net_vat'] += $data['net_vat'];
  228. }
  229. return $totals;
  230. }
  231. function getPreviousPeriodVATData($conn, $dateConditions) {
  232. $sql = "SELECT
  233. ae.*,
  234. ac.category_name,
  235. ac.category_type,
  236. ac.vat_percentage as category_vat
  237. FROM accounting_entries ae
  238. LEFT JOIN accounting_categories ac ON ae.category = ac.category_code
  239. WHERE ae.entry_date BETWEEN :start_date AND :end_date
  240. ORDER BY ae.entry_date";
  241. $stmt = $conn->prepare($sql);
  242. $stmt->bindParam(':start_date', $dateConditions['start_date']);
  243. $stmt->bindParam(':end_date', $dateConditions['end_date']);
  244. $stmt->execute();
  245. $entries = $stmt->fetchAll(PDO::FETCH_ASSOC);
  246. return calculateVATBreakdown($entries);
  247. }
  248. ?>