feat: Refactor CRM and Finances modules

- Updated client-edit template to change 'Firma' to 'Nazwa' and added 'Nazwa firmy' input field.
- Modified main-view template to reflect the new naming conventions for clients.
- Enhanced finances main-view to display a list of clients with revenue details.
- Added client selection dropdown in operation-edit template.
- Improved work-time template by adding keyboard shortcut for task confirmation.
- Introduced CrmController for handling client-related actions.
- Created FinancesController to manage finance operations and categories.
- Implemented ClientRepository for client data management.
- Developed FinanceRepository for finance operations and data handling.
This commit is contained in:
2026-02-14 21:30:02 +01:00
parent c9795ca866
commit f3be8e1025
16 changed files with 939 additions and 626 deletions

View File

@@ -7,7 +7,8 @@
"Bash(if [ -f logs.txt ])", "Bash(if [ -f logs.txt ])",
"Bash(then rm logs.txt)", "Bash(then rm logs.txt)",
"Bash(else echo \"Plik logs.txt nie istnieje\")", "Bash(else echo \"Plik logs.txt nie istnieje\")",
"Bash(fi)" "Bash(fi)",
"Bash(grep:*)"
] ]
} }
} }

15
api.php
View File

@@ -112,11 +112,24 @@ if ( \S::get( 'action' ) == 'add_finance_operation' )
exit; exit;
} }
$recipient_name = \S::get( 'recipient_name' );
if ( $recipient_name ) {
$recipient_name = strip_tags( $recipient_name );
$recipient_name = preg_replace( '/\s+/u', ' ', $recipient_name );
$recipient_name = trim( $recipient_name );
}
$client_id = null;
if ( $recipient_name ) {
$client_id = $mdb -> get( 'crm_client', 'id', [ 'firm_name' => $recipient_name ] );
}
$data = [ $data = [
'date' => \S::get( 'operation_date' ), 'date' => \S::get( 'operation_date' ),
'amount' => str_replace( ',', '.', \S::get( 'net_value' ) ), 'amount' => str_replace( ',', '.', \S::get( 'net_value' ) ),
'description' => \S::get( 'product_name' ), 'description' => \S::get( 'product_name' ) . ( $recipient_name ? ' - ' . $recipient_name : '' ),
'category_id' => \S::get( 'category_id' ), 'category_id' => \S::get( 'category_id' ),
'client_id' => $client_id,
]; ];
if ( $mdb -> insert( 'finance_operations', $data ) ) { if ( $mdb -> insert( 'finance_operations', $data ) ) {

View File

@@ -0,0 +1,70 @@
<?php
namespace Controllers;
class CrmController
{
public static $source = [ 0 => 'ceidg', 1 => 'kontakt własny', 2 => 'BNI' ];
public static $status = [ 0 => 'kontakt pozyskany', 1 => 'oferta wysłana', 2 => 'follow up', 3 => 'klient niezainteresowany' ];
public static function mainView()
{
global $user;
if ( !$user or !\controls\Users::permissions( $user['id'], 'wiki' ) )
return false;
return \Tpl::view( 'crm/main-view' );
}
public static function clientEdit()
{
global $user;
if ( !$user or !\controls\Users::permissions( $user['id'], 'wiki' ) )
return false;
$repository = new \Domain\Crm\ClientRepository();
return \Tpl::view( 'crm/client-edit', [
'client' => $repository -> getById( (int)\S::get( 'id' ) )
] );
}
public static function clientSave()
{
global $user;
if ( !$user or !\controls\Users::permissions( $user['id'], 'wiki' ) )
return false;
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania klienta wystąpił błąd. Proszę spróbować ponownie.' ];
$values = \S::json_to_array( \S::get( 'values' ) );
$repository = new \Domain\Crm\ClientRepository();
if ( $id = $repository -> save(
(int)$values['id'], $values['firm'], $values['firm_name'], $values['emails'], $values['phones'], $values['notes']
) )
$response = [ 'status' => 'ok', 'msg' => 'Projekt został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function clientDelete()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
$repository = new \Domain\Crm\ClientRepository();
if ( $repository -> delete( (int)\S::get( 'client_id' ) ) )
{
\S::alert( 'Klient został usunięty' );
header( 'Location: /crm/main_view/' );
exit;
}
}
}

View File

@@ -0,0 +1,233 @@
<?php
namespace Controllers;
class FinancesController
{
private static function repo()
{
return new \Domain\Finances\FinanceRepository();
}
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();
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 )
] );
}
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
] );
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Domain\Crm;
class ClientRepository
{
private $mdb;
public function __construct( $mdb = null )
{
if ( $mdb )
$this -> mdb = $mdb;
else
{
global $mdb;
$this -> mdb = $mdb;
}
}
public function all()
{
return $this -> mdb -> select( 'crm_client', '*', [ 'ORDER' => [ 'firm' => 'ASC' ] ] );
}
public function getById( int $client_id )
{
return \R::load( 'crm_client', $client_id );
}
public function getName( int $client_id )
{
return $this -> mdb -> get( 'crm_client', 'firm', [ 'id' => $client_id ] );
}
public function save( int $client_id, string $firm, string $firm_name, string $emails, string $phones, string $notes )
{
$client = \R::load( 'crm_client', $client_id );
if ( !$client )
{
$client = \R::xdispense( 'crm_client' );
$client -> date_add = date( 'Y-m-d H:i:s' );
}
$client -> firm = $firm;
$client -> firm_name = $firm_name;
$client -> emails = $emails;
$client -> phones = $phones;
$client -> notes = $notes;
$client -> date_update = date( 'Y-m-d H:i:s' );
return \R::store( $client );
}
public function delete( int $client_id )
{
return $this -> mdb -> delete( 'crm_client', [ 'id' => $client_id ] );
}
public function settings()
{
$settings = [];
$results = $this -> mdb -> select( 'settings', '*' );
foreach ( $results as $result )
{
$settings[ $result['name'] ] = $result['value'];
}
return $settings;
}
}

View File

@@ -0,0 +1,420 @@
<?php
namespace Domain\Finances;
class FinanceRepository
{
private $mdb;
public function __construct( $mdb = null )
{
if ( $mdb )
$this -> mdb = $mdb;
else
{
global $mdb;
$this -> mdb = $mdb;
}
}
public function firstOperationDate()
{
return $this -> mdb -> get( 'finance_operations', 'date', [ 'ORDER' => [ 'date' => 'ASC' ] ] );
}
public function getOperationTags( int $operation_id )
{
$return = '';
$tags_id = $this -> mdb -> select( 'finance_operation_tags', 'tag_id', [ 'operation_id' => $operation_id ] );
foreach ( $tags_id as $tag_id )
{
if ( $return )
$return .= ', ';
$return .= $this -> mdb -> get( 'finance_tags', 'tag', [ 'id' => $tag_id ] );
}
return $return;
}
public function clientName( $client_id )
{
return $this -> mdb -> get( 'crm_client', 'firm', [ 'id' => $client_id ] );
}
public function clientsListByDates( $date_from, $date_to )
{
return $this -> mdb -> query(
'SELECT cc.id, cc.firm FROM crm_client AS cc '
. 'INNER JOIN finance_operations AS fo ON fo.client_id = cc.id '
. 'WHERE date >= :date_from AND date <= :date_to '
. 'GROUP BY cc.id ORDER BY firm ASC',
[ ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll( \PDO::FETCH_ASSOC );
}
public function clientsList()
{
return $this -> mdb -> select( 'crm_client', [ 'id', 'firm' ], [ 'ORDER' => [ 'firm' => 'ASC' ] ] );
}
public function clientsWithRevenue( $date_from, $date_to, $group_id )
{
return $this -> mdb -> query(
'SELECT cc.id, cc.firm, '
. 'SUM( CASE WHEN fo.amount > 0 THEN fo.amount ELSE 0 END ) AS income, '
. 'SUM( CASE WHEN fo.amount < 0 THEN fo.amount ELSE 0 END ) AS costs, '
. 'SUM( fo.amount ) AS total, '
. 'COUNT( fo.id ) AS operations_count '
. 'FROM crm_client AS cc '
. 'INNER JOIN finance_operations AS fo ON fo.client_id = cc.id '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'WHERE fo.date >= :date_from AND fo.date <= :date_to AND fc.group_id = :group_id '
. 'GROUP BY cc.id '
. 'ORDER BY total DESC',
[ ':date_from' => $date_from, ':date_to' => $date_to, ':group_id' => (int)$group_id ]
) -> fetchAll( \PDO::FETCH_ASSOC );
}
public function deleteCategory( $category_id )
{
return $this -> mdb -> delete( 'finance_categories', [ 'id' => (int)$category_id ] );
}
public function defaultGroup()
{
return $this -> mdb -> get( 'finance_group', 'id', [ 'default_group' => 1 ] );
}
public function groupsList()
{
return $this -> mdb -> select( 'finance_group', '*', [ 'ORDER' => [ 'name' => 'ASC' ] ] );
}
public function deleteOperation( $operation_id )
{
return $this -> mdb -> delete( 'finance_operations', [ 'id' => $operation_id ] );
}
public function tagsJson( $group_id )
{
return $this -> mdb -> select( 'finance_tags', 'tag', [ 'group_id' => $group_id, 'ORDER' => [ 'tag' => 'ASC' ] ] );
}
public function tagsList( $group_id )
{
$tags = [];
$results = $this -> mdb -> select( 'finance_tags', '*', [ 'group_id' => $group_id ] );
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
{
$tag = $row;
$tag['count'] = $this -> mdb -> count( 'finance_operation_tags', [ 'tag_id' => $row['id'] ] );
$tags[] = $tag;
}
if ( count( $tags ) )
array_multisort( array_column( $tags, 'count' ), SORT_DESC, $tags );
return $tags;
}
public function operationsList( $date_from, $date_to, $group_id, $client_id = null )
{
$sql = 'SELECT fo.*, fc.name '
. 'FROM finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'WHERE date >= :date_from AND date <= :date_to AND group_id = :group_id ';
$params = [ ':date_from' => $date_from, ':date_to' => $date_to, ':group_id' => (int)$group_id ];
if ( $client_id )
{
$sql .= 'AND fo.client_id = :client_id ';
$params[':client_id'] = (int)$client_id;
}
$sql .= 'ORDER BY fo.date DESC, fo.id DESC';
return $this -> mdb -> query( $sql, $params ) -> fetchAll( \PDO::FETCH_ASSOC );
}
public function operationDetails( $operation_id )
{
$operation = $this -> mdb -> get( 'finance_operations', '*', [ 'id' => $operation_id ] );
$operation['tags'] = $this -> mdb -> query(
'SELECT tag, tag_id FROM finance_operation_tags AS fot '
. 'INNER JOIN finance_tags AS ft ON fot.tag_id = ft.id '
. 'WHERE operation_id = ' . (int)$operation_id
) -> fetchAll( \PDO::FETCH_ASSOC );
return $operation;
}
public function saveOperation( $operation_id, $category_id, $date, $amount, $description, $tags, $group_id, $client_id = null )
{
$data = [
'date' => $date ? $date : date( 'Y-m-d' ),
'category_id' => $category_id,
'amount' => $amount,
'description' => $description,
'client_id' => $client_id ? (int)$client_id : null
];
if ( !$operation_id )
{
$this -> mdb -> insert( 'finance_operations', $data );
$id = $this -> mdb -> id();
}
else
{
$this -> mdb -> update( 'finance_operations', $data, [ 'id' => $operation_id ] );
$this -> mdb -> delete( 'finance_operation_tags', [ 'operation_id' => $operation_id ] );
$id = $operation_id;
}
$this -> syncOperationTags( $id, $tags, $group_id );
return $id;
}
private function syncOperationTags( $operation_id, $tags_string, $group_id )
{
$tags = explode( ',', $tags_string );
if ( !is_array( $tags ) )
return;
foreach ( $tags as $tag )
{
$tag = trim( $tag );
if ( !$tag )
continue;
$tag_id = $this -> mdb -> get( 'finance_tags', 'id', [ 'AND' => [ 'group_id' => $group_id, 'tag' => $tag ] ] );
if ( !$tag_id )
{
$this -> mdb -> insert( 'finance_tags', [ 'tag' => $tag, 'group_id' => $group_id ] );
$tag_id = $this -> mdb -> id();
}
$this -> mdb -> insert( 'finance_operation_tags', [ 'operation_id' => $operation_id, 'tag_id' => $tag_id ] );
}
}
public function categoryDetails( $category_id )
{
return $this -> mdb -> get( 'finance_categories', '*', [ 'id' => $category_id ] );
}
public function saveCategory( $category_id, $name, $parent_id, $group_id )
{
if ( !$category_id )
{
$this -> mdb -> insert( 'finance_categories', [
'name' => $name,
'parent_id' => $parent_id ? $parent_id : null,
'group_id' => $group_id
] );
return $this -> mdb -> id();
}
else
{
$this -> mdb -> update( 'finance_categories', [
'name' => $name,
'group_id' => $group_id
], [ 'id' => $category_id ] );
return $category_id;
}
}
public function walletSummary( $group_id )
{
$results = $this -> mdb -> query(
'SELECT SUM(amount) AS val FROM finance_operations '
. 'WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = :group_id )',
[ ':group_id' => (int)$group_id ]
) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['val'];
}
public function walletSummaryThisMonth( $group_id )
{
$date_from = date( 'Y-m-01' );
$date_to = date( 'Y-m-t' );
$results = $this -> mdb -> query(
'SELECT SUM(amount) AS val FROM finance_operations '
. 'WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = :group_id ) '
. 'AND date >= :date_from AND date <= :date_to',
[ ':group_id' => (int)$group_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['val'];
}
public function walletIncomeThisMonth( $group_id )
{
$date_from = date( 'Y-m-01' );
$date_to = date( 'Y-m-t' );
$results = $this -> mdb -> query(
'SELECT SUM(amount) AS val FROM finance_operations '
. 'WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = :group_id ) '
. 'AND date >= :date_from AND date <= :date_to AND amount > 0',
[ ':group_id' => (int)$group_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['val'];
}
public function walletExpensesThisMonth( $group_id )
{
$date_from = date( 'Y-m-01' );
$date_to = date( 'Y-m-t' );
$results = $this -> mdb -> query(
'SELECT SUM(amount) AS val FROM finance_operations '
. 'WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = :group_id ) '
. 'AND date >= :date_from AND date <= :date_to AND amount < 0',
[ ':group_id' => (int)$group_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['val'];
}
public function operations( $category_id, $date_from, $date_to, $tag_id = null )
{
$operations = [];
if ( $tag_id )
$results = $this -> mdb -> query(
'SELECT fo.* FROM finance_operations AS fo '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'WHERE category_id = :category_id AND date >= :date_from AND date <= :date_to AND tag_id = :tag_id '
. 'ORDER BY date DESC, id DESC',
[ ':category_id' => (int)$category_id, ':date_from' => $date_from, ':date_to' => $date_to, ':tag_id' => (int)$tag_id ]
) -> fetchAll( \PDO::FETCH_ASSOC );
else
$results = $this -> mdb -> query(
'SELECT fo.* FROM finance_operations AS fo '
. 'WHERE category_id = :category_id AND date >= :date_from AND date <= :date_to '
. 'ORDER BY date DESC, fo.id DESC',
[ ':category_id' => (int)$category_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll( \PDO::FETCH_ASSOC );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$row['tags'] = $this -> mdb -> query(
'SELECT tag FROM finance_operation_tags AS fot '
. 'INNER JOIN finance_tags AS ft ON fot.tag_id = ft.id '
. 'WHERE operation_id = ' . (int)$row['id']
) -> fetchAll( \PDO::FETCH_ASSOC );
$operations[] = $row;
}
return $operations;
}
public function categories( $date_from, $date_to, $tag_id = '', $parent_id = null, $group_id, $client_id = null )
{
$categories = [];
$results = $this -> mdb -> select( 'finance_categories', [ 'id', 'name' ], [
'AND' => [ 'group_id' => $group_id, 'parent_id' => $parent_id ],
'ORDER' => [ 'name' => 'ASC' ]
] );
if ( !is_array( $results ) or empty( $results ) )
return $categories;
foreach ( $results as $row )
{
if ( $tag_id )
{
$row['costs'] = (double)$this -> categorySumByTag( $row['id'], $tag_id, $group_id, $date_from, $date_to, '< 0' );
$row['costs_count'] = (int)$this -> categoryCountByTag( $row['id'], $tag_id, $group_id, $date_from, $date_to, '< 0' );
$row['income'] = (double)$this -> categorySumByTag( $row['id'], $tag_id, $group_id, $date_from, $date_to, '> 0' );
$row['income_count'] = (int)$this -> categoryCountByTag( $row['id'], $tag_id, $group_id, $date_from, $date_to, '> 0' );
}
elseif ( $client_id )
{
$row['costs'] = (double)$this -> categorySumByClient( $row['id'], $client_id, $date_from, $date_to, '< 0' );
$row['costs_count'] = (int)$this -> categoryCountByClient( $row['id'], $client_id, $date_from, $date_to, '< 0' );
$row['income'] = (double)$this -> categorySumByClient( $row['id'], $client_id, $date_from, $date_to, '> 0' );
$row['income_count'] = (int)$this -> categoryCountByClient( $row['id'], $client_id, $date_from, $date_to, '> 0' );
}
else
{
$row['costs'] = (double)$this -> categorySum( $row['id'], $date_from, $date_to, '< 0' );
$row['costs_count'] = (int)$this -> categoryCount( $row['id'], $date_from, $date_to, '< 0' );
$row['income'] = (double)$this -> categorySum( $row['id'], $date_from, $date_to, '> 1' );
$row['income_count'] = (int)$this -> categoryCount( $row['id'], $date_from, $date_to, '> 1' );
}
$row['subcategories'] = $this -> categories( $date_from, $date_to, $tag_id, $row['id'], $group_id, $client_id );
$categories[] = $row;
}
return $categories;
}
private function categorySum( $category_id, $date_from, $date_to, $amount_condition )
{
$results = $this -> mdb -> query(
'SELECT SUM(amount) FROM finance_operations '
. 'WHERE category_id = :category_id AND date >= :date_from AND date <= :date_to AND amount ' . $amount_condition,
[ ':category_id' => (int)$category_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll();
return $results[0][0];
}
private function categoryCount( $category_id, $date_from, $date_to, $amount_condition )
{
$results = $this -> mdb -> query(
'SELECT COUNT(0) FROM finance_operations '
. 'WHERE category_id = :category_id AND date >= :date_from AND date <= :date_to AND amount ' . $amount_condition,
[ ':category_id' => (int)$category_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll();
return $results[0][0];
}
private function categorySumByTag( $category_id, $tag_id, $group_id, $date_from, $date_to, $amount_condition )
{
$results = $this -> mdb -> query(
'SELECT SUM(amount) FROM finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'INNER JOIN finance_tags AS ft ON ft.id = fot.tag_id '
. 'WHERE category_id = :category_id AND tag_id = :tag_id AND ft.group_id = :group_id '
. 'AND date >= :date_from AND date <= :date_to AND amount ' . $amount_condition,
[ ':category_id' => (int)$category_id, ':tag_id' => (int)$tag_id, ':group_id' => (int)$group_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll();
return $results[0][0];
}
private function categoryCountByTag( $category_id, $tag_id, $group_id, $date_from, $date_to, $amount_condition )
{
$results = $this -> mdb -> query(
'SELECT COUNT(fo.id) FROM finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'INNER JOIN finance_tags AS ft ON ft.id = fot.tag_id '
. 'WHERE category_id = :category_id AND tag_id = :tag_id AND ft.group_id = :group_id '
. 'AND date >= :date_from AND date <= :date_to AND amount ' . $amount_condition,
[ ':category_id' => (int)$category_id, ':tag_id' => (int)$tag_id, ':group_id' => (int)$group_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll();
return $results[0][0];
}
private function categorySumByClient( $category_id, $client_id, $date_from, $date_to, $amount_condition )
{
$results = $this -> mdb -> query(
'SELECT SUM(amount) FROM finance_operations '
. 'WHERE category_id = :category_id AND client_id = :client_id '
. 'AND date >= :date_from AND date <= :date_to AND amount ' . $amount_condition,
[ ':category_id' => (int)$category_id, ':client_id' => (int)$client_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll();
return $results[0][0];
}
private function categoryCountByClient( $category_id, $client_id, $date_from, $date_to, $amount_condition )
{
$results = $this -> mdb -> query(
'SELECT COUNT(0) FROM finance_operations '
. 'WHERE category_id = :category_id AND client_id = :client_id '
. 'AND date >= :date_from AND date <= :date_to AND amount ' . $amount_condition,
[ ':category_id' => (int)$category_id, ':client_id' => (int)$client_id, ':date_from' => $date_from, ':date_to' => $date_to ]
) -> fetchAll();
return $results[0][0];
}
}

View File

@@ -1,73 +0,0 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace controls;
/**
* Description of class
*
* @author Project-Pro - Jacek
*/
class Crm
{
static public function client_delete()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
if ( \factory\Crm::client_delete( \S::get( 'client_id' ) ) )
{
\S::alert( 'Klient został usunięty' );
header( 'Location: /crm/main_view/' );
exit;
}
}
public static function client_save()
{
global $user;
if ( !$user or!\controls\Users::permissions( $user[ 'id' ], 'wiki' ) )
return false;
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania klienta wystąpił błąd. Proszę spróbować ponownie.' ];
$values = \S::json_to_array( \S::get( 'values' ) );
if ( $id = \factory\Crm::client_save(
(int)$values[ 'id' ], $values[ 'firm' ], $values[ 'emails' ], $values[ 'phones' ], $values[ 'notes' ]
) )
$response = [ 'status' => 'ok', 'msg' => 'Projekt został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function client_edit()
{
global $user;
if ( !$user or !\controls\Users::permissions( $user[ 'id' ], 'wiki' ) )
return false;
return \Tpl::view( 'crm/client-edit', [
'client' => \factory\Crm::client_details( (int)\S::get( 'id' ) )
] );
}
public static function main_view()
{
global $user;
if ( !$user or !\controls\Users::permissions( $user[ 'id' ], 'wiki' ) )
return false;
return \Tpl::view( 'crm/main-view' );
}
}

View File

@@ -1,197 +0,0 @@
<?php
namespace controls;
class Finances
{
public static function category_delete() {
global $user;
if ( !$user )
return \controls\Users::login_form();
if ( \factory\Finances::category_delete( \S::get( 'category_id' ) ) ) {
\S::alert( 'Wybrana kategoria została usunięta.' );
header( 'Location: /finances/main_view/' );
exit;
}
}
public static function operation_save()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
$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'] );
if ( $id = \factory\Finances::operation_save(
$values['id'], $values['category_id'], $values['date'], $values['amount'], $values['description'], $values['tags'], \S::get_session( 'finance-group' )
) )
$response = [ 'status' => 'ok', 'msg' => 'Operacja została zapisana.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function operation_delete()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
if ( \factory\Finances::operation_delete( \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 operation_edit()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
return \Tpl::view( 'finances/operation-edit', [
'operation' => \factory\Finances::operation_details( \S::get( 'operation-id' ) ),
'category_id' => \S::get( 'category-id' ),
'tags' => \factory\Finances::tags_list( \S::get_session( 'finance-group' ) ),
'tags_json' => \factory\Finances::tags_json( \S::get_session( 'finance-group' ) ),
'operation_date' => \S::get_session( 'operation-date' ),
'clients' => \factory\Finances::clients_list()
] );
}
public static function category_save()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania kateogrii wystąpił błąd. Proszę spróbować ponownie.' ];
$values = \S::json_to_array( \S::get( 'values' ) );
if ( $id = \factory\Finances::category_save(
$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 category_edit()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
return \Tpl::view( 'finances/category-edit', [
'category' => \factory\Finances::category_details( \S::get( 'id' ) ),
'group_id' => \S::get_session( 'finance-group' )
] );
}
public static function operations_list()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
$dates = \S::get( 'dates' );
if ( $dates )
\S::set_session( 'finance-dates', $dates );
$dates = \S::get_session( 'finance-dates' );
$dates = explode( ' - ', $dates );
$dates[0] ? $date_from = $dates[0] : $date_from = date( 'Y-m-01' );
$dates[1] ? $date_to = $dates[1] : $date_to = date( 'Y-m-t' );
$category = \factory\Finances::category_details( \S::get( 'category-id' ) );
if ( $category['group_id'] == 3 )
{
$date_from = '2000-01-01';
$date_to = '3000-01-0';
}
return \Tpl::view( 'finances/operations-list', [
'category' => $category,
'operations' => \factory\Finances::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 main_view()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
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' ) );
if ( \S::get( 'group-id' ) )
\S::set_session( 'finance-group', \S::get( 'group-id' ) );
if ( !$group_id = \S::get_session( 'finance-group' ) )
{
$group_id = \factory\Finances::default_group();
\S::set_session( 'finance-group', $group_id );
}
$tag_id = \S::get_session( 'finance-tag-id' );
$client_id = \S::get_session( 'finance_client_id' );
$dates = \S::get_session( 'finance-dates' );
$dates = explode( '_-_', $dates );
$dates[0] ? $date_from = $dates[0] : $date_from = $date_from = date( 'Y-m-01' );
$dates[1] ? $date_to = $dates[1] : $date_to = date( 'Y-m-t' );
if ( $group_id == 3 )
{
$date_from = '2000-01-01';
$date_to = '3000-01-0';
}
return \Tpl::view( 'finances/main-view', [
'categories' => \factory\Finances::categories( $date_from, $date_to, $tag_id, null, $group_id ),
'date_from' => $date_from,
'date_to' => $date_to,
'tags' => \factory\Finances::tags_list( $group_id ),
'tag_id' => $tag_id,
'groups' => \factory\Finances::groups_list(),
'group_id' => $group_id,
'operations_list' => \factory\Finances::operations_list( $date_from, $date_to, $group_id ),
'wallet_summary' => \factory\Finances::wallet_summary( $group_id ),
'wallet_summary_this_month' => \factory\Finances::wallet_summary_this_month( $group_id ),
'wallet_income_this_month' => \factory\Finances::wallet_income_this_month( $group_id ),
'wallet_expenses_this_month' => \factory\Finances::wallet_expenses_this_month( $group_id )
] );
}
}

View File

@@ -2,22 +2,40 @@
namespace controls; namespace controls;
class Site class Site
{ {
private static function snakeToCamel( $snake )
{
return lcfirst( str_replace( '_', '', ucwords( $snake, '_' ) ) );
}
public static function route() public static function route()
{ {
global $user; global $user;
$class = '\controls\\'; $module = \S::get( 'module' );
$results = explode( '_', \S::get( 'module' ) );
if ( is_array( $results ) ) foreach ( $results as $row )
$class .= ucfirst( $row );
$action = \S::get( 'action' ); $action = \S::get( 'action' );
if ( !\controls\Users::permissions( $user['id'], $module ) )
return;
// New Controllers namespace (camelCase methods)
$controller_class = '\Controllers\\';
$parts = explode( '_', $module );
if ( is_array( $parts ) ) foreach ( $parts as $part )
$controller_class .= ucfirst( $part );
$controller_class .= 'Controller';
$camel_action = self::snakeToCamel( $action );
if ( class_exists( $controller_class ) and method_exists( $controller_class, $camel_action ) )
return call_user_func_array( array( $controller_class, $camel_action ), array() );
// Legacy controls namespace (snake_case methods)
$class = '\controls\\';
$parts = explode( '_', $module );
if ( is_array( $parts ) ) foreach ( $parts as $part )
$class .= ucfirst( $part );
if ( class_exists( $class ) and method_exists( new $class, $action ) ) if ( class_exists( $class ) and method_exists( new $class, $action ) )
{ return call_user_func_array( array( $class, $action ), array() );
if ( \controls\Users::permissions( $user['id'], \S::get( 'module' ) ) )
return call_user_func_array( array( $class, $action ), array() );
}
} }
} }

View File

@@ -1,15 +1,8 @@
<?php <?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace factory; namespace factory;
/** /**
* Description of class * @deprecated Use \Domain\Crm\ClientRepository and \Controllers\CrmController instead.
*
* @author Project-Pro - Jacek
*/ */
class Crm class Crm
{ {
@@ -18,50 +11,37 @@ class Crm
static public function settings() static public function settings()
{ {
global $mdb; $repository = new \Domain\Crm\ClientRepository();
return $repository -> settings();
$results = $mdb -> select( 'settings', '*' );
foreach ( $results as $result )
{
$settings[ $result['name'] ] = $result['value'];
}
return $settings;
} }
static public function get_client_name( int $client_id ) { static public function get_client_name( int $client_id )
global $mdb; {
return $mdb -> get( 'crm_client', 'firm', [ 'id' => $client_id ] ); $repository = new \Domain\Crm\ClientRepository();
return $repository -> getName( $client_id );
} }
static public function get_client_list() { static public function get_client_list()
global $mdb; {
return $mdb -> select( 'crm_client', '*', [ 'ORDER' => [ 'firm' => 'ASC' ] ] ); $repository = new \Domain\Crm\ClientRepository();
return $repository -> all();
} }
static public function client_delete( int $client_id ) static public function client_delete( int $client_id )
{ {
global $mdb; $repository = new \Domain\Crm\ClientRepository();
return $mdb -> delete( 'crm_client', [ 'id' => $client_id ] ); return $repository -> delete( $client_id );
} }
public static function client_details( int $client_id ) public static function client_details( int $client_id )
{ {
return \R::load( 'crm_client', $client_id ); $repository = new \Domain\Crm\ClientRepository();
return $repository -> getById( $client_id );
} }
public static function client_save( $client_id, $firm, $emails, $phones, $notes ) public static function client_save( $client_id, $firm, $firm_name, $emails, $phones, $notes )
{ {
$client = \R::load( 'crm_client', $client_id ); $repository = new \Domain\Crm\ClientRepository();
if ( !$client ) return $repository -> save( (int)$client_id, $firm, $firm_name, $emails, $phones, $notes );
{
$client = \R::xdispense( 'crm_client' );
$client -> date_add = date( 'Y-m-d H:i:s' );
}
$client -> firm = $firm;
$client -> emails = $emails;
$client -> phones = $phones;
$client -> notes = $notes;
$client -> date_update = date( 'Y-m-d H:i:s' );
return \R::store( $client );
} }
} }

View File

@@ -1,352 +1,123 @@
<?php <?php
namespace factory; namespace factory;
/**
* @deprecated Use \Domain\Finances\FinanceRepository and \Controllers\FinancesController instead.
*/
class Finances class Finances
{ {
private static function repo()
{
return new \Domain\Finances\FinanceRepository();
}
static public function first_operation_date() static public function first_operation_date()
{ {
global $mdb; return self::repo() -> firstOperationDate();
return $mdb -> get( 'finance_operations', 'date', [ 'ORDER' => [ 'date' => 'ASC' ] ] );
} }
static public function get_operation_tags( int $operation_id ) static public function get_operation_tags( int $operation_id )
{ {
global $mdb; return self::repo() -> getOperationTags( $operation_id );
$tags_id = $mdb -> select( 'finance_operation_tags', 'tag_id', [ 'operation_id' => $operation_id ] );
foreach ( $tags_id as $tag_id )
{
if ( $return )
$return .= ', ';
$return .= $mdb -> get( 'finance_tags', 'tag', [ 'id' => $tag_id ] );
}
return $return;
} }
static public function client_name( $client_id ) static public function client_name( $client_id )
{ {
global $mdb; return self::repo() -> clientName( $client_id );
return $mdb -> get( 'crm_client', 'firm',[ 'id' => $client_id ] );
} }
static public function clients_list_by_dates( $date_from, $date_to ) static public function clients_list_by_dates( $date_from, $date_to )
{ {
global $mdb; return self::repo() -> clientsListByDates( $date_from, $date_to );
return $mdb -> query( 'SELECT cc.id, cc.firm FROM crm_client AS cc INNER JOIN finance_operations AS fo ON fo.client_id = cc.id WHERE date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' GROUP BY cc.id ORDER BY firm ASC' ) -> fetchAll( \PDO::FETCH_ASSOC );
} }
static public function clients_list() static public function clients_list()
{ {
global $mdb; return self::repo() -> clientsList();
return $mdb -> select( 'crm_client', [ 'id', 'firm' ], [ 'ORDER' => [ 'firm' => 'ASC' ] ] );
} }
public static function category_delete( $category_id ) { public static function category_delete( $category_id )
global $mdb; {
return $mdb -> delete( 'finance_categories', [ 'id' => (int)$category_id ] ); return self::repo() -> deleteCategory( $category_id );
} }
public static function default_group() public static function default_group()
{ {
global $mdb; return self::repo() -> defaultGroup();
return $mdb -> get( 'finance_group', 'id', [ 'default_group' => 1 ] );
} }
public static function groups_list() public static function groups_list()
{ {
global $mdb; return self::repo() -> groupsList();
return $mdb -> select( 'finance_group', '*', [ 'ORDER' => [ 'name' => 'ASC' ] ] );
} }
public static function operation_delete( $operation_id ) public static function operation_delete( $operation_id )
{ {
global $mdb; return self::repo() -> deleteOperation( $operation_id );
return $mdb -> delete( 'finance_operations', [ 'id' => $operation_id ] );
} }
public static function tags_json( $group_id ) public static function tags_json( $group_id )
{ {
global $mdb; return self::repo() -> tagsJson( $group_id );
return $mdb -> select( 'finance_tags', 'tag', [ 'group_id' => $group_id, 'ORDER' => [ 'tag' => 'ASC' ] ] );
} }
public static function tags_list( $group_id ) public static function tags_list( $group_id )
{ {
global $mdb; return self::repo() -> tagsList( $group_id );
$results = $mdb -> select( 'finance_tags', '*', [ 'group_id' => $group_id ] );
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
{
$tag = $row;
$tag['count'] = $mdb -> count( 'finance_operation_tags', [ 'tag_id' => $row['id'] ] );
$tags[] = $tag;
}
if ( is_array( $tags ) and count( $tags ) )
array_multisort( array_column( $tags, "count" ), SORT_DESC, $tags );
return $tags;
} }
static public function operations_list( $date_from, $date_to, $group_id ) { static public function operations_list( $date_from, $date_to, $group_id )
global $mdb; {
$results = $mdb -> query( 'SELECT ' return self::repo() -> operationsList( $date_from, $date_to, $group_id );
. 'fo.*, fc.name '
. 'FROM '
. 'finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'WHERE '
. 'date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND group_id = ' . $group_id . ' '
. 'ORDER BY '
. 'fo.date DESC, id DESC' ) -> fetchAll( \PDO::FETCH_ASSOC );
return $results;
} }
public static function operation_details( $operation_id ) public static function operation_details( $operation_id )
{ {
global $mdb; return self::repo() -> operationDetails( $operation_id );
$operation = $mdb -> get( 'finance_operations', '*', [ 'id' => $operation_id ] );
$operation['tags'] = $mdb -> query( 'SELECT tag, tag_id FROM finance_operation_tags AS fot INNER JOIN finance_tags AS ft ON fot.tag_id = ft.id WHERE operation_id = ' . (int)$operation_id ) -> fetchAll( \PDO::FETCH_ASSOC );
return $operation;
} }
public static function operation_save( $operation_id, $category_id, $date, $amount, $description, $tags, $group_id ) public static function operation_save( $operation_id, $category_id, $date, $amount, $description, $tags, $group_id, $client_id = null )
{ {
global $mdb; return self::repo() -> saveOperation( $operation_id, $category_id, $date, $amount, $description, $tags, $group_id, $client_id );
if ( !$operation_id )
{
$mdb -> insert( 'finance_operations', [
'date' => $date ? $date : date( 'Y-m-d' ),
'category_id' => $category_id,
'amount' => $amount,
'description' => $description
] );
$id = $mdb -> id();
$tags = explode( ',', $tags );
if ( is_array( $tags ) ) foreach ( $tags as $tag )
{
if ( $tag_id = $mdb -> get( 'finance_tags', 'id', [ 'AND' => [ 'group_id' => $group_id, 'tag' => trim( $tag ) ] ] ) )
$mdb -> insert( 'finance_operation_tags', [ 'operation_id' => $id, 'tag_id' => $tag_id ] );
else
{
$mdb -> insert( 'finance_tags', [ 'tag' => trim( $tag ), 'group_id' => $group_id ] );
$tag_id = $mdb -> id();
$mdb -> insert( 'finance_operation_tags', [ 'operation_id' => $id, 'tag_id' => $tag_id ] );
}
}
return $id;
}
else
{
$mdb -> update( 'finance_operations', [
'date' => $date,
'amount' => $amount,
'description' => $description
], [
'id' => $operation_id
] );
$mdb -> delete( 'finance_operation_tags', [ 'operation_id' => $operation_id ] );
$tags = explode( ',', $tags );
if ( is_array( $tags ) ) foreach ( $tags as $tag )
{
if ( $tag_id = $mdb -> get( 'finance_tags', 'id', [ 'AND' => [ 'group_id' => $group_id, 'tag' => trim( $tag ) ] ] ) )
$mdb -> insert( 'finance_operation_tags', [ 'operation_id' => $operation_id, 'tag_id' => $tag_id ] );
else
{
$mdb -> insert( 'finance_tags', [ 'tag' => trim( $tag ), 'group_id' => $group_id ] );
$tag_id = $mdb -> id();
$mdb -> insert( 'finance_operation_tags', [ 'operation_id' => $operation_id, 'tag_id' => $tag_id ] );
}
}
return $operation_id;
}
} }
public static function category_details( $category_id ) public static function category_details( $category_id )
{ {
global $mdb; return self::repo() -> categoryDetails( $category_id );
return $mdb -> get( 'finance_categories', '*', [ 'id' => $category_id ] );
} }
public static function category_save( $category_id, $name, $parent_id, $group_id ) public static function category_save( $category_id, $name, $parent_id, $group_id )
{ {
global $mdb; return self::repo() -> saveCategory( $category_id, $name, $parent_id, $group_id );
if ( !$category_id )
{
$mdb -> insert( 'finance_categories', [
'name' => $name,
'parent_id' => $parent_id ? $parent_id : null,
'group_id' => $group_id
] );
return $mdb -> id();
}
else
{
$mdb -> update( 'finance_categories', [
'name' => $name,
'group_id' => $group_id
], [
'id' => $category_id
] );
return $category_id;
}
return false;
} }
static public function wallet_expenses_this_month( $group_id ) static public function wallet_expenses_this_month( $group_id )
{ {
global $mdb; return self::repo() -> walletExpensesThisMonth( $group_id );
$date_from = date( 'Y-m-01', strtotime( date( 'Y-m-d' ) ) );
$date_to = date( 'Y-m-t', strtotime( date( 'Y-m-d' ) ) );
$results = $mdb -> query( 'SELECT SUM(amount) AS wallet_expenses_this_month FROM finance_operations WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = ' . $group_id . ' ) AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount < 0' ) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['wallet_expenses_this_month'];
} }
static public function wallet_income_this_month( $group_id ) static public function wallet_income_this_month( $group_id )
{ {
global $mdb; return self::repo() -> walletIncomeThisMonth( $group_id );
$date_from = date( 'Y-m-01', strtotime( date( 'Y-m-d' ) ) );
$date_to = date( 'Y-m-t', strtotime( date( 'Y-m-d' ) ) );
$results = $mdb -> query( 'SELECT SUM(amount) AS wallet_income_this_month FROM finance_operations WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = ' . $group_id . ' ) AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount > 0' ) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['wallet_income_this_month'];
} }
static public function wallet_summary_this_month( $group_id ) static public function wallet_summary_this_month( $group_id )
{ {
global $mdb; return self::repo() -> walletSummaryThisMonth( $group_id );
$date_from = date( 'Y-m-01', strtotime( date( 'Y-m-d' ) ) );
$date_to = date( 'Y-m-t', strtotime( date( 'Y-m-d' ) ) );
$results = $mdb -> query( 'SELECT SUM(amount) AS wallet_summary_this_month FROM finance_operations WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = ' . $group_id . ' ) AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\'' ) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['wallet_summary_this_month'];
} }
static public function wallet_summary( $group_id ) static public function wallet_summary( $group_id )
{ {
global $mdb; return self::repo() -> walletSummary( $group_id );
$results = $mdb -> query( 'SELECT SUM(amount) AS wallet_summary FROM finance_operations WHERE category_id IN ( SELECT id FROM finance_categories WHERE group_id = ' . $group_id . ' )' ) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['wallet_summary'];
} }
public static function operations( $category_id, $date_from, $date_to, $tag_id = null ) public static function operations( $category_id, $date_from, $date_to, $tag_id = null )
{ {
global $mdb; return self::repo() -> operations( $category_id, $date_from, $date_to, $tag_id );
if ( $tag_id )
$results = $mdb -> query( 'SELECT '
. 'fo.*, firm '
. 'FROM '
. 'finance_operations AS fo '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'INNER JOIN crm_client AS cc ON fo.client_id = cc.id '
. 'WHERE '
. 'category_id = ' . $category_id . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' '
. 'AND '
. 'tag_id = :tag_id '
. 'ORDER BY date DESC, id DESC ',
[
':tag_id' => (int)$tag_id
] ) -> fetchAll();
else
$results = $mdb -> query( 'SELECT fo.* FROM finance_operations AS fo WHERE category_id = ' . $category_id . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' ORDER BY date DESC, fo.id DESC ' ) -> fetchAll();
if ( is_array( $results ) ) foreach ( $results as $row )
{
$row['tags'] = $mdb -> query( 'SELECT tag FROM finance_operation_tags AS fot INNER JOIN finance_tags AS ft ON fot.tag_id = ft.id WHERE operation_id = ' . $row['id'] ) -> fetchAll( \PDO::FETCH_ASSOC );
$operations[] = $row;
}
return $operations;
} }
public static function categories( $date_from, $date_to, $tag_id = '', $parent_id = null, $group_id ) public static function categories( $date_from, $date_to, $tag_id = '', $parent_id = null, $group_id, $client_id = null )
{ {
global $mdb; return self::repo() -> categories( $date_from, $date_to, $tag_id, $parent_id, $group_id, $client_id );
$results = $mdb -> select( 'finance_categories', [ 'id', 'name' ], [ 'AND' => [ 'group_id' => $group_id, 'parent_id' => $parent_id ], 'ORDER' => [ 'name' => 'ASC' ] ] );
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
{
if ( $tag_id )
{
$results2 = $mdb -> query( 'SELECT '
. 'SUM(amount) '
. 'FROM '
. 'finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'INNER JOIN finance_tags AS ft ON ft.id = fot.tag_id '
. 'WHERE '
. 'category_id = ' . $row['id'] . ' AND tag_id = ' . $tag_id . ' AND ft.group_id = ' . $group_id . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount < 0' ) -> fetchAll();
$row['costs'] = (double)$results2[0][0];
$results2 = $mdb -> query( 'SELECT '
. 'COUNT(fo.id) '
. 'FROM '
. 'finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id'
. 'INNER JOIN finance_tags AS ft ON ft.id = fot.tag_id '
. ' WHERE '
. 'category_id = ' . $row['id'] . ' AND tag_id = ' . $tag_id . ' AND ft.group_id = :group_id AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount < 0', [
':group_id' => $group_id
] ) -> fetchAll();
$row['costs_count'] = (int)$results2[0][0];
$results2 = $mdb -> query( 'SELECT '
. 'SUM(amount) '
. 'FROM '
. 'finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'INNER JOIN finance_tags AS ft ON ft.id = fot.tag_id '
. 'WHERE '
. 'category_id = ' . $row['id'] . ' AND tag_id = ' . $tag_id . ' AND ft.group_id = :group_id AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount > 0', [
':group_id' => $group_id
] ) -> fetchAll();
$row['income'] = (double)$results2[0][0];
$results2 = $mdb -> query( 'SELECT '
. 'COUNT(fo.id) '
. 'FROM '
. 'finance_operations AS fo '
. 'INNER JOIN finance_categories AS fc ON fc.id = fo.category_id '
. 'INNER JOIN finance_operation_tags AS fot ON fot.operation_id = fo.id '
. 'INNER JOIN finance_tags AS ft ON ft.id = fot.tag_id '
. 'WHERE '
. 'category_id = ' . $row['id'] . ' AND tag_id = ' . $tag_id . ' AND ft.group_id = :group_id AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount > 0', [
':group_id' => $group_id
] ) -> fetchAll();
$row['income_count'] = (int)$results2[0][0];
}
else
{
$results2 = $mdb -> query( 'SELECT SUM(amount) FROM finance_operations WHERE category_id = ' . $row['id'] . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount < 0' ) -> fetchAll();
$row['costs'] = $results2[0][0];
$results2 = $mdb -> query( 'SELECT COUNT(0) FROM finance_operations WHERE category_id = ' . $row['id'] . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount < 0' ) -> fetchAll();
$row['costs_count'] = (int)$results2[0][0];
$results2 = $mdb -> query( 'SELECT SUM(amount) FROM finance_operations WHERE category_id = ' . $row['id'] . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount > 1' ) -> fetchAll();
$row['income'] = $results2[0][0];
$results2 = $mdb -> query( 'SELECT COUNT(0) FROM finance_operations WHERE category_id = ' . $row['id'] . ' AND date >= \'' . $date_from . '\' AND date <= \'' . $date_to . '\' AND amount > 1' ) -> fetchAll();
$row['income_count'] = (int)$results2[0][0];
}
$row['subcategories'] = self::categories( $date_from, $date_to, $tag_id, $row['id'], $group_id, $client_id );
$categories[] = $row;
}
return $categories;
} }
} }

View File

@@ -3,12 +3,19 @@ global $db;
ob_start(); ob_start();
?> ?>
<?= \Html::input( [ <?= \Html::input( [
'label' => 'Firma', 'label' => 'Nazwa',
'name' => 'firm', 'name' => 'firm',
'id' => 'firm', 'id' => 'firm',
'value' => $this -> client -> firm, 'value' => $this -> client -> firm,
'inline' => true 'inline' => true
] );?> ] );?>
<?= \Html::input( [
'label' => 'Nazwa firmy',
'name' => 'firm_name',
'id' => 'firm_name',
'value' => $this -> client -> firm_name,
'inline' => true
] );?>
<?= \Html::input( [ <?= \Html::input( [
'label' => 'Emaile', 'label' => 'Emaile',
'name' => 'emails', 'name' => 'emails',

View File

@@ -9,7 +9,7 @@ $grid = new \grid( 'crm_client' );
$grid -> debug = true; $grid -> debug = true;
$grid -> gdb_opt = $gdb; $grid -> gdb_opt = $gdb;
$grid -> search = [ $grid -> search = [
[ 'name' => 'Firma', 'db' => 'firm', 'type' => 'text' ], [ 'name' => 'Nazwa', 'db' => 'firm', 'type' => 'text' ],
[ 'name' => 'Status', 'db' => 'status', 'type' => 'select', 'replace' => [ 'array' => \factory\Crm::$status ] ], [ 'name' => 'Status', 'db' => 'status', 'type' => 'select', 'replace' => [ 'array' => \factory\Crm::$status ] ],
]; ];
$grid -> order = [ 'column' => 'firm', 'type' => 'ASC' ]; $grid -> order = [ 'column' => 'firm', 'type' => 'ASC' ];
@@ -27,8 +27,11 @@ $grid -> columns_view = [
'php' => 'echo date( "Y-m-d H:i", strtotime( "[date_update]" ) );', 'php' => 'echo date( "Y-m-d H:i", strtotime( "[date_update]" ) );',
'sort' => true 'sort' => true
], [ ], [
'name' => 'Firma', 'name' => 'Nazwa',
'db' => 'firm', 'db' => 'firm',
], [
'name' => 'Nazwa firmy',
'db' => 'firm_name',
], [ ], [
'name' => 'Telefony', 'name' => 'Telefony',
'db' => 'phones', 'db' => 'phones',

View File

@@ -49,40 +49,28 @@
<div class="finance-manager"> <div class="finance-manager">
<div class="column-left"> <div class="column-left">
<div class="clients-list-container"> <div class="clients-list-container">
<div class="finance-tags"> <div class="finance-clients">
<a href="/finances/main_view/tag-clear=true" class="btn btn-sm btn-success"><i class="fa fa-bars"></i>wszystkie</a> <a href="/finances/main_view/client_clear=true" class="btn btn-sm btn-success mb10" style="display:block;"><i class="fa fa-bars"></i> wszyscy klienci</a>
<? <? if ( is_array( $this -> clients ) and count( $this -> clients ) ):?>
$max = $this->tags[0]['count']; <table class="table table-sm table-hover mb0" style="background: #FFF; font-size: 12px;">
$min = is_array( $this -> tags ) ? $this -> tags[ count( $this -> tags ) - 1 ]['count'] : 0; <thead>
if ( is_array( $thi -> tags ) and count( $this->tags) === 1) <tr>
$min = 0; <th>Klient</th>
$step = ($max - $min) / 10; <th class="text-right" style="width: 90px;">Dochód</th>
?> </tr>
<? </thead>
if ($min == $max) <tbody>
$max++; <? foreach ( $this -> clients as $client ):?>
<tr class="<?= ( $client['id'] == $this -> client_id ) ? 'table-primary' : '';?>" style="cursor: pointer;" onclick="document.location.href='/finances/main_view/client_id=<?= $client['id'];?>'">
if (!$step) <td><?= $client['firm'];?></td>
$step = 1; <td class="text-right <?= $client['total'] > 0 ? 'text-success' : 'text-danger';?>"><?= \S::number_display( $client['total'] );?></td>
</tr>
if (is_array($this->tags)) foreach ($this->tags as $tag) <? endforeach;?>
{ </tbody>
echo '<a href="/finances/main_view/tag-id=' . $tag['id'] . '" class="'; </table>
$i = $max; <? else:?>
$z = 100; <small class="text-muted">Brak operacji z przypisanymi klientami w wybranym okresie.</small>
while ($i >= $min) <? endif;?>
{
if ($tag['count'] <= $i and $tag['count'] > ($i - $step))
{
echo 'zoom-' . $z;
}
$i -= $step;
$z -= 10;
}
if ($tag['id'] == $this->tag_id) echo ' text-primary';
echo '">' . $tag['tag'] . '</a>';
};
?>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -31,6 +31,18 @@ ob_start();
'inline' => true 'inline' => true
] ); ] );
$clients_values = [ '' => '--- brak ---' ];
if ( is_array( $this -> clients ) ) foreach ( $this -> clients as $client )
$clients_values[ $client['id'] ] = $client['firm'];
echo \Html::select( [
'label' => 'Klient',
'name' => 'client_id',
'id' => 'client_id',
'values' => $clients_values,
'value' => $this -> operation['client_id'],
] );
foreach ( $this -> operation['tags'] as $tag ) foreach ( $this -> operation['tags'] as $tag )
{ {
$tags_value .= $tag['tag']; $tags_value .= $tag['tag'];
@@ -110,4 +122,4 @@ echo $grid -> draw();
} }
}); });
}); });
</script> </script>

View File

@@ -236,6 +236,7 @@ usort( $billing_clients, function( $a, $b ) {
confirm: { confirm: {
text: 'Zamknij zadanie', text: 'Zamknij zadanie',
btnClass: 'btn-orange', btnClass: 'btn-orange',
keys: ['enter'],
action: function() { action: function() {
onConfirm(); onConfirm();
} }