Improvements to OFX

This commit is contained in:
Hillel Coren 2017-07-11 13:22:11 +03:00
parent 05e5ae1167
commit 967c503134
9 changed files with 81 additions and 12 deletions

View File

@ -154,6 +154,9 @@ if (! defined('APP_NAME')) {
define('DEFAULT_BODY_FONT', 1); // Roboto define('DEFAULT_BODY_FONT', 1); // Roboto
define('DEFAULT_SEND_RECURRING_HOUR', 8); define('DEFAULT_SEND_RECURRING_HOUR', 8);
define('DEFAULT_BANK_OFX_VERSION', 102);
define('DEFAULT_BANK_APP_VERSION', 2500);
define('IMPORT_CSV', 'CSV'); define('IMPORT_CSV', 'CSV');
define('IMPORT_JSON', 'JSON'); define('IMPORT_JSON', 'JSON');
define('IMPORT_FRESHBOOKS', 'FreshBooks'); define('IMPORT_FRESHBOOKS', 'FreshBooks');

View File

@ -97,10 +97,18 @@ class BankAccountController extends BaseController
$username = Crypt::decrypt($username); $username = Crypt::decrypt($username);
$bankId = $bankAccount->bank_id; $bankId = $bankAccount->bank_id;
} else { } else {
$bankId = Input::get('bank_id'); $bankAccount = new BankAccount;
$bankAccount->bank_id = Input::get('bank_id');
} }
return json_encode($this->bankAccountService->loadBankAccounts($bankId, $username, $password, $publicId)); $bankAccount->app_version = Input::get('app_version');
$bankAccount->ofx_version = Input::get('ofx_version');
if ($publicId) {
$bankAccount->save();
}
return json_encode($this->bankAccountService->loadBankAccounts($bankAccount, $username, $password, $publicId));
} }
public function store(CreateBankAccountRequest $request) public function store(CreateBankAccountRequest $request)
@ -111,7 +119,7 @@ class BankAccountController extends BaseController
$username = trim(Input::get('bank_username')); $username = trim(Input::get('bank_username'));
$password = trim(Input::get('bank_password')); $password = trim(Input::get('bank_password'));
return json_encode($this->bankAccountService->loadBankAccounts($bankId, $username, $password, true)); return json_encode($this->bankAccountService->loadBankAccounts($bankAccount, $username, $password, true));
} }
public function importExpenses($bankId) public function importExpenses($bankId)

View File

@ -90,6 +90,8 @@ class Login
public $bank; public $bank;
public $id; public $id;
public $pass; public $pass;
public $ofxVersion;
public $appVersion;
public function __construct($bank, $id, $pass) public function __construct($bank, $id, $pass)
{ {
@ -103,7 +105,7 @@ class Login
$ofxRequest = $ofxRequest =
"OFXHEADER:100\n". "OFXHEADER:100\n".
"DATA:OFXSGML\n". "DATA:OFXSGML\n".
"VERSION:102\n". "VERSION:" . $this->ofxVersion . "\n".
"SECURITY:NONE\n". "SECURITY:NONE\n".
"ENCODING:USASCII\n". "ENCODING:USASCII\n".
"CHARSET:1252\n". "CHARSET:1252\n".
@ -124,7 +126,7 @@ class Login
'<FID>'.$this->bank->fid."\n". '<FID>'.$this->bank->fid."\n".
"</FI>\n". "</FI>\n".
"<APPID>QWIN\n". "<APPID>QWIN\n".
"<APPVER>2500\n". "<APPVER>" . $this->appVersion . "\n".
"</SONRQ>\n". "</SONRQ>\n".
"</SIGNONMSGSRQV1>\n". "</SIGNONMSGSRQV1>\n".
"<SIGNUPMSGSRQV1>\n". "<SIGNUPMSGSRQV1>\n".
@ -173,7 +175,7 @@ class Account
$ofxRequest = $ofxRequest =
"OFXHEADER:100\n". "OFXHEADER:100\n".
"DATA:OFXSGML\n". "DATA:OFXSGML\n".
"VERSION:102\n". "VERSION:" . $this->login->ofxVersion . "\n".
"SECURITY:NONE\n". "SECURITY:NONE\n".
"ENCODING:USASCII\n". "ENCODING:USASCII\n".
"CHARSET:1252\n". "CHARSET:1252\n".
@ -193,7 +195,7 @@ class Account
'<FID>'.$this->login->bank->fid."\n". '<FID>'.$this->login->bank->fid."\n".
"</FI>\n". "</FI>\n".
"<APPID>QWIN\n". "<APPID>QWIN\n".
"<APPVER>2500\n". "<APPVER>" . $this->login->appVersion . "\n".
"</SONRQ>\n". "</SONRQ>\n".
"</SIGNONMSGSRQV1>\n"; "</SIGNONMSGSRQV1>\n";
if ($this->type == 'BANK') { if ($this->type == 'BANK') {

View File

@ -10,11 +10,21 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class BankAccount extends EntityModel class BankAccount extends EntityModel
{ {
use SoftDeletes; use SoftDeletes;
/** /**
* @var array * @var array
*/ */
protected $dates = ['deleted_at']; protected $dates = ['deleted_at'];
/**
* @var array
*/
protected $fillable = [
'bank_id',
'app_version',
'ofx_version',
];
/** /**
* @return mixed * @return mixed
*/ */

View File

@ -31,8 +31,8 @@ class BankAccountRepository extends BaseRepository
public function save($input) public function save($input)
{ {
$bankAccount = BankAccount::createNew(); $bankAccount = BankAccount::createNew();
$bankAccount->bank_id = $input['bank_id'];
$bankAccount->username = Crypt::encrypt(trim($input['bank_username'])); $bankAccount->username = Crypt::encrypt(trim($input['bank_username']));
$bankAccount->fill($input);
$account = \Auth::user()->account; $account = \Auth::user()->account;
$account->bank_accounts()->save($bankAccount); $account->bank_accounts()->save($bankAccount);

View File

@ -14,6 +14,7 @@ use App\Ninja\Repositories\VendorRepository;
use Hash; use Hash;
use stdClass; use stdClass;
use Utils; use Utils;
use Carbon;
/** /**
* Class BankAccountService. * Class BankAccountService.
@ -74,6 +75,7 @@ class BankAccountService extends BaseService
$expenses = Expense::scope() $expenses = Expense::scope()
->bankId($bankId) ->bankId($bankId)
->where('transaction_id', '!=', '') ->where('transaction_id', '!=', '')
->where('expense_date', '>=', Carbon::now()->subYear()->format('Y-m-d'))
->withTrashed() ->withTrashed()
->get(['transaction_id']) ->get(['transaction_id'])
->toArray(); ->toArray();
@ -92,12 +94,13 @@ class BankAccountService extends BaseService
* *
* @return array|bool * @return array|bool
*/ */
public function loadBankAccounts($bankId, $username, $password, $includeTransactions = true) public function loadBankAccounts($bankAccount, $username, $password, $includeTransactions = true)
{ {
if (! $bankId || ! $username || ! $password) { if (! $bankAccount || ! $username || ! $password) {
return false; return false;
} }
$bankId = $bankAccount->bank_id;
$expenses = $this->getExpenses(); $expenses = $this->getExpenses();
$vendorMap = $this->createVendorMap(); $vendorMap = $this->createVendorMap();
$bankAccounts = BankSubaccount::scope() $bankAccounts = BankSubaccount::scope()
@ -112,7 +115,11 @@ class BankAccountService extends BaseService
try { try {
$finance = new Finance(); $finance = new Finance();
$finance->banks[$bankId] = $bank->getOFXBank($finance); $finance->banks[$bankId] = $bank->getOFXBank($finance);
$finance->banks[$bankId]->logins[] = new Login($finance->banks[$bankId], $username, $password);
$login = new Login($finance->banks[$bankId], $username, $password);
$login->appVersion = $bankAccount->app_version;
$login->ofxVersion = $bankAccount->ofx_version;
$finance->banks[$bankId]->logins[] = $login;
foreach ($finance->banks as $bank) { foreach ($finance->banks as $bank) {
foreach ($bank->logins as $login) { foreach ($bank->logins as $login) {

View File

@ -74,6 +74,10 @@ class UpdateDarkMode extends Migration
$table->unsignedInteger('recurring_expense_id')->nullable(); $table->unsignedInteger('recurring_expense_id')->nullable();
}); });
Schema::table('bank_accounts', function ($table) {
$table->mediumInteger('app_version')->default(DEFAULT_BANK_APP_VERSION);
$table->mediumInteger('ofx_version')->default(DEFAULT_BANK_OFX_VERSION);
});
} }
/** /**
@ -94,5 +98,10 @@ class UpdateDarkMode extends Migration
$table->dropColumn('credit_number_prefix'); $table->dropColumn('credit_number_prefix');
$table->dropColumn('credit_number_pattern'); $table->dropColumn('credit_number_pattern');
}); });
Schema::table('bank_accounts', function ($table) {
$table->dropColumn('app_version');
$table->dropColumn('ofx_version');
});
} }
} }

View File

@ -2299,6 +2299,8 @@ $LANG = array(
'padding_help' => 'The number of zero\'s to pad the number.', 'padding_help' => 'The number of zero\'s to pad the number.',
'import_warning_invalid_date' => 'Warning: The date format appears to be invalid.', 'import_warning_invalid_date' => 'Warning: The date format appears to be invalid.',
'product_notes' => 'Product Notes', 'product_notes' => 'Product Notes',
'app_version' => 'App Version',
'ofx_version' => 'OFX Version',
); );

View File

@ -30,9 +30,11 @@
<div data-bind="visible: page() == 'login'"> <div data-bind="visible: page() == 'login'">
<div class="form-padding-right"> <div class="form-padding-right">
@if ($bankAccount) @if ($bankAccount)
{!! Former::populateField('public_id', $bankAccount->public_id) !!} {!! Former::populate($bankAccount) !!}
{!! Former::hidden('public_id') !!} {!! Former::hidden('public_id') !!}
@else @else
{!! Former::populateField('app_version', DEFAULT_BANK_APP_VERSION) !!}
{!! Former::populateField('ofx_version', DEFAULT_BANK_OFX_VERSION) !!}
{!! Former::select('bank_id') {!! Former::select('bank_id')
->data_bind('combobox: bank_id') ->data_bind('combobox: bank_id')
->addOption('', '') ->addOption('', '')
@ -40,6 +42,8 @@
->blockHelp(trans('texts.bank_accounts_help', ['link' => OFX_HOME_URL])) !!} ->blockHelp(trans('texts.bank_accounts_help', ['link' => OFX_HOME_URL])) !!}
@endif @endif
<br/>
{!! Former::password('bank_username') {!! Former::password('bank_username')
->data_bind("value: bank_username, valueUpdate: 'afterkeydown'") ->data_bind("value: bank_username, valueUpdate: 'afterkeydown'")
->label(trans('texts.username')) !!} ->label(trans('texts.username')) !!}
@ -48,6 +52,30 @@
->label(trans('texts.password')) ->label(trans('texts.password'))
->data_bind("value: bank_password, valueUpdate: 'afterkeydown'") ->data_bind("value: bank_password, valueUpdate: 'afterkeydown'")
->blockHelp(trans(Request::secure() ? 'texts.bank_password_help' : 'texts.bank_password_warning')) !!} ->blockHelp(trans(Request::secure() ? 'texts.bank_password_help' : 'texts.bank_password_warning')) !!}
<br/>
{!! Former::select('app_version')
->addOption('Quicken 2005', 1400)
->addOption('Quicken 2006', 1500)
->addOption('Quicken 2007', 1600)
->addOption('Quicken 2008', 1700)
->addOption('Quicken 2009', 1800)
->addOption('Quicken 2010', 1900)
->addOption('Quicken 2011', 2000)
->addOption('Quicken 2012', 2100)
->addOption('Quicken 2013', 2200)
->addOption('Quicken 2014', 2300)
->addOption('Quicken 2015', 2400)
->addOption('Quicken 2016', 2500)
->addOption('Quicken 2017', 2600) !!}
{!! Former::select('ofx_version')
->addOption('100', 100)
->addOption('101', 101)
->addOption('102', 102)
->addOption('103', 103) !!}
</div> </div>
</div> </div>