defaultGroup(); \S::set_session( 'finance-group', $group_id ); } return $group_id; } public static function mainView() { if ( !self::requireAuth() ) return false; $repo = self::repo(); $importRepo = self::importRepo(); $importRepo -> ensureTables(); if ( \S::get( 'tag-clear' ) ) unset( $_SESSION['finance-tag-id'] ); if ( \S::get( 'client_clear' ) ) unset( $_SESSION['finance_client_id'] ); if ( \S::get( 'dates' ) ) \S::set_session( 'finance-dates', \S::get( 'dates' ) ); if ( \S::get( 'tag-id' ) ) \S::set_session( 'finance-tag-id', \S::get( 'tag-id' ) ); if ( \S::get( 'client_id' ) ) \S::set_session( 'finance_client_id', \S::get( 'client_id' ) ); $group_id = self::resolveGroup( $repo ); $tag_id = \S::get_session( 'finance-tag-id' ); $client_id = \S::get_session( 'finance_client_id' ); list( $date_from, $date_to ) = self::resolveDates(); if ( $group_id == 3 ) { $date_from = '2000-01-01'; $date_to = '3000-01-01'; } return \Tpl::view( 'finances/main-view', [ 'categories' => $repo -> categories( $date_from, $date_to, $tag_id, null, $group_id, $client_id ), 'date_from' => $date_from, 'date_to' => $date_to, 'clients' => $repo -> clientsWithRevenue( $date_from, $date_to, $group_id ), 'client_id' => $client_id, 'groups' => $repo -> groupsList(), 'group_id' => $group_id, 'operations_list' => $repo -> operationsList( $date_from, $date_to, $group_id, $client_id ), 'wallet_summary' => $repo -> walletSummary( $group_id ), 'wallet_summary_this_month' => $repo -> walletSummaryThisMonth( $group_id ), 'wallet_income_this_month' => $repo -> walletIncomeThisMonth( $group_id ), 'wallet_expenses_this_month' => $repo -> walletExpensesThisMonth( $group_id ), 'fakturownia_pending_clients' => self::preparePendingRows( $importRepo -> pendingClientMappings() ), 'fakturownia_pending_items' => self::preparePendingRows( $importRepo -> pendingItemMappings() ), 'fakturownia_crm_clients' => $repo -> clientsList(), 'fakturownia_categories' => self::prepareCategoryOptions( $repo -> categoriesFlatList() ), 'fakturownia_last_summary' => self::lastImportSummary( $importRepo ) ] ); } private static function preparePendingRows( $rows ) { $output = []; if ( !is_array( $rows ) ) return $output; foreach ( $rows as $row ) { $payload = []; if ( isset( $row['payload_json'] ) && $row['payload_json'] ) { $decoded = json_decode( $row['payload_json'], true ); if ( is_array( $decoded ) ) $payload = $decoded; } $output[] = [ 'external_key' => (string)$row['external_key'], 'external_name' => (string)$row['external_name'], 'hits' => (int)$row['hits'], 'last_seen_at' => (string)$row['last_seen_at'], 'payload' => $payload ]; } return $output; } private static function lastImportSummary( $importRepo ) { $raw = $importRepo -> getState( 'last_import_summary' ); if ( !$raw ) return null; $decoded = json_decode( $raw, true ); return is_array( $decoded ) ? $decoded : null; } private static function prepareCategoryOptions( $categories ) { $options = []; if ( !is_array( $categories ) || empty( $categories ) ) return $options; $byId = []; foreach ( $categories as $category ) { $id = isset( $category['id'] ) ? (int)$category['id'] : 0; if ( $id <= 0 ) continue; $byId[ $id ] = $category; } foreach ( $categories as $category ) { $id = isset( $category['id'] ) ? (int)$category['id'] : 0; if ( $id <= 0 ) continue; $label = self::buildCategoryPathLabel( $id, $byId ); $options[] = [ 'id' => $id, 'name' => $label, 'group_id' => isset( $category['group_id'] ) ? (int)$category['group_id'] : 0 ]; } usort( $options, function( $left, $right ) { return strcmp( $left['name'], $right['name'] ); } ); return $options; } private static function buildCategoryPathLabel( $categoryId, $byId ) { $parts = []; $guard = 0; $currentId = (int)$categoryId; while ( $currentId > 0 && isset( $byId[ $currentId ] ) ) { $category = $byId[ $currentId ]; $name = trim( (string)( $category['name'] ?? '' ) ); if ( $name !== '' ) array_unshift( $parts, $name ); $parentId = isset( $category['parent_id'] ) ? (int)$category['parent_id'] : 0; if ( $parentId <= 0 || $parentId === $currentId ) break; $currentId = $parentId; $guard++; if ( $guard > 20 ) break; } if ( empty( $parts ) ) return 'Kategoria #' . (int)$categoryId; return implode( ' > ', $parts ); } public static function operationEdit() { if ( !self::requireAuth() ) return false; $repo = self::repo(); return \Tpl::view( 'finances/operation-edit', [ 'operation' => $repo -> operationDetails( \S::get( 'operation-id' ) ), 'category_id' => \S::get( 'category-id' ), 'tags' => $repo -> tagsList( \S::get_session( 'finance-group' ) ), 'tags_json' => $repo -> tagsJson( \S::get_session( 'finance-group' ) ), 'operation_date' => \S::get_session( 'operation-date' ), 'clients' => $repo -> clientsList() ] ); } public static function operationSave() { if ( !self::requireAuth() ) return false; $repo = self::repo(); $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania operacji wystąpił błąd. Proszę spróbować ponownie.' ]; $values = \S::json_to_array( \S::get( 'values' ) ); \S::set_session( 'operation-date', $values['date'] ); $client_id = isset( $values['client_id'] ) ? (int)$values['client_id'] : null; if ( $id = $repo -> saveOperation( $values['id'], $values['category_id'], $values['date'], $values['amount'], $values['description'], $values['tags'], \S::get_session( 'finance-group' ), $client_id ) ) $response = [ 'status' => 'ok', 'msg' => 'Operacja została zapisana.', 'id' => $id ]; echo json_encode( $response ); exit; } public static function operationDelete() { if ( !self::requireAuth() ) return false; $repo = self::repo(); if ( $repo -> deleteOperation( \S::get( 'operation-id' ) ) ) { \S::alert( 'Wybrana operacja została usunięta.' ); header( 'Location: /finances/operations_list/category-id=' . \S::get( 'category-id' ) ); exit; } } public static function categoryEdit() { if ( !self::requireAuth() ) return false; $repo = self::repo(); return \Tpl::view( 'finances/category-edit', [ 'category' => $repo -> categoryDetails( \S::get( 'id' ) ), 'group_id' => \S::get_session( 'finance-group' ) ] ); } public static function categorySave() { if ( !self::requireAuth() ) return false; $repo = self::repo(); $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania kategorii wystąpił błąd. Proszę spróbować ponownie.' ]; $values = \S::json_to_array( \S::get( 'values' ) ); if ( $id = $repo -> saveCategory( $values['id'], $values['name'], $values['parent_id'], $values['group_id'] ) ) $response = [ 'status' => 'ok', 'msg' => 'Kategoria została zapisana.', 'id' => $id ]; echo json_encode( $response ); exit; } public static function categoryDelete() { if ( !self::requireAuth() ) return false; $repo = self::repo(); if ( $repo -> deleteCategory( \S::get( 'category_id' ) ) ) { \S::alert( 'Wybrana kategoria została usunięta.' ); header( 'Location: /finances/main_view/' ); exit; } } public static function operationsList() { if ( !self::requireAuth() ) return false; $repo = self::repo(); $dates = \S::get( 'dates' ); if ( $dates ) \S::set_session( 'finance-dates', $dates ); $dates = \S::get_session( 'finance-dates' ); $dates = explode( ' - ', $dates ); $date_from = $dates[0] ? $dates[0] : date( 'Y-m-01' ); $date_to = $dates[1] ? $dates[1] : date( 'Y-m-t' ); $category = $repo -> categoryDetails( \S::get( 'category-id' ) ); if ( $category['group_id'] == 3 ) { $date_from = '2000-01-01'; $date_to = '3000-01-01'; } return \Tpl::view( 'finances/operations-list', [ 'category' => $category, 'operations' => $repo -> operations( \S::get( 'category-id' ), $date_from, $date_to, \S::get_session( 'finance-tag-id' ) ), 'date_from' => $date_from, 'date_to' => $date_to ] ); } public static function fakturowniaClientMappingSave() { if ( !self::requireAuth() ) return false; if ( !\S::csrf_verify() ) { \S::alert( 'Nieprawidlowy token bezpieczenstwa. Odswiez strone i sproboj ponownie.' ); header( 'Location: /finances/main_view/' ); exit; } $externalKey = trim( (string)\S::get( 'external_key' ) ); $externalName = trim( (string)\S::get( 'external_name' ) ); $crmClientId = (int)\S::get( 'crm_client_id' ); $repo = self::repo(); if ( $externalKey === '' || $externalName === '' || $crmClientId <= 0 || !$repo -> clientExists( $crmClientId ) ) { \S::alert( 'Nie udalo sie zapisac mapowania klienta. Uzupelnij wszystkie pola.' ); header( 'Location: /finances/main_view/' ); exit; } $importRepo = self::importRepo(); $importRepo -> ensureTables(); $importRepo -> saveClientMapping( $externalKey, $externalName, $crmClientId ); \S::alert( 'Mapowanie klienta zostalo zapisane.' ); header( 'Location: /finances/main_view/' ); exit; } public static function fakturowniaItemMappingSave() { if ( !self::requireAuth() ) return false; if ( !\S::csrf_verify() ) { \S::alert( 'Nieprawidlowy token bezpieczenstwa. Odswiez strone i sproboj ponownie.' ); header( 'Location: /finances/main_view/' ); exit; } $externalKey = trim( (string)\S::get( 'external_key' ) ); $externalName = trim( (string)\S::get( 'external_name' ) ); $financeCategoryId = (int)\S::get( 'finance_category_id' ); $repo = self::repo(); if ( $externalKey === '' || $externalName === '' || $financeCategoryId <= 0 || !$repo -> categoryExists( $financeCategoryId ) ) { \S::alert( 'Nie udalo sie zapisac mapowania pozycji. Uzupelnij wszystkie pola.' ); header( 'Location: /finances/main_view/' ); exit; } $importRepo = self::importRepo(); $importRepo -> ensureTables(); $importRepo -> saveItemMapping( $externalKey, $externalName, $financeCategoryId ); \S::alert( 'Mapowanie pozycji zostalo zapisane.' ); header( 'Location: /finances/main_view/' ); exit; } }