diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 13172ba9747d..4cac85ef50ca --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Most online invoicing sites are expensive. They shouldn't be. The aim of this project is to provide a free, open-source alternative. Additionally, the hope is this codebase will serve as a sample site for Laravel as well as other JavaScript technologies. -If you'd like to get involved please send an email to hillelcoren at gmail. - ### Features * Core application built using Laravel 4 * Invoice PDF generation directly in the browser diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 51be35c41fbe..30f5d9df8983 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -51,14 +51,31 @@ class AccountController extends \BaseController { else if ($section == ACCOUNT_SETTINGS) { $account = Account::with('account_gateways')->find(Auth::user()->account_id); - $gateways = Gateway::all(); - - foreach ($gateways as $gateway) - { - $gateway->fields = Omnipay::create($gateway->provider)->getDefaultParameters(); - } + $accountGateway = null; - return View::make('accounts.settings', array('account' => $account, 'gateways' => $gateways)); + if (count($account->account_gateways) > 0) + { + $accountGateway = $account->account_gateways[0]; + } + + $data = [ + 'account' => $account, + 'accountGateway' => $accountGateway, + 'config' => json_decode($accountGateway->config), + 'gateways' => Gateway::all() + ]; + + foreach ($data['gateways'] as $gateway) + { + $gateway->fields = Omnipay::create($gateway->provider)->getDefaultParameters(); + + if ($accountGateway && $accountGateway->gateway_id == $gateway->id) + { + $accountGateway->fields = $gateway->fields; + } + } + + return View::make('accounts.settings', $data); } else if ($section == ACCOUNT_IMPORT) { @@ -313,27 +330,22 @@ class AccountController extends \BaseController { return View::make('accounts.import_map', $data); } - private function saveSetting() + private function saveSettings() { - $gateways = Gateway::all(); $rules = array(); - - foreach ($gateways as $gateway) + + if ($gatewayId = Input::get('gateway_id')) { - if (!Input::get('gateway_'.$gateway->id)) - { - continue; - } - + $gateway = Gateway::find($gatewayId); $fields = Omnipay::create($gateway->provider)->getDefaultParameters(); - + foreach ($fields as $field => $details) { - if (in_array($field, array('username','password','signature'))) + if (!in_array($field, ['testMode', 'developerMode', 'headerImageUrl', 'solutionType', 'landingPage'])) { $rules[$gateway->id.'_'.$field] = 'required'; - } - } + } + } } $validator = Validator::make(Input::all(), $rules); @@ -347,25 +359,24 @@ class AccountController extends \BaseController { else { $account = Account::find(Auth::user()->account_id); - - /* Payment Gateways */ $account->account_gateways()->forceDelete(); - foreach ($gateways as $gateway) - { - if (!Input::get('gateway_'.$gateway->id)) - { - continue; - } + if ($gatewayId) + { $accountGateway = new AccountGateway; - $accountGateway->gateway_id = $gateway->id; - $accountGateway->username = Input::get($gateway->id.'_username'); - $accountGateway->password = Input::get($gateway->id.'_password'); - $accountGateway->signature = Input::get($gateway->id.'_signature'); + $accountGateway->gateway_id = $gatewayId; + + $config = new stdClass; + foreach ($fields as $field => $details) + { + $config->$field = Input::get($gateway->id.'_'.$field); + } + + $accountGateway->config = json_encode($config); $account->account_gateways()->save($accountGateway); } - Session::flash('message', 'Successfully updated account'); + Session::flash('message', 'Successfully updated settings'); return Redirect::to('account/settings'); } } @@ -411,7 +422,7 @@ class AccountController extends \BaseController { Image::make($path)->resize(150, 100, true, false)->save('logo/' . $account->key . '.jpg'); } - Session::flash('message', 'Successfully updated account'); + Session::flash('message', 'Successfully updated details'); return Redirect::to('account/details'); } } diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index 7c005c94584f..915e426e6b39 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -18,7 +18,7 @@ class InvoiceController extends \BaseController { return Datatable::collection(Invoice::with('client','invoice_items')->where('account_id','=',Auth::user()->account_id)->get()) ->addColumn('number', function($model) { - return link_to('invoices/' . $model->id . '/edit', $model->number); + return link_to('invoices/' . $model->id . '/edit', $model->invoice_number); }) ->addColumn('client', function($model) { @@ -47,33 +47,35 @@ class InvoiceController extends \BaseController { return View::make('invoices.view')->with('invoice', $invoice); } - private function createGateway($config) + private function createGateway($accountGateway) { - /* - $gateway = Omnipay::create($config->gateway->provider); - $gateway->setUsername($config->username); - $gateway->setPassword($config->password); - $gateway->setSignature($config->signature); - */ - - $gateway = Omnipay::create('PayPal_Express'); - $gateway->setUsername('hillelcoren_api1.gmail.com'); - $gateway->setPassword('1385044249'); - $gateway->setSignature('AFcWxV21C7fd0v3bYYYRCpSSRl31AWJs8aLiB19haXzcAicPwo6qC7Hm'); - - $gateway->setTestMode(true); - $gateway->setSolutionType ("Sole"); - $gateway->setLandingPage("Billing"); - //$gateway->headerImageUrl = ""; + $gateway = Omnipay::create($accountGateway->gateway->provider); + $config = json_decode($accountGateway->config); + + /* + $gateway->setSolutionType ("Sole"); + $gateway->setLandingPage("Billing"); + */ + + foreach ($config as $key => $val) + { + if (!$val) + { + continue; + } + $function = "set" . ucfirst($key); + $gateway->$function($val); + } + return $gateway; } private function getPaymentDetails($invoice) { $data = array( - 'firstName' => 'Bobby', - 'lastName' => 'Tables', + 'firstName' => '', + 'lastName' => '', ); $card = new CreditCard($data); @@ -90,25 +92,31 @@ class InvoiceController extends \BaseController { public function show_payment($invoiceKey) { $invoice = Invoice::with('invoice_items', 'client.account.account_gateways.gateway')->where('invoice_key', '=', $invoiceKey)->firstOrFail(); - //$config = $invoice->client->account->account_gateways[0]; - - $gateway = InvoiceController::createGateway(false); + $accountGateway = $invoice->client->account->account_gateways[0]; + $gateway = InvoiceController::createGateway($accountGateway); try { $details = InvoiceController::getPaymentDetails($invoice); - $response = $gateway->purchase($details)->send(); + $response = $gateway->purchase($details)->send(); + $ref = $response->getTransactionReference(); + + if (!$ref) + { + var_dump($response); + exit('Sorry, there was an error processing your payment. Please try again later.'); + } $payment = new Payment; $payment->invoice_id = $invoice->id; $payment->account_id = $invoice->account_id; - $payment->contact_id = 0; - $payment->transaction_reference = $response->getTransactionReference(); + $payment->contact_id = 0; // TODO_FIX + $payment->transaction_reference = $ref; $payment->save(); if ($response->isSuccessful()) { - + } else if ($response->isRedirect()) { @@ -116,7 +124,7 @@ class InvoiceController extends \BaseController { } else { - exit($response->getMessage()); + } } catch (\Exception $e) @@ -133,7 +141,9 @@ class InvoiceController extends \BaseController { $token = Request::query('token'); $payment = Payment::with('invoice.invoice_items')->where('transaction_reference','=',$token)->firstOrFail(); - $gateway = InvoiceController::createGateway(false); + $invoice = Invoice::with('client.account.account_gateways.gateway')->where('id', '=', $payment->invoice_id)->firstOrFail(); + $accountGateway = $invoice->client->account->account_gateways[0]; + $gateway = InvoiceController::createGateway($accountGateway); try { @@ -180,6 +190,7 @@ class InvoiceController extends \BaseController { 'url' => 'invoices', 'title' => 'New', 'client' => $client, + 'items' => json_decode(Input::old('items')), 'account' => Auth::user()->account, 'products' => Product::getProducts()->get(), 'clients' => Client::where('account_id','=',Auth::user()->account_id)->get()); @@ -199,13 +210,15 @@ class InvoiceController extends \BaseController { private function save($id = null) { $rules = array( - 'number' => 'required', - 'client' => 'required', + 'client' => 'required', + 'invoice_number' => 'required', + 'invoice_date' => 'required' ); $validator = Validator::make(Input::all(), $rules); if ($validator->fails()) { return Redirect::to('invoices/create') + ->withInput() ->withErrors($validator); } else { @@ -238,20 +251,25 @@ class InvoiceController extends \BaseController { $invoice->account_id = Auth::user()->account_id; } - $date = DateTime::createFromFormat('m/d/Y', Input::get('issued_on')); + $date = DateTime::createFromFormat('m/d/Y', Input::get('invoice_date')); $invoice->client_id = $clientId; - $invoice->number = Input::get('number'); + $invoice->invoice_number = Input::get('invoice_number'); $invoice->discount = 0; - $invoice->issued_on = $date->format('Y-m-d'); + $invoice->invoice_date = $date->format('Y-m-d'); $invoice->save(); $items = json_decode(Input::get('items')); foreach ($items as $item) { - if (!isset($item->cost) || !isset($item->qty)) { - continue; + if (!isset($item->cost)) + { + $item->cost = 0; } + if (!isset($item->qty)) + { + $item->qty = 0; + } $product = Product::findProduct($item->product_key); @@ -260,11 +278,13 @@ class InvoiceController extends \BaseController { $product = new Product; $product->account_id = Auth::user()->account_id; $product->product_key = $item->product_key; - $product->notes = $item->notes; - $product->cost = $item->cost; - $product->save(); } + $product->notes = $item->notes; + $product->cost = $item->cost; + $product->qty = $item->qty; + $product->save(); + $invoiceItem = new InvoiceItem; $invoiceItem->product_id = $product->id; $invoiceItem->product_key = $item->product_key; diff --git a/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php b/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php index 33b32aefe8f5..8f5459958037 100755 --- a/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php +++ b/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php @@ -51,6 +51,7 @@ class ConfideSetupUsersTable extends Migration { $t->string('name'); $t->string('provider'); + $t->boolean('visible')->default(true); }); Schema::create('account_gateways', function($t) @@ -61,9 +62,7 @@ class ConfideSetupUsersTable extends Migration { $t->timestamps(); $t->softDeletes(); - $t->string('username'); - $t->string('password'); - $t->string('signature'); + $t->text('config'); }); Schema::create('users', function($t) @@ -140,9 +139,9 @@ class ConfideSetupUsersTable extends Migration { $t->softDeletes(); $t->string('invoice_key')->unique(); - $t->string('number'); + $t->string('invoice_number'); $t->float('discount'); - $t->date('issued_on'); + $t->date('invoice_date'); //$t->foreign('account_id')->references('id')->on('accounts'); }); @@ -173,6 +172,7 @@ class ConfideSetupUsersTable extends Migration { $t->string('product_key'); $t->string('notes'); $t->decimal('cost', 8, 2); + $t->integer('qty'); //$t->foreign('account_id')->references('id')->on('accounts'); }); diff --git a/app/database/seeds/ConstantsSeeder.php b/app/database/seeds/ConstantsSeeder.php index d5b5757c4b87..0651c122f887 100755 --- a/app/database/seeds/ConstantsSeeder.php +++ b/app/database/seeds/ConstantsSeeder.php @@ -7,15 +7,43 @@ class ConstantsSeeder extends Seeder { DB::table('gateways')->delete(); - Gateway::create(array( - 'name' => 'PayPal Express', - 'provider' => 'PayPal_Express' - )); + $gateways = [ + array('name'=>'Authorize.Net AIM', 'provider'=>'AuthorizeNet_AIM'), + array('name'=>'Authorize.Net SIM', 'provider'=>'AuthorizeNet_SIM'), + array('name'=>'Buckaroo', 'provider'=>'Buckaroo'), + array('name'=>'Buckaroo Ideal', 'provider'=>'Buckaroo_Ideal'), + array('name'=>'Buckaroo PayPal', 'provider'=>'Buckaroo_PayPal'), + array('name'=>'CardSave', 'provider'=>'CardSave'), + array('name'=>'Eway Rapid', 'provider'=>'Eway_Rapid'), + array('name'=>'FirstData Connect', 'provider'=>'FirstData_Connect'), + array('name'=>'GoCardless', 'provider'=>'GoCardless'), + array('name'=>'Migs ThreeParty', 'provider'=>'Migs_ThreeParty'), + array('name'=>'Migs TwoParty', 'provider'=>'Migs_TwoParty'), + array('name'=>'Mollie', 'provider'=>'Mollie'), + array('name'=>'MultiSafepay', 'provider'=>'MultiSafepay'), + array('name'=>'Netaxept', 'provider'=>'Netaxept'), + array('name'=>'NetBanx', 'provider'=>'NetBanx'), + array('name'=>'PayFast', 'provider'=>'PayFast'), + array('name'=>'Payflow Pro', 'provider'=>'Payflow_Pro'), + array('name'=>'PaymentExpress PxPay', 'provider'=>'PaymentExpress_PxPay'), + array('name'=>'PaymentExpress PxPost', 'provider'=>'PaymentExpress_PxPost'), + array('name'=>'PayPal Express', 'provider'=>'PayPal_Express'), + array('name'=>'PayPal Pro', 'provider'=>'PayPal_Pro'), + array('name'=>'Pin', 'provider'=>'Pin'), + array('name'=>'SagePay Direct', 'provider'=>'SagePay_Direct'), + array('name'=>'SagePay Server', 'provider'=>'SagePay_Server'), + array('name'=>'SecurePay DirectPost', 'provider'=>'SecurePay_DirectPost'), + array('name'=>'Stripe', 'provider'=>'Stripe'), + array('name'=>'TargetPay Direct eBanking', 'provider'=>'TargetPay_Directebanking'), + array('name'=>'TargetPay Ideal', 'provider'=>'TargetPay_Ideal'), + array('name'=>'TargetPay Mr Cash', 'provider'=>'TargetPay_Mrcash'), + array('name'=>'TwoCheckout', 'provider'=>'TwoCheckout'), + array('name'=>'WorldPay', 'provider'=>'WorldPay'), + ]; - /* - ActivityType::create(array( - 'name' => 'Created invoice' - )); - */ + foreach ($gateways as $gateway) + { + Gateway::create($gateway); + } } } \ No newline at end of file diff --git a/app/database/seeds/DatabaseSeeder.php b/app/database/seeds/DatabaseSeeder.php index 0e62e38a2863..f92251cb2daf 100755 --- a/app/database/seeds/DatabaseSeeder.php +++ b/app/database/seeds/DatabaseSeeder.php @@ -9,6 +9,8 @@ class DatabaseSeeder extends Seeder { */ public function run() { + $this->command->info('Running DatabaseSeeder'); + Eloquent::unguard(); $this->call('UserTableSeeder'); diff --git a/app/models/Activity.php b/app/models/Activity.php index 856a75efe2c1..ac197024bdca 100755 --- a/app/models/Activity.php +++ b/app/models/Activity.php @@ -80,7 +80,7 @@ class Activity extends Eloquent { $activity = new Activity; $activity->contact_id = $payment->contact_id; - $activity->message = $contact->getFullName() . ' created payment ' . $payment->transaction_reference; + //$activity->message = $contact->getFullName() . ' created payment ' . $payment->transaction_reference; } $activity->payment_id = $payment->id; @@ -107,7 +107,7 @@ class Activity extends Eloquent $activity->invoice_id = $invoice->id; $activity->client_id = $invoice->client_id; $activity->activity_type_id = ACTIVITY_TYPE_VIEW_INVOICE; - $activity->message = $contact->getFullName() . ' viewed invoice ' . $invoice->number; + //$activity->message = $contact->getFullName() . ' viewed invoice ' . $invoice->number; $activity->save(); } } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php index 9c171ef33f75..bfa50886db2d 100755 --- a/app/routes.php +++ b/app/routes.php @@ -11,6 +11,9 @@ | */ +//dd(Omnipay::getFactory()->find()); + + Route::get('/', 'HomeController@showWelcome'); Route::post('get_started', 'AccountController@getStarted'); @@ -97,6 +100,11 @@ function toArray($data) return json_decode(json_encode((array) $data), true); } +function toSpaceCase($camelStr) +{ + return preg_replace('/([a-z])([A-Z])/s','$1 $2', $camelStr); +} + define("ENV_DEVELOPMENT", "local"); define("ENV_STAGING", "staging"); define("ENV_PRODUCTION", "production"); diff --git a/app/views/accounts/settings.blade.php b/app/views/accounts/settings.blade.php index 33b151137c04..1cf523a5b607 100755 --- a/app/views/accounts/settings.blade.php +++ b/app/views/accounts/settings.blade.php @@ -4,48 +4,57 @@ @parent {{ Former::open()->addClass('col-md-9 col-md-offset-1') }} - {{ Former::legend('Payment Gateways') }} + {{ Former::legend('Payment Gateway') }} + + @if ($accountGateway) + {{ Former::populateField('gateway_id', $accountGateway->gateway_id) }} + @foreach ($accountGateway->fields as $field => $junk) + {{ Former::populateField($accountGateway->gateway_id.'_'.$field, $config->$field) }} + @endforeach + @endif + + {{ Former::select('gateway_id')->label('Provider')->addOption('', '')->fromQuery($gateways, 'name', 'id')->onchange('setFieldsShown()'); }} @foreach ($gateways as $gateway) - {{ Former::checkbox('gateway_'.$gateway->id)->label('')->text($gateway->provider) - ->check($account->isGatewayConfigured($gateway->id)) }} - - + @endforeach + {{ Former::actions( Button::lg_primary_submit('Save') ) }} {{ Former::close() }} diff --git a/app/views/header.blade.php b/app/views/header.blade.php index b810712ca06a..ab77cec6fbeb 100755 --- a/app/views/header.blade.php +++ b/app/views/header.blade.php @@ -88,16 +88,6 @@ } */ - a.ul { - text-decoration: underline; - cursor: pointer; - } - - a.ul:hover { - text-decoration: none; - } - - /* DataTables and BootStrap */ .dataTables_wrapper { padding-top: 16px; diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index ca9cad1967a5..b4003a0b2a4c 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -5,33 +5,35 @@

 

{{ Former::open($url)->method($method)->addClass('main_form')->rules(array( - 'number' => 'required', + 'invoice_number' => 'required', + 'invoice_date' => 'required' )); }} @if ($invoice) {{ Former::populate($invoice); }} - {{ Former::populateField('issued_on', DateTime::createFromFormat('Y-m-d', $invoice->issued_on)->format('m/d/Y')); }} + {{ Former::populateField('invoice_date', DateTime::createFromFormat('Y-m-d', $invoice->invoice_date)->format('m/d/Y')); }} @else - {{ Former::populateField('issued_on', date('m/d/Y')) }} + {{ Former::populateField('invoice_date', date('m/d/Y')) }} @endif
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'id')->select($client ? $client->id : '') - ->help('Create new client'); }} + ->help('Create new client'); }}
- {{ Former::text('number')->label('Invoice #') }} - {{ Former::text('issued_on')->label('Invoice Date') }} + {{ Former::text('invoice_number')->label('Invoice #') }} + {{ Former::text('invoice_date') }} {{-- Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'") --}}

 

- + {{ Former::hidden('items')->data_bind("value: ko.toJSON(items)") }} + @@ -46,12 +48,13 @@ - - + + + @@ -118,14 +124,14 @@
-   + + - {{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'product_key')->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }} + {{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'product_key') + ->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }} @@ -87,8 +90,11 @@
- Invoice Total + Add line item + Invoice Total