418 lines
12 KiB
PHP
418 lines
12 KiB
PHP
<?php
|
|
namespace Controllers;
|
|
|
|
class FinancesController
|
|
{
|
|
private static function repo()
|
|
{
|
|
return new \Domain\Finances\FinanceRepository();
|
|
}
|
|
|
|
private static function importRepo()
|
|
{
|
|
return new \Domain\Finances\FakturowniaImportRepository();
|
|
}
|
|
|
|
private static function requireAuth()
|
|
{
|
|
global $user;
|
|
|
|
if ( !$user )
|
|
{
|
|
\controls\Users::login_form();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static function resolveDates()
|
|
{
|
|
$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' );
|
|
|
|
return [ $date_from, $date_to ];
|
|
}
|
|
|
|
private static function resolveGroup( $repo )
|
|
{
|
|
if ( \S::get( 'group-id' ) )
|
|
\S::set_session( 'finance-group', \S::get( 'group-id' ) );
|
|
|
|
$group_id = \S::get_session( 'finance-group' );
|
|
|
|
if ( !$group_id )
|
|
{
|
|
$group_id = $repo -> 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;
|
|
}
|
|
}
|