mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 12:12:48 +01:00
Added support for all Omnipay providers
This commit is contained in:
parent
426e7838c9
commit
746d5ec773
2
README.md
Executable file → Normal file
2
README.md
Executable file → Normal file
@ -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
|
||||
|
@ -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();
|
||||
$accountGateway = null;
|
||||
|
||||
foreach ($gateways as $gateway)
|
||||
if (count($account->account_gateways) > 0)
|
||||
{
|
||||
$gateway->fields = Omnipay::create($gateway->provider)->getDefaultParameters();
|
||||
$accountGateway = $account->account_gateways[0];
|
||||
}
|
||||
|
||||
return View::make('accounts.settings', array('account' => $account, 'gateways' => $gateways));
|
||||
$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,23 +330,18 @@ 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';
|
||||
}
|
||||
@ -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 ($gatewayId)
|
||||
{
|
||||
if (!Input::get('gateway_'.$gateway->id))
|
||||
$accountGateway = new AccountGateway;
|
||||
$accountGateway->gateway_id = $gatewayId;
|
||||
|
||||
$config = new stdClass;
|
||||
foreach ($fields as $field => $details)
|
||||
{
|
||||
continue;
|
||||
$config->$field = Input::get($gateway->id.'_'.$field);
|
||||
}
|
||||
|
||||
$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->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');
|
||||
}
|
||||
}
|
||||
|
@ -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,24 +47,26 @@ class InvoiceController extends \BaseController {
|
||||
return View::make('invoices.view')->with('invoice', $invoice);
|
||||
}
|
||||
|
||||
private function createGateway($config)
|
||||
private function createGateway($accountGateway)
|
||||
{
|
||||
$gateway = Omnipay::create($accountGateway->gateway->provider);
|
||||
$config = json_decode($accountGateway->config);
|
||||
|
||||
/*
|
||||
$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 = "";
|
||||
*/
|
||||
|
||||
foreach ($config as $key => $val)
|
||||
{
|
||||
if (!$val)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$function = "set" . ucfirst($key);
|
||||
$gateway->$function($val);
|
||||
}
|
||||
|
||||
return $gateway;
|
||||
}
|
||||
@ -72,8 +74,8 @@ class InvoiceController extends \BaseController {
|
||||
private function getPaymentDetails($invoice)
|
||||
{
|
||||
$data = array(
|
||||
'firstName' => 'Bobby',
|
||||
'lastName' => 'Tables',
|
||||
'firstName' => '',
|
||||
'lastName' => '',
|
||||
);
|
||||
|
||||
$card = new CreditCard($data);
|
||||
@ -90,20 +92,26 @@ 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();
|
||||
$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())
|
||||
@ -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',
|
||||
'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,19 +251,24 @@ 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,10 +278,12 @@ 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->qty = $item->qty;
|
||||
$product->save();
|
||||
}
|
||||
|
||||
$invoiceItem = new InvoiceItem;
|
||||
$invoiceItem->product_id = $product->id;
|
||||
|
@ -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');
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ class DatabaseSeeder extends Seeder {
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->command->info('Running DatabaseSeeder');
|
||||
|
||||
Eloquent::unguard();
|
||||
|
||||
$this->call('UserTableSeeder');
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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");
|
||||
|
@ -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)) }}
|
||||
|
||||
<div id="gateway_{{ $gateway->id }}_div" style="display: none">
|
||||
@foreach ($gateway->fields as $field => $details)
|
||||
@if ($config = $account->getGatewayConfig($gateway->id))
|
||||
{{ Former::populateField($gateway->id.'_'.$field, $config[$field]) }}
|
||||
@endif
|
||||
@if (in_array($field, array('username','password','signature')))
|
||||
{{ Former::text($gateway->id.'_'.$field)->label($field) }}
|
||||
|
||||
@if ($field == 'solutionType' || $field == 'landingPage')
|
||||
{{-- do nothing --}}
|
||||
@elseif ($field == 'testMode' || $field == 'developerMode')
|
||||
{{ Former::checkbox($gateway->id.'_'.$field)->label(toSpaceCase($field))->text('Enable') }}
|
||||
@else
|
||||
{{ Former::text($gateway->id.'_'.$field)->label(toSpaceCase($field)) }}
|
||||
@endif
|
||||
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@endforeach
|
||||
|
||||
|
||||
{{ Former::actions( Button::lg_primary_submit('Save') ) }}
|
||||
{{ Former::close() }}
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$(function() {
|
||||
|
||||
function setFieldsShown(id) {
|
||||
if ($('#gateway_' + id).is(':checked')) {
|
||||
$('#gateway_' + id + '_div').show();
|
||||
var gateways = {{ $gateways }};
|
||||
function setFieldsShown() {
|
||||
var val = $('#gateway_id').val();
|
||||
for (var i=0; i<gateways.length; i++) {
|
||||
var gateway = gateways[i];
|
||||
if (val == gateway.id) {
|
||||
$('#gateway_' + gateway.id + '_div').show();
|
||||
} else {
|
||||
$('#gateway_' + id + '_div').hide();
|
||||
$('#gateway_' + gateway.id + '_div').hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@foreach ($gateways as $gateway)
|
||||
$('#gateway_{{ $gateway->id }}').click(function() {
|
||||
setFieldsShown('{{ $gateway->id }}');
|
||||
});
|
||||
setFieldsShown('{{ $gateway->id }}');
|
||||
@endforeach
|
||||
$(function() {
|
||||
setFieldsShown();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -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;
|
||||
|
@ -5,33 +5,35 @@
|
||||
<p> </p>
|
||||
|
||||
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
|
||||
'number' => 'required',
|
||||
'invoice_number' => 'required',
|
||||
'invoice_date' => 'required'
|
||||
)); }}
|
||||
|
||||
<!-- <h3>{{ $title }} Invoice</h3> -->
|
||||
|
||||
@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
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ Former::select('client')->addOption('', '')->fromQuery($clients, 'name', 'id')->select($client ? $client->id : '')
|
||||
->help('<a class="ul" data-toggle="modal" data-target="#myModal">Create new client</a>'); }}
|
||||
->help('<a data-toggle="modal" data-target="#myModal">Create new client</a>'); }}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{{ 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'") --}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<input type="text" name="items" data-bind="value: ko.toJSON(items)" style="display:none"/>
|
||||
{{ Former::hidden('items')->data_bind("value: ko.toJSON(items)") }}
|
||||
|
||||
<table class="table invoice-table" style="margin-bottom: 0px !important">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -46,12 +48,13 @@
|
||||
</thead>
|
||||
<tbody data-bind="sortable: { data: items, afterMove: onDragged }">
|
||||
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
|
||||
<td style="width:50px;" class="hide-border">
|
||||
<i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i>
|
||||
<td style="width:20px;" class="hide-border">
|
||||
<!-- <i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i> -->
|
||||
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
|
||||
</td>
|
||||
<td style="width:120px">
|
||||
{{ 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') }}
|
||||
</td>
|
||||
<td style="width:300px">
|
||||
<textarea data-bind="value: notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" class="form-control" onchange="refreshPDF()"></textarea>
|
||||
@ -87,8 +90,11 @@
|
||||
<td style="text-align: right"><span data-bind="text: discounted"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" class="hide-border"/>
|
||||
<td colspan="2">Invoice Total</td>
|
||||
<td class="hide-border"></td>
|
||||
<td colspan="2" class="hide-border">
|
||||
<a href="#" onclick="model.addItem()">Add line item</a>
|
||||
</td>
|
||||
<td colspan="2"><b>Invoice Total</b></td>
|
||||
<td style="text-align: right"><span data-bind="text: total"/></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
@ -118,14 +124,14 @@
|
||||
<h4 class="modal-title" id="myModalLabel">New Client</h4>
|
||||
</div>
|
||||
<div class="modal-body" style="min-height:80px">
|
||||
<div class="form-group required">
|
||||
<div class="form-group">
|
||||
<label for="name" class="control-label col-lg-2 col-sm-4">Name<sup>*</sup></label>
|
||||
<div class="col-lg-10 col-sm-8">
|
||||
<input class="form-control" id="client_name" type="text" name="client_name" onkeypress="nameKeyPress(event)">
|
||||
<span class="help-block" id="nameHelp" style="display: none">Please provide a value</span><span> </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<div class="form-group">
|
||||
<label for="email" class="control-label col-lg-2 col-sm-4">Email<sup>*</sup></label>
|
||||
<div class="col-lg-10 col-sm-8">
|
||||
<input class="form-control" id="client_email" type="text" name="client_email" onkeypress="nameKeyPress(event)">
|
||||
@ -161,7 +167,7 @@
|
||||
|
||||
$(function() {
|
||||
|
||||
$('#issued_on').datepicker({
|
||||
$('#invoice_date').datepicker({
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
}).on('changeDate', function(e) {
|
||||
@ -175,7 +181,7 @@
|
||||
});
|
||||
|
||||
@if ($client)
|
||||
$('input#number').focus();
|
||||
$('input#invoice_number').focus();
|
||||
@else
|
||||
$('[name="client_combobox"]').focus();
|
||||
@endif
|
||||
@ -190,7 +196,7 @@
|
||||
$('#client_name').focus();
|
||||
})
|
||||
|
||||
$('#number').change(refreshPDF);
|
||||
$('#invoice_number').change(refreshPDF);
|
||||
|
||||
applyComboboxListeners();
|
||||
refreshPDF();
|
||||
@ -211,6 +217,7 @@
|
||||
console.log(model);
|
||||
model.notes(product.notes);
|
||||
model.cost(product.cost);
|
||||
model.qty(product.qty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -224,8 +231,8 @@
|
||||
|
||||
function createInvoiceModel() {
|
||||
var invoice = {
|
||||
number: $('#number').val(),
|
||||
issued_on: $('#issued_on').val(),
|
||||
invoice_number: $('#invoice_number').val(),
|
||||
invoice_date: $('#invoice_date').val(),
|
||||
client: {
|
||||
name: $('[name="client_combobox"]').val()
|
||||
},
|
||||
@ -285,7 +292,7 @@
|
||||
$('#emailHelp').css( "display", "none" );
|
||||
//$('#client_name').val('');
|
||||
$('#myModal').modal('hide');
|
||||
$('input#number').focus();
|
||||
$('input#invoice_number').focus();
|
||||
|
||||
refreshPDF();
|
||||
}
|
||||
@ -304,13 +311,22 @@
|
||||
self.discount = ko.observable();
|
||||
self.items = ko.observableArray();
|
||||
|
||||
@if ($invoice)
|
||||
@if (isset($items) && $items)
|
||||
@foreach ($items as $item)
|
||||
var item = new ItemModel();
|
||||
item.product_key("{{ $item->product_key }}");
|
||||
item.notes('{{ str_replace("\n", "\\n", $item->notes) }}');
|
||||
item.cost("{{ isset($item->cost) ? $item->cost : '' }}");
|
||||
item.qty("{{ isset($item->qty) ? $item->qty : '' }}");
|
||||
self.items.push(item);
|
||||
@endforeach
|
||||
@elseif ($invoice)
|
||||
self.discount({{ $invoice->discount }});
|
||||
@if (count($invoice->invoice_items) > 0)
|
||||
@foreach ($invoice->invoice_items as $item)
|
||||
var item = new ItemModel();
|
||||
item.product_key("{{ $item->product_key }}");
|
||||
item.notes('{{ str_replace("\n", "\\notes", $item->notes) }}');
|
||||
item.notes('{{ str_replace("\n", "\\n", $item->notes) }}');
|
||||
item.cost("{{ $item->cost }}");
|
||||
item.qty("{{ $item->qty }}");
|
||||
self.items.push(item);
|
||||
@ -320,7 +336,6 @@
|
||||
@endif
|
||||
@else
|
||||
var model1 = new ItemModel();
|
||||
var model2 = new ItemModel();
|
||||
/*
|
||||
model1.item('TEST');
|
||||
model1.notes('Some test text');
|
||||
@ -328,7 +343,6 @@
|
||||
model1.qty(1);
|
||||
*/
|
||||
self.items.push(model1);
|
||||
self.items.push(model2);
|
||||
@endif
|
||||
|
||||
self.removeItem = function(item) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
@if (true || $invoice->client->account->isGatewayConfigured())
|
||||
@if ($invoice->client->account->isGatewayConfigured())
|
||||
{{ Button::primary_link(URL::to('payment/' . $invoice->invoice_key), 'Pay Now', array('class' => 'btn-lg pull-right')) }}
|
||||
<div class="clearfix"></div><p> </p>
|
||||
@endif
|
||||
|
@ -1,8 +1,8 @@
|
||||
function generatePDF(invoice) {
|
||||
|
||||
var clientName = invoice.client.name;
|
||||
var invoiceNumber = invoice.number;
|
||||
var issuedOn = invoice.issued_on;
|
||||
var invoiceNumber = invoice.invoice_number;
|
||||
var issuedOn = invoice.invoice_date;
|
||||
var amount = '$0.00';
|
||||
|
||||
var marginLeft = 90;
|
||||
@ -28,7 +28,6 @@ function generatePDF(invoice) {
|
||||
doc.addImage(invoice.image, 'JPEG', 30, 30, invoice.imageWidth, invoice.imageHeight);
|
||||
}
|
||||
|
||||
|
||||
doc.setDrawColor(200,200,200);
|
||||
doc.setFillColor(230,230,230);
|
||||
doc.rect(headerLeft - 6, headerTop + rowHeight + 4, headerRight - headerLeft + 12, rowHeight + 2, 'FD');
|
||||
@ -46,7 +45,6 @@ function generatePDF(invoice) {
|
||||
doc.setFontType("bold");
|
||||
doc.text(headerLeft, headerTop + (2 * rowHeight), 'Amount Due');
|
||||
|
||||
|
||||
doc.setDrawColor(200,200,200);
|
||||
doc.setFillColor(230,230,230);
|
||||
doc.rect(tableLeft - 6, tableTop - 12, headerRight - tableLeft + 12, rowHeight + 2, 'FD');
|
||||
@ -113,7 +111,7 @@ function formatNumber(num) {
|
||||
}
|
||||
|
||||
function formatMoney(num) {
|
||||
num = parseInt(num);
|
||||
num = parseFloat(num);
|
||||
if (!num) return '$0.00';
|
||||
var p = num.toFixed(2).split(".");
|
||||
return "$" + p[0].split("").reverse().reduce(function(acc, num, i, orig) {
|
||||
|
Loading…
Reference in New Issue
Block a user