initial commit

This commit is contained in:
2026-06-25 13:03:45 +06:00
commit 4589f4a8d0
3229 changed files with 941958 additions and 0 deletions

5
app/.htaccess Normal file
View File

@@ -0,0 +1,5 @@
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>

65
app/Config/acl.ini.php Normal file
View File

@@ -0,0 +1,65 @@
;<?php exit() ?>
;/**
; * ACL Configuration
; *
; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
; * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
; * @link http://cakephp.org CakePHP(tm) Project
; * @package app.Config
; * @since CakePHP(tm) v 0.10.0.1076
; * @license http://www.opensource.org/licenses/mit-license.php MIT License
; */
; acl.ini.php - Cake ACL Configuration
; ---------------------------------------------------------------------
; Use this file to specify user permissions.
; aco = access control object (something in your application)
; aro = access request object (something requesting access)
;
; User records are added as follows:
;
; [uid]
; groups = group1, group2, group3
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; Group records are added in a similar manner:
;
; [gid]
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; The allow, deny, and groups sections are all optional.
; NOTE: groups names *cannot* ever be the same as usernames!
;
; ACL permissions are checked in the following order:
; 1. Check for user denies (and DENY if specified)
; 2. Check for user allows (and ALLOW if specified)
; 3. Gather user's groups
; 4. Check group denies (and DENY if specified)
; 5. Check group allows (and ALLOW if specified)
; 6. If no aro, aco, or group information is found, DENY
;
; ---------------------------------------------------------------------
;-------------------------------------
;Users
;-------------------------------------
[username-goes-here]
groups = group1, group2
deny = aco1, aco2
allow = aco3, aco4
;-------------------------------------
;Groups
;-------------------------------------
[groupname-goes-here]
deny = aco5, aco6
allow = aco7, aco8

145
app/Config/acl.php Normal file
View File

@@ -0,0 +1,145 @@
<?php
/**
* This is the PHP base ACL configuration file.
*
* Use it to configure access control of your CakePHP application.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 2.1
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Example
* -------
*
* Assumptions:
*
* 1. In your application you created a User model with the following properties:
* username, group_id, password, email, firstname, lastname and so on.
* 2. You configured AuthComponent to authorize actions via
* $this->Auth->authorize = array('Actions' => array('actionPath' => 'controllers/'),...)
*
* Now, when a user (i.e. jeff) authenticates successfully and requests a controller action (i.e. /invoices/delete)
* that is not allowed by default (e.g. via $this->Auth->allow('edit') in the Invoices controller) then AuthComponent
* will ask the configured ACL interface if access is granted. Under the assumptions 1. and 2. this will be
* done via a call to Acl->check() with
*
* {{{
* array('User' => array('username' => 'jeff', 'group_id' => 4, ...))
* }}}
*
* as ARO and
*
* {{{
* '/controllers/invoices/delete'
* }}}
*
* as ACO.
*
* If the configured map looks like
*
* {{{
* $config['map'] = array(
* 'User' => 'User/username',
* 'Role' => 'User/group_id',
* );
* }}}
*
* then PhpAcl will lookup if we defined a role like User/jeff. If that role is not found, PhpAcl will try to
* find a definition for Role/4. If the definition isn't found then a default role (Role/default) will be used to
* check rules for the given ACO. The search can be expanded by defining aliases in the alias configuration.
* E.g. if you want to use a more readable name than Role/4 in your definitions you can define an alias like
*
* {{{
* $config['alias'] = array(
* 'Role/4' => 'Role/editor',
* );
* }}}
*
* In the roles configuration you can define roles on the lhs and inherited roles on the rhs:
*
* {{{
* $config['roles'] = array(
* 'Role/admin' => null,
* 'Role/accountant' => null,
* 'Role/editor' => null,
* 'Role/manager' => 'Role/editor, Role/accountant',
* 'User/jeff' => 'Role/manager',
* );
* }}}
*
* In this example manager inherits all rules from editor and accountant. Role/admin doesn't inherit from any role.
* Lets define some rules:
*
* {{{
* $config['rules'] = array(
* 'allow' => array(
* '*' => 'Role/admin',
* 'controllers/users/(dashboard|profile)' => 'Role/default',
* 'controllers/invoices/*' => 'Role/accountant',
* 'controllers/articles/*' => 'Role/editor',
* 'controllers/users/*' => 'Role/manager',
* 'controllers/invoices/delete' => 'Role/manager',
* ),
* 'deny' => array(
* 'controllers/invoices/delete' => 'Role/accountant, User/jeff',
* 'controllers/articles/(delete|publish)' => 'Role/editor',
* ),
* );
* }}}
*
* Ok, so as jeff inherits from Role/manager he's matched every rule that references User/jeff, Role/manager,
* Role/editor, and Role/accountant. However, for jeff, rules for User/jeff are more specific than
* rules for Role/manager, rules for Role/manager are more specific than rules for Role/editor and so on.
* This is important when allow and deny rules match for a role. E.g. Role/accountant is allowed
* controllers/invoices/* but at the same time controllers/invoices/delete is denied. But there is a more
* specific rule defined for Role/manager which is allowed controllers/invoices/delete. However, the most specific
* rule denies access to the delete action explicitly for User/jeff, so he'll be denied access to the resource.
*
* If we would remove the role definition for User/jeff, then jeff would be granted access as he would be resolved
* to Role/manager and Role/manager has an allow rule.
*/
/**
* The role map defines how to resolve the user record from your application
* to the roles you defined in the roles configuration.
*/
$config['map'] = array(
'User' => 'User/username',
'Role' => 'User/group_id',
);
/**
* define aliases to map your model information to
* the roles defined in your role configuration.
*/
$config['alias'] = array(
'Role/4' => 'Role/editor',
);
/**
* role configuration
*/
$config['roles'] = array(
'Role/admin' => null,
);
/**
* rule configuration
*/
$config['rules'] = array(
'allow' => array(
'*' => 'Role/admin',
),
'deny' => array(),
);

View File

@@ -0,0 +1,64 @@
<?php
define('IS_GOOGLE_ANALYTIC',0); // 0 = disable google analytics, 1 = enable google analytics
define('MAINTENANCE_MOOD', 0); // 1= maintenance message will be displayed on website. 0 = normal mood, no alert or message shown
// define('HTTP_SITE_URL', 'https://expensecount.org');
define('HTTP_SITE_URL', 'http://localhost/expensecount');
define('CDN_URL', HTTP_SITE_URL.'/cdn/');
define('SUPPORT_EMAIL', 'admin@expensecount.com');
define('FIREBASE_DB_PATH', 'root/dev');
define('IS_FIREBASE_ACTIVATED', false);
define('FIREBASE_SERVICE_ACCOUNT_CREDENTIALS', '../../chtlbd-159010-5a04c5d334cf.json');
// define('FIREBASE_SERVICE_ACCOUNT_CREDENTIALS', '../../go_ser_pri.json'); // for production
define('USER_RESET_PASSWORD_EXPIRE_WITHIN_TIME', '+1 days');
define('REMEMBER_ME_EXPIRE_WITHIN_TIME', '+90 days');
define('IS_EMAIL_SEND_DURING_USER_REGISTRATION', true);
define('IS_EMAIL_SEND_DURING_RESET_PASSWORD', true);
define('IS_USER_WALLET_ACTIVE', true);
define("APP_DB_HOST","localhost");
define("APP_DB_USERNAME","root");
define("APP_DB_PASSWORD","");
define("APP_DB_NAME","expense_test_db");
define("ARCHIEVE_DB_NAME","expense_test_archive");
define("GOOGLE_CLIENT_ID","324461531591-ugsm13l3gvq74i43b9bnl23sc39v6r7i"); // https://console.cloud.google.com/apis/dashboard
define("GOOGLE_CLIENT_SECRET","xbYQRNbYThzUBFbNzkTYrdHB");
define("GOOGLE_API_KEY","AIzaSyAzK22UZBOxHST7VKV7se876TElXBQAJmM");
// Paypal Settings
define('PAYPAL_ID', 'dgfdfadsf');
define('PAYPAL_CLIENT_ID', 'test');
define('PAYPAL_CLIENT_SECRET', 'test');
define('PAYPAL_ON_PRODUCTION', false);
define('PAYPAL_CURRENCY_CODE', 'USD');
define('PAYPAL_NOTIFY_URL', HTTP_SITE_URL.'/pages/paypalipn');
define('PAYPAL_CANCEL_RETURN_URL', HTTP_SITE_URL.'/pages/paypalcancel');
define('PAYPAL_SUCCESS_RETURN_URL', HTTP_SITE_URL.'/pages/createGroup');
define('PAYPAL_URL', (PAYPAL_ON_PRODUCTION == true) ? 'https://www.paypal.com/cgi-bin/webscr' : 'https://www.sandbox.paypal.com/cgi-bin/webscr');
define('NO_PERMIT', 1);
define('PUBLIC_PERMIT', 2);
define('EDIT_PERMIT', 3);
define('VIEW_PERMIT', 4);
define('ADMIN_PERMIT', 5);
define('OWNER', 6);
define('FIREBASE_SECRET', ROOT . DS .'go_ser_pri.json');
define('NUMBER_OF_EXPENSE_IMAGES',3);
define('PERMISSION_ENABLED',true);
define('RESTRICTION_MODE_HIDE',true);
define('PARTICIPENT_NAME_LENGTH',20);
define('FIREBASE_PROJECT_ID', 'expensecount-312c7');
define('REPORTING_EMAIL', 'admin@expensecount.com');
define('BACKUP_LIMIT', 100);

125
app/Config/bootstrap.php Normal file
View File

@@ -0,0 +1,125 @@
<?php
require 'app.settings.php';
require_once ROOT . DS . 'lib' . DS . 'firebase' . DS . 'vendor' . DS . 'autoload.php';
/**
* This file is loaded automatically by the app/webroot/index.php file after core.php
*
* This file should load/create any application wide configuration settings, such as
* Caching, Logging, loading additional configuration files.
*
* You should also use this file to include any files that provide global functions/constants
* that your application uses.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.10.8.2117
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
// Setup a 'default' cache configuration for use in the application.
Cache::config('default', array('engine' => 'File'));
/**
* The settings below can be used to set additional paths to models, views and controllers.
*
* App::build(array(
* 'Model' => array('/path/to/models/', '/next/path/to/models/'),
* 'Model/Behavior' => array('/path/to/behaviors/', '/next/path/to/behaviors/'),
* 'Model/Datasource' => array('/path/to/datasources/', '/next/path/to/datasources/'),
* 'Model/Datasource/Database' => array('/path/to/databases/', '/next/path/to/database/'),
* 'Model/Datasource/Session' => array('/path/to/sessions/', '/next/path/to/sessions/'),
* 'Controller' => array('/path/to/controllers/', '/next/path/to/controllers/'),
* 'Controller/Component' => array('/path/to/components/', '/next/path/to/components/'),
* 'Controller/Component/Auth' => array('/path/to/auths/', '/next/path/to/auths/'),
* 'Controller/Component/Acl' => array('/path/to/acls/', '/next/path/to/acls/'),
* 'View' => array('/path/to/views/', '/next/path/to/views/'),
* 'View/Helper' => array('/path/to/helpers/', '/next/path/to/helpers/'),
* 'Console' => array('/path/to/consoles/', '/next/path/to/consoles/'),
* 'Console/Command' => array('/path/to/commands/', '/next/path/to/commands/'),
* 'Console/Command/Task' => array('/path/to/tasks/', '/next/path/to/tasks/'),
* 'Lib' => array('/path/to/libs/', '/next/path/to/libs/'),
* 'Locale' => array('/path/to/locales/', '/next/path/to/locales/'),
* 'Vendor' => array('/path/to/vendors/', '/next/path/to/vendors/'),
* 'Plugin' => array('/path/to/plugins/', '/next/path/to/plugins/'),
* ));
*
*/
/**
* Custom Inflector rules can be set to correctly pluralize or singularize table, model, controller names or whatever other
* string is passed to the inflection functions
*
* Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
* Inflector::rules('plural', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
*
*/
/**
* Plugins need to be loaded manually, you can either load them one by one or all of them in a single call
* Uncomment one of the lines below, as you need. Make sure you read the documentation on CakePlugin to use more
* advanced ways of loading plugins
*
* CakePlugin::loadAll(); // Loads all plugins at once
* CakePlugin::load('DebugKit'); //Loads a single plugin named DebugKit
*
*/
/**
* You can attach event listeners to the request lifecycle as Dispatcher Filter. By default CakePHP bundles two filters:
*
* - AssetDispatcher filter will serve your asset files (css, images, js, etc) from your themes and plugins
* - CacheDispatcher filter will read the Cache.check configure variable and try to serve cached content generated from controllers
*
* Feel free to remove or add filters as you see fit for your application. A few examples:
*
* Configure::write('Dispatcher.filters', array(
* 'MyCacheFilter', // will use MyCacheFilter class from the Routing/Filter package in your app.
* 'MyCacheFilter' => array('prefix' => 'my_cache_'), // will use MyCacheFilter class from the Routing/Filter package in your app with settings array.
* 'MyPlugin.MyFilter', // will use MyFilter class from the Routing/Filter package in MyPlugin plugin.
* array('callable' => $aFunction, 'on' => 'before', 'priority' => 9), // A valid PHP callback type to be called on beforeDispatch
* array('callable' => $anotherMethod, 'on' => 'after'), // A valid PHP callback type to be called on afterDispatch
*
* ));
*/
Configure::write('Dispatcher.filters', array(
'AssetDispatcher',
'CacheDispatcher'
));
/**
* Configures default file logging options
*/
App::uses('CakeLog', 'Log');
CakeLog::config('debug', array(
'engine' => 'File',
'types' => array('notice', 'info', 'debug'),
'file' => 'debug',
));
CakeLog::config('error', array(
'engine' => 'File',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'file' => 'error',
));
Configure::write(array(
'expensecount.form.validation.success'=>'+000',
'expensecount.form.validation.separator'=>'#',
'expensecount.form.validation.pipe'=>'|',
'expensecount.backup.mode'=> true,
'expensecount.email.validation.pipe'=>'|',
'expensecount.email.smtp.host'=>'smtpout.secureserver.net',
'expensecount.email.smtp.username'=>'admin@expensecount.com',
'expensecount.email.smtp.password'=>'Toronto4321#',
'expensecount.email.smtp.from'=>'admin@expensecount.com',
));

391
app/Config/core.php Normal file
View File

@@ -0,0 +1,391 @@
<?php
/**
* This is core configuration file.
*
* Use it to configure core behavior of Cake.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* CakePHP Debug Level:
*
* Production Mode:
* 0: No error messages, errors, or warnings shown. Flash messages redirect.
*
* Development Mode:
* 1: Errors and warnings shown, model caches refreshed, flash messages halted.
* 2: As in 1, but also with full debug messages and SQL output.
*
* In production mode, flash messages redirect after a time interval.
* In development mode, you need to click the flash message to continue.
*/
Configure::write('debug',0);
/**
* Configure the Error handler used to handle errors for your application. By default
* ErrorHandler::handleError() is used. It will display errors using Debugger, when debug > 0
* and log errors with CakeLog when debug = 0.
*
* Options:
*
* - `handler` - callback - The callback to handle errors. You can set this to any callable type,
* including anonymous functions.
* Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class
* - `level` - integer - The level of errors you are interested in capturing.
* - `trace` - boolean - Include stack traces for errors in log fi3les.
*
* @see ErrorHandler for more information on error handling and configuration.
*/
Configure::write('Error', array(
'handler' => 'ErrorHandler::handleError',
'level' => E_ALL & ~E_DEPRECATED,
'trace' => true
));
/**
* Configure the Exception handler used for uncaught exceptions. By default,
* ErrorHandler::handleException() is used. It will display a HTML page for the exception, and
* while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0,
* framework errors will be coerced into generic HTTP errors.
*
* Options:
*
* - `handler` - callback - The callback to handle exceptions. You can set this to any callback type,
* including anonymous functions.
* Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class
* - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you
* should place the file for that class in app/Lib/Error. This class needs to implement a render method.
* - `log` - boolean - Should Exceptions be logged?
* - `skipLog` - array - list of exceptions to skip for logging. Exceptions that
* extend one of the listed exceptions will also be skipped for logging.
* Example: `'skipLog' => array('NotFoundException', 'UnauthorizedException')`
*
* @see ErrorHandler for more information on exception handling and configuration.
*/
Configure::write('Exception', array(
'handler' => 'ErrorHandler::handleException',
'renderer' => 'ExceptionRenderer',
'log' => true
));
/**
* Application wide charset encoding
*/
Configure::write('App.encoding', 'UTF-8');
/**
* To configure CakePHP *not* to use mod_rewrite and to
* use CakePHP pretty URLs, remove these .htaccess
* files:
*
* /.htaccess
* /app/.htaccess
* /app/webroot/.htaccess
*
* And uncomment the App.baseUrl below. But keep in mind
* that plugin assets such as images, CSS and JavaScript files
* will not work without URL rewriting!
* To work around this issue you should either symlink or copy
* the plugin assets into you app's webroot directory. This is
* recommended even when you are using mod_rewrite. Handling static
* assets through the Dispatcher is incredibly inefficient and
* included primarily as a development convenience - and
* thus not recommended for production applications.
*/
//Configure::write('App.baseUrl', env('SCRIPT_NAME'));
/**
* To configure CakePHP to use a particular domain URL
* for any URL generation inside the application, set the following
* configuration variable to the http(s) address to your domain. This
* will override the automatic detection of full base URL and can be
* useful when generating links from the CLI (e.g. sending emails)
*/
//Configure::write('App.fullBaseUrl', 'http://example.com');
/**
* Web path to the public images directory under webroot.
* If not set defaults to 'img/'
*/
//Configure::write('App.imageBaseUrl', 'img/');
/**
* Web path to the CSS files directory under webroot.
* If not set defaults to 'css/'
*/
//Configure::write('App.cssBaseUrl', 'css/');
/**
* Web path to the js files directory under webroot.
* If not set defaults to 'js/'
*/
//Configure::write('App.jsBaseUrl', 'js/');
/**
* Uncomment the define below to use CakePHP prefix routes.
*
* The value of the define determines the names of the routes
* and their associated controller actions:
*
* Set to an array of prefixes you want to use in your application. Use for
* admin or other prefixed routes.
*
* Routing.prefixes = array('admin', 'manager');
*
* Enables:
* `admin_index()` and `/admin/controller/index`
* `manager_index()` and `/manager/controller/index`
*
*/
//Configure::write('Routing.prefixes', array('admin'));
/**
* Turn off all caching application-wide.
*
*/
Configure::write('Cache.disable', true);
/**
* Enable cache checking.
*
* If set to true, for view caching you must still use the controller
* public $cacheAction inside your controllers to define caching settings.
* You can either set it controller-wide by setting public $cacheAction = true,
* or in each action using $this->cacheAction = true.
*
*/
//Configure::write('Cache.check', true);
/**
* Enable cache view prefixes.
*
* If set it will be prepended to the cache name for view file caching. This is
* helpful if you deploy the same application via multiple subdomains and languages,
* for instance. Each version can then have its own view cache namespace.
* Note: The final cache file name will then be `prefix_cachefilename`.
*/
//Configure::write('Cache.viewPrefix', 'prefix');
/**
* Session configuration.
*
* Contains an array of settings to use for session configuration. The defaults key is
* used to define a default preset to use for sessions, any settings declared here will override
* the settings of the default config.
*
* ## Options
*
* - `Session.cookie` - The name of the cookie to use. Defaults to 'CAKEPHP'
* - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP
* - `Session.cookieTimeout` - The number of minutes you want session cookies to live for.
* - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the
* value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX
* - `Session.defaults` - The default configuration set to use as a basis for your session.
* There are four builtins: php, cake, cache, database.
* - `Session.handler` - Can be used to enable a custom session handler. Expects an array of callables,
* that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler`
* to the ini array.
* - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and
* sessionids that change frequently. See CakeSession::$requestCountdown.
* - `Session.ini` - An associative array of additional ini values to set.
*
* The built in defaults are:
*
* - 'php' - Uses settings defined in your php.ini.
* - 'cake' - Saves session files in CakePHP's /tmp directory.
* - 'database' - Uses CakePHP's database sessions.
* - 'cache' - Use the Cache class to save sessions.
*
* To define a custom session handler, save it at /app/Model/Datasource/Session/<name>.php.
* Make sure the class implements `CakeSessionHandlerInterface` and set Session.handler to <name>
*
* To use database sessions, run the app/Config/Schema/sessions.php schema using
* the cake shell command: cake schema create Sessions
*
*/
Configure::write('Session', array(
'defaults' => 'php'
));
/**
* A random string used in security hashing methods.
*/
Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
/**
* A random numeric string (digits only) used to encrypt/decrypt strings.
*/
Configure::write('Security.cipherSeed', '76859309657453542496749683645');
/**
* Apply timestamps with the last modified time to static assets (js, css, images).
* Will append a query string parameter containing the time the file was modified. This is
* useful for invalidating browser caches.
*
* Set to `true` to apply timestamps when debug > 0. Set to 'force' to always enable
* timestamping regardless of debug value.
*/
//Configure::write('Asset.timestamp', true);
/**
* Compress CSS output by removing comments, whitespace, repeating tags, etc.
* This requires a/var/cache directory to be writable by the web server for caching.
* and /vendors/csspp/csspp.php
*
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use HtmlHelper::css().
*/
//Configure::write('Asset.filter.css', 'css.php');
/**
* Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the
* output, and setting the config below to the name of the script.
*
* To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JsHelper::link().
*/
//Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php');
/**
* The class name and database used in CakePHP's
* access control lists.
*/
Configure::write('Acl.classname', 'DbAcl');
Configure::write('Acl.database', 'default');
//set default language to english
Configure::write('Config.language', "eng");
/**
* Uncomment this line and correct your server timezone to fix
* any date & time related errors.
*/
//date_default_timezone_set('UTC');
/**
* `Config.timezone` is available in which you can set users' timezone string.
* If a method of CakeTime class is called with $timezone parameter as null and `Config.timezone` is set,
* then the value of `Config.timezone` will be used. This feature allows you to set users' timezone just
* once instead of passing it each time in function calls.
*/
//Configure::write('Config.timezone', 'Europe/Paris');
/**
* Cache Engine Configuration
* Default settings provided below
*
* File storage engine.
*
* Cache::config('default', array(
* 'engine' => 'File', //[required]
* 'duration' => 3600, //[optional]
* 'probability' => 100, //[optional]
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
* 'lock' => false, //[optional] use file locking
* 'serialize' => true, //[optional]
* 'mask' => 0664, //[optional]
* ));
*
* APC (http://pecl.php.net/package/APC)
*
* Cache::config('default', array(
* 'engine' => 'Apc', //[required]
* 'duration' => 3600, //[optional]
* 'probability' => 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*
* Xcache (http://xcache.lighttpd.net/)
*
* Cache::config('default', array(
* 'engine' => 'Xcache', //[required]
* 'duration' => 3600, //[optional]
* 'probability' => 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'user' => 'user', //user from xcache.admin.user settings
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* ));
*
* Memcached (http://www.danga.com/memcached/)
*
* Uses the memcached extension. See http://php.net/memcached
*
* Cache::config('default', array(
* 'engine' => 'Memcached', //[required]
* 'duration' => 3600, //[optional]
* 'probability' => 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'servers' => array(
* '127.0.0.1:11211' // localhost, default port 11211
* ), //[optional]
* 'persistent' => 'my_connection', // [optional] The name of the persistent connection.
* 'compress' => false, // [optional] compress data in Memcached (slower, but uses less memory)
* ));
*
* Wincache (http://php.net/wincache)
*
* Cache::config('default', array(
* 'engine' => 'Wincache', //[required]
* 'duration' => 3600, //[optional]
* 'probability' => 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*/
/**
* Configure the cache handlers that CakePHP will use for internal
* metadata like class maps, and model schema.
*
* By default File is used, but for improved performance you should use APC.
*
* Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
* Please check the comments in bootstrap.php for more info on the cache engines available
* and their settings.
*/
$engine = 'File';
// In development mode, caches should expire quickly.
$duration = '+999 days';
if (Configure::read('debug') > 0) {
$duration = '+10 seconds';
}
// Prefix each application on the same server with a different string, to avoid Memcache and APC conflicts.
$prefix = 'myapp_';
/**
* Configure the cache used for general framework caching. Path information,
* object listings, and translation cache files are stored with this configuration.
*/
Cache::config('_cake_core_', array(
'engine' => $engine,
'prefix' => $prefix . 'cake_core_',
'path' => CACHE . 'persistent' . DS,
'serialize' => ($engine === 'File'),
'duration' => $duration
));
/**
* Configure the cache for model and datasource caches. This cache configuration
* is used to store schema descriptions, and table listings in connections.
*/
Cache::config('_cake_model_', array(
'engine' => $engine,
'prefix' => $prefix . 'cake_model_',
'path' => CACHE . 'models' . DS,
'serialize' => ($engine === 'File'),
'duration' => $duration
));

101
app/Config/database.php Normal file
View File

@@ -0,0 +1,101 @@
<?php
/**
*
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Database configuration class.
*
* You can specify multiple configurations for production, development and testing.
*
* datasource => The name of a supported datasource; valid options are as follows:
* Database/Mysql - MySQL 4 & 5,
* Database/Sqlite - SQLite (PHP5 only),
* Database/Postgres - PostgreSQL 7 and higher,
* Database/Sqlserver - Microsoft SQL Server 2005 and higher
*
* You can add custom database datasources (or override existing datasources) by adding the
* appropriate file to app/Model/Datasource/Database. Datasources should be named 'MyDatasource.php',
*
*
* persistent => true / false
* Determines whether or not the database should use a persistent connection
*
* host =>
* the host you connect to the database. To add a socket or port number, use 'port' => #
*
* prefix =>
* Uses the given prefix for all the tables in this database. This setting can be overridden
* on a per-table basis with the Model::$tablePrefix property.
*
* schema =>
* For Postgres/Sqlserver specifies which schema you would like to use the tables in.
* Postgres defaults to 'public'. For Sqlserver, it defaults to empty and use
* the connected user's default schema (typically 'dbo').
*
* encoding =>
* For MySQL, Postgres specifies the character encoding to use when connecting to the
* database. Uses database default not specified.
*
* unix_socket =>
* For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port`
*
* settings =>
* Array of key/value pairs, on connection it executes SET statements for each pair
* For MySQL : http://dev.mysql.com/doc/refman/5.6/en/set-statement.html
* For Postgres : http://www.postgresql.org/docs/9.2/static/sql-set.html
* For Sql Server : http://msdn.microsoft.com/en-us/library/ms190356.aspx
*
* flags =>
* A key/value array of driver specific connection options.
*/
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => APP_DB_HOST,
'login' => APP_DB_USERNAME,
'password' => APP_DB_PASSWORD,
'database' => APP_DB_NAME,
'prefix' => '',
'encoding' => 'utf8',
);
public $archieve = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => APP_DB_HOST,
'login' => APP_DB_USERNAME,
'password' => APP_DB_PASSWORD,
'database' => ARCHIEVE_DB_NAME,
'prefix' => '',
'encoding' => 'utf8',
);
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'root',
'password' => '',
'database' => 'test_database_name',
'prefix' => '',
'encoding' => 'utf8',
);
}

View File

@@ -0,0 +1,94 @@
<?php
/**
*
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* This is email configuration file.
*
* Use it to configure email transports of CakePHP.
*
* Email configuration class.
* You can specify multiple configurations for production, development and testing.
*
* transport => The name of a supported transport; valid options are as follows:
* Mail - Send using PHP mail function
* Smtp - Send using SMTP
* Debug - Do not send the email, just return the result
*
* You can add custom transports (or override existing transports) by adding the
* appropriate file to app/Network/Email. Transports should be named 'YourTransport.php',
* where 'Your' is the name of the transport.
*
* from =>
* The origin email. See CakeEmail::from() about the valid values
*
*/
class EmailConfig {
public $default = array(
'transport' => 'Mail',
'from' => 'you@localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);
public $smtp = array(
'transport' => 'Smtp',
'from' => array('site@localhost' => 'My Site'),
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => 'user',
'password' => 'secret',
'client' => null,
'log' => false,
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);
public $fast = array(
'from' => 'you@localhost',
'sender' => null,
'to' => null,
'cc' => null,
'bcc' => null,
'replyTo' => null,
'readReceipt' => null,
'returnPath' => null,
'messageId' => true,
'subject' => null,
'message' => null,
'headers' => null,
'viewRender' => null,
'template' => false,
'layout' => false,
'viewVars' => null,
'attachments' => null,
'emailFormat' => null,
'transport' => 'Smtp',
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => 'user',
'password' => 'secret',
'client' => null,
'log' => true,
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);
}

95
app/Config/routes.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
/**
* Routes configuration
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different URLs to chosen controllers and their actions (functions).
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Here, we are connecting '/' (base path) to controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
* to use (in this case, /app/View/Pages/home.ctp)...
*/
//Router::connect('/pages/:action/*', array('controller' => 'pages'));
Router::connect('/', array('controller' => 'Home', 'action' => 'index', 'home'));
//Router::connect('/*', array('controller' => 'Maintenance', 'action' => 'index', 'home'));
Router::connect('/Home/:action/*', array('controller'=>'Home'));
Router::connect('/Expense/:action/*', array('controller'=>'Expense'));
Router::connect('/GroupSetting/:action/*', array('controller'=>'GroupSetting'));
Router::connect('/m/*', array('controller'=>'Mobile'));
Router::connect('/Mobile/:action/*', array('controller'=>'Mobile'));
//Router::connect('/geservicesclient/:action/*', array('controller'=>'GeservicesClient'));
//Router::connect('/Expense/changeGroupExpense', array('controller' => 'Expense', 'action' => 'changeGroupExpense', ''));
//Router::connect('/Expense/changeParticipant', array('controller' => 'Expense', 'action' => 'changeParticipant', ''));
Router::mapResources('geservices');
Router::connect('/geservices/:action/*', array('controller'=>'Geservices'));
Router::connect('/meservices/:action/*', array('controller'=>'Meservices'));
Router::connect('/feservices/:action/*', array('controller'=>'Feservices'));
Router::connect('/users/:action/*', array('controller'=>'Users'));
Router::connect('/products/:action/*', array('controller'=>'Products'));
Router::connect('/filters/:action/*', array('controller'=>'Filters'));
Router::connect('/FBAction/:action/*', array('controller'=>'FBAction'));
Router::connect('/fbapp', array('controller' => 'FBHome', 'action' => 'index', 'home'));
Router::connect('/pages/:action/*', array('controller' => 'pages'));
Router::connect('/emails/:action/*', array('controller' => 'emails'));
Router::connect('/en', array('controller' => 'Home', 'action' => 'changeLanguage','eng'));
Router::connect('/es', array('controller' => 'Home', 'action' => 'changeLanguage','spa'));
Router::connect('/*', array('controller' => 'Expense', 'action' => 'index', ''));
/**
* ...and connect the rest of 'Pages' controller's URLs.
*/
Router::parseExtensions('json');
// Router::connect('/*', array('controller' => 'Home', 'action' => 'loadUniqueURL', 'home'));
/**
* Load all plugin routes. See the CakePlugin documentation on
* how to customize the loading of plugin routes.
*/
CakePlugin::routes();
/**
* Load the CakePHP default routes. Only remove this if you do not want to use
* the built-in default routes.
*/
require CAKE . 'Config' . DS . 'routes.php';

View File

@@ -0,0 +1,33 @@
<?php
/**
* AppShell file
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 2.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Shell', 'Console');
/**
* Application Shell
*
* Add your application-wide methods in the class below, your shells
* will inherit them.
*
* @package app.Console.Command
*/
class AppShell extends Shell {
public function getSystemCurrentTimeStamp(){
date_default_timezone_set("UTC");
return date("Y-m-d H:i:s");
}
}

View File

@@ -0,0 +1,279 @@
<?php
/**
* @property NotificationComponent $Notification
*/
class BackupShell extends AppShell
{
public $unique_url;
public $uses = array('AccessInfo','ExpiredRecord');
public function main() {
}
/*
* command: Console/cake Backup generateAccessInfo
* Run it only once to generate accessinfo for records before 25 february 2018
*/
public function generateAccessInfo(){
$backup_mode = Configure::read('expensecount.backup.mode');
$db = ConnectionManager::getDataSource('default');
$limit = 100;
if($backup_mode){
//retrieve all expense which is not exist in Access Info and update date before 4 months
// create access info records for those expenses; id=>expense_id, unique_url=>unique_url, access_time=>created_date
$range = date('Y-m-d', strtotime("25 February, 2018"));
$expense_counts = $db->query("SELECT id, unique_url, create_date FROM `expenses` WHERE id not in(select id from access_infos) and `create_date` < '$range'");
foreach ($expense_counts as $key=>$value) {
$expense_id = $value['expenses']['id'];
$unique_url = $value['expenses']['unique_url'];
// $access_time = $value['expenses']['create_date'];
$access_time = date('Y-m-d H:i:s', $value['expenses']['update_date']);
$db->query("insert into access_infos(id, unique_url, access_time) values(".$expense_id.",'".$unique_url."','".$access_time."')");
}
}
exit;
//insert multiple record into the table Expired_Records
//check the case whether the record insertion successful or not for multi insertion when pk already exist
}
/*
* command: Console/cake Backup shiftExpiredRecords
* Run it in every hours once
* This method generates records into the table expired_records and delete all records fron access info
*/
public function shiftExpiredRecords(){
$backup_mode = Configure::read('expensecount.backup.mode');
$month = isset($this->args[0]) ? (int)$this->args[0] : 4; // default 4 months
$type = isset($this->args[1]) ? (int)$this->args[1] : 1; // default 1. 1 = Months, 2 = Days; Type will always be 1 because no value is passed for this parameter.
if ($month <= 0) {
echo('Month must be a positive number');
exit;
}
if($backup_mode){
//retrieve all expried records
$result = $this->AccessInfo->getExpiredExpenses($month,$type);
if(!empty($result)){
$currentDate = $this->getSystemCurrentTimeStamp();
foreach($result as $key=>$value){
$deleteList[] = $value["AccessInfo"]["id"];
$data["ExpiredRecord"][$key]["id"] = $value["AccessInfo"]["id"];
$data["ExpiredRecord"][$key]["unique_url"] = $value["AccessInfo"]["unique_url"];
$data["ExpiredRecord"][$key]["inserted_on"] = $currentDate;
}
$error = $this->ExpiredRecord->saveAllExpiredRecords($data);
if(empty($error)){
//delete all records from AccessInfo table
$this->AccessInfo->deleteAllExpiredExpenses($deleteList);
}
}
}
exit;
//insert multiple record into the table Expired_Records
//check the case whether the record insertion successful or not for multi insertion when pk already exist
}
/*
* command: Console/cake Backup initiateBackup 100
* Run it in every six hours once
* This method scan expire_records table and shift records to backup tables;
* After taking backup, it delete records from expire_records table.
*/
public function initiateBackup($limit = BACKUP_LIMIT){
$limit = isset($this->args[0]) ? (int)$this->args[0] : BACKUP_LIMIT;
$this->backupAndRemoveOriginalRecords($limit);
}
/*
* Command : Console/cake Backup backupSingleExpense 1ILcOUb0fe3JpgB
* This method shifts and backup single expense from live tables to backup tables in the production database.
*/
public function backupSingleExpense($unique_url=null)
{
$unique_url = isset($this->args[0]) ? $this->args[0] : null;
$db = ConnectionManager::getDataSource('default');
try {
$backup_expense = $db->query("select * from backup_expenses where unique_url='".$unique_url."'");
} catch (Exception $ex) {
}
if (empty($backup_expense)) {
$expense = $db->query("select * from expenses where unique_url= '".$unique_url."'");
if(!empty($expense)) {
$this->loadModel('Backup');
$this->Backup->processBackupAndRemove($expense);
} else {
echo "Expense is not found in production database. Could not perform backup!";
exit;
}
} else {
echo "Expense is already in backup database. Could not perform backup!";
exit;
}
}
/*
* command: Console/cake Backup archieveSingleItem 1ILcOUb0fe3JpgB
* Run it to archieve a sinle expense
*
* This method shifts one single expense from backup tables(live db) to archieve database
*
*/
public function archieveSingleItem($unique_url=null)
{
$unique_url = isset($this->args[0]) ? $this->args[0] : null;
$this->loadModel('Backup');
$this->Backup->archieveSingleExpense($unique_url);
}
/*
* command: Console/cake Backup initiateArchive 10 100
* Run it to archive records older than custom month, with a row limit.
* e.g. 10 months before from the current date and 100 records
*/
public function initiateArchive($month = 50, $limit = BACKUP_LIMIT){
$month = isset($this->args[0]) ? (int)$this->args[0] : 50;
$limit = isset($this->args[1]) ? (int)$this->args[1] : BACKUP_LIMIT;
$this->archiveAndRemoveOriginalRecords($limit,$month);
}
/*
* command: Console/cake Backup initiateRemoveArchive 10 100
* Run it to remove archived records older than custom month, with a row limit.
* e.g. 10 months before from the current date and 100 records
*/
public function initiateRemoveArchive($month = 50, $limit = BACKUP_LIMIT){
$month = isset($this->args[0]) ? (int)$this->args[0] : 50;
$limit = isset($this->args[1]) ? (int)$this->args[1] : BACKUP_LIMIT;
$this->removeArchiveRecords($limit,$month);
}
private function backupAndRemoveOriginalRecords($limit = BACKUP_LIMIT){
$backup_mode = Configure::read('expensecount.backup.mode');
if($backup_mode){
//retrieve 100 records from the table expired_records
$query = "select id,unique_url from expired_records limit 0,".$limit;
$db = ConnectionManager::getDataSource('default');
$expiredRecordList = $db->query($query);
$db->begin();
try {
if (!empty($expiredRecordList)) {
$this->loadModel('Backup');
$this->Backup->processBackupAndRemove($expiredRecordList, true);
$db->commit();
}
}catch (Exception $ex) {
$db->rollback();
$message = "Backup process failed. Rolled back. Error: " . $ex->getMessage();
$this->emailSend($message,"Backup process failed");
echo $message;
}
}
exit;
}
private function archiveAndRemoveOriginalRecords($limit = BACKUP_LIMIT, $month = 36){
$month = (int)$month;
if ($month <= 0) {
echo('Month must be a positive number');
exit;
}
$backup_mode = Configure::read('expensecount.backup.mode');
$db = ConnectionManager::getDataSource('default');
$before_date = (new DateTime())
->modify("-{$month} months")
->format('Y-m-d');
$range = strtotime($before_date);
if($backup_mode){
//retrieve records from the table back_expenses
$query = "SELECT id, unique_url
FROM backup_expenses WHERE update_date <= $range
LIMIT $limit";
$backupRecordList = $db->query($query);
if(!empty($backupRecordList)){
$this->loadModel('Backup');
$this->Backup->processArchiveAndRemove($backupRecordList,true);
}
}
exit;
}
private function removeArchiveRecords($limit = BACKUP_LIMIT, $month = 36){
$month = (int)$month;
if ($month <= 0) {
echo('Month must be a positive number');
exit;
}
$backup_mode = Configure::read('expensecount.backup.mode');
$before_date = (new DateTime())
->modify("-{$month} months")
->format('Y-m-d');
$range = strtotime($before_date);
$db = ConnectionManager::getDataSource('archieve');
if ($backup_mode) {
//retrieve records from the table expenses
$query = "SELECT id, unique_url
FROM expenses WHERE update_date <= $range
LIMIT $limit";
$archiveRecordList = $db->query($query);
if (!empty($archiveRecordList)) {
$this->loadModel('Backup');
$this->Backup->processRemoveArchive($archiveRecordList, true);
}
}
}
private function emailSend($message = null, $subject = null)
{
App::uses('ComponentCollection', 'Controller');
App::uses('NotificationComponent', 'Controller/Component');
$this->Notification = new NotificationComponent(new ComponentCollection());
$this->Notification->sendEmail(array(
"email_from" => SUPPORT_EMAIL,
"email_to" => REPORTING_EMAIL,
"title" => $message,
"template" => "backup_archive_process_error",
"subject" => $subject,
));
}
}
?>

View File

@@ -0,0 +1,33 @@
<?php
class RestoreShell extends AppShell
{
public $uses = array('AccessInfo', 'ExpiredRecord', 'Expense', 'ExpenseEmail', 'GroupExpense',
'Participant', 'Meal', 'FamilyExpense', 'Log', 'GroupSetting', 'PermissionTable');
public function main()
{
//
}
/*
* Command: Console/cake Restore restoreSingleExpense
* For restoring a single item
*
* This methods first tries to restore single expense from backup tables to live tables. If there
* is no such expense in backup table, it tries to restore from archieve database to live database.
* If the expense is already exist in live tables, it does not do anything.
*
*
*/
public function restoreSingleExpense()
{
$unique_url = "2ruQCFbb";
$this->loadModel("Backup");
$this->Backup->restore($unique_url);
}
}

View File

View File

@@ -0,0 +1,29 @@
Backup Commands
========================
1. command: console\cakce Backup generateAccessInfo
Run it only once to generate accessinfo for records before 25 february 2018
2. command: console\cake Backup shiftExpiredRecords
Run it in every hours once
This method generates records into the table expired_records and delete all records fron access info
3. command: console\cake Backup initiateBackup
Run it in every six hours once
This method scan expire_records table and shift records to backup tables;
After taking backup, it delete records from expire_records table.
4. Command : console\cake Backup backupSingleExpense
This method shifts and backup single expense from live tables to backup tables in the production database.
5. command: console\cake Backup archieveSingleItem
Run it to archieve a sinle expense
This method shifts one single expense from backup tables(live db) to archieve database
Restore Commands
==========================
1. Command: console\cake Restore restoreSingleExpense
For restoring a single item
This methods first tries to restore single expense from backup tables to live tables. If there
is no such expense in backup table, it tries to restore from archieve database to live database.
If the expense is already exist in live tables, it does not do anything.

View File

@@ -0,0 +1,75 @@
/*
List of Archive Commands
* Command:
* php app\Console\cake.php Backup initiateArchive <months> <limit>
*
* Description:
=======================================================
1. Get data from the "backup_expenses" table in the current database.
2. Save the data to the "expenses" table in the archive database(another database).
Steps
======
1. Go to Project Folder
2. Run the command like
In Widows:
C:\xampp_php7\htdocs\expensecount> C:\xampp_php7\php\php.exe app\Console\cake.php Backup initiateArchive 50 100
(project dir)> "PHP executable" "Entry Point CakePHP shells" "Shell Class" "Function" "Months" "Rows"
( it means
1. 50 month before data from current month
2. 100 record at a time
)
*===========================================================
* Parameters:
* <months> Number of months before the current date. Records older than
* this period will be moved to the archive database.
* <limit> Maximum number of records to archive in a single execution.
*
* Example:
* Console/cake Backup initiateArchive 100 100
*
* This command archives up to 100 records that are older than
* 10 months from the current date.
*
* Usage Notes:
* - Suitable for scheduled execution via cron or manual maintenance tasks.
* - Ensure backup processes are functioning correctly before execution.
*/
/*
Single Archive Commands
* Command:
* php app\Console\cake.php Backup archieveSingleItem <unique_url>
*
* Description:
===================
1. Get data from the "backup_expenses" table by unique_url in the current database.
2. Save the data to the "expenses" table in the archive database(another database).
Steps
======
1. Go to Project Folder
2. Run the command like
In Widows:
C:\xampp_php7\htdocs\expensecount> C:\xampp_php7\php\php.exe app\Console\cake.php Backup archieveSingleItem 1ILcOUb0fe3JpgB
(project dir)> "PHP executable" "Entry Point CakePHP shells" "Shell Class" "Function" "unique_url"
( it means
1. Archive data by unique_url 1ILcOUb0fe3JpgB
)
*
* Parameters:
* <unique_url> The unique identifier of the expense to be archived.
*
* Usage:
* Run this command to archive one specific expense on demand.
* Example:
* php app\Console\cake.php Backup archieveSingleItem 1ILcOUb0fe3JpgB
*
* Purpose:
* - Supports manual or targeted archival of individual expense records.
* - Helps keep backup and live databases lightweight.
*
* Notes:
* - Ensure the expense exists in the backup tables before running the command.
*/

View File

@@ -0,0 +1,36 @@
/*
* Command:
* php app\Console\cake.php Backup initiateRemoveArchive <months> <limit>
*
* Description:
=======================================================
1. Get the data to the "expenses" table in the archive database.
2. Removed from respective tables in archive tables
Steps
======
1. Go to Project Folder
2. Run the command like
In Widows:
C:\xampp_php7\htdocs\expensecount> C:\xampp_php7\php\php.exe app\Console\cake.php Backup initiateRemoveArchive 50 100
(project dir)> "PHP executable" "Entry Point CakePHP shells" "Shell Class" "Function" "Months" "Rows"
( it means
1. 50 month before data from current month
2. 100 record at a time
)
*===========================================================
*
* Parameters:
* <months> Number of months before the current date. Records older than
* this period will be permanently removed.
* <limit> Maximum number of records to remove in a single execution.
*
* Example:
* php app\Console\cake.php Backup initiateRemoveArchive 10 100
*
* This command deletes up to 100 archived records that are older than
* 10 months from the current date.
*
* Usage Notes:
* - Intended to be run via cron or manually as part of archive maintenance.
*/

View File

@@ -0,0 +1,106 @@
/*
Generate Access Info
* Command:
* Console/cake Backup generateAccessInfo
*
* Description:
* Generates access information for expense records created before
* 25 February 2018. This prepares historical records for further
* backup and archival processing.
*
* Execution Frequency:
* Run **only once**.
*
* Purpose:
* - Prepares old expense records for backup and archival.
* - Ensures access information is available for subsequent backup commands.
*
* Usage Notes:
* - Intended for one-time execution during initial setup.
* - Verify database connectivity before running the command.
*/
/*
Shift Expired Records
* Command:
* Console/cake Backup shiftExpiredRecords <month>
*
* Description:
* Identifies expired records and moves them into the `expired_records` table.
* After shifting, all corresponding records are deleted from the `access_info` table.
*
* Execution Frequency:
* Recommended to run once every hour.
*
* Purpose:
* - Prepares expired records for backup processing.
* - Keeps the `access_info` table clean and up-to-date.
*
* Usage:
* Run this command to backup a specific expense on demand.
* Example:
* Console/cake Backup shiftExpiredRecords 4
* Usage Notes:
* - Suitable for scheduled execution via cron.
* - Ensure database connectivity before running this command.
*/
/*
Bulk Expense Backup
* Command:
* Console/cake Backup initiateBackup <limit>
*
* Description:
* Scans the `expired_records` table and moves the records into the backup tables.
* After successfully taking the backup, the records are deleted from the `expired_records` table.
*
* Execution Frequency:
* Recommended to run once every six hours.
*
* Purpose:
* - Transfers expired records from live tables to backup tables.
* - Keeps the `expired_records` table from growing indefinitely.
*
* Usage:
* Run this command to backup a specific expense on demand.
* Example:
* Console/cake Backup initiateBackup 100
*
* Usage Notes:
* - Suitable for scheduled execution via cron.
* - Ensure database backups are functioning correctly before running this command.
* - Recommended to run during low-traffic periods to minimize load.
*/
/*
Single Expense Backup
* Command:
* Console/cake Backup backupSingleExpense <unique_url>
*
* Description:
* Backs up a single expense record from the live tables to the backup tables
* in the production database. This is useful for manually backing up
* individual records without running bulk backup operations.
*
* Parameters:
* <unique_url> The unique identifier of the expense to be backed up.
*
* Usage:
* Run this command to backup a specific expense on demand.
* Example:
* Console/cake Backup backupSingleExpense 1ILcOUb0fe3JpgB
*
* Purpose:
* - Supports targeted backup of individual expense records.
* - Helps ensure important records are safely copied to backup tables.
*
* Notes:
* - Ensure the record exists in the live tables before running the command.
*/

View File

41
app/Console/cake Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
################################################################################
#
# Bake is a shell script for running CakePHP bake script
#
# CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
# Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
#
# Licensed under The MIT License
# For full copyright and license information, please see the LICENSE.txt
# Redistributions of files must retain the above copyright notice.
#
# @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
# @link http://cakephp.org CakePHP(tm) Project
# @package app.Console
# @since CakePHP(tm) v 1.2.0.5012
# @license http://www.opensource.org/licenses/mit-license.php MIT License
#
################################################################################
# Canonicalize by following every symlink of the given name recursively
canonicalize() {
NAME="$1"
if [ -f "$NAME" ]
then
DIR=$(dirname -- "$NAME")
NAME=$(cd -P "$DIR" && pwd -P)/$(basename -- "$NAME")
fi
while [ -h "$NAME" ]; do
DIR=$(dirname -- "$NAME")
SYM=$(readlink "$NAME")
NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
done
echo "$NAME"
}
CONSOLE=$(dirname -- "$(canonicalize "$0")")
APP=$(dirname "$CONSOLE")
exec php -q "$CONSOLE"/cake.php -working "$APP" "$@"
exit

31
app/Console/cake.bat Normal file
View File

@@ -0,0 +1,31 @@
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Bake is a shell script for running CakePHP bake script
::
:: CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
:: Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
::
:: Licensed under The MIT License
:: Redistributions of files must retain the above copyright notice.
::
:: @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
:: @link http://cakephp.org CakePHP(tm) Project
:: @package app.Console
:: @since CakePHP(tm) v 2.0
:: @license http://www.opensource.org/licenses/mit-license.php MIT License
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: In order for this script to work as intended, the cake\console\ folder must be in your PATH
@echo.
@echo off
SET app=%0
SET lib=%~dp0
php -q "%lib%cake.php" -working "%CD% " %*
echo.
exit /B %ERRORLEVEL%

47
app/Console/cake.php Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/php -q
<?php
/**
* Command-line code generation utility to automate programmer chores.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Console
* @since CakePHP(tm) v 2.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
$dispatcher = 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php';
if (function_exists('ini_set')) {
$root = dirname(dirname(dirname(__FILE__)));
$appDir = basename(dirname(dirname(__FILE__)));
$install = $root . DS . 'lib';
$composerInstall = $root . DS . $appDir . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib';
// the following lines differ from its sibling
// /lib/Cake/Console/Templates/skel/Console/cake.php
if (file_exists($composerInstall . DS . $dispatcher)) {
$install = $composerInstall;
}
ini_set('include_path', $install . PATH_SEPARATOR . ini_get('include_path'));
unset($root, $appDir, $install, $composerInstall);
}
if (!include $dispatcher) {
trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($dispatcher);
return ShellDispatcher::run($argv);

View File

@@ -0,0 +1,673 @@
<?php
/**
* Application level Controller
*
* This file is application-wide controller file. You can put all
* application-wide controller-related methods here.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Controller
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Controller', 'Controller');
/**
* Application Controller
*
* Add your application-wide methods in the class below, your controllers
* will inherit them.
*
* @package app.Controller
* @link http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
*/
class AppController extends Controller {
public $firebase;
public $components = array('Session','Cookie');
//platform= 1/2/3; 1=iOS,2=Android,3=Windows
public $operation_type = array('ADD'=>1,'EDIT'=>2,'DELETE'=>3);
public function beforeFilter() {
//This line will be implemented where I will change language.
//$this->Session->write('Config.language', 'fra');
$this->firebase = '';
if ($this->Session->check('Config.language')) {
//echo "cuurent_session";exit;
$lang = $this->Session->read('Config.language');
if($lang != Configure::read('Config.language')){
Configure::write('Config.language', $this->Session->read('Config.language'));
}
} else if($this->Cookie->check('Config.expcount.language')){
//echo "cuurent_cookie";exit;
$language = $this->Cookie->read('Config.expcount.language');
$this->Session->write("Config.language",$language);
Configure::write('Config.language',$language);
}
$this->set("current_lang",Configure::read('Config.language'));
}
public function getClientIp(){
$ipaddress = '';
if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_X_FORWARDED']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_FORWARDED']))
$ipaddress = $_SERVER['HTTP_FORWARDED'];
else if(isset($_SERVER['REMOTE_ADDR']))
$ipaddress = $_SERVER['REMOTE_ADDR'];
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
public function getUserAgent(){
$maxlength = 80;
$userAgent = (isset($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : '';
if(strlen($userAgent) < 80){
$maxlength = strlen($userAgent);
}
return substr($userAgent, 0, $maxlength);;
}
public function objectToArray($d) {
if (is_object($d))
$d = get_object_vars($d);
return is_array($d) ? array_map(__METHOD__, $d) : $d;
}
public function getSystemCurrentIntTime(){
date_default_timezone_set("UTC");
return time();
}
public function getSystemCurrentTimeStamp(){
date_default_timezone_set("UTC");
return date("Y-m-d H:i:s");
}
public function setDefaultTimeStamp(){
date_default_timezone_set("UTC");
}
public function getIntToStrDate($intDate){
return date("d-M-Y",$intDate);
}
public function isValidNewExpenseDate($newExpenseDate){
$result = true;
$newExpenseDateArray = explode('-', $newExpenseDate);
if(count($newExpenseDateArray) != 3){
$result = false;
} else {
$month = strtolower($newExpenseDateArray[1]);
$monthArray = array("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
if(!in_array($month,$monthArray)){
$result = false;
}
}
return $result;
}
public function getStrToIntDate($strDate){
list($day, $month, $year) = explode('-', $strDate);
$month = strtolower($month);
if($month == "jan"){
$month = "01";
} else if($month == "feb"){
$month = "02";
} else if($month == "mar"){
$month = "03";
} else if($month == "apr"){
$month = "04";
} else if($month == "may"){
$month = "05";
} else if($month == "jun"){
$month = "06";
} else if($month == "jul"){
$month = "07";
} else if($month == "aug"){
$month = "08";
} else if($month == "sep"){
$month = "09";
} else if($month == "oct"){
$month = "10";
} else if($month == "nov"){
$month = "11";
} else if($month == "dec"){
$month = "12";
}
return (string)mktime(0, 0, 0, $month, $day, $year);
}
public function getExpenseCreationDate($intDate){
$intDateArray = explode("-",$intDate);
if(count($intDateArray)>1){
return $intDate;
} else {
return date("Y-m-d H:i:s", $intDate);
}
}
public function getExpenseCreationStrToIntDate($strDate){
$strDateArray = explode(" ",$strDate);
list($year, $month, $day) = explode('-', $strDateArray[0]);
list($hour, $min, $sec) = explode(':', $strDateArray[1]);
return mktime($hour, $min, $sec, $month, $day, $year);
}
public function isValidExpenseUniqueURL($unique_url, $firstValue){
if( substr($unique_url, 0, 1) == $firstValue)
return true;
else
return false;
}
public function isValidToken($access_token, $device_id, $random_number){
$unique_number = $device_id.$random_number; // device id + six digit random number
$salt = 'Nop@ss%!*-+@s=_17';
$generated_token = hash('sha256', $unique_number . $salt);
if($access_token == $generated_token){
return true;
} else {
return false;
}
}
public function getUserToken($device_id, $random_number){
$unique_number = $device_id.$random_number; // device id + six digit random number
$salt = 'Nop@ss%!*-+@s=_17';
return hash('sha256', $unique_number . $salt);
}
public function getResetPasswordToken($device_id, $random_number, $email){
$unique_number = $device_id.$random_number.$email; // device id + six digit random number + email
$salt = 'Nomatter%!*-+@s=_17';
return hash('sha256', $unique_number . $salt);
}
public function isItemAlreadyAdded($dbExpenseList,$currentItemUniqueId){
$result = false;
if(!empty($dbExpenseList) && !empty($currentItemUniqueId)){
foreach($dbExpenseList as $key=>$value){
if(!empty($value["syn_add_unique_id"]) && $value["syn_add_unique_id"] == $currentItemUniqueId){
$result = true;
break;
}
}
}
return $result;
}
public function getSource($detect){
$source = 2;
if ($detect->isAndroid()) {
$source = 4;
} else if($detect->isIphone()){
$source = 5;
} else if($detect->isWindows()){
$source = 6;
}
return $source;
}
public function getCaptchaResponse($captcha)
{
// echo RECAPTCH_SECRET_KEY;exit;
$secretKey = RECAPTCH_SECRET_KEY;
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secretKey.'&response='.$captcha);
$responseData = json_decode($verifyResponse);
return $responseData;
}
public function setDefaultWhat($expenseList){
$result = array();
if(!empty($expenseList)) {
foreach($expenseList as $key=>$value ) {
if(isset($value["what"]))
$value["what"] = trim($value["what"]);
if(isset($value["what"]) && empty($value["what"])) {
$value["what"] = "N/A";
}
$result[$key] = $value;
}
}
return $result;
}
public function updateFirebase($unique_url)
{
require_once "../../lib/firebase/vendor/autoload.php";
// $startime = time();
$expense_type = substr($unique_url, 0 , 1);
$expense_name = '';
if($expense_type == 1) {
$expense_name = "GroupExpense";
} elseif ($expense_type == 2) {
$expense_name = "MessExpense";
} elseif ($expense_type == 3) {
$expense_name = "FamilyExpense";
}
$db_dir = $expense_name.'/'.$unique_url;
$serviceAccount = \Kreait\Firebase\ServiceAccount::fromJsonFile('../../go_ser_pri.json');
$firebase = (new \Kreait\Firebase\Factory())
->withServiceAccount($serviceAccount)
->create();
$database = $firebase->getDatabase();
$newPost = $database
->getReference(FIREBASE_DB_PATH);
$current_row = $newPost->getChild($db_dir.'/ver'); //FamilyExpense/3Po9rHbzvdZO0n4
$current_ver = $current_row->getValue();
$update_ver = $current_ver + 1;
$current_row->set($update_ver);
//$time_diff = time() - $startime;
// echo "time : ".$time_diff."<br>";
}
public function processValidation($method = 'POST')
{
$status = "-1";
$status_desc = "FAILED";
$error = "";
$secretKey = "";
$data = array();
if($method == 'GET') {
$object = $this->request->query;
} else{
$object = $this->request->input('json_decode');
}
if (!empty($object)) {
$data = $this->objectToArray($object);
}
//check maintenance mood
if (MAINTENANCE_MOOD) {
$status = "035";
$status_desc = "Service is in maintenance mood. Please try again later.";
$error = $status;
} else if (empty($data)) {
$status = "031";
$status_desc = "Invalid JSON input sent";
} else {
if ($status == "-1") {
if (!$this->isValidToken($data["access_token"], $data["device_id"], $data["random_number"])) {
$status = "057"; // token is not valid
$status_desc = "TOKEN IS NOT VALID. Please provide access_token, device_id and random_number ";
} else {
$status = "";
$status_desc = "PASS";
}
}
}
return array($data, $status, $status_desc, $error);
}
public function apiLogAppCrashData($data, $status, $status_desc)
{
$this->loadModel('LogAppCrashes');
$crash["unique_url"] = "";
$crash["error_code"] = $status;
$crash["error_desc"] = $status_desc;
$crash["request"] = serialize($data);
$crash["response"] = ""; //serialize($latestExpenseData);
$crash["crash_date"] = $this->getSystemCurrentTimeStamp();
$crash["ip"] = $this->getClientIp();
$crash["device_info"] = $this->getUserAgent();
$this->LogAppCrashes->insertLogAppCrashes($crash);
}
public function processResponse($error, $data, $status, $status_desc)
{
$input["status"] = $status;
$input["status_desc"] = $status_desc;
if (!empty($error) || $status != "+000") {
$input["input"] = $data;
$input['error'] = $error;
$this->apiLogAppCrashData($data, $status, $status_desc);
}
$this->set(array(
'response' => $input,
'_serialize' => array('response')
));
}
public function isExistFirebaseUser($user_id)
{
$result = false;
$firebaseUser = array();
$this->initializeFirebase();
$firebaseUser = $this->firebase->getAuth()->getUser($user_id);
if(!empty($firebaseUser)){
$result = true;
}
return array($result,$firebaseUser);
}
public function validateUser($user_id) {
//check validity
$error = "";
$error_desc = "";
$userObj = array();
$this->loadModel('User');
list($result, $userObj) = $this->User->isExistUserById($user_id);
if(IS_FIREBASE_ACTIVATED){
if(!$result){
list($result, $userObj) = $this->isExistFirebaseUser($user_id);
}
}
if(!$result){
$error = "-997";
$error_desc = "User not exist!";
}
return array($error, $error_desc, $userObj);
}
public function validateUniqueUrl($url) {
//check validity
$error = "";
$error_desc = "";
$expObj = array();
if (empty($error)) {
$this->loadModel('Expense');
$expInfo = $this->Expense->findByUniqueUrl($url);
if(!$expInfo){
$error = "-997";
$error_desc = "Unique_url not exist!";
}
}
return array($error, $error_desc,$expObj);
}
public function systemGeneratedUniqueId($user_id,$expense_type)
{
return $expense_type.'-'.$user_id.'-'.time().'-'.rand(1000,9999);
}
public function isValidUserProfile($profile_id, $profile_type)
{
$this->loadModel('User');
return $this->User->isUserExistByProfile( $profile_id, $profile_type);
}
public function addUserGroupDuringExpenseCreate($user_id, $unique_url, $expense_type)
{
$result = array();
$status = '';
$status_desc = '';
$newUserGroup = array();
$this->loadModel('UserGroup');
$this->loadModel('User');
$userObj = $this->User->getUserByUserId($user_id);
if(sizeof($userObj)) {
$existUserGroup = $this->UserGroup->isExistUserGroup($user_id, $unique_url);
if(empty($existUserGroup[0])) {
$inputData['user_id'] = $user_id;
$inputData['unique_url'] = $unique_url;
$inputData['participant_id'] = '1_0';
$result[] = $this->UserGroup->add($inputData);
} else {
$status = "12";
$status_desc = "UserGroup is Exist";
}
// increment the version in firebase
$this->userGroupUpdateOnFirebase($user_id, $expense_type);
} else {
$status = "13";
$status_desc = "User is invalid";
}
return array($status, $status_desc, $result);
}
public function isForceUpgradeRequire($version_recceived, $version_expected) {
return intval($version_recceived) < intval($version_expected);
}
public function initializeFirebase() {
require_once "../../lib/firebase/vendor/autoload.php";
$serviceAccount = \Kreait\Firebase\ServiceAccount::fromJsonFile(FIREBASE_SERVICE_ACCOUNT_CREDENTIALS);
$this->firebase = (new \Kreait\Firebase\Factory())
->withServiceAccount($serviceAccount)
->create();
}
function callAPI($api_url, $request_method = "GET", $post_fields = '') {
if (!empty($api_url)) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $request_method,
CURLOPT_POSTFIELDS => $post_fields,
CURLOPT_HTTPHEADER => array(
"accept: application/json",
"content-type: application/json"
)
));
$response = curl_exec($curl);
$err = curl_error($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpcode == 200) {
return $response;
} else {
return "Something went wrong";
}
}
return false;
}
function callGETAPI($api_url) {
if (!empty($api_url)) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
// CURLOPT_POSTFIELDS => $post_fields,
CURLOPT_HTTPHEADER => array(
"accept: application/json",
"content-type: application/json"
)
));
$response = curl_exec($curl);
$err = curl_error($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpcode == 200) {
return $response;
} else {
return "Something went wrong";
}
}
return false;
}
function deviceData(){
$data["device_id"] = session_id();
$data["random_number"] = rand(1000, 9999);
$data["access_token"] = $this->getUserToken($data["device_id"], $data["random_number"]);
return $data;
}
public function setCookie($data, $unique_url, $UpdateFlag = null){
//set cookie for my expenses
$this->autoRender = false;
$new_cookie = ['title'=>$data['title'],'unique_url'=>$unique_url, 'create_date'=>$data['create_date']];
$prev_cookie[] = $new_cookie;
if($this->Cookie->read('Expenses') != "") {
$prev_cookie = $this->Cookie->read('Expenses');
if($UpdateFlag){
$key = array_search($unique_url, array_column($prev_cookie, 'unique_url'));
$prev_cookie[$key]['title'] = $data['title'];
setcookie("CakeCookie[Expenses]", json_encode($prev_cookie), time() + (86400 * 1000), "/");
}else{
array_push($prev_cookie, $new_cookie);
}
}
if(!$UpdateFlag){
$this->Cookie->write('Expenses', $prev_cookie, false, '24000 hours');
}
}
public function isPaid($uid)
{
$this->loadModel('User');
$user = $this->User->findById($uid);
if (!empty($user) && !empty($user['User']['user_subscription_id'])) {
$this->loadModel('UserSubscription');
$userSub = $this->UserSubscription->findById($user['User']['user_subscription_id']);
$currtDate = strtotime(date('Y-m-d H:i:s'));
$userSubDate = strtotime($userSub['UserSubscription']['valid_to']);
if ($userSubDate >= $currtDate) {
return true;
}
}
return false;
}
public function userGroupUpdateOnFirebase($userId, $expenseType) {
/*
* expensecount-312c7/root/{env}/myProfileUser/{expenseType}/{userId}/ver
* env: prod, dev
* userId: myProfile user_id
* expenseType: GroupExpense, MessExpense, FamilyExpense
*/
require_once "../../lib/firebase/vendor/autoload.php";
$serviceAccount = \Kreait\Firebase\ServiceAccount::fromJsonFile('../../go_ser_pri.json');
$this->firebase = (new \Kreait\Firebase\Factory())
->withServiceAccount($serviceAccount)
->create();
$database = $this->firebase->getDatabase();
$newPost = $database->getReference(FIREBASE_DB_PATH);
$current_row = $newPost->getChild('/myProfileUser/'.$expenseType.'/'.$userId.'/ver');
$current_ver = $current_row->getValue();
if(!isset($current_ver)) {
$update_ver = 1;
} else {
$update_ver = $current_ver + 1;
}
$current_row->set($update_ver);
}
public function validateDeleteParticipant($ParticipantArray){
$error = "";
if(empty($ParticipantArray)){
$error = "8";
}
if($error == ""){
foreach($ParticipantArray as $key=>$value){
if (!array_key_exists('expense_id', $value)||!array_key_exists('id', $value)) {
$error = "9";
break;
}
$idArray[$key] = $value["id"];
}
}
//check id duplicacy
if($error == ""){
$previousLength = count($idArray);
$idArray = array_unique($idArray);
if($previousLength != count($idArray)){
$error = "10";
}
}
return $error;
}
}

View File

@@ -0,0 +1,170 @@
<?php
/*
CaptchaComponent
*/
App::uses('Component', 'Controller');
class CaptchaComponent extends Component{
public $settings = array(
'characters' => null,
'winHeight' => 50,
'winWidth' => 320,
'fontSize' => 25,
'fontPath' => 'tahomabd.ttf',
'bgNoise' => false,
'lineNoise' => false,
'bgColor' => '#F58220',
'noiseColor' => '#000',
'textColor' => '#fff',
'noiseLevel' => '45'
);
////////////////////////////////////////////////////////////////////////////////
function __construct($collection, $settings){
$this->Controller = $collection->getController();
}
////////////////////////////////////////////////////////////////////////////////
public function ShowImage($custom = array())
{
$new_settings = array_merge($this->settings, $custom);
$this->settings = $new_settings;
$this -> win();
}
////////////////////////////////////////////////////////////////////////////////
private function win()
{
//background image
$image = imagecreatetruecolor($this->settings['winWidth'], $this->settings['winHeight'])
or die("<b>" . __FILE__ . "</b><br />" . __LINE__ . " :
" ."Cannot Initialize new GD image stream");
$bgColor = $this->hex2rgb($this->settings['bgColor']);
$noiseColor = $this->hex2rgb($this->settings['noiseColor']);
$textColor = $this->hex2rgb($this->settings['textColor']);
$bg = imagecolorallocate($image, $bgColor[0], $bgColor[1], $bgColor[2]);
imagefill($image, 10, 10, $bg);
for ($x=0; $x < $this->settings['noiseLevel']; $x++)
{
for ($y=0; $y < $this->settings['noiseLevel']; $y++)
{
$temp_color = imagecolorallocate($image,$noiseColor[0],$noiseColor[1],$noiseColor[2]);
imagesetpixel( $image, rand(0,$this->settings['winWidth']), rand(0,$this->settings['winHeight']) , $temp_color );
}
}
$char_color = imagecolorallocatealpha($image, $textColor[0], $textColor[1], $textColor[2], 0);
//Font
$font = $this->settings['fontPath'];
$font_size = $this->settings['fontSize'];
////////////////////////////////////
//Image characters
$char = "";
if ( empty($this->settings['characters']) )
{
$this->settings['characters'] = mt_rand(100,10000);
}
$r_x1 = 10; $r_x2 = 20;
$r_y1 = $this->settings['winHeight']/1.8; $r_y2 = $r_y1+10;
$this->settings['characters'] = (string)$this->settings['characters'];
for($i = 0; $i < strlen($this->settings['characters']); $i++ )
{
$char = $this->settings['characters'][$i];
$random_x = mt_rand($r_x1 , $r_x2);
$random_y = mt_rand($r_y1 , $r_y2);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
$r_x1+=40; $r_x2+=40;
}
////////////////////////////////////
if ($this -> settings['bgNoise'])
$image = $this -> apply_wave($image, $this->settings['winWidth'],
$this->settings['winHeight']);
////////////////////////////////////
//lines
if ($this -> settings['lineNoise'])
{
for ($i=0; $i<$this->settings['winWidth']; $i++ )
{
if ($i%10 == 0)
{
imageline ( $image, $i, 0,
$i+10, 50, $char_color );
imageline ( $image, $i, 0,
$i-10, 50, $char_color );
}
}
}
////////////////////////////////////
return imagepng($image);
imagedestroy($image);
}
///////////////////////////////////////////////////////////
private function apply_wave($image, $width, $height)
{
$x_period = 10;
$y_period = 10;
$y_amplitude = 5;
$x_amplitude = 5;
$xp = $x_period*rand(1,3);
$k = rand(0,100);
for ($a = 0; $a<$width; $a++)
imagecopy($image, $image, $a-1, sin($k+$a/$xp)*$x_amplitude,
$a, 0, 1, $height);
$yp = $y_period*rand(1,2);
$k = rand(0,100);
for ($a = 0; $a<$height; $a++)
imagecopy($image, $image, sin($k+$a/$yp)*$y_amplitude,
$a-1, 0, $a, $width, 1);
return $image;
}
private function hex2rgb($hex) {
$hex = str_replace("#", "", $hex);
if(strlen($hex) == 3) {
$r = hexdec(substr($hex,0,1).substr($hex,0,1));
$g = hexdec(substr($hex,1,1).substr($hex,1,1));
$b = hexdec(substr($hex,2,1).substr($hex,2,1));
} else {
$r = hexdec(substr($hex,0,2));
$g = hexdec(substr($hex,2,2));
$b = hexdec(substr($hex,4,2));
}
$rgb = array($r, $g, $b);
//return implode(",", $rgb); // returns the rgb values separated by commas
return $rgb; // returns an array with the rgb values
}
}

View File

@@ -0,0 +1,262 @@
<?php
App::uses('Component', 'Controller');
use GuzzleHttp\Client;
require_once(APP . 'Controller' . DS . 'Traits' . DS . 'ImageUploadTrait.php');
class ImageUploadComponent extends Component
{
use ImageUploadTrait;
private $total_image = NUMBER_OF_EXPENSE_IMAGES ?? 3;
public function AddImageBucket($imagesData, $id, $unique_url, $app_name)
{
$images = null;
$imageCount = count($imagesData);
$imageResponses = [];
if ($imageCount >= 1) {
$imageResponse = null;
$message = "It is not valid format.";
$firebasePath = $this->getRootFolder() . '/' . $app_name . '/' . $unique_url . '/' . $id . '/';
foreach ($imagesData as $key => $image) {
if ($key > ($this->total_image - 1)) {
break;
}
$message = "Image has not been provided.";
if (!empty($image['data'])) {
$base64Image = $image['data'];
$decodedImage = base64_decode($base64Image);
$isImage = $this->checkImageFromBase64EncodedString($base64Image) || $this->checkImageFromBase64DecodedString($decodedImage);
$message = "Image is not valid format.";
if ($isImage) {
$no = $key + 1;
$filename = 'img' . $no . '.jpg';
$result = $this->uploadBase64Image($base64Image, $firebasePath . $filename);
if ($result['status']) {
if ($no == 1) {
$images = $filename;
} else {
$images = $images . ',' . $filename;
}
}
$message = $result['message'];
}
}
$imageResponse["img" . $key] = $message;
}
$imageResponses[$unique_url] = $imageResponse;
}
return ["images" => $images, "response" => $imageResponses];
}
public function DeleteImageBucket($Expanses, $unique_url, $app_name)
{
$deleteResponses = [];
foreach ($Expanses as $item => $Expanse) {
$firebasePath = $this->getRootFolder() . '/' . $app_name . '/' . $unique_url . '/' . $Expanse['id'] . '/';
$response = $this->deleteFolder($firebasePath);
$deleteResponses[$item] = $response['message'];
}
return $deleteResponses;
}
public function DeleteSingleImageBucket($dbimages, $id, $unique_url, $app_name, $deletedimages)
{
$images = explode(',', $dbimages);
$firebasePath = $this->getRootFolder() . '/' . $app_name . '/' . $unique_url . '/' . $id . '/';
$delete_image_responses = null;
$message = "Image not found.";
foreach ($deletedimages as $key => $deletedimage) {
$image_name = $deletedimage['name'];
if (in_array($image_name, $images)) {
$result = $this->singleImageDelete($firebasePath . $image_name);
$images = array_diff($images, array($image_name));
// if image exist in db but not in firebase
if (!$result['status']) {
$images = array_filter($images, function ($item) use ($image_name) {
return $item !== $image_name;
});
}
$message = $result['message'];
}
$delete_image_responses[$image_name] = $message;
}
return ['images' => implode(',', $images), 'response' => $delete_image_responses];
}
public function ModifyImageBucket($dbimages, $id, $unique_url, $app_name, $expanse_images)
{
$images = [];
$imageResponse = null;
if (!empty($dbimages)) {
$images = explode(',', $dbimages);
}
if (!empty($expanse_images)) {
$firebasePath = $this->getRootFolder() . '/' . $app_name . '/' . $unique_url . '/' . $id . '/';
$image_count = count($expanse_images) + count($images);
if ($image_count <= $this->total_image) {
foreach ($expanse_images as $key => $image) {
$message = "Image has not been provided.";
$filename = $this->imageUniqueName($images);
if (!empty($image['data']) && !empty($filename)) {
$base64Image = $image['data'];
$result = $this->uploadBase64Image($base64Image, $firebasePath . $filename);
if ($result['status']) {
array_push($images, $filename);
}
$message = $result['message'];
}
$imageResponse["img" . $key] = $message;
}
}
if ($image_count > $this->total_image) {
$imageResponse['status'] = false;
$imageResponse['message'] = "Should be maximum 3 images. Given {$image_count}";
}
}
return ["images" => implode(',', $images), "response" => $imageResponse];
}
private function checkImageFromBase64EncodedString($base64String)
{
$result = false;
if (preg_match('/^data:(.*?);base64,/', $base64String, $match)) {
$mimeType = $match[1];
if (strpos($mimeType, 'image') !== false) {
$result = true;
}
}
return $result;
}
private function checkImageFromBase64DecodedString($decodedData)
{
$result = false;
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->buffer($decodedData);
if (strpos($mimeType, 'image') !== false) {
$result = true;
}
return $result;
}
private function imageUniqueName($dbImages)
{
$image_name = null;
for ($i = 1; $i <= $this->total_image; $i++) {
$filename = 'img' . $i . '.jpg';
// check image exist or not
if (!in_array($filename, $dbImages)) {
$image_name = $filename;
break;
}
}
return $image_name;
}
public function getRootFolder()
{
if (strpos(HTTP_SITE_URL, "expensecount.com") !== false) {
return "prod";
} elseif (strpos(HTTP_SITE_URL, "localhost") !== false) {
return "local";
}
return "dev";
}
public function ExportImageBucket($unique_url, $app_name)
{
$firebasePath = $this->getRootFolder() . '/' . $app_name . '/' . $unique_url . '/' ;
$expire_time='+2 days';
$expiresAt = new DateTime($expire_time);
$savePath = $this->getRootFolder() . '/' . $app_name . '/zip/'.$expiresAt->format('Y-m-d H:i:s').'/' . $unique_url . '/report.zip' ;
return $this->downloadImage($firebasePath, $expire_time,$savePath);
}
public function ReceiptExportInsideFirebase($unique_url, $app_name) {
$url = 'https://us-central1-expensecount-312c7.cloudfunctions.net/generateGroupZip';
$data = [
"prefix"=> $this->getRootFolder() . '/' . $app_name . '/' ,
"unique_url"=> $unique_url,
"zip_file_prefix" => $this->getRootFolder() . '/' . $app_name . '/zip/'
];
$client = new Client();
try {
$response = $client->post($url, [
'headers' => [
'Content-Type' => 'application/json'
],
'body' => json_encode($data)
]);
$result = json_decode($response->getBody()->getContents(), true);
if(!empty($result['zip_path'])) {
$result['link'] = $this->downloadLink($result['zip_path']);
$result['expire_time'] = new DateTime('+2 days');
}
return $result;
} catch (\Exception $e) {
return ["message"=> "Error: " . $e->getMessage(),"success"=>false];
}
}
}

View File

@@ -0,0 +1,87 @@
<?php
/*
CaptchaComponent
*/
App::uses('Component', 'Controller');
class MobileDetectComponent extends Component{
protected $accept;
protected $userAgent;
protected $isMobile = false;
protected $isAndroid = null;
protected $isBlackberry = null;
protected $isIphone = null;
protected $isIpad = null;
protected $isOpera = null;
protected $isPalm = null;
protected $isWindows = null;
protected $isGeneric = null;
protected $devices = array(
"android" => "android",
"blackberry" => "blackberry",
"iphone" => "(iphone|ipod)",
"ipad" => "ipad",
"opera" => "opera mini",
"palm" => "(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)",
"windows" => "windows ce; (iemobile|ppc|smartphone)",
"generic" => "(kindle|mobile|mmp|midp|o2|pda|pocket|psp|symbian|smartphone|treo|up.browser|up.link|vodafone|wap)"
);
public function __construct() {
$this->userAgent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
$this->accept = isset( $_SERVER['HTTP_ACCEPT'] ) ? $_SERVER['HTTP_ACCEPT'] : '';
if (isset($_SERVER['HTTP_X_WAP_PROFILE'])|| isset($_SERVER['HTTP_PROFILE'])) {
$this->isMobile = true;
} elseif (strpos($this->accept,'text/vnd.wap.wml') > 0 || strpos($this->accept,'application/vnd.wap.xhtml+xml') > 0) {
$this->isMobile = true;
} else {
foreach ($this->devices as $device => $regexp) {
if ($this->isDevice($device)) {
$this->isMobile = true;
}
}
}
}
/**
* Overloads isAndroid() | isBlackberry() | isOpera() | isPalm() | isWindows() | isGeneric() through isDevice()
*
* @param string $name
* @param array $arguments
* @return bool
*/
public function __call($name, $arguments) {
$device = strtolower(substr($name, 2));
if ($name == "is" . ucfirst($device)) {
return $this->isDevice($device);
} else {
trigger_error("Method $name not defined", E_USER_ERROR);
}
}
/**
* Returns true if any type of mobile device detected, including special ones
* @return bool
*/
public function isMobile() {
return $this->isMobile;
}
protected function isDevice($device) {
$var = "is" . ucfirst($device);
$return = $this->$var === null ? (bool) preg_match("/" . $this->devices[$device] . "/i", $this->userAgent) : $this->$var;
if ($device != 'generic' && $return == true) {
$this->isGeneric = false;
}
return $return;
}
}

View File

@@ -0,0 +1,162 @@
<?php
App::uses('Component', 'Controller');
App::uses('CakeEmail', 'Network/Email');
require_once(APP . 'Controller' . DS . 'Traits' . DS . 'ApiCallTrait.php');
use Google\Auth\Credentials\ServiceAccountCredentials;
class NotificationComponent extends Component
{
use ApiCallTrait;
/**
* @var AppModel|bool|mixed|Model|object|string|null
*/
private $PushToken;
public function initialize(Controller $controller)
{
$this->PushToken = ClassRegistry::init('PushToken');
}
public function sendEmail($data) {
$default = array(
'host' => Configure::read('expensecount.email.smtp.host'),
'port' => 587,
'auth' => 'plain',
'username' => Configure::read('expensecount.email.smtp.username'),
'password' => Configure::read('expensecount.email.smtp.password'),
'tsl' => false,
'transport' => 'Smtp',
'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
'returnPath' => Configure::read('expensecount.email.smtp.from'),
'layout' => false,
'emailFormat' => 'html',
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
try {
$Email = new CakeEmail($default);
$Email->to($data["email_to"]);
$Email->emailFormat('html');
$Email->template($data["template"], null)->viewVars(array('data' => $data));
$Email->subject($data["subject"]);
$Email->replyTo($data["email_from"]);
$Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount.com"));
$Email->delivery = 'Smtp';
return $Email->send();
}catch (Exception $e) {
CakeLog::write(LOG_ERR, 'Email sending failed: ' . $e->getMessage());
return $e->getMessage();
}
}
private function getAccessToken()
{
$cacheFile = TMP . 'fcm_token.cache';
if (file_exists($cacheFile)) {
$cached = json_decode(file_get_contents($cacheFile), true);
if (!empty($cached['token']) && $cached['expires_at'] > time()) {
return $cached['token'];
}
}
$scopes = ['https://www.googleapis.com/auth/firebase.messaging'];
$credentials = new ServiceAccountCredentials(
$scopes,
json_decode(file_get_contents(FIREBASE_SECRET), true)
);
$token = $credentials->fetchAuthToken();
if (!isset($token['access_token'])) {
throw new \Exception('Unable to get access token');
}
// Google tokens expire in 3600s; cache for 55 minutes to stay safely within that.
file_put_contents($cacheFile, json_encode([
'token' => $token['access_token'],
'expires_at' => time() + 3300,
]));
return $token['access_token'];
}
public function sendPushNotification($tokens, $message, $async = false)
{
$projectId = FIREBASE_PROJECT_ID;
if (empty($projectId)) {
CakeLog::write(LOG_ERR, 'Push notification: Firebase project_id not configured');
return ['error' => 'Firebase project_id not configured'];
}
$url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";
try {
$accessToken = $this->getAccessToken();
} catch (\Exception $e) {
CakeLog::write(LOG_ERR, 'Push notification: Failed to get access token: ' . $e->getMessage());
return ['error' => 'Failed to get access token: ' . $e->getMessage()];
}
$responses = [];
foreach ($tokens as $key => $token) {
$payload = [
"message" => [
"token" => $token['token'],
"data" => $message,
"apns" => [
"payload" => [
"aps" => [
"alert" => [
"title" => $message['title'],
"body" => $message['body']
],
"sound" => "default",
"badge" => 1,
"mutable-content" => 1,
"content-available" => 1
]
]
]
]
];
$apiResponse = $this->fireAndForget($url, $payload, $accessToken);
$responses[] = ['request' => [$token['user_id'], $token['device_id']], 'response' => $apiResponse];
}
return $responses;
}
public function send($users,$message){
$tokens = array();
if(!empty($users)){
$filter = array('status' => 1,'user_id' => $users);
$db_token = $this->PushToken->getToken($filter);
if(!empty($db_token)) {
foreach ($db_token as $token) {
$tokens[] = ['user_id'=>$token['PushToken']['user_id'],
'device_id'=>$token['PushToken']['device_id'],
'token'=> $token['PushToken']['push_token']];
}
}
if(!empty($tokens)) {
$response = $this->sendPushNotification($tokens, $message, true);
}else{
$response["status"] = "-99";
$response["status_desc"] = "Push Token Not Found!";
$response["input"] = $users;
}
}else{
$response["status"] = "-99";
$response["status_desc"] = "User Not Found!";
$response["input"] = $users;
}
return $response;
}
}

View File

@@ -0,0 +1,44 @@
<?php
App::uses('Component', 'Controller');
class PermissionComponent extends Component
{
/**
* @var AppModel|bool|mixed|Model|object|string|null
*/
private $GroupSetting;
private $PermissionTable;
private $permission = NO_PERMIT;
private $restricted_modes = ['ON' => 1, 'OFF' => 0];
public function initialize(Controller $controller)
{
$this->GroupSetting = ClassRegistry::init('GroupSetting');
$this->PermissionTable = ClassRegistry::init('PermissionTable');
}
public function PermissionByUserId($unique_url, $user_id)
{
$group_setting = $this->GroupSetting->getGroupSettingByURL($unique_url);
if (empty($group_setting)) {
return PUBLIC_PERMIT;
}
$restricted_mode = $group_setting['is_restricted_mode'] ;
if($restricted_mode == $this->restricted_modes['OFF']){
return PUBLIC_PERMIT;
}
if ($restricted_mode == $this->restricted_modes['ON']) {
$user_permission = $this->PermissionTable->getPermissionByUrlAndUserId($unique_url, $user_id);
if (!empty($user_permission['PermissionTable'])) {
$this->permission = $user_permission['PermissionTable']['role'];
}
}
return $this->permission;
}
}

View File

View File

@@ -0,0 +1,237 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;
use Cake\ORM\TableRegistry;
use Cake\Network\Email\Email;
use Aura\Intl\Exception;
/**
* User Management and REST API controller
*
* This controller will be used to send out email to the uses
*
* @link http://book.cakephp.org/3.0/en/controllers/pages-controller.html
*/
class EmailsController extends AppController {
public $uses = array('TempExpenseEmail','ExpenseEmail');
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
}
/**
* This function will be called to login and authenticate user
*
* @param params will be as post request
* @return json response output
* @link http://host/Emails/processRegEmails
*/
public function processRegEmails(){
$this->defineConstant();
$content = "";// $this->readFileContent();
try{
if($content == ""){
//first time writing in the file
//$this->writeFileContent("FALSE");
$this->startFetchAndProcess();
//$this->writeFileContent("TRUE");
} else {
//every 5 second, it will come here and try to fetch DB // set 5 sec in cron job
$contentArray = explode(':',$content);
if($contentArray[0] == "FALSE"){
//if FALSE returns morn than 2 min, then write TRUE in the file
$currentTime = time();
$lastUpdatedTimeTime = $contentArray[1];
if((round(abs($currentTime - $lastUpdatedTimeTime) / 60,2)) > EMAIL_ROWS_PROCESS_TIME_MIN_MAX){ // SET it in constant
$this->writeFileContent("TRUE");
}
return;
} else {
$this->writeFileContent("FALSE");
$this->startFetchAndProcess();
$this->writeFileContent("TRUE");
}
}
} catch(Exception $ex){
}
exit;
}
private function startFetchAndProcess(){
//fetch first 10 rows from DB where sending_count < 3
$update_time_target = date("Y-m-d H:i:s", strtotime("-3 min"));
$emailInfo = $this->TempExpenseEmail->find('all',
array(
'conditions' => array('count_email_attempt < ' => MAX_SENDING_COUNT, 'update_date <' => $update_time_target),
'limit' => NUM_OF_EMAIL_ROW_FETCH,
'order'=>array('create_date ASC')
)); // SET it in constant
/* $dbo = $this->TempExpenseEmail->getDatasource();
$logs = $dbo->_queriesLog;
var_dump($logs);
echo "<pre>";
print_r($emailInfo); exit;
*/
if(!empty($emailInfo)){
foreach($emailInfo as $key=>$value){
$value = $value["TempExpenseEmail"];
$count = $value["count_email_attempt"];
$count++;
try{
$currentDate = "'".date("Y-m-d H:i:s")."'";
//process each row and update sending count
$userUpdated = $this->TempExpenseEmail->updateAll(
array('count_email_attempt' => $count,'update_date' => $currentDate ),
array('id' => $value["id"]));
$emailData = array();
$emailData["title"] = $value["title"];
$emailData["unique_url"] = $value["unique_url"];
$emailData["email"] = $value["email"];
//send email
$this->sendEmail($emailData);
//insert into ExpenseEmail
$inputData = array();
$inputData["id"] = $value["id"];
$inputData["unique_url"] = $value["unique_url"];
$inputData["email"] = $value["email"];
$inputData["title"] = $value["title"];
$inputData["count_email_attempt"] = $value["count_email_attempt"];
$this->ExpenseEmail->insertExpenseEmail($inputData);
// delete the email record after successful sending
$result = $this->TempExpenseEmail->deleteAll(array('id' => $value["id"]));
} catch(Exception $ex){
}
}
}
}
private function writeFileContent($flag){
$handle = fopen(REGISTRATION_EMAIL_SCHEDULE_TRACKING_FILE,"w+");
try{
fwrite($handle, $flag.":".time());
} catch(Exceptoin $ex){
}
fclose($handle);
}
private function readFileContent(){
$handle = fopen(REGISTRATION_EMAIL_SCHEDULE_TRACKING_FILE, "r");
try{
$contents = fread($handle, filesize(REGISTRATION_EMAIL_SCHEDULE_TRACKING_FILE));
} catch(Exceptoin $ex){
}
fclose($handle);
return trim($contents);
}
private function sendEmail($emailData){
$data = array();
$data["email"] = $emailData["email"];
$data["expense_title"] = $emailData["title"];
$data["unique_url"] = $emailData["unique_url"];
$default = array(
'host' => Configure::read('expensecount.email.smtp.host'),
'port' => 587,
'auth' => 'plain',
'username' => Configure::read('expensecount.email.smtp.username'),
'password' => Configure::read('expensecount.email.smtp.password'),
'tsl' => false,
'transport' => 'Smtp',
'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
'returnPath' => Configure::read('expensecount.email.smtp.from'),
'layout' => false,
'emailFormat' => 'html',
//'template' => 'only_text',
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
App::uses('CakeEmail', 'Network/Email');
//echo $Email->
$Email = new CakeEmail($default);
$Email->to($data["email"]);
$Email->emailFormat('html');
$Email->template('email',null)->viewVars( array('data' => $data));
$Email->subject('ExpenseCount "'.$data["expense_title"].'" ');
$Email->replyTo(Configure::read('expensecount.email.smtp.from'));
$Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount.com"));
//$Email->smtpOptions = $default;
$Email->delivery = 'Smtp';
$Email->send();
}
private function getEmailTemplate($templatePath,$local){
return $templatePath."_".$local;
}
private function defineConstant(){
define("EMAIL_ROWS_PROCESS_TIME_MIN_MAX",2); //value in minute
define("NUM_OF_EMAIL_ROW_FETCH",10);
define("MAX_SENDING_COUNT",3);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
<?php
class FBActionController extends AppController
{
var $name = 'FBAction';
var $uses = array('Expense','Participant');
var $helpers = array('Html', 'Form');
public function beforeRender() {
parent::beforeRender();
$this->layout = 'facebook';
}
public function createGroupExpense(){
}
}
?>

View File

@@ -0,0 +1,312 @@
<?php
session_start();
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Faceboob\FacebookSDKException;
use Facebook\FacebookCanvasLoginHelper;
use Facebook\GraphObject;
use Facebook\GraphUser;
use Facebook\GraphSessionInfo;
use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookCurlHttpClient;
use Facebook\FacebookRedirectLoginHelper;
class FBHomeController extends AppController
{
var $name = 'Facebook';
var $uses = array('Expense','Participant');
var $helpers = array('Html', 'Form');
public function beforeRender() {
parent::beforeRender();
$this->layout = 'facebook';
}
function index()
{
$app_id = '1539535046303692';
$app_secret = '0f0e28f812b7c330c57be7ec8024a760';
$app_namespace = 'expensecount';
App::import('vendor', 'Facebook'.DS.'Entities'.DS.'AccessToken');
App::import('vendor', 'Facebook'.DS.'FacebookSession');
App::import('vendor', 'Facebook'.DS.'FacebookRequest');
App::import('vendor', 'Facebook'.DS.'FacebookResponse');
App::import('vendor', 'Facebook'.DS.'FacebookSDKException');
App::import('vendor', 'Facebook'.DS.'Entities'.DS.'SignedRequest');
App::import('vendor', 'Facebook'.DS.'FacebookSignedRequestFromInputHelper');
App::import('vendor', 'Facebook'.DS.'FacebookRedirectLoginHelper');
App::import('vendor', 'Facebook'.DS.'FacebookCanvasLoginHelper');
App::import('vendor', 'Facebook'.DS.'GraphObject');
App::import('vendor', 'Facebook'.DS.'GraphUser');
App::import('vendor', 'Facebook'.DS.'GraphSessionInfo');
App::import('vendor', 'Facebook'.DS.'HttpClients'.DS.'FacebookHttpable');
App::import('vendor', 'Facebook'.DS.'HttpClients'.DS.'FacebookCurl');
App::import('vendor', 'Facebook'.DS.'HttpClients'.DS.'FacebookCurlHttpClient');
// Facebook APP keys
FacebookSession::setDefaultApplication($app_id,$app_secret);
// Helper for fb canvas authentication
$helper = new FacebookCanvasLoginHelper();
// see if $_SESSION exists
if (isset($_SESSION) && isset($_SESSION['fb_token']))
{
// create new fb session from saved fb_token
$session = new FacebookSession($_SESSION['fb_token']);
// validate the fb_token to make sure it's still valid
try
{
$session->validate();
}
catch (Exception $e)
{
// catch any exceptions
$session = null;
}
}
else
{
// no $_SESSION exists
try
{
// create fb session
$session = $helper->getSession();
}
catch(FacebookRequestException $ex)
{
// When Facebook returns an error
//print_r($ex);
$session = null;
}
catch(\Exception $ex)
{
// When validation fails or other local issues
//print_r($ex);
$session = null;
}
}
// check if 1 of the 2 methods above set $session
if (isset($session))
{
$request = new FacebookRequest( $session, 'GET', '/me/friends' );
try{
$response = $request->execute();
$graphObject = $response->getGraphObject();
//echo print_r( $graphObject, 1 );
/* $fid = $graphObject->getProperty('id');// echo $fid;
$femail = $graphObject->getProperty('email')// echo $femail;
$ffirst_name = $graphObject->getProperty('name ');// echo $ffirst_name; */
//$facebook_id = $graphObject->getProperty('id');
//$request = new FacebookRequest( $session, 'GET', '/'.$facebook_id.'/friends?access_token='.$session->getToken() );
// $response = $request->execute();
//$graphObject = $response->getGraphObject();
//var_dump($graphObject);exit;
$expenseIdArray = $this->Participant->getExpenseIdListByFacebookId($facebook_id);
if(!empty($expenseIdArray)){
$data = $this->Expense->findExpenseInfoByIds($expenseIdArray);
if(!empty($data)){
$expenseList = $data["expenseList"];
$participantList = $data["participantList"];
foreach($expenseList as $key=>$value){
$finalResult[$key]["unique_url"] = $value["Expense"]["unique_url"];
$finalResult[$key]["title"] = $value["Expense"]["title"];
$finalResult[$key]["currency"] = $value["Expense"]["currency"];
$finalResult[$key]["description"] = $value["Expense"]["description"];
$finalResult[$key]["create_date"] = $value["Expense"]["create_date"];
$finalResult[$key]["expense_type"] = $value["Expense"]["expense_type"];
$finalResult[$key]["participantName"] = $this->getParticipantName($value["Expense"]["id"],$participantList);
}
}
}
$first_name = $graphObject->getProperty('first_name');
if(strlen($first_name) > 15){
$first_name = substr($first_name,0,15);
}
$this->set("expenseList",$finalResult);
$this->set("facebook_token",$session->getToken());
$this->set("facebook_name",$first_name);
//$this->Session->write("aaa",$session->getToken());
//echo "<br/>";
//echo "id:".$facebook_id;
//echo "Session<pre>";
// print_r($session->getToken());exit;
//echo "<br/>";
// echo "Name:".$graphObject->getProperty('first_name');
//echo "<br/>";
//echo "Email:".$graphObject->getProperty('email');
//get list of expense info based on facebook ID
$this->render('index');
/* echo $fid;
echo "===========<br/>";
echo $femail;
echo "===========<br/>";
echo $ffirst_name;
echo "===========<br/>"; */
} catch (Exception $ex) {
// echo $ex->getMessage();
}
}
else
{
$helper = new FacebookRedirectLoginHelper("https://apps.facebook.com/expensecount");
$auth_url = $helper->getLoginUrl();
echo "<script>window.top.location.href='".$auth_url."'</script>";
//session_destroy();
// We use javascript because of facebook bug https://developers.facebook.com/bugs/722275367815777
// Fix from here: http://stackoverflow.com/a/23685616/796443
// IF bug is fixed this line won't be needed, as app will ask for permissions onload without JS redirect.
//$oauthJS = "window.top.location = 'https://www.facebook.com/dialog/oauth?client_id=$app_id&redirect_uri=https://apps.facebook.com/$app_namespace/&scope=user_location,email';";
}
//App::import('vendor', 'Facebook'.DS.'FacebookRequest');
/* App::import('vendor', 'Facebook'.DS.'FacebookSDKException');
App::import('vendor', 'Facebook'.DS.'FacebookRequestException');
App::import('vendor', 'Facebook'.DS.'GraphObject');
App::import('vendor', 'Facebook'.DS.'GraphUser');
App::import('vendor', 'Facebook'.DS.'FacebookSession');
//$Facebook = new FacebookSession('942666942429370','d41f9f9dc531dcf2f6de520ca1111a71');
FacebookSession::setDefaultApplication('942666942429370', 'd41f9f9dc531dcf2f6de520ca1111a71'); */
//collect facebook data and set it to input form
//FacebookSession::setDefaultApplication('', '');
/* App::import('Vendor', 'FacebookRedirectLoginHelper', array('file' =>'FacebookRedirectLoginHelper.php'));
App::import('Vendor', 'FacebookSDKException', array('file' =>'FacebookSDKException.php'));
App::import('Vendor', 'FacebookSession', array('file' => 'FacebookSession.php'));
App::import('Vendor', 'FacebookRequest', ['file' =>'FacebookRequest.php']);
App::import('Vendor', 'FacebookRequestException', ['file' =>'FacebookRequestException.php']);
$helper = new \Facebook\FacebookRedirectLoginHelper(Router::url('/', true), "942666942429370", $secret);
*/
$data["User"]["name"] = "Rajib Deb"; //fb
$data["User"]["phone"] = "0162005136"; // fb
$data["User"]["email"] = "test@gmail.com";//fb
/* if($session) {
try {
$user_profile = (new FacebookRequest(
$session, 'GET', '/me'
))->execute()->getGraphObject(GraphUser::className());
echo "Name: " . $user_profile->getName();
} catch(FacebookRequestException $e) {
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
} else {
echo "NO session";
}
*/
$this->request->data = $data;
}
public function getParticipantName($expenseId,$participantList){
$participantName = "";
if(!empty($participantList)){
foreach($participantList as $key=>$value){
if(trim($value["Participant"]["expense_id"]) == trim($expenseId)){
$participantName = $value["Participant"]["name"];
}
}
}
return $participantName;
}
public function createDonor()
{
$data["name"] = $this->data["User"]["name"]; //fb
$data["phone"] = $this->data["User"]["phone"]; // fb
$data["email"] = $this->data["User"]["email"];//fb
$data["bloodgroup"] = $this->data["User"]["bloodgroup"]; //input // A+=1,B+=2,O+=3,AB+=4,A-=5,B-=6,O-=7,AB-=8
$data["birth_date"] = $this->data["User"]["birth_date"];
$data["password"] = ""; //
$data["from_facebook"] = 1;
$data["district"] = $this->data["User"]["district"];
$data["area"] = $this->data["User"]["district"];
$data["facebook_profile"] = $this->data["User"]["facebook_profile"];
$data["last_donate_date"] = $this->data["User"]["last_donate_date"];;
$this->loadModel('User');
$status = $this->User->createUser($data);
if($status == true){
echo __("LBL_DATA_SAVED");
//echo $unique_url;
//$this->Session->write('Config.language', 'ind');
//$this->render('index');
} else {
echo __("LBL_DATA_INSERTION_FAILED");
}
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,448 @@
<?php
App::uses('ConnectionManager', 'Model');
class FiltersController extends AppController
{
var $uses = array('AccessInfo','ExpiredRecord');
//public $components = array('RequestHandler');
public function beforeRender() {
parent::beforeRender();
}
//Run daily once
//shift the ids from access_infos to the table expired_records.
public function findExpiredRecords(){
//retrieve all expried records
$object = $this->request->input('json_decode');
if(!empty($object)){
$data = $this->objectToArray($object);
}
if(!empty($data['month'])) {
$result = $this->AccessInfo->getExpiredExpenses($data['month']);
if (!empty($result)) {
$currentDate = $this->getSystemCurrentTimeStamp();
foreach ($result as $key => $value) {
$deleteList[] = $value["AccessInfo"]["id"];
$data["ExpiredRecord"][$key]["id"] = $value["AccessInfo"]["id"];
$data["ExpiredRecord"][$key]["unique_url"] = $value["AccessInfo"]["unique_url"];
$data["ExpiredRecord"][$key]["inserted_on"] = $currentDate;
}
$error = $this->ExpiredRecord->saveAllExpiredRecords($data);
if (empty($error)) {
//delete all records from AccessInfo table
$this->AccessInfo->deleteAllExpiredExpenses($deleteList);
}
}
}
exit;
//echo "<pre>";
//print_r($result);exit;
//insert multiple record into the table Expired_Records
//check the case whether the record insertion successful or not for multi insertion when pk already exist
}
// Run it in every hour once;
//Retrieve 100 records and process.Insert records into the backup tables as well as delete original records
public function backupAndRemoveOriginalRecords(){
$backup_mode = Configure::read('expensecount.backup.mode');
$limit = 100;
if($backup_mode == true){
//retrieve 100 records from the table expired_records
$query = "select id,unique_url from expired_records limit 0,".$limit;
$db = ConnectionManager::getDataSource('default');
$expiredRecordList = $db->query($query);
if(!empty($expiredRecordList)){
//get all the expense_id
foreach($expiredRecordList as $key=>$value){
$expenseIdList[] = $value["expired_records"]["id"];
$expenseType = substr($value["expired_records"]["unique_url"], 0, 1);
if($expenseType == "1" || $expenseType == "2"){
$groupAndMessExpenseList[] = $value["expired_records"]["id"];
} else if($expenseType == "3" ){
$familyExpenseList[] = $value["expired_records"]["id"];
}
if($expenseType == "2"){
$messExpenseList[] = $value["expired_records"]["id"];
}
}
$expenseIds = implode(",",$expenseIdList);
try{
//delete records from backup_expenses in case any previous records avilable
$db->query("delete from backup_expenses where id in(".$expenseIds.")"); // delete from expenses
//process to shift expenses table to backup_expenses table
$db->query("insert into backup_expenses select * from expenses where id in(".$expenseIds.")");
} catch(Exception $ex){
}
try{
//delete from expenses
$db->query("delete from expenses where id in(".$expenseIds.")"); // delete from expenses
} catch(Exception $ex){
}
try{
//delete records from backup_expense_emails in case any previous records avilable
$db->query("delete from backup_expense_emails where id in(".$expenseIds.")"); // delete from expenses
//process to shift expense_emails table to backup_expense_emails table
$db->query("insert into backup_expense_emails select * from expense_emails where id in(".$expenseIds.")");
} catch(Exception $ex){
}
try{
// delete from expense_emails
$db->query("delete from expense_emails where id in(".$expenseIds.")"); // delete from participants
} catch(Exception $ex){
}
if(!empty($groupAndMessExpenseList)){
$groupExpenseIds = implode(",",$groupAndMessExpenseList);
try{
//delete records from backup_group_expenses in case any previous records avilable
$db->query("delete from backup_group_expenses where expense_id in(".$groupExpenseIds.")");
//process to shift group_expenses table to backup_group_expenses table
$db->query("insert into backup_group_expenses select * from group_expenses where expense_id in(".$groupExpenseIds.")");
} catch(Exception $ex){
}
try{
// delete from group_expenses
$db->query("delete from group_expenses where expense_id in(".$groupExpenseIds.")"); // delete from group_expenses
} catch(Exception $ex){
}
try{
//delete records from backup_participants in case any previous records avilable
$db->query("delete from backup_participants where expense_id in(".$groupExpenseIds.")");
//process to shift participants table to backup_participants table
$db->query("insert into backup_participants select * from participants where expense_id in(".$groupExpenseIds.")");
} catch(Exception $ex){
}
try{
// delete from participants
$db->query("delete from participants where expense_id in(".$groupExpenseIds.")"); // delete from participants
} catch(Exception $ex){
}
}
//For mess expense specially
if(!empty($messExpenseList)){
$messExpenseIds = implode(",",$messExpenseList);
try{
//delete records from backup_meals in case any previous records avilable
$db->query("delete from backup_meals where expense_id in(".$messExpenseIds.")");
//process to shift meals table to backup_meal table
$db->query("insert into backup_meals select * from meals where expense_id in(".$messExpenseIds.")");
} catch(Exception $ex){
}
try{
//delete from meals
$db->query("delete from meals where expense_id in(".$messExpenseIds.")"); // delete from meals
} catch(Exception $ex){
}
}
//if it is family expense
if(!empty($familyExpenseList)){
$familyExpenseIds = implode(",",$familyExpenseList);
try{
//delete records from backup_family_expenses in case any previous records avilable
$db->query("delete from backup_family_expenses where expense_id in(".$familyExpenseIds.")");
//process to shift family_expenses table to backup_family_expenses table
$db->query("insert into backup_family_expenses select * from family_expenses where expense_id in(".$familyExpenseIds.")");
} catch(Exception $ex){
}
try{
//delete from family_expenses
$db->query("delete from family_expenses where expense_id in(".$familyExpenseIds.")"); // delete from family_expenses
} catch(Exception $ex){
}
}
try{
//delete records from backup_family_expenses in case any previous records avilable
$db->query("delete from backup_logs where expense_id in(".$expenseIds.")");
//process to shift logs table to backup_logs table
$db->query("insert into backup_logs select * from logs where expense_id in(".$expenseIds.")");
} catch(Exception $ex){
}
try{
//delete from logs
$db->query("delete from logs where expense_id in(".$expenseIds.")"); // delete from logs
} catch(Exception $ex){
}
try{
//delete records from backup_family_expenses in case any previous records avilable
$db->query("delete from backup_email_histories where expense_id in(".$expenseIds.")");
//process to shift logs table to backup_logs table
$db->query("insert into backup_email_histories select * from email_histories where expense_id in(".$expenseIds.")");
} catch(Exception $ex){
}
try{
//delete from logs
$db->query("delete from email_histories where expense_id in(".$expenseIds.")"); // delete from logs
} catch(Exception $ex){
}
try{
//process to delete records from table expired_records
$db->query("delete from expired_records where id in(".$expenseIds.")"); // delete from expired_records
} catch(Exception $ex){
}
}
}
exit;
}
// Run Manually
public function mergeBackupData(){
$db = ConnectionManager::getDataSource('default');
// expense
try{
//process to shift backup_expenses table to expenses table
$db->query("insert into expenses select * from backup_expenses");
} catch(Exception $ex){
}
try{
//delete from backup_expenses
$db->query("delete from backup_expenses");
} catch(Exception $ex){
}
// group_expenses
try{
//process to shift backup_expenses table to expenses table
$db->query("insert into group_expenses select * from backup_group_expenses");
} catch(Exception $ex){
}
try{
//delete from backup_expenses
$db->query("delete from backup_group_expenses");
} catch(Exception $ex){
}
//family_expenses
try{
//process to shift backup_expenses table to expenses table
$db->query("insert into family_expenses select * from backup_family_expenses");
} catch(Exception $ex){
}
try{
//delete from backup_expenses
$db->query("delete from backup_family_expenses");
} catch(Exception $ex){
}
// meals
try{
//process to shift backup_expenses table to expenses table
$db->query("insert into meals select * from backup_meals");
} catch(Exception $ex){
}
try{
//delete from backup_expenses
$db->query("delete from backup_meals");
} catch(Exception $ex){
}
//participants
try{
//process to shift backup_expenses table to expenses table
$db->query("insert into participants select * from backup_participants");
} catch(Exception $ex){
}
try{
//delete from backup_expenses
$db->query("delete from backup_participants");
} catch(Exception $ex){
}
//logs
try{
//process to shift backup_expenses table to expenses table
$db->query("insert into logs select * from backup_logs");
} catch(Exception $ex){
}
try{
//delete from backup_expenses
$db->query("delete from backup_logs");
} catch(Exception $ex){
}
//backup_expense_emails
try{
//process to shift backup_expense_emails table to expense_emails table
$db->query("insert into expense_emails select * from backup_expense_emails");
} catch(Exception $ex){
}
try{
//delete from backup_expense_emails
$db->query("delete from backup_expense_emails");
} catch(Exception $ex){
}
exit;
}
/*
* Command : console\cake Backup backupSingleExpense
* This method shifts and backup single expense from live tables to backup tables in the production database.
*/
public function backupSingleExpense($unique_url)
{
$db = ConnectionManager::getDataSource('default');
try {
$backup_expense = $db->query("select * from backup_expenses where unique_url='".$unique_url."'");
} catch (Exception $ex) {
}
if (empty($backup_expense)) {
$expense = $db->query("select * from expenses where unique_url= '".$unique_url."'");
if(!empty($expense)) {
$this->loadModel('Backup');
$this->Backup->processBackupAndRemove($expense);
} else {
echo "Expense is not found in production database. Could not perform backup!";
exit;
}
} else {
echo "Expense is already in backup database. Could not perform backup!";
exit;
}
echo "Backup Process Completed!";
exit;
}
/*
* command: console\cake Backup archieveSingleItem
* Run it to archieve a sinle expense
*
* This method shifts one single expense from backup tables(live db) to archieve database
*
*/
public function archieveSingleItem($unique_url)
{
$this->loadModel('Backup');
$this->Backup->archieveSingleExpense($unique_url);
echo "Restore Process Completed!";
exit;
}
/*
* Command: console\cake Restore restore
* For restoring a single item
*
* This methods first tries to restore single expense from backup tables to live tables. If there
* is no such expense in backup table, it tries to restore from archieve database to live database.
* If the expense is already exist in live tables, it does not do anything.
*
*
*/
public function restoreSingleExpense($unique_url)
{
$this->loadModel("Backup");
$this->Backup->restore($unique_url);
echo "Restore Process Completed!";
exit;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,254 @@
<?php
class GroupSettingController extends AppController
{
var $uses = array(
'GroupSetting'
);
public $components = array('RequestHandler', 'Permission');
private $platform = "3" ; // 1 = Android, 2 = iPhone, 3 = Web
private $app_version = "2";
private $version = 0;
private $application_version = "3.2";
private $validation_status = "-1";
public function beforeRender()
{
parent::beforeRender();
}
public function addPermission()
{
if ($this->request->is('ajax')) {
$this->autoRender = false;
$response = [
'status' => false,
'message' => 'Failed'
];
$request = $this->basicRequest();
$user_id = $this->Session->read('userData.id');
$profile_id = $this->Session->read('userData.profile_id');
$request["expense_id"] = $this->data["expense_id"];
$request["unique_url"] = $this->data["unique_url"];
$request["user_id"] = $user_id;
$request["profile_id"] = $profile_id;
$request["addPermissions"] = [];
$request["modifyPermissions"] = [];
$request["deletePermissions"] = [];
$operation = [
"email" => $this->data["email"],
"name" => $this->data["name"],
"role" => $this->data["permission"]
];
if ($this->data["operation_type"] == $this->operation_type['ADD']) {
$request["addPermissions"][] = $operation;
} else if ($this->data["operation_type"] == $this->operation_type['EDIT']) {
$request["modifyPermissions"][] = $operation;
} else if ($this->data["operation_type"] == $this->operation_type['DELETE']) {
$request["deletePermissions"][] = $operation;
}
$apiResponse = $this->callAPI(HTTP_SITE_URL . "/Expense/permissions.json", 'POST', json_encode($request));
$apiResponseArr = json_decode($apiResponse, true);
if (isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) {
$response['status'] = true;
$response['message'] = 'Saved successfully.';
$response['permissions'] = $apiResponseArr['response']['data']['settings']['permissions'];
}else{
$response['message'] = isset($apiResponseArr['response']['status_desc'])
? $apiResponseArr['response']['status_desc']
: $response['message'];
}
header('Content-Type: application/json');
echo json_encode($response);
exit;
}
else {
throw new BadRequestException('Invalid request method');
}
}
public function addRestriction()
{
if ($this->request->is('ajax')) {
$this->autoRender = false;
$profile_id = $this->Session->read('userData.profile_id');
$user_id = $this->Session->read('userData.id');
$response = [
'status' => false,
'message' => 'Failed'
];
$request = $this->basicRequest();
$request["expense_id"] = $this->data["expense_id"];
$request["unique_url"] = $this->data["unique_url"];
$request["user_id"] = $user_id;
$request["profile_id"] = $profile_id;
$request["is_restricted_mode"] = $this->data["mode"];
$apiResponse = $this->callAPI(HTTP_SITE_URL . "/Expense/restriction.json", 'POST', json_encode($request));
$apiResponseArr = json_decode($apiResponse, true);
if (isset($apiResponseArr['response']['status'])) {
$response['restricted_mode'] = false;
$response['status'] = true;
if ($apiResponseArr['response']['status'] == '+000') {
$response['message'] = "Restricted Mode saved successfully.";
if($apiResponseArr['response']['GroupSetting']['is_restricted_mode'] == 1) {
$response['restricted_mode'] = true;
}
}
if($apiResponseArr['response']['status'] == '-1') {
$response['message'] = $apiResponseArr['response']['status_desc'];
}
}
header('Content-Type: application/json');
echo json_encode($response);
exit;
} else {
throw new BadRequestException('Invalid request method');
}
}
public function fixed_price()
{
$object = $this->request->input('json_decode');
if (!empty($object)) {
$data = $this->objectToArray($object);
}
if (!isset($data['skip_process_validation'])) {
list($data, $status, $status_desc, $error) = $this->processValidation();
}
if (!empty($data) && empty($status)) {
list($status, $status_desc, $error) = $this->requestValidate($data);
}
if (empty($status)) {
$object = json_decode(json_encode($object), true);
list($status, $status_desc, $expObj) = $this->validateUniqueUrl($object['unique_url']);
}
$input = array();
if (empty($status)) {
$status_message = [
'code' => "061",
'message' => 'Error: Expense not found.'
];
$status = $status_message['code'];
$status_desc = $status_message['message'];
$expense = $this->Expense->find('first', array(
'conditions' => array('Expense.id' => $object['expense_id'], 'Expense.unique_url' => $object['unique_url'])
));
$this->loadModel('GroupSettings');
//check expense_id and unique_url is exist or not
$groupSettings = $this->GroupSetting->find('first', array(
'conditions' => array('GroupSetting.expense_id' => $object['expense_id'], 'GroupSetting.unique_url' => $object['unique_url'])
));
if (!empty($expense['Expense']) && !empty($groupSettings['GroupSetting'])) {
$is_add_possible = false;
if(!empty($expense['Expense']['user_id']) || $expense['Expense']['create_user'] != 'system') {
if($expense['Expense']['user_id'] == $object['user_id'] && $groupSettings['GroupSetting']['is_restricted_mode'] == 1){
$is_add_possible = true; // only owner can add the fixed price
}
if($groupSettings['GroupSetting']['is_restricted_mode'] == 0){
$is_add_possible = true; // anyone can add the fixed price
}
}
if($is_add_possible){
$data['id'] = $groupSettings['GroupSetting']['id'];
$data['version'] = $groupSettings['GroupSetting']['version'] + 1;
$data['is_fixed_price'] = (isset($object['is_fixed_price']) && $object['is_fixed_price'] >0) ? true : false;
$data['expense_id'] = $groupSettings['GroupSetting']['expense_id'];
$data['unique_url'] = $groupSettings['GroupSetting']['unique_url'];
if (!empty($expense['Expense'])) {
$expense['Expense']['version'] = $expense['Expense']['version'] + 1;
}
$this->GroupSetting->save($data);
$this->Expense->save($expense);
$groupSettings['GroupSetting']['is_fixed_price'] = $object['is_fixed_price'];
$status_desc = "SUCCESS";
$status = "+000";
$input['GroupSetting'] = $groupSettings['GroupSetting'];
}
}
}
if ($status != "+000") {
$this->processResponse($input, $data, $status, $status_desc);
} else {
$this->updateFirebase($object['unique_url']);
$input["status"] = $status;
$input["status_desc"] = $status_desc;
$input["api_version"] = 3;
$this->set(array(
'response' => $input,
'_serialize' => array('response')
));
}
}
public function requestValidate($object)
{
//check validity
$error = "";
$error_desc = "";
$expObj = array();
if (empty($object['expense_id'])) {
$error = $this->validation_status;
$error_desc = "expense_id must be provided!";
$expObj['expense_id'] = $error_desc;
}
if (empty($object['unique_url'])) {
$error = $this->validation_status;
$error_desc = "unique_url must be provided!";
$expObj['unique_url'] = $error_desc;
}
if (!empty($object['user_id']) && !is_numeric($object['user_id'])) {
$error = $this->validation_status;
$error_desc = 'user_id must be provided as numeric.';
}
if (!isset($object['is_fixed_price'])) {
$error = $this->validation_status;
$error_desc = "is_fixed_price must be provided!";
$expObj['is_fixed_price'] = $error_desc;
}
return array($error, $error_desc, $expObj);
}
private function basicRequest(){
$deviceData = $this->deviceData();
$request = [
"platform" => $this->platform, // 1 = Android, 2 = iPhone, 3 = Web
"app_version" => $this->app_version, // optional
"version" => $this->version, // optional
"application_version" => $this->application_version, // optional
"device_id" => $deviceData['device_id'],
"random_number" => $deviceData['random_number'],
"access_token" => $deviceData['access_token'],
];
return $request;
}
}

View File

@@ -0,0 +1,694 @@
<?php
class HomeController extends AppController
{
var $name = 'Homes';
public $uses = array('Expense', 'TempExpenseEmail','AccessInfo');
var $helpers = array('Html', 'Form');
public $components = array('RequestHandler', 'Captcha');
private $user_id;
public function initialize()
{
$this->setDefaultTimeStamp();
}
public function beforeRender()
{
parent::beforeRender();
$this->layout = 'visitor';
if ($this->Session->check("homecontroller_layout")) {
//$this->layout = '';
$this->Session->delete("homecontroller_layout");
}
}
/* public function beforeFilter() {
parent::beforeFilter();
$this->Cookie->name = 'Expenses';
$this->Cookie->time = 3600; // or '1 hour'
$this->Cookie->path = '/Home/createGroupExpense';
$this->Cookie->domain = 'localhost';
$this->Cookie->secure = true; // i.e. only sent if using secure HTTPS
$this->Cookie->key = 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^';
$this->Cookie->httpOnly = true;
$this->Cookie->type('aes');
}*/
function index() {}
function track()
{
/*$unique_url = $this->Session->read("user_unique_url");
$expense_title = $this->Session->read("user_expense_title");
$this->set('unique_url',$unique_url);
$this->set('expense_title',$expense_title);*/
}
public function changeLanguage($lang = null)
{
$language = $this->data["Home"]["global_selected_language"];
if (empty($language)) {
$language = $lang;
}
$url = $this->data["Home"]["global_current_url"];
if (empty($url)) {
$url = $this->webroot;
}
$language = trim($language);
$allowedLanguage = array("eng", "ben", "jpn", "hin", "may", "chi", "rus", "urd", "spa", "ccn", "czh", "ben");
if (!in_array($language, $allowedLanguage)) {
$language = "eng";
}
$this->Session->write("Config.language", $language);
$this->Cookie->write("Config.expcount.language", $language);
$this->redirect(FULL_BASE_URL . $url);
exit;
}
private function getSecretKey($length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
public function createGroupExpense($token = "", $name = "")
{
$this->user_id = $this->Session->read('userData.id');
$profile_id = $this->Session->read('userData.profile_id');
if ((isset($token) && trim($token) != "")
&& (isset($name) && trim($name) != "")
) {
if (strlen($name) > 15) {
$name = substr($name, 0, 15);
}
//validate token;if token is valid, just set a session for facebook layout.
$this->Session->write("homecontroller_layout", "facebook");
$this->set("facebook_token", $token);
$this->set("facebook_name", $name);
}
if ($this->request->is('ajax')) {
Configure::write('debug', 0);
$this->Expense->setGroupExpenseValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
echo Configure::read('expensecount.form.validation.success');
} else {
$errorMsg = "";
$errorMsgArray = $this->Expense->invalidFields();
foreach ($errorMsgArray as $key => $value) {
$errorMsg .= $key . Configure::read('expensecount.form.validation.pipe') . $value[0] . Configure::read('expensecount.form.validation.separator');
}
echo $errorMsg;
}
exit;
}
else if ($this->request->is('Post') && $this->data["Expense"]) {
$captcha = $this->Session->read('captcha_code');
if (strlen($captcha) > 0 && ($captcha == $this->request->data['Expense']['captcha'])) {
$this->Session->delete('captcha_code');
$this->Expense->setGroupExpenseValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
$data["title"] = $this->data["Expense"]["title"];
$data["your_name"] = $this->data["Expense"]["YourName"];
$data["participants"] = $this->data["Expense"]["participants"];
$data["email"] = $this->data["Expense"]["emails"];
$data["currency"] = $this->data["Expense"]["currency"];
$data["description"] = $this->data["Expense"]["description"];
$data["language"] = Configure::read('Config.language');
if(!empty($profile_id)){
$data['create_user'] = $profile_id;
}
if (isset($this->data["Expense"]["createDate"])) {
$data["create_date"] = $this->data["Expense"]["createDate"];
} else {
$data["create_date"] = $this->getSystemCurrentTimeStamp();
}
$data["expense_type"] = "1";
$data["source"] = "1";
$data["ip"] = $this->getClientIp();
$data["user_agent"] = $this->getUserAgent();
$data["secret_key"] = $this->data["Expense"]["captcha"];
$data['user_id'] = $this->user_id;
$this->loadModel('Expense');
$expenseIdStr = $this->Expense->createExpense($data, false);
if ($expenseIdStr != "") {
$expenseIdStrArr = explode(",", $expenseIdStr);
$unique_url = $expenseIdStrArr[1];
// data for userGroup
if (!empty($this->user_id)) {
$userGrpdata['user_id'] = $this->user_id;
$userGrpdata['unique_url'] = $unique_url;
$userGrpdata['participant_id'] = '1' . '_0'; // creator id
$userGrpdata['skip_process_validation'] = 1;
$this->addGroupSetting(['unique_url'=>$unique_url,'is_restricted_mode'=>$this->data["Expense"]['restrictedMode'], 'expense_id'=>$expenseIdStrArr[0]]);
$this->addPermission( [
'expense_id' => $expenseIdStrArr[0],
'unique_url' => $unique_url,
'profile_id' => $profile_id,
'user_id' => $this->user_id,
"role" => OWNER
]);
//add userGroup
$this->callAPI(HTTP_SITE_URL . "/users/groupadd.json", 'POST', json_encode($userGrpdata));
}
//set cookie for my expenses
if(empty($profile_id) && empty($this->user_id)){
$this->setCookie($data, $unique_url);
}
$tmp_email = trim($this->data["Expense"]["emails"]);
if (!empty($tmp_email)) {
$this->Session->write('just_created_email', $tmp_email);
}
$this->Session->write('just_created', "yes");
$this->redirect(array('controller' => $unique_url));
} else {
$this->Session->setFlash(__('DATA_CREATION_FAIL'));
}
} else {
$this->Session->setFlash(__('CAPTCHA_NOT_EMPTY_MAX_CHAR'));
}
}
} else {
$token = $this->getSecretKey(5);
$this->set("captcha", $token);
$this->Session->write("captcha_code", $token);
$this->setPermission();
}
}
public function createMessExpense($token = "", $name = "")
{
$this->user_id = $this->Session->read('userData.id');
$profile_id = $this->Session->read('userData.profile_id');
if ((isset($token) && trim($token) != "") && (isset($name) && trim($name) != "")) {
if (strlen($name) > 15) {
$name = substr($name, 0, 15);
}
//validate token;if token is valid, just set a session for facebook layout.
$this->Session->write("homecontroller_layout", "facebook");
$this->set("facebook_token", $token);
$this->set("facebook_name", $name);
}
if ($this->request->is('ajax')) {
Configure::write('debug', 0);
$this->Expense->setGroupExpenseValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
echo Configure::read('expensecount.form.validation.success');
} else {
$errorMsg = "";
$errorMsgArray = $this->Expense->invalidFields();
foreach ($errorMsgArray as $key => $value) {
$errorMsg .= $key . Configure::read('expensecount.form.validation.pipe') . $value[0] . Configure::read('expensecount.form.validation.separator');
}
echo $errorMsg;
}
exit;
}
else if ($this->request->is('Post') && $this->data["Expense"]) {
$captcha = $this->Session->read('captcha_code');
if (strlen($captcha) > 0 && ($captcha == $this->request->data['Expense']['captcha'])) {
$this->Session->delete('captcha_code');
$this->Expense->setGroupExpenseValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
$data["title"] = $this->data["Expense"]["title"];
$data["your_name"] = $this->data["Expense"]["YourName"];
$data["participants"] = $this->data["Expense"]["participants"];
$data["email"] = $this->data["Expense"]["emails"];
$data["currency"] = $this->data["Expense"]["currency"];
$data["description"] = $this->data["Expense"]["description"];
$data["language"] = Configure::read('Config.language');
if(!empty($profile_id)){
$data['create_user'] = $profile_id;
}
if (isset($this->data["Expense"]["createDate"])) {
$data["create_date"] = $this->data["Expense"]["createDate"];
} else {
$data["create_date"] = $this->getSystemCurrentTimeStamp();
}
$data["expense_type"] = "2";
$data["source"] = "1";
$data["ip"] = $this->getClientIp();
$data["user_agent"] = $this->getUserAgent();
$data["secret_key"] = $this->data["Expense"]["captcha"];
$data['user_id'] = $this->user_id;
$this->loadModel('Expense');
$expenseIdStr = $this->Expense->createExpense($data, false);
if ($expenseIdStr != "") {
$expenseIdStrArr = explode(",", $expenseIdStr);
$unique_url = $expenseIdStrArr[1];
// data for userGroup
if (!empty($this->user_id)) {
$userGrpdata['user_id'] = $this->user_id;
$userGrpdata['unique_url'] = $unique_url;
$userGrpdata['participant_id'] = '1' . '_0'; // creator id
$userGrpdata['skip_process_validation'] = 1;
$this->addGroupSetting(['unique_url'=>$unique_url,'is_restricted_mode'=>$this->data["Expense"]['restrictedMode'], 'expense_id'=>$expenseIdStrArr[0]]);
$this->addPermission( [
'expense_id' => $expenseIdStrArr[0],
'unique_url' => $unique_url,
'profile_id' => $profile_id,
'user_id' => $this->user_id,
"role" => OWNER
]);
//add userGroup
$this->callAPI(HTTP_SITE_URL . "/users/groupadd.json", 'POST', json_encode($userGrpdata));
}
//set cookie for my expenses
if(empty($profile_id) && empty($this->user_id)){
$this->setCookie($data, $unique_url);
}
$tmp_email = trim($this->data["Expense"]["emails"]);
if (!empty($tmp_email)) {
$this->Session->write('just_created_email', $tmp_email);
}
$this->Session->write('just_created', "yes");
$this->redirect(array('controller' => $unique_url));
} else {
$this->Session->setFlash(__('DATA_CREATION_FAIL'));
}
} else {
$this->Session->setFlash(__('CAPTCHA_NOT_EMPTY_MAX_CHAR'));
}
}
} else {
$token = $this->getSecretKey(5);
$this->set("captcha", $token);
$this->Session->write("captcha_code", $token);
$this->setPermission();
}
}
public function createFamilyExpense($token = "", $name = "")
{
$this->user_id = $this->Session->read('userData.id');
$profile_id = $this->Session->read('userData.profile_id');
if ((isset($token) && trim($token) != "")
&& (isset($name) && trim($name) != "")
) {
if (strlen($name) > 15) {
$name = substr($name, 0, 15);
}
//validate token;if token is valid, just set a session for facebook layout.
$this->Session->write("homecontroller_layout", "facebook");
$this->set("facebook_token", $token);
$this->set("facebook_name", $name);
}
if ($this->request->is('ajax')) {
Configure::write('debug', 0);
$this->Expense->setFamilyExpenseValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
echo Configure::read('expensecount.form.validation.success');
} else {
$errorMsg = "";
$errorMsgArray = $this->Expense->invalidFields();
foreach ($errorMsgArray as $key => $value) {
$errorMsg .= $key . Configure::read('expensecount.form.validation.pipe') . $value[0] . Configure::read('expensecount.form.validation.separator');
}
echo $errorMsg;
}
exit;
} else if ($this->request->is('Post') && $this->data["Expense"]) {
$captcha = $this->Session->read('captcha_code');
if (strlen($captcha) > 0 && ($captcha == $this->request->data['Expense']['captcha'])) {
$this->Session->delete('captcha_code');
$this->Expense->setFamilyExpenseValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
$data["title"] = $this->data["Expense"]["title"];
$data["currency"] = $this->data["Expense"]["currency"];
$data["description"] = $this->data["Expense"]["description"];
$data["language"] = Configure::read('Config.language');
$data["email"] = $this->data["Expense"]["emails"];
if(!empty($profile_id)){
$data['create_user'] = $profile_id;
}
if (isset($this->data["Expense"]["createDate"])) {
$data["create_date"] = $this->data["Expense"]["createDate"];
} else {
$data["create_date"] = $this->getSystemCurrentTimeStamp();
}
$data["expense_type"] = "3"; //1=group expense,2=mess expense,3=family expense
$data["source"] = "1";
$data["ip"] = $this->getClientIp();
$data["user_agent"] = $this->getUserAgent();
$data["secret_key"] = $this->data["Expense"]["captcha"];
$data['user_id'] = $this->user_id;
$this->loadModel('Expense');
$expenseIdStr = $this->Expense->createExpense($data, false);
if ($expenseIdStr != "") {
$expenseIdStrArr = explode(",", $expenseIdStr);
$unique_url = $expenseIdStrArr[1];
// data for userGroup
if (!empty($this->user_id)) {
$userGrpdata['user_id'] = $this->user_id;
$userGrpdata['unique_url'] = $unique_url;
$userGrpdata['participant_id'] = '1' . '_0';
$userGrpdata['skip_process_validation'] = 1;
$this->addGroupSetting(['unique_url'=>$unique_url,'is_restricted_mode'=>$this->data["Expense"]['restrictedMode'], 'expense_id'=>$expenseIdStrArr[0]]);
$this->addPermission( [
'expense_id' => $expenseIdStrArr[0],
'unique_url' => $unique_url,
'profile_id' => $profile_id,
'user_id' => $this->user_id,
"role" => OWNER
]);
//add userGroup
$this->callAPI(HTTP_SITE_URL . "/users/groupadd.json", 'POST', json_encode($userGrpdata));
}
//set cookie for my expenses
if(empty($profile_id) && empty($this->user_id)) {
$this->setCookie($data, $unique_url);
}
$tmp_email = trim($this->data["Expense"]["emails"]);
if (!empty($tmp_email)) {
$this->Session->write('just_created_email', $tmp_email);
}
$this->Session->write('just_created', "yes");
$this->redirect(array('controller' => $unique_url));
} else {
$this->Session->setFlash(__('DATA_CREATION_FAIL'));
}
} else {
$this->Session->setFlash(__('CAPTCHA_NOT_EMPTY_MAX_CHAR'));
}
}
} else {
$token = $this->getSecretKey(5);
$this->set("captcha", $token);
$this->Session->write("captcha_code", $token);
$this->setPermission();
}
}
public function groupExpense() {}
public function messExpense() {}
public function familyExpense() {}
public function updateGroupExpense()
{
if ($this->request->is('ajax')) {
Configure::write('debug', 0);
$this->Expense->setGroupExpenseModifyValidation();
$this->Expense->set($this->data);
if ($this->Expense->validates()) {
// $fp = fopen("ajit.txt",'a+');
// fwrite($fp,json_encode($this->data['unique_url']));
// fclose($fp);
$data["id"] = $this->data["Expense"]["expenseid"];
$data["title"] = $this->data["Expense"]["title"];
$data["currency"] = $this->data["Expense"]["currency"];
$data["description"] = $this->data["Expense"]["description"];
$data["version"] = $this->data["Expense"]["version"];
//$data["expenseType"] = $this->data["Expense"]["expenseType"];
if (
isset($this->data["Expense"]["defaultBreakfast"])
&& isset($this->data["Expense"]["defaultLunch"])
&& isset($this->data["Expense"]["defaultDinner"])
) {
$defaultBreakfast = 0;
$defaultLunch = 0;
$defaultDinner = 0;
if (trim($this->data["Expense"]["defaultBreakfast"]) != "") {
$defaultBreakfast = trim($this->data["Expense"]["defaultBreakfast"]);
}
if (trim($this->data["Expense"]["defaultLunch"]) != "") {
$defaultLunch = trim($this->data["Expense"]["defaultLunch"]);
}
if (trim($this->data["Expense"]["defaultDinner"]) != "") {
$defaultDinner = trim($this->data["Expense"]["defaultDinner"]);
}
$data["default_meal"] = $defaultBreakfast . "|" . $defaultLunch . "|" . $defaultDinner;
}
if ($data["version"] > 999) {
$data["version"] = 1;
}
$message = $this->Expense->modifyExpense($data);
//insert/update access info
$access_info["id"] = $this->data["Expense"]["expenseid"];
$access_info["unique_url"] = $this->data["unique_url"];
$this->insertAccessInfo($access_info);
//set cookie for my expenses
$curExpInfo = $this->Expense->findById($this->data["Expense"]["expenseid"]);
$dataCookie["title"] = $this->data["Expense"]["title"];
$dataCookie["create_date"] = $curExpInfo["Expense"]["create_date"];
$this->setCookie($dataCookie, $this->data['unique_url'], 1);
//update firebase version
$this->updateFirebase($this->data['unique_url']);
if (empty($message)) {
echo Configure::read('expensecount.form.validation.success');
} else {
$errorMsg = "";
foreach ($message as $key => $value) {
$errorMsg .= $key . Configure::read('expensecount.form.validation.pipe') . $value . Configure::read('expensecount.form.validation.separator');
}
echo $errorMsg;
}
} else {
$errorMsg = "";
$errorMsgArray = $this->Expense->invalidFields();
foreach ($errorMsgArray as $key => $value) {
$errorMsg .= $key . Configure::read('expensecount.form.validation.pipe') . $value[0] . Configure::read('expensecount.form.validation.separator');
}
echo $errorMsg;
}
exit;
}
exit;
}
public function get_captcha()
{
$this->autoRender = false;
App::import('Component', 'Captcha');
//generate random charcters for captcha
$random = mt_rand(100, 99999);
//save characters in session
$this->Session->write('captcha_code', $random);
$settings = array(
'characters' => $random,
'winHeight' => 70, // captcha image height
'winWidth' => 220, // captcha image width
'fontSize' => 25, // captcha image characters fontsize
'fontPath' => WWW_ROOT . 'tahomabd.ttf', // captcha image font
'noiseColor' => '#ccc',
'bgColor' => '#fff',
'noiseLevel' => '100',
'textColor' => '#000'
);
$img = $this->Captcha->ShowImage($settings);
echo $img;
}
public function sendEmail($value)
{
exit;
}
public function editGroupExpense()
{
$data["id"] = 13;
$data["title"] = __("LBL_TEST_TITLE_MODIFIED");
$data["currency"] = "BDT";
$data["description"] = __("LBL_THIS_UPDATE_DESCRIPTION");
$data["language"] = "bd";
$data["is_secret"] = "1";
$data["secret_key"] = "bbb";
$this->loadModel('Expense');
$unique_url = $this->Expense->updateGroupexpense($data);
if ($unique_url != "") {
echo __("LBL_DATA_MODIFIED");
}
}
public function addParticipant()
{
$data["group_expense_id"] = 13;
$data["name"] = "Rohit";
$this->loadModel('Participant');
$result = $this->Participant->addParticipant($data);
if ($result == "1") {
echo __("LBL_PARTICIPANT_ADDED");
}
}
public function removeParticipant()
{
$data["participant_id"] = 33;
$this->loadModel('Participant');
$result = $this->Participant->removeParticipant($data);
if ($result == "1") {
echo __("LBL_PARTICIPANT_REMOVED");
}
}
private function addGroupSetting($data)
{
$this->loadModel('GroupSetting');
$request = [
'is_restricted_mode' => $data['is_restricted_mode'],
'expense_id' => $data['expense_id'],
'unique_url' => $data['unique_url']
];
return $this->GroupSetting->saveGroupSetting($request);
}
private function setPermission(){
$this->user_id = $this->Session->read('userData.id');
$permission_permitted = (!empty($this->user_id) && $this->user_id>0);
$this->set('permitted', $permission_permitted);
}
private function addPermission($request)
{
$PermissionTable = ClassRegistry::init('PermissionTable');
return $PermissionTable->addPermission($request);
}
private function insertAccessInfo($data){
//insert data into the table access_infos
$accessInfoData["id"] = $data["id"];
$accessInfoData["unique_url"] = $data["unique_url"];
$accessInfoData["access_time"] = $this->getSystemCurrentTimeStamp();
$error = $this->AccessInfo->saveAccessInfo($accessInfoData);
}
/*public function updateMultipleParticipant(){
$data = array("30"=>"Frank","31"=>"Sharel");
$this->loadModel('Participant');
$result= $this->Participant->updateMultipleParticipant($data);
if($result == "1"){
echo "Participants have been modified!";
}
}*/
}

View File

@@ -0,0 +1,33 @@
<?php
class MaintenanceController extends AppController
{
var $name = 'Maintenance';
var $helpers = array('Html');
public function initialize()
{
$this->setDefaultTimeStamp();
}
public function beforeRender() {
parent::beforeRender();
$this->layout = 'empty';
}
function index()
{
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
<?php
class MobileController extends AppController
{
var $name = 'Mobile';
var $helpers = array('Html', 'Form');
public $components = array('MobileDetect');
public function beforeRender() {
parent::beforeRender();
$this->layout = 'mobile';
if($this->Session->check("homecontroller_layout")){
//$this->layout = '';
$this->Session->delete("homecontroller_layout");
}
}
function index()
{
$uniqueURL = $this->Session->read("current_unique_url");
// echo $uniqueURL;exit;
$expenseType = trim(substr($uniqueURL, 0, 1));
$this->set("expenseType",$expenseType);
if($expenseType == "6" || $expenseType == "7" || $expenseType == "8"){
$this->loadWeb($uniqueURL);
} else {
$detect = new MobileDetectComponent();
if ($detect->isAndroid()) {
$this->set("device","android");
} else if($detect->isIphone()){
$this->set("device","iphone");
} else if($detect->isWindows()){
$this->set("device","windows");
} else {
$this->set("device","pc");
}
$this->set("unique_url",$uniqueURL);
}
//get user's OS and show relevant page
// allplayer://expensecount.com/unique_url
}
public function loadWeb($unique_url){
$this->Session->write("skip_mobile_option","yes");
if(empty($unique_url)){
$this->redirect(array('controller'=> 'Home','action'=> 'index'));
exit;
}
$this->redirect(array('controller'=> $unique_url));
exit;
}
}
?>

View File

@@ -0,0 +1,927 @@
<?php
/**
* Static content controller.
*
* This file will render views from views/pages/
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Controller
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Cake\Network\Email\Email;
use Cake\ORM\TableRegistry;
App::uses('AppController', 'Controller');
/**
* Static content controller
*
* Override this controller by placing a copy in controllers directory of an application
*
* @package app.Controller
* @link http://book.cakephp.org/2.0/en/controllers/pages-controller.html
*/
class PagesController extends AppController {
/**
* This controller does not use a model
*
* @var array
*/
public $uses = array('Comment','GroupExpense','FamilyExpense','Meal','LogAppVisitors','UserGroup','UserSubscription');
var $helpers = array('Html', 'Form');
public $components = array('Captcha','MobileDetect','Permission');
private $group_status = ['Active' => 1,'Archived' => 2];
public function beforeRender() {
parent::beforeRender();
$this->layout = 'visitor';
if($this->Session->check("mobile_app_layout")){
$this->layout = 'mobile';
$this->Session->delete("mobile_app_layout");
}
}
function index()
{
}
public function termscondition(){
}
public function privacypolicy(){
}
public function faq(){
}
public function news(){
}
public function downloadAndroidApp(){
$this->render('download_android_app');
}
public function feedback()
{
if ($this->request->is('Post') && $this->request->data["Comment"]) {
$error = "";
//validate email and comment
$email = trim($this->request->data['Comment']["feedbackemail"]);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = "EMAIL_ERR";
$this->set('email_error', "Email is invalid");
}
$comment = trim($this->request->data['Comment']["comment"]);
if (empty($comment)) {
$error = "COMMENT_ERR";
$this->set("comment_error", __("LBL_WRITE_IN_COMMENT_BOX"));
}
if (isset($_COOKIE['ecc']) && $_COOKIE['ecc'] !== $this->request->data['captcha']){
$message = '<div class="alert alert-danger alert-dismissible" role="alert">' . 'Captcha doesn\'t not match' . '</div>';
$this->Session->write('system.message', $message);
$error ='captcha';
}else{
$this->Session->write('system.message','');
}
// $responseData = $this->getCaptchaResponse($this->request->data['captcha-response']);
// if($responseData->success){
if( $error == "" ) {
$captcha = $this->Session->read('captcha_code');
if (strlen($captcha) > 0 && ($captcha == $this->request->data['Comment']['captcha'])) {
$this->Session->delete('captcha_code');
//if ( $error == "" && strlen($captcha)> 0 && ($captcha == $this->request->data['Comment']['captcha']) ){
//insert into comment table
$this->request->data['Comment']["ip"] = $this->getClientIp();
$this->request->data['Comment']["create_date"] = date("Y-m-d h:i:s");
$result = $this->Comment->createFeedback($this->request->data['Comment']);
if (!empty($result)) {
$this->set("error", __("LBL_DATA_SAVING_FAILED"));
} else {
$this->request->data["Comment"]["captcha"] = "";
$this->set("success", "Message Sent!");
$params = array();
$params["email"] = trim($this->request->data['Comment']["feedbackemail"]);
$trimed_comment = trim($this->request->data['Comment']["comment"]);
$params["comment"] = nl2br($trimed_comment);
$params["ip"] = $this->request->data['Comment']["ip"];
$this->sendEmail($params);
}
} else {
$this->request->data["Comment"]["captcha"] = "";
$this->set("captcha_error", __("LBL_CAPTCHA_ERROR"));
}
}
} else {
$token = $this->getSecretKey(5);
$this->set("captcha",$token);
$this->Session->write("captcha_code",$token);
$this->Session->write('system.message', '');
}
}
private function getSecretKey($length = 10){
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
private function sendEmail($params){
$data = array();
$data["email_from"] = $params["email"];
$data["comment"] = $params["comment"];
$data["ip"] = $params["ip"];
$default = array(
'host' => Configure::read('expensecount.email.smtp.host'),
'port' => 587,
'auth' => 'plain',
'username' => Configure::read('expensecount.email.smtp.username'),
'password' => Configure::read('expensecount.email.smtp.password'),
'tsl' => false,
'transport' => 'Smtp',
'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
'returnPath' => Configure::read('expensecount.email.smtp.from'),
'layout' => false,
'emailFormat' => 'html',
//'template' => 'only_text',
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
App::uses('CakeEmail', 'Network/Email');
//echo $Email->
$Email = new CakeEmail($default);
$Email->to(array(SUPPORT_EMAIL,"asoftbd07@gmail.com"));
$Email->emailFormat('html');
$Email->template('feedback',null)->viewVars( array('data' => $data));
$Email->subject('ExpenseCount-Feedback on "'.date("Y-m-d h:i:s").'" ');
$Email->replyTo($data["email_from"]);
$Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount.com"));
//$Email->smtpOptions = $default;
$Email->delivery = 'Smtp';
$Email->send();
}
public function aboutus(){/*
$data = array();
$data["email"] = "rajibcuetcse@gmail.com";
$data["expense_title"] = "PAGE CONTROLLER";
$data["unique_url"] = "UTF34234";
$default = array(
'host' => Configure::read('expensecount.email.smtp.host'),
'port' => 25,
'auth' => 'plain',
'username' => Configure::read('expensecount.email.smtp.username'),
'password' => Configure::read('expensecount.email.smtp.password'),
'tsl' => false,
'transport' => 'smtp',
'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
'returnPath' => Configure::read('expensecount.email.smtp.from'),
'layout' => false,
'emailFormat' => 'html',
// 'template' => 'email',
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
App::uses('CakeEmail', 'Network/Email');
//echo $Email->
$Email = new CakeEmail();
$Email->to($data["email"]);
$Email->emailFormat('html');
$Email->template('email',null)->viewVars( array('data' => $data));
$Email->subject('ExpenseCount "'.$data["expense_title"].'" ');
$Email->replyTo(Configure::read('expensecount.email.smtp.from'));
$Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount"));
$Email->smtpOptions = $default;
$Email->delivery = 'smtp';
$Email->send();
exit;
*/}
public function mobileApps($expense_type="")
{
if($this->request->is('post')){
$expense_type = $this->request->data('expense_type');
$app_type = $this->request->data('app_type');
$this->saveAppVisitorsInfo($expense_type,$app_type);
if($expense_type == 1 && $app_type == 1){
return $this->redirect("https://play.google.com/store/apps/details?id=com.expensecount.groupExpense");
}elseif ($expense_type == 1 && $app_type == 2){
return $this->redirect("https://itunes.apple.com/us/app/groupexpense/id1150902475?mt=8");
}elseif ($expense_type == 2 && $app_type == 1){
return $this->redirect("https://play.google.com/store/apps/details?id=com.expensecount.messExpense");
}elseif ($expense_type == 2 && $app_type == 2){
return $this->redirect("https://itunes.apple.com/us/app/messexpense/id1179871989?mt=8");
}elseif ($expense_type == 3 && $app_type == 1){
return $this->redirect("https://play.google.com/store/apps/details?id=com.expensecount.familyExpense");
}elseif ($expense_type == 3 && $app_type == 2){
return $this->redirect("https://itunes.apple.com/us/app/familyexpense/id1193007779?mt=8");
}
}
$detect = new MobileDetectComponent();
if($this->Session->check("mobile_app_layout")){
$this->Session->delete("mobile_app_layout");
}
if ($detect->isAndroid()) {
$this->Session->write("mobile_app_layout","true");
$this->set("device","android");
} else if($detect->isIphone()){
$this->Session->write("mobile_app_layout","true");
$this->set("device","iphone");
} else if($detect->isWindows()){
$this->Session->write("mobile_app_layout","true");
$this->set("device","windows");
} else {
$this->set("device","pc");
}
$this->set("expenseType",$expense_type);
}
private function saveAppVisitorsInfo($expense_type,$app_type){
$result = false;
$inputData["expense_type"] = $expense_type;
$inputData["app_type"] = $app_type;
$inputData["visiting_date"] = $this->getSystemCurrentTimeStamp();
$inputData["ip"] = $this->getClientIp();
$inputData["device_info"] = $this->getUserAgent();
//pr($inputData);exit;
$result = $this->LogAppVisitors->insertLogAppVisitors($inputData);
return $result;
}
public function facebookApp(){
}
public function get_captcha()
{
$this->autoRender = false;
App::import('Component','Captcha');
//generate random charcters for captcha
$random = mt_rand(100, 99999);
//save characters in session
$this->Session->write('captcha_code', $random);
$settings = array(
'characters' => $random,
'winHeight' => 70, // captcha image height
'winWidth' => 220, // captcha image width
'fontSize' => 25, // captcha image characters fontsize
'fontPath' => WWW_ROOT.'tahomabd.ttf', // captcha image font
'noiseColor' => '#ccc',
'bgColor' => '#fff',
'noiseLevel' => '100',
'textColor' => '#000'
);
$img = $this->Captcha->ShowImage($settings);
echo $img;
}
public function convertDateToString(){
/* $this->loadModel('GroupExpense');
$this->loadModel('FamilyExpense');
$this->loadModel('Meal');
$result = $this->GroupExpense->find('all', array(
'conditions' => array('expense_date_new' => null),
'limit' => 500
));
foreach($result as $key=>$value){
$id = $value["GroupExpense"]["id"];
$oldDate = $value["GroupExpense"]["expense_date"];
$data = array();
$data["id"] = $id;
$newDateStr = date("d-M-Y",$oldDate);
$newDateStrArray = explode("-",$newDateStr);
$newDateStrArray[1] = ucfirst($newDateStrArray[1]);
$newDateStr = implode("-",$newDateStrArray);
$data["expense_date_new"] = "'".$newDateStr."'";
//$data["expense_date"] = 0;
$this->GroupExpense->updateAll(
array('expense_date_new'=> $data["expense_date_new"]),
array('id' => $data["id"]));
}
echo "<pre>";
print_r($result); */
/* $result = $this->FamilyExpense->find('all', array(
'conditions' => array('expense_date_new' => null),
'limit' => 500
));
foreach($result as $key=>$value){
$id = $value["FamilyExpense"]["id"];
$oldDate = $value["FamilyExpense"]["expense_date"];
$data = array();
$data["id"] = $id;
$newDateStr = date("d-M-Y",$oldDate);
$newDateStrArray = explode("-",$newDateStr);
$newDateStrArray[1] = ucfirst($newDateStrArray[1]);
$newDateStr = implode("-",$newDateStrArray);
$data["expense_date_new"] = "'".$newDateStr."'";
//$data["expense_date"] = 0;
$this->FamilyExpense->updateAll(
array('expense_date_new'=> $data["expense_date_new"]),
array('id' => $data["id"]));
}
echo "<pre>";
print_r($result); */
/* $result = $this->Meal->find('all', array(
'conditions' => array('date_new' => null),
'limit' => 500
));
foreach($result as $key=>$value){
$id = $value["Meal"]["id"];
$oldDate = $value["Meal"]["date"];
$data = array();
$data["id"] = $id;
$newDateStr = date("d-M-Y",$oldDate);
$newDateStrArray = explode("-",$newDateStr);
$newDateStrArray[1] = ucfirst($newDateStrArray[1]);
$newDateStr = implode("-",$newDateStrArray);
$data["date_new"] = "'".$newDateStr."'";
//$data["date"] = 0;
$this->Meal->updateAll(
array('date_new'=> $data["date_new"]),
array('id' => $data["id"]));
}
echo "<pre>";
print_r($result); */
// $unique_url = $this->Expense->createExpense($data,false);
exit;
}
public function myExpenses($unique_url=null)
{
$this->Session->write('system.message', '');
$session_user_id = $this->Session->read('userData.id');
$session_user_id = isset($session_user_id) ? $session_user_id : '';
$userExpenses = [];
// If the user is logged in, get the expense group from the database; otherwise, get it from the cookie.
$this->Session->write('system.is_now_login', false);
if($this->Session->check('userData.id')){
$conditions = array('UserGroup.user_id' => $session_user_id, 'UserGroup.status' => $this->group_status['Active']);
$fields = array('UserGroup.unique_url','UserGroup.participant_id','Expense.title','Expense.create_date');
$userExpenses = $this->UserGroup->groupListWithExpense($fields, $conditions);
$archive_conditions = array('UserGroup.user_id' => $session_user_id, 'UserGroup.status' => $this->group_status['Archived']);
$archive_fields = array('UserGroup.unique_url','UserGroup.participant_id','Expense.title','Expense.create_date');
$archivedExpenses = $this->UserGroup->groupListWithExpense($archive_fields, $archive_conditions);
}else{
$userExpenses = $this->Cookie->read('Expenses');
$archivedExpenses=[];
}
$this->set('user_id', $session_user_id);
$this->set('my_expenses', $userExpenses);
$this->set('archived_expenses', $archivedExpenses);
}
public function removeGroup($unique_url)
{
$this->Session->write('system.message', '');
$session_user_id = $this->Session->read('userData.id');
$session_user_id = isset($session_user_id) ? $session_user_id : '';
if(!empty($unique_url)){
// delete a group from myExpense
if($this->Session->check('userData.id')) {
$userGrpdata['skip_process_validation'] = 1;
$userGrpdata['user_id'] = $session_user_id;
$userGrpdata['unique_url'] = $unique_url;
$this->callAPI(HTTP_SITE_URL . "/users/groupdelete.json", 'POST', json_encode($userGrpdata));
}
if (empty($session_user_id)) {
$expenses = $this->Cookie->read('Expenses');
foreach ($expenses as $key => $expense) {
if ($expense['unique_url'] == $unique_url) {
unset($expenses[$key]);
break;
}
}
$expenses = array_values($expenses);
$this->Cookie->write('Expenses', $expenses, false, '24000 hours');
}
}
return $this->redirect('myExpenses');
}
public function archiveGroup($unique_url)
{
$this->Session->write('system.message', '');
$session_user_id = $this->Session->read('userData.id');
$session_user_id = isset($session_user_id) ? $session_user_id : '';
if(!empty($unique_url)){
// delete a group from myExpense
if($this->Session->check('userData.id')) {
$userGrpdata['skip_process_validation'] = 1;
$userGrpdata['user_id'] = $session_user_id;
$userGrpdata['unique_url'] = $unique_url;
$userGrpdata['status'] = $this->group_status['Archived'];
$this->callAPI(HTTP_SITE_URL . "/users/groupRestore.json", 'POST', json_encode($userGrpdata));
}
}
return $this->redirect('myExpenses');
}
public function restoreGroup($unique_url)
{
$this->Session->write('system.message', '');
$session_user_id = $this->Session->read('userData.id');
$session_user_id = isset($session_user_id) ? $session_user_id : '';
if(!empty($unique_url)){
// restore a group from archived Expense
if($this->Session->check('userData.id')) {
$userGrpdata['skip_process_validation'] = 1;
$userGrpdata['user_id'] = $session_user_id;
$userGrpdata['unique_url'] = $unique_url;
$userGrpdata['status'] = $this->group_status['Active'];
$this->callAPI(HTTP_SITE_URL . "/users/groupRestore.json", 'POST', json_encode($userGrpdata));
}
}
return $this->redirect('myExpenses');
}
public function myExpenses_old($key=null, $refresh=null)
{
$session_user_id = ($this->Session->read('userData.id')) ? $this->Session->read('userData.id') : '' ;
//if ($session_user_id == '') {
//$this->redirect('/users/login');
//} else {
if(!empty($key) || (isset($key) && $key !== '')){
// delete a group from myExpense
$my_expenses = $this->Cookie->read('Expenses');
$userGrpdata['skip_process_validation'] = 1;
$userGrpdata['user_id'] = $session_user_id;
$userGrpdata['unique_url'] = $my_expenses[$key]['unique_url'];
$this->callAPI(HTTP_SITE_URL . "/users/groupdelete.json", 'POST', json_encode($userGrpdata));
unset($my_expenses[$key]);
$my_expenses = $this->Cookie->write('Expenses', $my_expenses, false, '24000 hours');
}
if($refresh == 1){
$this->Cookie->write('Expenses', null, false, '24000 hours');
}
if($this->Cookie->read('Expenses') === null) {
// system.is_now_login is used to check if user just loged in now. I think we might not need this.
// If there are groups in cookie show it; otherwise load from database; Reset the cookie during logout
$this->Session->write('system.is_now_login', false);
if($this->Session->check('userData.id')){
$user_id = $this->Session->read('userData.id');
$conditions = array('UserGroup.user_id' => $user_id);
$fields = array('UserGroup.unique_url','UserGroup.participant_id','Expense.title','Expense.create_date');
$userExpenses = $this->UserGroup->listWithExpense($fields, $conditions);
if(!empty($userExpenses)){
$this->Cookie->write('Expenses', $userExpenses, false, '24000 hour');
}
}
}
else {
$this->Session->write('system.message', '');
}
$my_expenses = $this->Cookie->read('Expenses');
$this->set('user_id', $session_user_id);
$this->set('my_expenses', $my_expenses);
//}
}
public function products()
{
$products = array();
$requestData = $this->deviceData();
$apiResponse = $this->callGETAPI(HTTP_SITE_URL . "/products/list.json?".http_build_query($requestData));
$apiResponseArr = json_decode($apiResponse, true);
if (isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) {
$allproducts = $apiResponseArr['response']['products'];
if(!empty($allproducts)){
foreach ($allproducts as $k => $product){
if(empty($products[$product['expense_type']])){
$products[$product['expense_type']] = $product;
}
$productPriceArray[$product['expense_type']][] = $product;
}
}
} else {
$this->Session->write('system.message', 'No Product Found');
}
$this->set(compact('products','productPriceArray'));
}
public function getProduct()
{
$this->autoRender = false;
$product = array();
if($this->request->is('ajax')) {
$this->loadModel('Product');
$conditions = array(
'expense_type' => $this->request->data['expense_type'],
'payment_cycle' => $this->request->data['payment_cycle']
);
$product = $this->Product->list($conditions);
}
echo json_encode($product[0]);
}
function preparingProductBuyInput($requestData)
{
/*
"product_id":"2",
"product_sku":"FE6M",
"user_id":"34",
"payment_type_id":"1",
"platform_id":"2",
"amount":"20",
"access_token":"0c1d9f14e828929a9fd7c0ca46bf4a6a8d0e6bc3ce78ed61d41cd8665521fd81",
"device_id":"234234-34234-234234-234234-324234",
"random_number":"4537",
*/
$item_name = explode('-',$requestData['item_name']);
$data['product_id'] = ltrim($item_name[1],'d');
$data['product_sku'] = ltrim($item_name[2],'s');
$data['user_id'] = ltrim($item_name[3],'u');
$data['expense_type'] = ltrim($item_name[0],'t');
$data['amount'] = $requestData['amt'];
$data['platform_id'] = 3; //1 = android, 2 = iphone 3 = web.
$data['payment_type_id'] = 3; //1= Wallet, 2 = Credit Card, 3=Paypal
$data["device_id"] = session_id();
$data["random_number"] = rand(1000, 9999);
$data["access_token"] = $this->getUserToken($data["device_id"], $data["random_number"]);
return $data;
}
public function paypalipn()
{
// echo 'this is paypal ipn page';
// pr($this->request->query);
// die;
$this->loadModel('UserSubscription');
$this->loadModel('User');
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// Read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
/*
* Post IPN data back to PayPal to validate the IPN data is genuine
* Without this step anyone can fake IPN data
*/
$paypalURL = PAYPAL_URL;
$ch = curl_init($paypalURL);
if ($ch == FALSE) {
return FALSE;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: company-name'));
$res = curl_exec($ch);
/*
* Inspect IPN validation result and act accordingly
* Split response headers and payload, a better way for strcmp
*/
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp($res, "VERIFIED") == 0 || strcasecmp($res, "VERIFIED") == 0) {
// Retrieve transaction data from PayPal
$inputData = array();
$paypalInfo = $_POST;
$inputData['subscr_id'] = $subscr_id = $paypalInfo['subscr_id'];
$inputData['payer_email'] = $payer_email = $paypalInfo['payer_email'];
$inputData['item_name'] = $item_name = $paypalInfo['item_name'];
$inputData['item_number'] = $item_number = $paypalInfo['item_number'];
$inputData['txn_id'] = $txn_id = !empty($paypalInfo['txn_id'])?$paypalInfo['txn_id']:'';
$inputData['payment_gross'] = $payment_gross = !empty($paypalInfo['mc_gross'])?$paypalInfo['mc_gross']:0;
$inputData['currency_code'] = $currency_code = $paypalInfo['mc_currency'];
$inputData['validity'] = $subscr_period = !empty($paypalInfo['period3'])?$paypalInfo['period3']:floor($payment_gross/$itemPrice);
$inputData['payment_status'] = $payment_status = !empty($paypalInfo['payment_status'])?$paypalInfo['payment_status']:'';
$inputData['user_id'] = $custom = $paypalInfo['custom'];
$subscr_date = !empty($paypalInfo['subscr_date'])?$paypalInfo['subscr_date']:date("Y-m-d H:i:s");
$dt = new DateTime($subscr_date);
$inputData['valid_from'] = $subscr_date = $dt->format("Y-m-d H:i:s");
$inputData['valid_to'] = $subscr_date_valid_to = date("Y-m-d H:i:s", strtotime(" + $subscr_period month", strtotime($subscr_date)));
if(!empty($txn_id)){
// Check if transaction data exists with the same TXN ID
// $prevPayment = $db->query("SELECT id FROM user_subscriptions WHERE txn_id = '".$txn_id."'");
// Insert transaction data into the database
/*$insert = $db->query("INSERT INTO user_subscriptions
(user_id,validity,valid_from,
valid_to,item_number,txn_id,payment_gross,
currency_code,subscr_id,payment_status,payer_email)
VALUES('".$custom."','".$subscr_period."','".$subscr_date."','"
.$subscr_date_valid_to."','".$item_number."','".$txn_id."','".$payment_gross."','"
.$currency_code."','".$subscr_id."','".$payment_status."','".$payer_email."')");
// Update subscription id in the users table
if($insert && !empty($custom)){
$subscription_id = $db->insert_id;
$update = $db->query("UPDATE users SET subscription_id = {$subscription_id} WHERE id = {$custom}");
}
*/
$existUserSub = $this->UserSubscription->isUserSubscriptionExist($txn_id);
if (isset($existUser[0]) && empty($existUser[0])) {
$UserSubObj = $this->UserSubscription->insertUserSubscription($inputData);
if (isset($UserSubObj[1]['id']) && ($UserSubObj[1]['id'] > 0)) {
$subscription_id = $UserSubObj[1]['id'];
$user_id = $custom;
$this->User->updateFieldsById($user_id, $fields = array('user_subscription_id' => $subscription_id));
}
}
}
}
die;
// return false;
}
public function paypalcancel()
{
// do nothing
}
public function createGroup()
{
echo 'this is createGroup page';
pr($this->request->query);
die;
$data = $this->preparingProductBuyInput($this->request->query);
$apiResponse = $this->callAPI(HTTP_SITE_URL . "/products/buy.json", 'POST', json_encode($data));
$apiResponseArr = json_decode($apiResponse, true);
if (isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) {
$this->redirect('/pages/myExpenses');
/*if ($data['expense_type'] == 1):
$this->redirect('/Home/createGroupExpense');
elseif ($data['expense_type'] == 2):
$this->redirect('/Home/createMessExpense');
elseif ($data['expense_type'] == 3):
$this->redirect('/Home/createFamilyExpense');
endif;*/
} else {
$message = 'Something Wrong';
$this->Session->write('system.message', $message);
$this->redirect('/pages/products');
}
}
public function getToken(){
$device_id = "2sdfd6788ds76f8sd6f8f";
$random_number = "c9du5htkwwACZWLcraKrngKbKPtJ1YaY";
$unique_number = $device_id.$random_number; // device id + six digit random number
$salt = 'Nop@ss%!*-+@s=_17';
$generated_token = hash('sha256', $unique_number . $salt);
echo $generated_token;exit;
}
public function getSecretKeyss()
{
$device_id = "2sdfd6788ds76f8sd6f8f";
$this->loadModel('AccessKey');
$access_key = $this->AccessKey->getAccessToken($device_id);
//print_r($access_key['AccessKey']['secret_key']);
echo $access_key;
exit;
}
public function addGroup()
{
$url = $this->request->data['unique_url'];
$unique_url = str_replace(HTTP_SITE_URL.'/', '', $url);
$sessionProfileId = $this->Session->read('userData.profile_id');
$sessionUserId = $this->Session->read('userData.id');
list($status, $status_desc, $expObj) = $this->validateUniqueUrl($unique_url);
if (empty($status)) {
$permission = $this->Permission->PermissionByUserId($unique_url, $sessionUserId);
if ($permission != NO_PERMIT) {
$user_group = $this->UserGroup->find('first', array(
'conditions' => array('UserGroup.unique_url' => $unique_url, 'UserGroup.user_id' => $sessionUserId)
));
if (empty($user_group)) {
$inputData['user_id'] = $sessionUserId;
$inputData['unique_url'] = $unique_url;
$inputData['participant_id'] = '1_0';
$result = $this->UserGroup->save($inputData);
$expense_name = 'GroupExpense';
$expense_type = substr($data["unique_url"], 0 , 1);
if ($expense_type == 2) {
$expense_name = "MessExpense";
} elseif ($expense_type == 3) {
$expense_name = "FamilyExpense";
}
$this->userGroupUpdateOnFirebase($sessionUserId, $expense_name);
$this->Cookie->delete('Expenses');
$this->Session->setFlash(__('LBL_Add_GROUP_SUCCESS_MESSAGE'), 'default', ['class' => 'alert alert-success']);
} else {
$this->Session->setFlash(__('LBL_Add_GROUP_EXISTS_MESSAGE'), 'default', ['class' => 'alert alert-danger']);
}
} else {
$this->Session->setFlash('You do not have permission to access this group!', 'default', ['class' => 'alert alert-danger']);
}
}
else{
$this->Session->setFlash( __('LBL_Add_GROUP_NOT_EXISTS_MESSAGE'), 'default', ['class' => 'alert alert-danger']);
}
return $this->redirect(['controller' => 'pages', 'action' => 'myExpenses']);
}
}

View File

@@ -0,0 +1,485 @@
<?php
ini_set('display_errors', 'Off');
ini_set('error_reporting', E_ALL);
class ProductsController extends AppController
{
var $uses = array('Expense', 'GroupExpense', 'Participant', 'DemoExpense', 'AccessInfo', 'User', 'Product', 'Wallet');
public $components = array(
'RequestHandler',
'MobileDetect'
);
private $app_version = "1"; // 1= old expense date, 2= new expense date
public function initialize()
{
$this->app_version = "1"; // 1= old app; 2=new app; date related
$this->setDefaultTimeStamp();
}
public function beforeFilter()
{
parent::beforeFilter(); // TODO: Change the autogenerated stub
}
public function beforeRender()
{
// parent::beforeRender();
// $this->layout = 'visitor';
}
// product List API
public function list()
{
list($data, $status, $status_desc, $error) = $this->processValidation('GET');
$input = array();
if (empty($status)) {
$activeStatus = 1;
$conditions = array('status' => $activeStatus);
$this->loadModel('Product');
$products = $this->Product->list($conditions);
if(!empty($products)){
$input["products"] = $products;
$status = "+000";
$status_desc = "SUCCESS.";
} else {
$status = "-995";
$status_desc = "Product Not Found.";
}
}
$this->processResponse($input, $data, $status, $status_desc);
}
// myproducts API
public function myproducts()
{
list($data, $status, $status_desc, $error) = $this->processValidation('GET');
if (empty($status)) {
list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
}
$input = array();
if (empty($status)) {
$this->loadModel('Product');
$this->loadModel('Order');
$activeStatus = 1;
$productIds = array();
$orderArr = array();
$expenseTypeArr = [1,2,3];
$orderConditions = array(
'user_id' => $data['user_id'],
'SUBSTR(order_unique_id,1,1)' => $data['expense_type'],
'expire_date > ' => $this->getSystemCurrentTimeStamp(),
);
$orders = $this->Order->list($orderConditions);
if(!empty($orders)){
foreach($orders as $k => $order){
if(!in_array($order['Order']['product_id'], $productIds)){
$productIds[] = $order['Order']['product_id'];
$orderArr[] = $order['Order'];
}
}
$prodConditions = array(
'status' => $activeStatus,
'id' => $productIds
);
if(in_array($data['expense_type'], $expenseTypeArr)){
$prodConditions['expense_type'] = $data['expense_type'];
}
$products = $this->Product->list($prodConditions);
$input["products"] = $products;
$input["orders"] = $orderArr;
$status = "+000";
$status_desc = "SUCCESS.";
} else {
$status = "-994";
$status_desc = "Order Not Found.";
}
}
$this->processResponse($input, $data, $status, $status_desc);
}
// product buy API
public function buy()
{
list($data, $status, $status_desc, $error) = $this->processValidation();
if (empty($status)) {
list($status, $status_desc) = $this->validateBuyProduct($data);
}
if (empty($status)) {
list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
}
$input = array();
if (empty($status)) {
$this->loadModel('Product');
$this->loadModel('Order');
$this->loadModel('OrderBilling');
$this->loadModel('Transaction');
$this->loadModel('Recurring');
$this->loadModel('Wallet');
$activeStatus = 1;
$conditions = array(
'id' => $data['product_id'],
'sku' => $data['product_sku'],
'status' => $activeStatus
);
$productData = $this->Product->list($conditions);
if (!empty($productData)) {
$product = $productData[0];
// user wallet data
$wConditions = array(
'user_id' => $data['user_id'],
'status' => $activeStatus
);
$userWallet = $this->Wallet->list($wConditions);
$userWalletData = (isset($userWallet[0]['Wallet'])) ? $userWallet[0]['Wallet'] : array();
// Insert into orders
$orderInput = $this->preparingOrderInput($data, $product, $userObj['id']);
$orderObj = $this->Order->add($orderInput);
$input["order"] = $orderObj[1];
unset($input["order"]['id']);
if (isset($orderObj[1]['id']) && ($orderObj[1]['id'] > 0)) {
// Order_billings
$billingData = (isset($data['billing_info'])) ? $data['billing_info'] : array();
$orderBillingInput = $this->preparingOrderBillingInput($userObj, $orderObj[1]['id'], $billingData);
$orderBillingObj = $this->OrderBilling->add($orderBillingInput);
// transactions
$transactionInput = $this->preparingTransactionInput($data, $product, $orderObj[1], $userWalletData);
$transactionObj = $this->Transaction->add($transactionInput);
}
// incase Recurrings
if ($product['type'] == 1) // 0 = One Time, 1 = Recurring
{
$recurringInput = $this->preparingRecurringInput($data, $product);
$recurringObj = $this->Recurring->add($recurringInput);
}
// Update user table expiry date
$this->updateUserTableExpiryDate($data['user_id'], $product);
$status = "+000";
$status_desc = "SUCCESS.";
} else {
$status = "-995";
$status_desc = "Product Not Found.";
}
}
$this->processResponse($input, $data, $status, $status_desc);
}
private function preparingOrderBillingInput($user, $order_id, $billingData)
{
$returnData = array();
$returnData['order_id'] = $order_id;
$returnData['first_name'] = (isset($billingData['first_name'])) ? $billingData['first_name'] : $user['first_name'];
$returnData['last_name'] = (isset($billingData['last_name'])) ? $billingData['last_name'] : $user['last_name'];
$returnData['address1'] = (isset($billingData['address1'])) ? $billingData['address1'] : '';
$returnData['address2'] = (isset($billingData['address2'])) ? $billingData['address2'] : '';
$returnData['city'] = (isset($billingData['city'])) ? $billingData['city'] : '';
$returnData['state'] = (isset($billingData['state'])) ? $billingData['state'] : '';
$returnData['zip'] = (isset($billingData['zip'])) ? $billingData['zip'] : '';
$returnData['country'] = (isset($billingData['country'])) ? $billingData['country'] : '';
$returnData['phone'] = (isset($billingData['phone'])) ? $billingData['phone'] : '';
$returnData['email'] = (isset($billingData['email'])) ? $billingData['email'] : $user['profile_id'];
$returnData["created_date"] = $this->getSystemCurrentTimeStamp();
$returnData["updated_date"] = $this->getSystemCurrentTimeStamp();
return $returnData;
}
private function preparingTransactionInput($data, $product, $order, $userWalletData)
{
$returnData = array();
$returnData['payment_id'] = $order['payment_id'];
$returnData['user_id'] = $data['user_id'];
$returnData['type'] = 1; // 1 = Purchase, 2 = Deposit
$returnData['entity_id'] = $order['id']; //order_id / deposit_id
$returnData['description'] = '';
$returnData['product_price'] = $product['price'];
$returnData['fee'] = 0;
$returnData['gross'] = $product['price'];
$returnData['cost'] = 0;
$returnData['net'] = $product['price'];
$returnData['currency_id'] = 1; // 1 = USD
$returnData['money_flow'] = '-';
$returnData['current_balance'] = (isset($userWalletData['balance']))? $userWalletData['balance'] : 0;
$returnData['status'] = 1; //0 = Pending, 1= Paid, 2 = Refund, 3 = Payment Fail
$returnData["created_date"] = $this->getSystemCurrentTimeStamp();
$returnData["updated_date"] = $this->getSystemCurrentTimeStamp();
return $returnData;
}
private function preparingRecurringInput($data, $product)
{
/*
* id
* user_id
* product_id
* expense_type 1=Group, 2= Mess, 3 = Family
* next_action_date
* amount
* total_amount
* payment_number Total number of installments
* payment_interval after how many payment cycle
* payment_cycle D, W, M, Y
* created_date
* updated_date
* */
$returnData = array();
$returnData['user_id'] = $data['user_id'];
$returnData['product_id'] = $data['product_id'];
$returnData['expense_type'] = $product['expense_type'];
$returnData['product_price'] = $product['price'];
$returnData["start_date"] = $this->getSystemCurrentTimeStamp();
$returnData['next_action_date'] = $this->getNextActionDate($product, $returnData["start_date"]);
$returnData["amount"] = $data['amount']; // for recurring product
$returnData['total_amount'] = $data['amount'] * $product['payment_number'];
$returnData['payment_number'] = $product['payment_number']; //Total number of installments
$returnData["payment_interval"] = $product['payment_interval']; // after how many payment cycle
$returnData['payment_cycle'] = $product['payment_cycle']; // D, W, M, Y
$returnData["created_date"] = $this->getSystemCurrentTimeStamp();
$returnData["updated_date"] = $this->getSystemCurrentTimeStamp();
return $returnData;
}
private function getNextActionDate($product, $start_date)
{
if ($product['type']) { // if recurring
$intervalType = 0; // day
if ($product['payment_interval'] > 0) {
switch ($product['payment_cycle']) {
case "D":
$unit = $product['payment_interval'];
break;
case "W":
$unit = $product['payment_interval'] * 7;
break;
case "M":
$intervalType = 1;
$unit = $product['payment_interval'];
break;
case "Y":
$intervalType = 2;
$unit = $product['payment_interval'];
break;
default:
$unit = 0;
}
}
if ($intervalType == 1) { // month
return date('Y-m-d H:i:s', strtotime('+' . $unit . ' months', strtotime($start_date)));
} elseif ($intervalType == 2) { // year
return date('Y-m-d H:i:s', strtotime('+' . $unit . ' years', strtotime($start_date)));
} else {
return date('Y-m-d H:i:s', strtotime('+' . $unit . ' days', strtotime($start_date)));
}
}
return false;
}
private function preparingOrderInput($data, $product, $user_id)
{
$returnData = array();
$returnData['payment_id'] = $this->systemGeneratedUniqueId($user_id, $product['expense_type']);
$order_unique_id = $this->orderUniqueId($data, $product['expense_type']);
$returnData['order_unique_id'] = $order_unique_id;
$returnData['purchase_token'] = hash('sha256',$order_unique_id);
$returnData['user_id'] = $data['user_id'];
$returnData['product_id'] = $data['product_id'];
$returnData['expire_date'] = $this->getProductExpireDate($product);
$returnData['product_price'] = $product['price'];
$returnData['fee'] = 0;
$returnData['gross'] = $product['price'];
$returnData['cost'] = 0;
$returnData['net'] = $product['price'];
$returnData['currency_id'] = $product['currency_id'];
$returnData['platform_id'] = $data['platform_id']; // 1=iOS,2=Android,3=Windows
$returnData["device_id"] = session_id();
$returnData['status'] = 1; //0 = Pending, 1= Paid, 2 = Refund, 3 = Payment Fail
$returnData['type'] = $product['type']; //0 = One Time, 1 = Recurring
$returnData["user_ip"] = $this->getClientIp();
$returnData['payment_type_id'] = $data['payment_type_id'];
$returnData["created_date"] = $this->getSystemCurrentTimeStamp();
$returnData["updated_date"] = $this->getSystemCurrentTimeStamp();
return $returnData;
}
private function orderUniqueId($data, $expense_type)
{
return $expense_type . '-' . $data['user_id'] . '-' . time();
}
private function updateUserTableExpiryDate($user_id, $product)
{
$status = false;
if ($user_id > 0) {
switch ($product['expense_type']) {
case "1":
$fields['group_expiry_date'] = '"' . $this->getProductExpireDate($product) . '"';
if ($this->User->updateFieldsById($user_id, $fields)) {
$status = true;
}
break;
case "2":
$fields['mess_expiry_date'] = '"' . $this->getProductExpireDate($product) . '"';
if ($this->User->updateFieldsById($user_id, $fields)) {
$status = true;
}
break;
case "3":
$fields['family_expiry_date'] = '"' . $this->getProductExpireDate($product) . '"';
if ($this->User->updateFieldsById($user_id, $fields)) {
$status = true;
}
break;
default:
// do nothing
break;
}
}
return $status;
}
private function getProductExpireDate($product)
{
$unit = 0;
$intervalType = 0; // day
if ($product['payment_interval'] > 0) {
switch ($product['payment_cycle']) {
case "D":
$unit = $product['payment_interval'];
break;
case "W":
$unit = $product['payment_interval'] * 7;
break;
case "M":
$intervalType = 1;
$unit = $product['payment_interval'];
break;
case "Y":
$intervalType = 2;
$unit = $product['payment_interval'];
break;
default:
$unit = 0;
}
}
if ($intervalType == 1) { // month
return date('Y-m-d H:i:s', strtotime('+' . $unit . ' months'));
} elseif ($intervalType == 2) { // year
return date('Y-m-d H:i:s', strtotime('+' . $unit . ' years'));
} else {
return date('Y-m-d H:i:s', strtotime('+' . $unit . ' days'));
}
}
private function validateBuyProduct($data)
{
//check validity
$error = "";
$error_desc = "";
if (empty($error)) {
if (!array_key_exists('product_id', $data)
|| !array_key_exists('product_sku', $data)
|| !array_key_exists('user_id', $data)
) {
$error = "6";
$error_desc = "product_id, product_sku and user_id are required";
}
}
if (empty($error)) {
if (array_key_exists('billing_info', $data)) {
if (array_key_exists('phone', $data['billing_info']) && ($data['billing_info']['phone'] != '')) {
if (!is_numeric($data['billing_info']['phone'])) {
$error = "7";
$error_desc = "phone number must be numeric";
}
}
}
}
if (empty($error)) {
if (array_key_exists('billing_info', $data)) {
if (array_key_exists('zip', $data['billing_info']) && ($data['billing_info']['zip'] != '')) {
if (!is_numeric($data['billing_info']['zip'])) {
$error = "8";
$error_desc = "zip code must be numeric";
}
}
}
}
if (empty($error)) {
if (array_key_exists('billing_info', $data)) {
if (array_key_exists('email', $data['billing_info'])) {
$regex = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/';
if (!preg_match($regex, $data['billing_info']['email'])) {
$error = "9";
$error_desc = "email address is invalid";
}
}
}
}
return array($error, $error_desc);
}
}

View File

@@ -0,0 +1,83 @@
<?php
trait ApiCallTrait
{
function callAPI($api_url, $request_method = "GET", $post_fields = [], $accessToken = null) {
if (empty($api_url)) {
return false;
}
$curl = curl_init();
$headers = [
"Accept: application/json",
"Content-Type: application/json"
];
// Add Authorization header if token is provided
if ($accessToken) {
$headers[] = "Authorization: Bearer " . $accessToken;
}
// Set cURL options
curl_setopt_array($curl, [
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $request_method,
CURLOPT_HTTPHEADER => $headers,
]);
// Set POST/PUT payload if provided
if (!empty($post_fields) && in_array(strtoupper($request_method), ['POST', 'PUT', 'PATCH'])) {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($post_fields));
}
$response = curl_exec($curl);
$err = curl_error($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($err) {
return "cURL Error: " . $err;
}
return $response;
}
public function fireAndForget($url, $payload, $accessToken)
{
$urlParts = parse_url($url);
$host = $urlParts['host'];
$path = $urlParts['path'];
$fp = fsockopen("ssl://{$host}", 443, $errno, $errstr, 5);
if (!$fp) {
CakeLog::write(LOG_ERR, "Push notification: fsockopen failed ({$errno}) {$errstr}");
return false;
}
$body = json_encode($payload);
$out = "POST {$path} HTTP/1.1\r\n";
$out .= "Host: {$host}\r\n";
$out .= "Authorization: Bearer {$accessToken}\r\n";
$out .= "Content-Type: application/json\r\n";
$out .= "Content-Length: " . strlen($body) . "\r\n";
$out .= "Connection: Close\r\n\r\n";
$out .= $body;
fwrite($fp, $out);
// Signal end of write so FCM receives the full request,
// then close without waiting for the response.
stream_socket_shutdown($fp, STREAM_SHUT_WR);
fclose($fp);
return true;
}
}

View File

@@ -0,0 +1,21 @@
<?php
trait ExtraGroupExpenseTrait
{
public function checkExtraGroupExpense($extras, $expense_title)
{
$result = 99;
$extras_value = 0;
if (!empty($extras)) {
$extras_array = explode("|", $extras);
$extras_value = $extras_array[0];
}
if ($extras_value == 1 || $expense_title == 'Balance Expense') {
$result = 1;
} elseif ($extras_value == 2) {
$result = 2;
}
return $result;
}
}

View File

@@ -0,0 +1,210 @@
<?php
use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;
trait ImageUploadTrait
{
protected $firebase;
private function getFirebaseInstance()
{
// $jsonfilePath = APP . DS . 'Config' . DS . FIREBASE_SECRET;
$jsonfilePath = FIREBASE_SECRET;
$serviceAccount = ServiceAccount::fromJsonFile($jsonfilePath);
$this->firebase = (new Factory)->withServiceAccount($serviceAccount)->create();
}
public function uploadBase64Image($base64Image, $storagePath)
{
try {
$this->getFirebaseInstance();
$imageData = base64_decode($base64Image);
$storage = $this->firebase->getStorage();
$bucket = $storage->getBucket();
$object = $bucket->upload($imageData, [
'name' => $storagePath
]);
if ($object) {
$imageUrl = "https://storage.googleapis.com/{$bucket->name()}/{$storagePath}";
return ['status' => true, 'message' => 'Uploaded', 'url' => $imageUrl];
} else {
return ['status' => false, 'message' => 'Upload failed.'];
}
} catch (\Exception $e) {
return ['status' => false, 'message' => 'Error uploading image: ' . $e->getMessage()];
}
}
public function deleteFolder($storagePath)
{
try {
$this->getFirebaseInstance();
$storage = $this->firebase->getStorage();
$bucket = $storage->getBucket();
$objects = $bucket->object($storagePath);
$objects = $bucket->objects([
'prefix' => $storagePath
]);
$filesDeleted = 0;
foreach ($objects as $object) {
$object->delete();
$filesDeleted++;
}
if ($filesDeleted > 0) {
return ['status' => true, 'message' => "Deleted folder :{$storagePath}"];
} else {
return ['status' => false, 'message' => "No files found in the folder."];
}
} catch (Exception $e) {
return ['status' => false, 'message' => $e->getMessage()];
}
}
public function singleImageDelete($storagePath)
{
try {
$this->getFirebaseInstance();
$storage = $this->firebase->getStorage();
$bucket = $storage->getBucket();
$object = $bucket->object($storagePath);
$filesDeleted = 0;
if ($object->exists()) {
$object->delete();
$filesDeleted++;
}
if ($filesDeleted > 0) {
return ['status' => true, 'message' => "File deleted."];
} else {
return ['status' => false, 'message' => "No file found."];
}
} catch (Exception $e) {
return ['status' => false, 'message' => $e->getMessage()];
}
}
public function downloadImage($basePath, $expire_time='+2 days',$save_path=null)
{
try {
$this->getFirebaseInstance();
$storage = $this->firebase->getStorage();
$bucket = $storage->getBucket();
// Get object from Firebase Storage
$zipPath = $basePath . "receipts_" . time() . ".zip";
$objects = $bucket->objects([
'prefix' => $basePath
]);
$files = [];
foreach ($objects as $object) {
$name = $object->name();
// skip "folder itself"
if (substr($name, -1) === '/') {
continue;
}
$files[] = $object;
}
$zip = new ZipArchive();
$zipFile = TMP . "receipts_" . time() . ".zip";
$zip->open($zipFile, ZipArchive::CREATE);
foreach ($files as $file) {
$fullPath = $file->name();
if (strpos($fullPath, $basePath) === 0) {
$relativePath = substr($fullPath, strlen($basePath));
} else {
$relativePath = basename($fullPath);
}
$content = $file->downloadAsString();
$zip->addFromString($relativePath, $content);
}
$zip->close();
$zipObject = $bucket->upload(
file_get_contents($zipFile),
[
'name' => $save_path
]
);
if (file_exists($zipFile)) {
unlink($zipFile);
}
$expiresAt = new DateTime($expire_time);
$downloadUrl = $zipObject->signedUrl($expiresAt);
return [
'status' => true,
'message' => 'Downloaded successfully.',
'download_url' => $downloadUrl,
'file_path' => $zipPath,
'expires_at' => $expiresAt->format('Y-m-d H:i:s')
];
} catch (\Exception $e) {
return [
'status' => false,
'message' => 'Error downloading image: ' . $e->getMessage()
];
}
}
public function downloadLink($downloadPath, $expire_time='+2 days')
{
try {
$this->getFirebaseInstance();
$storage = $this->firebase->getStorage();
$bucket = $storage->getBucket();
$object = $bucket->object($downloadPath);
$expiresAt = new DateTime($expire_time);
$downloadUrl = $object->signedUrl($expiresAt,[
'version' => 'v4'
]);
return $downloadUrl;
} catch (\Exception $e) {
return [
'status' => false,
'message' => 'Error downloading image: ' . $e->getMessage()
];
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
{
"require": {
"php": "<=5.6.36",
"dropbox/dropbox-sdk": "1.1.*",
"kunalvarma05/dropbox-php-sdk": "^0.2.1"
}
}

2
app/Controller/prod.txt Normal file
View File

@@ -0,0 +1,2 @@
ALTER TABLE `users` ADD `is_verified` TINYINT(4) NOT NULL DEFAULT '0' AFTER `gener`, ADD `nick_name` VARCHAR(20) NOT NULL AFTER `is_verified`;

0
app/Lib/empty Normal file
View File

165
app/License/LGPL-LICENSE Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

20
app/License/MIT-LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2003, 2004 Jim Weirich
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because one or more lines are too long

View File

File diff suppressed because it is too large Load Diff

View File

View File

@@ -0,0 +1,100 @@
msgid "ID"
msgstr "0104043"
msgid "LANGUAGE"
msgstr "English"
msgid "TITLE_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide title(max 50 characters)"
msgid "YOUR_NAME_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide name(max 20 characters)"
msgid "PARTICIPANT_NOT_EMPTY_MAX_CHAR"
msgstr "Participant should be ',' separator(Max 20 characters)"
msgid "CURRENCY_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide currency(max 3 characters)"
msgid "CAPTCHA_NOT_EMPTY_MAX_CHAR"
msgstr "Invalid captcha(max 5 characters)"
msgid "DATA_CREATION_FAIL"
msgstr "Data has not been saved!"
msgid "LBL_PDF"
msgstr "PDF"
msgid "LBL_CSV"
msgstr "CSV"
msgid "LBL_CHARGED"
msgstr "Charged"
msgid "LBL_PAID"
msgstr "Paid"
msgid "LBL_DUE"
msgstr "Due"
msgid "LBL_SUMMARY_REPORT"
msgstr "Summary"
msgid "LBL_INCOME_EXPENSE_BALANCE_COMPARISON"
msgstr "Income, Expense & Balance Comparison"
msgid "LBL_HIDE_SHOW"
msgstr "Hide/Show"
msgid "LBL_GROUP_EXPENSE_LOGO"
msgstr "images/group_expense.jpg"
msgid "LBL_MESS_EXPENSE_LOGO"
msgstr "images/mess_expense.jpg"
msgid "LBL_FAMILY_EXPENSE_LOGO"
msgstr "images/family_expense.jpg"
msgid "LBL_NO_MEAL_AVAILABLE"
msgstr "No meal available"
msgid "LBL_PREVIEW_BTN"
msgstr "Preview"
msgid "LBL_MEALS"
msgstr "Meals"
msgid "LBL_LOGIN"
msgstr "Log In"
msgid "LBL_LOGOUT"
msgstr "Log Out"
msgid "LBL_LOGOUT_MESSAGE"
msgstr "Your are successfully logout"
msgid "LBL_INCORRECT_EMAIL"
msgstr "The email address or password you entered is incorrect!"
msgid "LBL_PRODUCT"
msgstr "Product"
msgid "LBL_PRODUCTS"
msgstr "Products"
msgid "LBL_PRODUCT_PAGE_INFO"
msgstr "All product are shown here"
msgid "LBL_BALANCE_LINK"
msgstr "`${balancePaymentHtml}<p><b>${name1} </b> <b>${name2}</b> <I>কে <b>${balance} ${dashBoard.expense.currency}</b> দিবেন</I><span>`"
msgid "LBL_EXPENSE_NOT_PERMITTED"
msgstr "The group might not exists or you are not authorized!"
msgid "LBL_EXPENSE_NOT_EDIT_PERMISSION"
msgstr "You don't have the necessary permission to perform this operation!"
msgid "LBL_PARTICIPENT_NAME_ERROR"
msgstr "Name cannot contain , or |"

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

View File

@@ -0,0 +1,42 @@
msgid "ID"
msgstr "0104043"
msgid "LANGUAGE"
msgstr "English"
msgid "TITLE_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide title(max 50 characters)"
msgid "YOUR_NAME_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide name(max 20 characters)"
msgid "PARTICIPANT_NOT_EMPTY_MAX_CHAR"
msgstr "Participant should be ',' separator(Max 20 characters)"
msgid "CURRENCY_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide currency(max 3 characters)"
msgid "CAPTCHA_NOT_EMPTY_MAX_CHAR"
msgstr "Invalid captcha(max 5 characters)"
msgid "LBL_LOGIN"
msgstr "Log In"
msgid "LBL_LOGOUT"
msgstr "Log Out"
msgid "LBL_LOGOUT_MESSAGE"
msgstr "Your are successfully logout"
msgid "LBL_INCORRECT_EMAIL"
msgstr "The email address or password you entered is incorrect!"
msgid "LBL_PRODUCT"
msgstr "Product"
msgid "LBL_PRODUCTS"
msgstr "Products"
msgid "LBL_PRODUCT_PAGE_INFO"
msgstr "All product are shown here"

View File

View File

@@ -0,0 +1,138 @@
msgid "ID"
msgstr "0104043"
msgid "LANGUAGE"
msgstr "English"
msgid "TITLE_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide title(max 50 characters)"
msgid "YOUR_NAME_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide name(max 20 characters)"
msgid "PARTICIPANT_NOT_EMPTY_MAX_CHAR"
msgstr "Participant should be ',' separator(Max 20 characters)"
msgid "CURRENCY_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide currency(max 3 characters)"
msgid "CAPTCHA_NOT_EMPTY_MAX_CHAR"
msgstr "Invalid captcha(max 5 characters)"
msgid "LBL_LOGIN"
msgstr "Log In"
msgid "LBL_LOGOUT"
msgstr "Log Out"
msgid "LBL_LOGOUT_MESSAGE"
msgstr "Your are successfully logout"
msgid "LBL_INCORRECT_EMAIL"
msgstr "入力したメールアドレスまたはパスワードが間違っています!"
msgid "LBL_PRODUCT"
msgstr "Product"
msgid "LBL_PRODUCTS"
msgstr "Products"
msgid "LBL_PRODUCT_PAGE_INFO"
msgstr "All product are shown here"
msgid "LBL_BALANCE_LINK"
msgstr "`${balancePaymentHtml}<p><b>${name1} </b> <b>${name2}</b> <I>কে <b>${balance} ${dashBoard.expense.currency}</b> দিবেন</I><span>`"
msgid "LBL_EXPENSE_NOT_PERMITTED"
msgstr "The group might not exists or you are not authorized!"
msgid "LBL_EXPENSE_NOT_EDIT_PERMISSION"
msgstr "You don't have the necessary permission to perform this operation!"
msgid "LBL_EMAIL_MESSAGE"
msgstr "メールアドレスを入力してください"
msgid "LBL_PERMISSION_LIST"
msgstr "権限リスト"
msgid "LBL_ADD_PERMISSION"
msgstr "権限の追加"
msgid "LBL_EDIT_PERMISSION"
msgstr "権限の編集"
msgid "LBL_DELETE_PERMISSION"
msgstr "権限の削除"
msgid "LBL_ENABLE_RESTRICTION_MESSAGE_PERMISSION"
msgstr "この操作を実行する前に制限モードを有効にしてください"
msgid "LBL_ERROR_NOT_EDIT_PERMISSION"
msgstr "この権限は編集できません"
msgid "LBL_DELETE_MESSAGE_PERMISSION"
msgstr "権限を削除しますか?"
msgid "LBL_NOT_DELETE_MESSAGE_PERMISSION"
msgstr "この権限は削除できません。"
msgid "LBL_SELECT_PERMISSION_MESSAGE"
msgstr "権限を選択してください。"
msgid "LBL_EMAIL_EXIST_MESSAGE"
msgstr "メールアドレスが既に存在します。"
msgid "LBL_EXPENSE_TITLE_MESSAGE"
msgstr "タイトルを入力してください"
msgid "LBL_RESTRICTED"
msgstr "制限モード"
msgid "LBL_OFF"
msgstr "オフ"
msgid "LBL_ON_MESSAGE"
msgstr "オン"
msgid "LBL_RESTRICTED_MODE_ERROR_MESSAGE"
msgstr "モードを変更できません。まずすべての権限を削除する必要があります。"
msgid "LBL_EMAIL"
msgstr "メールアドレス"
msgid "LBL_PERMISSION"
msgstr "権限"
msgid "LBL_ADD_GROUP"
msgstr "グループを追加"
msgid "LBL_MESSAGE_UNIQUE_URL"
msgstr "固有のURLを入力してください。"
msgid "LBL_CLOSE"
msgstr "閉じる"
msgid "LBL_Add_URL"
msgstr "固有のURL"
msgid "LBL_Add_GROUP_SUCCESS_MESSAGE"
msgstr "グループの追加に成功しました!"
msgid "LBL_Add_GROUP_EXISTS_MESSAGE"
msgstr "このグループは既に存在します!"
msgid "LBL_Add_GROUP_NOT_EXISTS_MESSAGE"
msgstr "このグループは存在しません!"
msgid "LBL_OPERATION"
msgstr "手術"
msgid "LBL_CHANGED_BY"
msgstr "変更者"
msgid "LBL_PARTICIPENT_NOT_DELETE"
msgstr "この参加者は削除できません。"
msgid "LBL_PARTICIPENT_NAME_ERROR"
msgstr "名前に「,」または「|」を含めることはできません"

View File

View File

View File

@@ -0,0 +1,48 @@
msgid "ID"
msgstr "0104043"
msgid "LANGUAGE"
msgstr "English"
msgid "TITLE_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide title(max 50 characters)"
msgid "YOUR_NAME_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide name(max 20 characters)"
msgid "PARTICIPANT_NOT_EMPTY_MAX_CHAR"
msgstr "Participant should be ',' separator(Max 20 characters)"
msgid "CURRENCY_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide currency(max 3 characters)"
msgid "CAPTCHA_NOT_EMPTY_MAX_CHAR"
msgstr "Invalid captcha(max 5 characters)"
msgid "LBL_LOGIN"
msgstr "Log In"
msgid "LBL_LOGOUT"
msgstr "Log Out"
msgid "LBL_LOGOUT_MESSAGE"
msgstr "Your are successfully logout"
msgid "LBL_PRODUCT"
msgstr "Product"
msgid "LBL_PRODUCTS"
msgstr "Products"
msgid "LBL_PRODUCT_PAGE_INFO"
msgstr "All product are shown here"
msgid "LBL_BALANCE_LINK"
msgstr "`${balancePaymentHtml}<p><b>${name1} </b> <b>${name2}</b> <I>কে <b>${balance} ${dashBoard.expense.currency}</b> দিবেন</I><span>`"
msgid "LBL_EXPENSE_NOT_PERMITTED"
msgstr "The group might not exists or you are not authorized!"
msgid "LBL_EXPENSE_NOT_EDIT_PERMISSION"
msgstr "You don't have the necessary permission to perform this operation!"

View File

File diff suppressed because it is too large Load Diff

View File

View File

@@ -0,0 +1,51 @@
msgid "ID"
msgstr "0104043"
msgid "LANGUAGE"
msgstr "English"
msgid "TITLE_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide title(max 50 characters)"
msgid "YOUR_NAME_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide name(max 12 characters)"
msgid "PARTICIPANT_NOT_EMPTY_MAX_CHAR"
msgstr "Participant should be ',' separator(Max 20 characters)"
msgid "CURRENCY_NOT_EMPTY_MAX_CHAR"
msgstr "Please provide currency(max 3 characters)"
msgid "CAPTCHA_NOT_EMPTY_MAX_CHAR"
msgstr "Invalid captcha(max 5 characters)"
msgid "LBL_LOGIN"
msgstr "Log In"
msgid "LBL_LOGOUT"
msgstr "Log Out"
msgid "LBL_LOGOUT_MESSAGE"
msgstr "Your are successfully logout"
msgid "LBL_INCORRECT_EMAIL"
msgstr "The email address or password you entered is incorrect!"
msgid "LBL_PRODUCT"
msgstr "Product"
msgid "LBL_PRODUCTS"
msgstr "Products"
msgid "LBL_PRODUCT_PAGE_INFO"
msgstr "All product are shown here"
msgid "LBL_BALANCE_LINK"
msgstr "`${balancePaymentHtml}<p><b>${name1} </b> <b>${name2}</b> <I>কে <b>${balance} ${dashBoard.expense.currency}</b> দিবেন</I><span>`"
msgid "LBL_EXPENSE_NOT_PERMITTED"
msgstr "The group might not exists or you are not authorized!"
msgid "LBL_EXPENSE_NOT_EDIT_PERMISSION"
msgstr "You don't have the necessary permission to perform this operation!"

View File

49
app/Model/AccessInfo.php Normal file
View File

@@ -0,0 +1,49 @@
<?php
class AccessInfo extends AppModel
{
var $name='AccessInfo';
public function saveAccessInfo($formData){
$error = "";
$form["id"] = trim($formData["id"]);
$form["unique_url"] = trim($formData["unique_url"]);
$form["access_time"] = date('Y-m-d H:i:s');
$fileds = array('id','unique_url','access_time');
$data["AccessInfo"] = $form;
if(!empty($form["id"]) && !empty($form["unique_url"])){
if(!$this->save($data,false,$fileds)){
$error = "22";
}
}else{
$error = "23";
}
return $error;
}
public function getExpiredExpenses($month,$type=1){
$type_value = $type==1?"months":"days";
date_default_timezone_set("UTC");
$range = date('Y-m-d H:i:s', strtotime("-{$month} {$type_value}"));
$result = $this->find('all',
array(
'conditions' => array('AccessInfo.access_time < ' => $range
)
));
return $result;
}
public function deleteAllExpiredExpenses($deleteList){
$result = $this->deleteAll(
array(array('id' => $deleteList))
);
return $result;
}
}

52
app/Model/AccessKey.php Normal file
View File

@@ -0,0 +1,52 @@
<?php
class AccessKey extends AppModel
{
var $name='AccessKey';
public function saveAccessKey($formData){
$error = "";
$form["device_id"] = trim($formData["device_id"]);
$form["secret_key"] = trim($formData["secret_key"]);
$form["created_on"] = trim($formData["created_on"]);
$fileds = array('device_id', 'secret_key', 'created_on');
$data["AccessKey"] = $form;
if(!empty($form["device_id"]) && !empty($form["secret_key"])){
if(!$this->save($data,false,$fileds)){
$error = "22";
}
}else{
$error = "23";
}
return $error;
}
public function getAccessToken($device_id)
{
$error = "";
$access_key = $this->find('first', array(
'conditions' => array('device_id' => $device_id),
'order'=> array('created_on'=>'desc')
) );
if(empty($access_key)) {
$error = "23";
return $error;
} else {
return $access_key['AccessKey']['secret_key'];
}
}
public function deleteAccessKey($device_id)
{
$access_key = $this->find('first', array(
'conditions' => array('device_id' => $device_id),
'order'=> array('created_on'=>'desc')
) );
$this->delete($access_key['AccessKey']['id']);
}
}

37
app/Model/AppModel.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
/**
* Application model for CakePHP.
*
* This file is application-wide model file. You can put all
* application-wide model-related methods here.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Model
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('ExtraGroupExpenseTrait', 'Controller/Traits');
App::uses('Model', 'Model');
/**
* Application model for Cake.
*
* Add your application-wide methods in the class below, your models
* will inherit them.
*
* @package app.Model
*/
class AppModel extends Model {
use ExtraGroupExpenseTrait;
}

1039
app/Model/Backup.php Normal file

File diff suppressed because it is too large Load Diff

0
app/Model/Behavior/empty Normal file
View File

7
app/Model/Category.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
class Category extends AppModel
{
var $name='Category';
}

34
app/Model/Comment.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
class Comment extends AppModel
{
var $name='Comment';
function createFeedback($inputData){
$result = NULL;
$form["email"] = trim($inputData["feedbackemail"]);
$form["comment"] = trim($inputData["comment"]);
$form["ip"] = trim($inputData["ip"]);
$form["create_date"] = trim($inputData["create_date"]);
$fileds = array('email','comment','ip','create_date');
$dbData["Comment"] = $form;
//print_r($data["Feeback"]);exit;
if(!$this->save($dbData,false,$fileds)){
$result["22"] = __("LBL_EXPENSE_NOT_SAVED");
}
return $result;
}
}
?>

View File

122
app/Model/DemoExpense.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
class DemoExpense extends AppModel
{
var $name = 'DemoExpense';
public function setORMForDemoGroupExpense(){
$this->bindModel(
array('hasMany' => array(
'DemoParticipant' => array(
'className' => 'DemoParticipant',
'conditions' => array('DemoParticipant.expense_id' => 'DemoExpense.id'),
'order' => 'DemoParticipant.create_date ASC',
'foreignKey' => 'expense_id'
),
'DemoGroupExpense' => array(
'className' =>'DemoGroupExpense',
'conditions' => array('DemoGroupExpense.expense_id' => 'DemoExpense.id'),
'order' => 'DemoGroupExpense.create_date ASC',
'foreignKey' => 'expense_id'
)
)));
}
public function setORMForDemoFamilyExpense(){
$this->bindModel(array('hasMany' => array(
'DemoFamilyExpense' => array(
'className' =>'DemoFamilyExpense',
'conditions' => array('DemoFamilyExpense.expense_id' => 'DemoExpense.id'),
'order' => 'DemoFamilyExpense.create_date ASC',
'foreignKey' => 'expense_id'
)
)));
}
public function setORMForDemoMess(){
$this->bindModel(array('hasMany' => array(
'DemoParticipant' => array(
'className' => 'DemoParticipant',
'conditions' => array('DemoParticipant.expense_id' => 'DemoExpense.id'),
'order' => 'DemoParticipant.create_date ASC',
'foreignKey' => 'expense_id'
),
'DemoGroupExpense' => array(
'className' =>'DemoGroupExpense',
'conditions' => array('DemoGroupExpense.expense_id' => 'DemoExpense.id'),
'order' => 'DemoGroupExpense.create_date ASC',
'foreignKey' => 'expense_id'
) ,
'DemoMeal' => array(
'className' =>'DemoMeal',
'conditions' => array('DemoMeal.expense_id' => 'DemoExpense.id'),
'order' => 'DemoMeal.date ASC',
'foreignKey' => 'expense_id'
)
)));
}
public function getDemoGroupExpenseInfoByURL($unique_url){
$expenseType = substr($unique_url, 0, 1);
if($expenseType == "2" || $expenseType == "7"){
$this->setORMForDemoMess();
} else {
$this->setORMForDemoGroupExpense();
}
return $this->find('first', array('conditions' => array('DemoExpense.unique_url' =>$unique_url)));
}
public function getDemoFamilyExpenseInfoByURL($unique_url){
$this->setORMForDemoFamilyExpense();
return $this->find('first', array('conditions' => array('DemoExpense.unique_url' =>$unique_url)));
}
function findExpenseInfoByIds($expenseIdList){
$data = NULL;
if(!empty($expenseIdList) && count($expenseIdList) > 0){
$str = implode(",",$expenseIdList);
$this->hasMany = array();
$result = $this->find('all', array('conditions' => array(
'DemoExpense.id in ('.$str.')'
),
'order' => 'DemoExpense.create_date DESC'));
if(!empty($result)){
$data["expenseList"] = $result;
App::import('model','DemoParticipant');
$participant = new DemoParticipant();
$participantInfo = $participant->find('all', array('conditions' => array(
'DemoParticipant.expense_id in ('.$str.') ' ,'is_creator'=>'1'
)));
$data["participantList"]= $participantInfo;
}
}
// $log = $this->getDataSource()->getLog(false, false);
// debug($log);
return $data;
}
}
?>

View File

@@ -0,0 +1,9 @@
<?php
class DemoFamilyExpense extends AppModel
{
var $name='DemoFamilyExpense';
}

View File

@@ -0,0 +1,6 @@
<?php
class DemoGroupExpense extends AppModel
{
var $name='DemoGroupExpense';
}

7
app/Model/DemoMeal.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
class DemoMeal extends AppModel
{
var $name='DemoMeal';
}

View File

@@ -0,0 +1,7 @@
<?php
class DemoParticipant extends AppModel
{
var $name='DemoParticipant';
}
?>

18
app/Model/Deposit.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
class Deposit extends AppModel
{
var $name='Deposit';
function list($conditions = array() )
{
return $this->find('all', array('conditions' => $conditions));
}
}
?>

View File

@@ -0,0 +1,38 @@
<?php
class EmailHistory extends AppModel
{
var $name = 'EmailHistory';
function insertEmailHistory($form){
$result = null;
//1 = Input data format is not correct
//4 = participant already exist in database
//22 = Data not saved successfully in Database
$fileds = array('unique_url','sent_to','ip','create_date');
$dbData["EmailHistory"] = $form;
//insert into the table group_expenses
if(!$this->save($dbData,false,$fileds)){
$result["22"] = __("LBL_EMAIL_HISTORY_SAVED");
}
//$log = $this->getDataSource()->getLog(false, false);
// debug($log);
return $result;
}
}
?>

674
app/Model/Expense.php Normal file
View File

@@ -0,0 +1,674 @@
<?php
class Expense extends AppModel
{
var $name = 'Expense';
public $hasOne = 'GroupSettings';
function setGroupExpenseValidation()
{
$this->validate = array(
'title' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('TITLE_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '50'),
'message' => __('TITLE_NOT_EMPTY_MAX_CHAR')
)
),
'YourName' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('YOUR_NAME_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', PARTICIPENT_NAME_LENGTH),
'message' => __('YOUR_NAME_NOT_EMPTY_MAX_CHAR')
),
'noForbiddenChars' => array(
'rule' => ['custom', '/^[^,|]*$/'],
'message' => __('LBL_PARTICIPENT_NAME_ERROR')
)
),
'participants' => array(
'notBlank' => array(
'rule' => array('participantLengthCheck', PARTICIPENT_NAME_LENGTH),
'message' => __('PARTICIPANT_NOT_EMPTY_MAX_CHAR')
),
'duplicacy' => array(
'rule' => array('participantDuplicacyCheck', 'YourName'),
'message' => __('PARTICIPANT_DUPCICATE')
)
),
'emails' => array(
'notBlank' => array(
'rule' => array('validEmailCheck'),
'message' => __('EMAIL_IS_NOT_VALIE')
)
),
'currency' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('CURRENCY_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '3'),
'message' => __('CURRENCY_NOT_EMPTY_MAX_CHAR')
)
),
'captcha' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('CAPTCHA_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '5'),
'message' => __('CAPTCHA_NOT_EMPTY_MAX_CHAR')
)
)
);
}
function setFamilyExpenseValidation()
{
$this->validate = array(
'title' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('TITLE_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '50'),
'message' => __('TITLE_NOT_EMPTY_MAX_CHAR')
)
),
'currency' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('CURRENCY_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '3'),
'message' => __('CURRENCY_NOT_EMPTY_MAX_CHAR')
)
),
'emails' => array(
'notBlank' => array(
'rule' => array('validEmailCheck'),
'message' => __('EMAIL_IS_NOT_VALIE')
)
),
'captcha' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('CAPTCHA_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '5'),
'message' => __('CAPTCHA_NOT_EMPTY_MAX_CHAR')
)
)
);
}
function setGroupExpenseModifyValidation()
{
$this->validate = array(
'title' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('TITLE_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '50'),
'message' => __('TITLE_NOT_EMPTY_MAX_CHAR')
),
'noForbiddenChars' => array(
'rule' => ['custom', '/^[^,|]*$/'],
'message' => __('LBL_PARTICIPENT_NAME_ERROR')
)
),
'currency' => array(
'notBlank' => array(
'rule' => 'notBlank',
'message' => __('CURRENCY_NOT_EMPTY_MAX_CHAR')
),
'between' => array(
'rule' => array('maxLength', '3'),
'message' => __('CURRENCY_NOT_EMPTY_MAX_CHAR')
)
)
);
}
/*public $hasMany = array(
'Participant' => array(
'className' => 'Participant',
'conditions' => array('Participant.expense_id' => 'Expense.id'),
'order' => 'Participant.create_date ASC'
),
'GroupExpense' => array(
'className' =>'GroupExpense',
'conditions' => array('GroupExpense.expense_id' => 'Expense.id'),
'order' => 'GroupExpense.create_date ASC') ,
'Meal' => array(
'className' =>'Meal',
'conditions' => array('Meal.expense_id' => 'Expense.id'),
'order' => 'Meal.date ASC')
);*/
public function setORMForGroupExpense()
{
$this->bindModel(array('hasMany' => array(
'Participant' => array(
'className' => 'Participant',
'conditions' => array('Participant.expense_id' => 'Expense.id'),
'order' => 'Participant.create_date ASC'
),
'GroupExpense' => array(
'className' => 'GroupExpense',
'conditions' => array('GroupExpense.expense_id' => 'Expense.id'),
'order' => 'GroupExpense.create_date ASC'
)
)));
}
public function setORMForFamilyExpense()
{
$this->bindModel(array('hasMany' => array(
'FamilyExpense' => array(
'className' => 'FamilyExpense',
'conditions' => array('FamilyExpense.expense_id' => 'Expense.id'),
'order' => 'FamilyExpense.create_date ASC'
)
)));
}
public function setORMForMess()
{
$this->bindModel(array('hasMany' => array(
'Participant' => array(
'className' => 'Participant',
'conditions' => array('Participant.expense_id' => 'Expense.id'),
'order' => 'Participant.create_date ASC'
),
'GroupExpense' => array(
'className' => 'GroupExpense',
'conditions' => array('GroupExpense.expense_id' => 'Expense.id'),
'order' => 'GroupExpense.create_date ASC'
),
'Meal' => array(
'className' => 'Meal',
'conditions' => array('Meal.expense_id' => 'Expense.id'),
'order' => 'Meal.date ASC'
)
)));
}
public function getGroupExpenseInfoByURL($unique_url)
{
$expenseType = substr($unique_url, 0, 1);
if ($expenseType == "2" || $expenseType == "7") {
$this->setORMForMess();
} else {
$this->setORMForGroupExpense();
}
$this->unbindModel(
array(
'hasOne' => array('GroupSettings')
)
);
return $this->find('first', array('conditions' => array('BINARY(Expense.unique_url)' => $unique_url)));
}
public function getFamilyExpenseInfoByURL($unique_url)
{
$this->setORMForFamilyExpense();
$this->unbindModel(
array(
'hasOne' => array('GroupSettings')
)
);
return $this->find('first', array('conditions' => array('BINARY(Expense.unique_url)' => $unique_url)));
}
public function participantLengthCheck($check, $limit)
{
$result = true;
$value = trim($check["participants"]);
if ($value != "") {
$valueArray = explode(",", $value);
foreach ($valueArray as $key => $value) {
if (mb_strlen($value, 'UTF-8') > $limit) {
$result = false;
break;
}
}
}
return $result;
}
public function validEmailCheck($check)
{
$result = true;
$value = trim($check["emails"]);
if ($value != "") {
if (filter_var($value, FILTER_VALIDATE_EMAIL) === false) {
$result = false;
}
}
return $result;
}
public function participantDuplicacyCheck($check, $yourName)
{
$result = true;
$value = trim($check["participants"]);
if ($value != "") {
$valueArray = explode(",", $value);
foreach ($valueArray as $key => $value) {
$valueArray[$key] = trim(strtolower($value));
}
$length = count($valueArray);
$unique_array = array_unique($valueArray);
if (count($unique_array) != $length) {
$result = false;
} else {
foreach ($valueArray as $key => $value) {
if (trim(strtolower($value)) == trim(strtolower($this->data["Expense"][$yourName]))) {
$result = false;
break;
}
}
}
}
return $result;
}
function modifyExpense($expenseFormArray)
{
$result = null;
$form["id"] = trim($expenseFormArray["id"]);
$form["title"] = trim($expenseFormArray["title"]);
$form["currency"] = trim($expenseFormArray["currency"]);
$form["description"] = trim($expenseFormArray["description"]);
$form["version"] = trim($expenseFormArray["version"]);
if (isset($expenseFormArray["default_meal"])) {
$form["default_meal"] = trim($expenseFormArray["default_meal"]);
$fileds = array('id', 'title', 'currency', 'description', 'update_date', 'update_user', 'default_meal', 'version');
} else {
$fileds = array('id', 'title', 'currency', 'description', 'update_date', 'update_user', 'version');
}
$form["update_date"] = time();
$form["update_user"] = "system";
$data["Expense"] = $form;
if (!$this->save($data, false, $fileds)) {
$result["22"] = "expense not has been saved successfully";
}
return $result;
}
function createExpense($expenseFormArray, $isRemote, $archieved = false)
{
$result = "";
$form["unique_url"] = "NEW";
$form["title"] = trim($expenseFormArray["title"]);
$form["currency"] = trim($expenseFormArray["currency"]);
$form["description"] = trim($expenseFormArray["description"]);
$form["language"] = $expenseFormArray["language"];
$form["expense_type"] = $expenseFormArray["expense_type"]; // 1 = Group expense
$form["source"] = $expenseFormArray["source"]; //1=web,2=mobile,3=facebook
$form["create_date"] = $expenseFormArray["create_date"]; //
if (!empty($expenseFormArray["create_user"])) {
$form["create_user"] = $expenseFormArray["create_user"];
} else {
$form["create_user"] = "system";
}
$form["update_date"] = time();
$form["update_user"] = "system";
$form["ip"] = $expenseFormArray["ip"];;
$form["user_agent"] = $expenseFormArray["user_agent"];;
//$form["email"] = trim($expenseFormArray["email"]);
$form["version"] = "0";
$form["status"] = "1";
if ($form["expense_type"] == "2") {
$form["default_meal"] = "0.5|1.0|1.0";
} else {
$form["default_meal"] = "";
}
if (!empty($expenseFormArray["user_id"])) {
$form["user_id"] = $expenseFormArray["user_id"];
}
//insert into the table group_expenses
if ($form["expense_type"] == "1" || $form["expense_type"] == "2") {
$fileds = array(
'unique_url',
'title',
'currency',
'description',
'language',
'expense_type',
'source',
'create_user',
'create_date',
'update_date',
'update_user',
'status',
'default_meal',
'ip',
'user_agent',
'version',
'user_id'
);
if ($archieved) {
$fileds[] = 'id';
$form['unique_url'] = $expenseFormArray["unique_url"];
$form['id'] = $expenseFormArray["id"];
}
$data["Expense"] = $form;
if ($this->save($data, false, $fileds)) {
$id = $this->id;
if ($id != "") {
$this->id = $id;
if ($archieved) {
$this->insertParticipantsByRemote($id, $expenseFormArray["participants"]);
$result = $id . "," . $expenseFormArray["unique_url"];
} else {
$unique_url_id = $expenseFormArray["expense_type"] . $this->getUniqueURLById(time()) . $this->getUniqueURLById($id) . trim($expenseFormArray["secret_key"]);
//update group_expenses
if ($this->saveField("unique_url", $unique_url_id)) {
//insert into participant table
if ($isRemote == false) {
$this->insertParticipants($id, $expenseFormArray["your_name"], $expenseFormArray["participants"]);
} else {
$this->insertParticipantsByRemote($id, $expenseFormArray["participants"]);
}
$result = $id . "," . $unique_url_id;
}
}
}
}
}
else if ($form["expense_type"] == "3") {
$fileds = array(
'unique_url',
'title',
'currency',
'description',
'language',
'expense_type',
'source',
'create_user',
'create_date',
'update_date',
'update_user',
'status',
'default_meal',
'ip',
'user_agent',
'version',
'user_id'
);
if ($archieved) {
$fileds[] = 'id';
$form['unique_url'] = $expenseFormArray["unique_url"];
$form['id'] = $expenseFormArray["id"];
}
$data["Expense"] = $form;
if ($this->save($data, false, $fileds)) {
$id = $this->id;
if ($id != "") {
$this->id = $id;
if ($archieved) {
$result = $id . "," . $expenseFormArray["unique_url"];
} else {
$unique_url_id = $expenseFormArray["expense_type"] . $this->getUniqueURLById(time()) . $this->getUniqueURLById($id) . trim($expenseFormArray["secret_key"]);
//update group_expenses
if ($this->saveField("unique_url", $unique_url_id)) {
//insert into participant table
//if($isRemote == false){
//$this->insertParticipants($id, $expenseFormArray["your_name"],$expenseFormArray["participants"]);
$result = $id . "," . $unique_url_id;
//} else {
//$this->insertParticipantsByRemote($id,$expenseFormArray["participants"]);
//$result = $id.",".$unique_url_id;
//}
}
}
}
}
}
return $result;
}
/* function updateExpense($expenseFormArray){
$result = "";
$form["id"] =$expenseFormArray["id"];
$form["title"] = $expenseFormArray["title"];
$form["currency"] = $expenseFormArray["currency"];
$form["description"] = $expenseFormArray["description"];
$form["language"] = $expenseFormArray["language"];
$form["is_secret"] = $expenseFormArray["is_secret"];
$form["secret_key"] = $expenseFormArray["secret_key"];
$form["update_date"] = time();
$form["update_user"] = "system";
$form["version"] = $expenseFormArray["version"];
$fileds = array('title','currency','description',
'language','is_secret','secret_key','update_date','update_user');
$data["Expense"] = $form;
//update few fields of group_expenses table
if($this->save($data,false,$fileds)){
$result = 1;
}
return $result;
} */
function insertParticipants($id, $creator_name, $participants)
{
$data = array();
$form["Participant"][0]["participant_id"] = "1" . "_" . "0";
$form["Participant"][0]["expense_id"] = $id;
$form["Participant"][0]["name"] = $creator_name;
$form["Participant"][0]["is_creator"] = 1;
$i = 1;
if ($participants != "") {
$participant_array = explode(",", $participants);
foreach ($participant_array as $single_participant) {
if ($single_participant != "") {
$form["Participant"][$i]["participant_id"] = "1" . "_" . $i;
$form["Participant"][$i]["expense_id"] = $id;
$form["Participant"][$i]["name"] = $single_participant;
$form["Participant"][$i]["is_creator"] = 0;
$i = $i + 1;
}
}
}
App::import('model', 'Participant');
$participant = new Participant();
$participant->saveMany($form["Participant"]);
}
function insertParticipantsByRemote($id, $participantList)
{
$i = 0;
foreach ($participantList as $key => $value) {
$form["Participant"][$i]["participant_id"] = $value["participant_id"];
$form["Participant"][$i]["expense_id"] = $id;
$form["Participant"][$i]["name"] = $value["name"];
$form["Participant"][$i]["is_creator"] = $value["is_creator"];
$i = $i + 1;
}
App::import('model', 'Participant');
$participant = new Participant();
$participant->saveMany($form["Participant"]);
}
function findExpenseInfoByIds($expenseIdList)
{
$data = NULL;
if (!empty($expenseIdList) && count($expenseIdList) > 0) {
$str = implode(",", $expenseIdList);
$this->hasMany = array();
$result = $this->find('all', array(
'conditions' => array(
'Expense.id in (' . $str . ')'
),
'order' => 'Expense.create_date DESC'
));
if (!empty($result)) {
$data["expenseList"] = $result;
App::import('model', 'Participant');
$participant = new Participant();
$participantInfo = $participant->find('all', array('conditions' => array(
'Participant.expense_id in (' . $str . ') ',
'is_creator' => '1'
)));
$data["participantList"] = $participantInfo;
}
}
// $log = $this->getDataSource()->getLog(false, false);
// debug($log);
return $data;
}
function getUniqueURLById($in, $to_num = false, $pad_up = false)
{
$index = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$base = strlen($index);
if ($to_num) {
// Digital number <<-- alphabet letter code
$in = strrev($in);
$out = 0;
$len = strlen($in) - 1;
for ($t = 0; $t <= $len; $t++) {
$bcpow = bcpow($base, $len - $t);
$out = $out + strpos($index, substr($in, $t, 1)) * $bcpow;
}
if (is_numeric($pad_up)) {
$pad_up--;
if ($pad_up > 0) {
$out -= pow($base, $pad_up);
}
}
} else {
// Digital number -->> alphabet letter code
if (is_numeric($pad_up)) {
$pad_up--;
if ($pad_up > 0) {
$in += pow($base, $pad_up);
}
}
$out = "";
for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
$a = floor($in / bcpow($base, $t));
$out = $out . substr($index, $a, 1);
$in = $in - ($a * bcpow($base, $t));
}
$out = strrev($out); // reverse
}
return $out;
}
}

View File

View File

@@ -0,0 +1,32 @@
<?php
class ExpenseEmail extends AppModel
{
var $name='ExpenseEmail';
function insertExpenseEmail($inputData){
$result = NULL;
if(isset( $inputData["id"])) {
$form["id"] = $inputData["id"];
}
$form["unique_url"] = $inputData["unique_url"];
$form["email"] = $inputData["email"];
$form["title"] = $inputData["title"];
$form["count_email_attempt"] = $inputData["count_email_attempt"];
if(isset( $inputData["id"])) {
$fileds = array('id', 'unique_url', 'email', 'title', 'count_email_attempt');
} else {
$fileds = array( 'unique_url', 'email', 'title', 'count_email_attempt');
}
$dbData["ExpenseEmail"] = $form;
if(!$this->save($dbData,false,$fileds)){
$result["22"] = __("LBL_EXPENSE_EMAIL_SAVED_SUCCESSFULLY");
}
return $result;
}
}

View File

@@ -0,0 +1,16 @@
<?php
class ExpiredRecord extends AppModel
{
var $name='ExpiredRecord';
public function saveAllExpiredRecords($data){
$error = "";
if(!$this->saveMany($data["ExpiredRecord"])){
$error = 22;
}
return $error;
}
}

View File

@@ -0,0 +1,9 @@
<?php
class ExportReceipt extends AppModel
{
var $name='ExportReceipt';
}

350
app/Model/FamilyExpense.php Normal file
View File

@@ -0,0 +1,350 @@
<?php
class FamilyExpense extends AppModel
{
var $name='FamilyExpense';
//1 = Input data format is not correct
//2 = participant in this expense is deleted by other user or not available
private function validateAddExpense($data,$source){
$errorCode = "";
$checkParticipantList = array();
$form = $this->getFormDataByData($data);
//check expense ID
$expenseIdArray = explode("-",$form["id"]);
if(count($expenseIdArray) != 3 ){
$errorCode = "1";
}
if($errorCode == "" && $source == "1"){
//check expense id already exist in db or not
$data = $this->find('first', array('conditions' => array('FamilyExpense.id' =>$form["id"]), 'fields'=>array('id')));
if(!empty($data)){
$errorCode = "34";
}
}
return $errorCode;
}
private function validateEditExpense($data){
$errorCode= $this->validateAddExpense($data,2);
if(empty($errorCode)){
//check the expense is in DB or not
}
return $errorCode;
}
public function addFamilyExpense($data){
$result = null;
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$errorCode = $this->validateAddExpense($data,1);
if(empty($errorCode)){
$form = $this->getFormDataByData($data);
$fileds = array('id','expense_type','expense_id','record_type','what','category','expense_date','expense_date_new','create_date'.'update_date','amount','is_reimbursement','type','version','images');
$data["FamilyExpense"] = $form;
if(!$this->save($data,false,$fileds)){
$result["22"] = __("LBL_FAMILY_EXPENSE_NOT_SAVED");
}
} else {
$result[$errorCode] = __("LBL_ADD_FAMILY_EXPENSE_FAIL");
}
return $result;
}
public function addMultipleFamilyExpense($FinalFamilyExpenseArray,$expense_id){
$error = "";
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$i = 0;
if(!empty($FinalFamilyExpenseArray)){
foreach( $FinalFamilyExpenseArray as $key=>$value){
$value["source"] = "2"; //2=mobile
$value["expense_id"] = $expense_id;
$form["FamilyExpense"][$i] = $this->getFormDataByData($value);
$i = $i + 1;
}
if(!$this->saveMany($form["FamilyExpense"])){
$error = "22";
}
}
return $error;
}
private function getFormDataByData($data){
$form = array();
$form["id"] = $data["id"];
$form["expense_id"] = $data["expense_id"];
$form["record_type"] = $data["record_type"]; // 1= expense,2=income
$form["what"] = $data["what"];
$form["category"] = $data["category"];
if(isset($data["expense_date_old"])){
$form["expense_date"] = $data["expense_date_old"];
}
$form["expense_date_new"] = $data["expense_date"];
$form["amount"] = $data["amount"];
$form["category"] = $data["category"];
$form["type"] = "1"; // 1=normal expense,2=balance expense
$form["version"] = 0;
if(isset($data["is_reimbursement"])){
$form["is_reimbursement"] = $data["is_reimbursement"];
}
if(isset($data["syn_add_unique_id"])){
$form["syn_add_unique_id"] = $data["syn_add_unique_id"];
}
if(isset($data["create_date"]) && $this->isValidTimeStamp($data["create_date"]) ){
$form["create_date"] = $data["create_date"];
$form["create_date"] = date('Y-m-d H:i:s', $form["create_date"]);
} else if(isset($data["create_date"]) && !empty($data["create_date"])){
$form["create_date"] = $data["create_date"];
} else {
$form["create_date"] = $this->getSystemCurrentIntTime();
}
$form["update_date"] = $this->getSystemCurrentIntTime();
// ## New features
if(isset($data["category_id"]) && !empty($data["category_id"])) {
$form["category_id"] = $data["category_id"];
}
if(isset($data["custom_categories"]) && !empty($data["custom_categories"])) {
$form["custom_categories"] = $data["custom_categories"];
}
if(isset($data["receipts"]) && !empty($data["receipts"])) {
$form["receipts"] = $data["receipts"];
}
if(isset($data["changed_by"]) && !empty($data["changed_by"])) {
$form["changed_by"] = $data["changed_by"];
} else {
$form["changed_by"] = null;
}
$form['images'] = empty($data['images']) ? null : $data['images'];
// ##
return $form;
}
public function modifyMultipleFamilyExpense($expenseList,$expenseId){
$error = "";
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$i = 0;
if(!empty($expenseList)){
foreach( $expenseList as $key=>$value){
$value["expense_id"] = $expenseId;
$version = $value["version"];
$form["FamilyExpense"][$i] = $this->getFormDataByData($value);
$form["FamilyExpense"][$i]['version'] = ($version)+1;
$i++;
}
if(!$this->saveMany($form["FamilyExpense"])){
//data modify fails
$error = "22";
}
}
return $error;
}
public function modifyFamilyExpense($data){
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//3 = group expense not available in database;
//22 = Data not saved successfully in Database
//23 = Log insertion fail
$result = null;
$form = $this->getFormDataByData($data);
//retrieve the existing expense from DB
$dbExpense = $this->find('first', array('conditions' => array('FamilyExpense.id' =>$form["id"]), 'fields'=>array('version')));
/*$dbExpense = $this->find('all',
array('conditions' =>
array('FamilyExpense.id =' => $form["id"]))); */
if(empty($dbExpense)){
//if expense not available in DB
$result["3"] = __("LBL_FAMILY_EXPENSE_NOT_AVAILABLE");
} else {
//increase number of version
$form['version'] = ($dbExpense["FamilyExpense"]["version"])+1;
//check similar like Add expense
$errorCode = $this->validateEditExpense($data);
if(empty($errorCode)){
$fileds = array('id','expense_id','what','expense_date','expense_date_new','update_date','amount','category','is_reimbursement','version','images');
$data["FamilyExpense"] = $form;
if(!$this->save($data,false,$fileds)){
//data modify fails
$result["22"] = __("LBL_DATA_SAVED_SUCCESSFULLY_DATABASE");
}
} else {
//Found error
$result[$errorCode] = __("LBL_EDIT_FAMILY_EXPENSE_FAIL");
}
}
return $result;
}
public function deleteMultipleFamilyExpense($expenseList,$expenseId){
$error = "";
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$i = 0;
if(!empty($expenseList)){
foreach( $expenseList as $key=>$value){
$groupExpenseIdList[] = $value["id"];
$i++;
}
if(!$this->deleteAll(array('FamilyExpense.id' => $groupExpenseIdList))){
//data modify fails
$error = "22";
}
}
return $error;
}
public function deleteFamilyExpense($data){
$result = null;
$form = $this->getFormDataByData($data);
//retrieve the existing expense from DB
/*$dbExpense = $this->find('all',
array('conditions' =>
array('FamilyExpense.id =' => $form["id"])));*/
$dbExpense = $this->find('first', array('conditions' => array('FamilyExpense.id' =>$form["id"]), 'fields'=>array('id')));
if(empty($dbExpense)){
//if expense not available in DB
$result["3"] = __("LBL_FAMILY_EXPENSE_NOT_AVAILABLE");
} else {
if(!$this->delete(array('id'=>$form["id"]))){
//data modify fails
$result["22"] = __("LBL_FAMILY_EXPENSE_NOT_DELETED");
}
}
return $result;
}
private function isValidTimeStamp($timestamp)
{
return ((string) (int) $timestamp === $timestamp)
&& ($timestamp <= PHP_INT_MAX)
&& ($timestamp >= ~PHP_INT_MAX);
}
public function getImagesById($id){
return $this->find('first',array(
'fields' => array('FamilyExpense.id', 'FamilyExpense.images'),
'conditions' => array('FamilyExpense.id =' => $id)));
}
private function getSystemCurrentIntTime(){
date_default_timezone_set("UTC");
return time();
}
}

566
app/Model/GroupExpense.php Normal file
View File

@@ -0,0 +1,566 @@
<?php
class GroupExpense extends AppModel
{
var $name='GroupExpense';
//1 = Input data format is not correct
//2 = participant in this expense is deleted by other user or not available
private function validateAddExpense($data){
$errorCode = "";
$checkParticipantList = array();
$form = $this->getFormDataByData($data);
//check expense ID
$expenseIdArray = explode("-",$form["id"]);
if(count($expenseIdArray) != 3 || $expenseIdArray[0] == ""){
$errorCode = "1";
} else {
array_push($checkParticipantList,$expenseIdArray[0]);
}
//check the participant involes in the expense are available or not
if($errorCode == "" ){
array_push($checkParticipantList,$form["paid_by_participant_id"]);
if(!empty($form["participant_amount"])){
$participantAmtStrArray = explode(",",$form["participant_amount"]);
foreach($participantAmtStrArray as $key=>$value){
$parts = explode("|",$value);
array_push($checkParticipantList,$parts[0]);
}
}
//make array unique
$checkParticipantList = array_unique($checkParticipantList);
//retrieve participant from DB
$dbParticipantList = $this->getParticipantIdListByExpId($form['expense_id']);
//retrieve participants from DB
//print_r($checkParticipantList);exit;
/* $Str = "";
foreach($checkParticipantList as $key=>$value){
$Str .= "{". $key."=>".$value."}";
}
$fp = fopen("rajib.txt","w+");
fwrite($fp, $Str);
fclose($fp); */
foreach($checkParticipantList as $index=>$item){
if (!in_array($item, $dbParticipantList)) {
$errorCode = "2";
}
}
}
return $errorCode;
}
private function validateEditExpense($data){
$errorCode= $this->validateAddExpense($data);
if(empty($errorCode)){
//check the expense is in DB or not
}
return $errorCode;
}
public function getGroupExpenseLog($data){
$expense_id = $data["expense_id"];
$frommDate = $data["fromDate"]." 00:00:00";
/* $date = new DateTime($frommDate);
$frommDate = $date->format('Y-m-d'); */
$toDate = date("Y-m-d", strtotime("+1 day", strtotime($data["toDate"])));
/* $date = new DateTime($toDate);
$toDate = $date->format('Y-m-d'); */
App::import('model','Log');
$log = new Log();
$result = $log->find('all', array('conditions' => array(
'Log.expense_id' =>$expense_id,
'Log.create_date >= ' => $frommDate,
'Log.create_date <= ' => $toDate
),
'order' => 'Log.create_date DESC'));
// $log = $this->getDataSource()->getLog(false, false);
// $fp = fopen("testResult.txt","a+");
// fwrite($fp,$frommDate."=".$toDate);
// debug($log);
return $result;
}
private function getParticipantIdListByExpId($expense_id){
App::import('model','Participant');
$participant = new Participant();
$dbParticipantIdList = array();
$data = $participant->find('all',
array('conditions' =>
array('Participant.expense_id =' => $expense_id)));
foreach($data as $index=>$object){
array_push($dbParticipantIdList,$object["Participant"]["participant_id"]);
}
return $dbParticipantIdList;
}
public function addGroupExpense($data){
$result = null;
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$errorCode = $this->validateAddExpense($data);
if(empty($errorCode)){
$form = $this->getFormDataByData($data);
if($form["expense_type"] != "1"){
$form["participant_amount"] = "";
}
$fileds = array('id','expense_type','expense_id','what','expense_date','expense_date_new','create_date','update_date','amount','paid_by_participant_id','is_reimbursement','participant_amount','isDetails','type','version', 'extras','images');
$data["GroupExpense"] = $form;
if(!$this->save($data,false,$fileds)){
$result["22"] = __("LBL_GROUP_EXPENSE_NOT_SAVED");
}
} else {
$result[$errorCode] = __("LBL_ADD_EXPENSE_FAILS");
}
return $result;
}
public function addMultipleGroupExpense($expenseList,$expense_id){
$error = "";
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$i = 0;
if(!empty($expenseList)){
foreach( $expenseList as $key=>$value){
$value["source"] = "2"; //2=mobile
$value["expense_id"] = $expense_id;
if($value["expense_type"] != "1"){
$value["participant_amount"] = "";
}
$form["GroupExpense"][$i] = $this->getFormDataByData($value);
$i = $i + 1;
}
if(!$this->saveMany($form["GroupExpense"])){
$error = "22";
}
}
return $error;
}
private function getFormDataByData($data){
$form = array();
$form["id"] = $data["id"];
if(isset($data["expense_type"])){
$form["expense_type"] = $data["expense_type"];
} else {
$form["expense_type"] = "1"; //1=group expense,2 = mess expense
}
$form["expense_id"] = $data["expense_id"];
$form["what"] = $data["what"];
if(isset($data["expense_date_old"])){
$form["expense_date"] = $data["expense_date_old"];
}
$form["expense_date_new"] = $data["expense_date"];
$form["amount"] = $data["amount"];
$form["paid_by_participant_id"] = $data["paid_by_participant_id"];
$form["isDetails"] = $data["isDetails"];
$form["type"] = $data["type"]; // 1=normal expense,2=balance expense
if(isset($data["is_reimbursement"])){
$form["is_reimbursement"] = $data["is_reimbursement"];
}
if(isset($data["create_date"]) && $this->isValidTimeStamp($data["create_date"]) ){
$form["create_date"] = $data["create_date"];
$form["create_date"] = date('Y-m-d H:i:s', $form["create_date"]);
} else if(isset($data["create_date"]) && !empty($data["create_date"]) ){
$form["create_date"] = $data["create_date"];
} else {
$form["create_date"] = date('Y-m-d H:i:s');
}
$form["participant_amount"] = $data["participant_amount"];
if(isset($data["previous_desc"])){
$form["previous_desc"] = $data["previous_desc"];
}
if(isset($data["new_desc"])){
$form["new_desc"] = $data["new_desc"];
}
if(isset($data["previous_paid_by"])){
$form["previous_paid_by"] = $data["previous_paid_by"];
}
if(isset($data["syn_add_unique_id"])){
$form["syn_add_unique_id"] = $data["syn_add_unique_id"];
}
$form["version"] = 0;
$form["update_date"] = $this->getSystemCurrentIntTime();
//Make extras more accurately
$result = $this->checkExtraGroupExpense($data['extras'], $data['what']);
if($result != 99) {
$data["extras"] = substr_replace($data["extras"], $result, 0, 1);
}
// assign data to form
$form["extras"] = $data['extras'];
// ## New features
if(isset($data["category_id"]) && !empty($data["category_id"])) {
$form["category_id"] = $data["category_id"];
}
if(isset($data["custom_categories"]) && !empty($data["custom_categories"])) {
$form["custom_categories"] = $data["custom_categories"];
}
if(isset($data["receipts"]) && !empty($data["receipts"])) {
$form["receipts"] = $data["receipts"];
}
if(isset($data["changed_by"]) && !empty($data["changed_by"])) {
$form["changed_by"] = $data["changed_by"];
} else {
$form["changed_by"] = null;
}
$form['images'] = empty($data['images']) ? null : $data['images'];
// ##
return $form;
}
public function modifyMultipleGroupExpense($expenseList,$expenseId){
$error = "";
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$i = 0;
foreach( $expenseList as $key=>$value){
$value["expense_id"] = $expenseId;
$version = $value["version"];
if($value["expense_type"] != "1"){
$value["participant_amount"] = "";
}
$form["GroupExpense"][$i] = $this->getFormDataByData($value);
$form["GroupExpense"][$i]['version'] = ($version)+1;
//set log List
$logList["Log"][$i]['expense_id'] = $form["GroupExpense"][$i]["expense_id"];
$logList["Log"][$i]['previous_desc'] = $form["GroupExpense"][$i]["previous_desc"];
$logList["Log"][$i]['new_desc'] = $form["GroupExpense"][$i]["new_desc"];
$logList["Log"][$i]['previous_paid_by'] = $form["GroupExpense"][$i]["previous_paid_by"];
$i++;
}
App::import('model','Log');
$log = new Log();
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//3 = group expense not available in database;
//22 = Data not saved successfully in Database
//23 = Log insertion fail
//increase number of version
//check similar like Add expense
//$errorCode = $this->validateEditExpense($data);
if(!$this->saveMany($form["GroupExpense"])){
//data modify fails
$error = "22";
} else {
//data modify successfull.hence insert logs
if(!$log->saveMany($logList["Log"])){
//data modify fails
$error = "23";
}
}
return $error;
}
public function modifyGroupExpense($data){
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//3 = group expense not available in database;
//22 = Data not saved successfully in Database
//23 = Log insertion fail
$result = null;
$form = $this->getFormDataByData($data);
//retrieve the existing expense from DB
$dbExpense = $this->find('all',
array('conditions' =>
array('GroupExpense.id =' => $form["id"])));
if(empty($dbExpense)){
//if expense not available in DB
$result["3"] = __("LBL_GROUP_EXPENSE_NOT_AVAILABLE");
} else {
//increase number of version
$form['version'] = ($dbExpense["0"]["GroupExpense"]["version"])+1;
//check similar like Add expense
//$data["expense_date"] = $this->data["date"];
$errorCode = $this->validateEditExpense($data);
if(empty($errorCode)){
if($form["expense_type"] != "1"){
$form["participant_amount"] = "";
}
$fileds = array('id','expense_type','expense_id','what','expense_date','expense_date_new','create_date','update_date','amount','paid_by_participant_id','is_reimbursement','participant_amount','isDetails','version', 'extras','images');
$data["GroupExpense"] = $form;
if(!$this->save($data,false,$fileds)){
//data modify fails
$result["22"] = __("LBL_DATA_SAVED_SUCCESSFULLY_DATABASE");
} else {
//data modify successfull.hence insert logs
App::import('model','Log');
$log = new Log();
$fileds = array('expense_id','previous_paid_by','changed_by','previous_desc','new_desc');
$logData['Log'] = $this->getEditLogData($form);
if(!$log->save($logData,false,$fileds)){
//data modify fails
$result["23"] = __("LBL_LOG_INSERTATION_FAIL");
}
}
} else {
//Found error
$result[$errorCode] = __("LBL_EDIT_EXPENSE_FAILS");
}
}
return $result;
}
private function getEditLogData($form){
$result = array();
$result['expense_id'] = $form['expense_id'];
$result['previous_desc'] = $form['previous_desc'];
$result['new_desc'] = $form['new_desc'];
$result['previous_paid_by'] = $form['previous_paid_by'];
$result['changed_by'] = $form['changed_by'];
return $result;
}
public function deleteMultipleGroupExpense($expenseList,$expenseId){
$error = "";
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//22 = Data not saved successfully in Database
$i = 0;
foreach( $expenseList as $key=>$value){
$groupExpenseIdList[] = $value["id"];
//set log List
$logList["Log"][$i]['expense_id'] = $expenseId;
$logList["Log"][$i]['previous_desc'] = $value["previous_desc"];
$logList["Log"][$i]['new_desc'] = $value["new_desc"];
$logList["Log"][$i]['previous_paid_by'] = $value["previous_paid_by"];
$i++;
}
App::import('model','Log');
$log = new Log();
//check the any of the involves participant(s) has been deleted or not
//check account is closed already or not
//update participant's balance
//3 = group expense not available in database;
//22 = Data not saved successfully in Database
//23 = Log insertion fail
//increase number of version
//check similar like Add expense
//$errorCode = $this->validateEditExpense($data);
if(!$this->deleteAll(array('GroupExpense.id' => $groupExpenseIdList))){
//data modify fails
$error = "22";
} else {
//data modify successfull.hence insert logs
if(!$log->saveMany($logList["Log"])){
//data modify fails
$error = "23";
}
}
return $error;
}
public function deleteGroupExpense($data){
$result = null;
$form = $this->getFormDataByData($data);
//retrieve the existing expense from DB
$dbExpense = $this->find('all',
array('conditions' =>
array('GroupExpense.id =' => $form["id"])));
if(empty($dbExpense)){
//if expense not available in DB
$result["3"] = __("LBL_GROUP_EXPENSE_NOT_AVAILABLE");
} else {
if(!$this->delete(array('id'=>$form["id"]))){
//data modify fails
$result["22"] = __("LBL_GROUP_EXPENSE_NOT_DELETED_SUCCESSFULLY");
} else {
//data modify successfull.hence insert logs
App::import('model','Log');
$log = new Log();
$fileds = array('expense_id','previous_paid_by','changed_by','previous_desc','new_desc');
$logData['Log'] = $this->getEditLogData($form);
if(!$log->save($logData,false,$fileds)){
//data modify fails
$result["23"] = __("LBL_LOG_INSERTATION_FAIL");
}
}
}
return $result;
}
public function getImagesById($id){
return $this->find('first',array(
'fields' => array('GroupExpense.id', 'GroupExpense.images'),
'conditions' => array('GroupExpense.id =' => $id)));
}
private function isValidTimeStamp($timestamp)
{
return ((string) (int) $timestamp === $timestamp)
&& ($timestamp <= PHP_INT_MAX)
&& ($timestamp >= ~PHP_INT_MAX);
}
private function getSystemCurrentIntTime(){
date_default_timezone_set("UTC");
return time();
}
}

View File

@@ -0,0 +1,78 @@
<?php
class GroupSetting extends AppModel
{
var $name='GroupSetting';
private $restricted_modes = ['ON' => 1, 'OFF' => 0];
public function getGroupSettingByURL($unique_url,$custom_select = false){
$options = array(
'conditions' => array('GroupSetting.unique_url' => $unique_url)
);
if ($custom_select) {
$options['fields'] = array(
'GroupSetting.categories',
'GroupSetting.version',
'GroupSetting.is_restricted_mode'
);
}
$groupSettingData = $this->find('first', $options);
if (empty($groupSettingData) && empty($groupSettingData['GroupSetting'])) {
return false;
}
$groupSettingData['GroupSetting']['categories'] = json_decode($groupSettingData['GroupSetting']['categories'], true);
return $groupSettingData['GroupSetting'];
}
public function saveGroupSetting($groupSettingData)
{
$request = $this->_prepareFields($groupSettingData);
return $this->save($request);
}
public function PermissionEnabled($unique_url){
$group_setting = $this->getGroupSettingByURL($unique_url);
if (empty($group_setting)) {
return PUBLIC_PERMIT;
}
$isRestricted = isset($group_setting['is_restricted_mode']) &&
$group_setting['is_restricted_mode'] == $this->restricted_modes['OFF'];
if ($isRestricted) {
return NO_PERMIT;
}
return $group_setting;
}
protected function _prepareFields($data)
{
$returnData = array();
if (isset($data['is_restricted_mode'])) {
$returnData['is_restricted_mode'] = $data['is_restricted_mode'];
}
if (isset($data['expense_id'])) {
$returnData['expense_id'] = $data['expense_id'];
}
if (isset($data['unique_url'])) {
$returnData['unique_url'] = $data['unique_url'];
}
$returnData['categories'] = (!empty($data['categories'])) ? $data['categories'] : '[]';
if (!empty($data['id'])) {
$returnData['id'] = $data['id'];
$returnData['version'] = $data['version'] + 1;
}
else{
$returnData['version'] = 0;
}
return $returnData;
}
}

View File

@@ -0,0 +1,38 @@
<?php
class LoadingHistory extends AppModel
{
var $name = 'LoadingHistory';
function insertLoadingHistory($form){
$result = null;
//1 = Input data format is not correct
//4 = participant already exist in database
//22 = Data not saved successfully in Database
$fileds = array('expense_id','unique_url','ip','user_agent','create_date');
$dbData["LoadingHistory"] = $form;
//insert into the table group_expenses
if(!$this->save($dbData,false,$fileds)){
$result["22"] = __("LBL_LOGIN_HISTORY_NOT_SAVED");
}
//$log = $this->getDataSource()->getLog(false, false);
// debug($log);
return $result;
}
}
?>

6
app/Model/Log.php Normal file
View File

@@ -0,0 +1,6 @@
<?php
class Log extends AppModel
{
var $name='Log';
}
?>

View File

@@ -0,0 +1,50 @@
<?php
class LogAppCrashes extends AppModel
{
var $name='LogAppCrashes';
function insertLogAppCrashes($inputData){
$result = false;
// $expense_type = substr($inputData["unique_url"], 0, 1);
if(!isset($inputData["expense_type"])){
$form["expense_type"] = 0;
} else {
$form["expense_type"] = trim($inputData["expense_type"]);
}
$input_request_data = $this->convertJson($inputData['request']);
$input_response_data = $this->convertJson($inputData['response']);
$form["error_code"] = trim($inputData["error_code"]);
$form["error_desc"] = trim($inputData["error_desc"]);
$form["request"] = $input_request_data;
$form["response"] = $input_response_data;
$form["crash_date"] = trim($inputData["crash_date"]);
$form["ip"] = trim($inputData["ip"]);
$form["device_info"] = trim($inputData["device_info"]);
$fileds = array('expense_type','error_code','error_desc','request','response','crash_date','ip','device_info');
$dbData["LogAppCrashes"] = $form;
//print_r($data["Feeback"]);exit;
if(!$this->save($dbData,false,$fileds)){
$result = true;
}
return $result;
}
private function convertJson($input_data)
{
$data = trim($input_data);
$unserialized_data = unserialize($data);
$json_data = json_encode($unserialized_data);
return $json_data;
}
}

Some files were not shown because too many files have changed in this diff Show More