mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-09-19 16:01:34 +02:00
Working on UI for subscriptions
This commit is contained in:
parent
df937c72a5
commit
f761ff289c
158
app/Http/Controllers/SubscriptionController.php
Normal file
158
app/Http/Controllers/SubscriptionController.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Subscription;
|
||||
use App\Services\SubscriptionService;
|
||||
use Auth;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use Validator;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class SubscriptionController.
|
||||
*/
|
||||
class SubscriptionController extends BaseController
|
||||
{
|
||||
/**
|
||||
* @var SubscriptionService
|
||||
*/
|
||||
protected $subscriptionService;
|
||||
|
||||
/**
|
||||
* SubscriptionController constructor.
|
||||
*
|
||||
* @param SubscriptionService $subscriptionService
|
||||
*/
|
||||
public function __construct(SubscriptionService $subscriptionService)
|
||||
{
|
||||
//parent::__construct();
|
||||
|
||||
$this->subscriptionService = $subscriptionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getDatatable()
|
||||
{
|
||||
return $this->subscriptionService->getDatatable(Auth::user()->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $publicId
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit($publicId)
|
||||
{
|
||||
$subscription = Subscription::scope($publicId)->firstOrFail();
|
||||
|
||||
$data = [
|
||||
'subscription' => $subscription,
|
||||
'method' => 'PUT',
|
||||
'url' => 'subscriptions/' . $publicId,
|
||||
'title' => trans('texts.edit_subscription'),
|
||||
];
|
||||
|
||||
return View::make('accounts.subscription', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $publicId
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update($publicId)
|
||||
{
|
||||
return $this->save($publicId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$data = [
|
||||
'subscription' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'subscriptions',
|
||||
'title' => trans('texts.add_subscription'),
|
||||
];
|
||||
|
||||
return View::make('accounts.subscription', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function bulk()
|
||||
{
|
||||
$action = Input::get('bulk_action');
|
||||
$ids = Input::get('bulk_public_id');
|
||||
$count = $this->subscriptionService->bulk($ids, $action);
|
||||
|
||||
Session::flash('message', trans('texts.archived_subscription'));
|
||||
|
||||
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $subscriptionPublicId
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function save($subscriptionPublicId = false)
|
||||
{
|
||||
if (Auth::user()->account->hasFeature(FEATURE_API)) {
|
||||
$rules = [
|
||||
'event_id' => 'required',
|
||||
'target_url' => 'required|url',
|
||||
];
|
||||
|
||||
if ($subscriptionPublicId) {
|
||||
$subscription = Subscription::scope($subscriptionPublicId)->firstOrFail();
|
||||
} else {
|
||||
$subscription = Subscription::createNew();
|
||||
}
|
||||
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return Redirect::to($subscriptionPublicId ? 'subscriptions/edit' : 'subscriptions/create')->withInput()->withErrors($validator);
|
||||
}
|
||||
|
||||
$subscription->fill(request()->all());
|
||||
$subscription->save();
|
||||
|
||||
if ($subscriptionPublicId) {
|
||||
$message = trans('texts.updated_subscription');
|
||||
} else {
|
||||
$message = trans('texts.created_subscription');
|
||||
}
|
||||
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
|
||||
}
|
||||
}
|
@ -8,15 +8,24 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class Subscription.
|
||||
*/
|
||||
class Subscription extends Eloquent
|
||||
class Subscription extends EntityModel
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'event_id',
|
||||
'target_url',
|
||||
];
|
||||
}
|
||||
|
23
app/Ninja/Repositories/SubscriptionRepository.php
Normal file
23
app/Ninja/Repositories/SubscriptionRepository.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ninja\Repositories;
|
||||
|
||||
use App\Models\Subscription;
|
||||
use DB;
|
||||
|
||||
class SubscriptionRepository extends BaseRepository
|
||||
{
|
||||
public function getClassName()
|
||||
{
|
||||
return 'App\Models\Subscription';
|
||||
}
|
||||
|
||||
public function find($userId)
|
||||
{
|
||||
$query = DB::table('account_subscriptions')
|
||||
->where('account_subscriptions.user_id', '=', $userId)
|
||||
->whereNull('account_subscriptions.deleted_at');
|
||||
|
||||
return $query->select('account_subscriptions.public_id', 'account_subscriptions.name', 'account_subscriptions.subscription', 'account_subscriptions.public_id', 'account_subscriptions.deleted_at');
|
||||
}
|
||||
}
|
55
app/Services/SubscriptionService.php
Normal file
55
app/Services/SubscriptionService.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Ninja\Datatables\SubscriptionDatatable;
|
||||
use App\Ninja\Repositories\SubscriptionRepository;
|
||||
|
||||
/**
|
||||
* Class SubscriptionService.
|
||||
*/
|
||||
class SubscriptionService extends BaseService
|
||||
{
|
||||
/**
|
||||
* @var SubscriptionRepository
|
||||
*/
|
||||
protected $subscriptionRepo;
|
||||
|
||||
/**
|
||||
* @var DatatableService
|
||||
*/
|
||||
protected $datatableService;
|
||||
|
||||
/**
|
||||
* SubscriptionService constructor.
|
||||
*
|
||||
* @param SubscriptionRepository $subscriptionRepo
|
||||
* @param DatatableService $datatableService
|
||||
*/
|
||||
public function __construct(SubscriptionRepository $subscriptionRepo, DatatableService $datatableService)
|
||||
{
|
||||
$this->subscriptionRepo = $subscriptionRepo;
|
||||
$this->datatableService = $datatableService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubscriptionRepository
|
||||
*/
|
||||
protected function getRepo()
|
||||
{
|
||||
return $this->subscriptionRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $userId
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getDatatable($userId)
|
||||
{
|
||||
$datatable = new SubscriptionDatatable(false);
|
||||
$query = $this->subscriptionRepo->find($userId);
|
||||
|
||||
return $this->datatableService->createDatatable($datatable, $query);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use App\Models\Subscription;
|
||||
|
||||
class AddSubdomainToLookups extends Migration
|
||||
{
|
||||
@ -64,6 +65,29 @@ class AddSubdomainToLookups extends Migration
|
||||
$table->unique(['account_id', 'public_id']);
|
||||
});
|
||||
|
||||
Schema::table('subscriptions', function ($table) {
|
||||
$table->unsignedInteger('public_id')->nullable();
|
||||
$table->unsignedInteger('user_id')->nullable();
|
||||
});
|
||||
|
||||
$accountPublicIds = [];
|
||||
foreach (Subscription::all() as $subscription) {
|
||||
$accountId = $subscription->account_id;
|
||||
if (isset($accountPublicIds[$accountId])) {
|
||||
$publicId = $accountPublicIds[$accountId];
|
||||
$accountPublicIds[$accountId]++;
|
||||
} else {
|
||||
$publicId = 1;
|
||||
$accountPublicIds[$accountId] = 2;
|
||||
}
|
||||
$subscription->public_id = $publicId;
|
||||
$subscription->save();
|
||||
}
|
||||
|
||||
Schema::table('subscriptions', function ($table) {
|
||||
$table->unique(['account_id', 'public_id']);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,5 +123,15 @@ class AddSubdomainToLookups extends Migration
|
||||
});
|
||||
|
||||
Schema::dropIfExists('scheduled_reports');
|
||||
|
||||
Schema::table('subscriptions', function ($table) {
|
||||
$table->dropUnique('subscriptions_account_id_public_id_unique');
|
||||
});
|
||||
|
||||
Schema::table('subscriptions', function ($table) {
|
||||
$table->dropColumn('public_id');
|
||||
$table->dropColumn('user_id');
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2567,6 +2567,21 @@ $LANG = array(
|
||||
'apple_pay_domain' => 'Use <code>:domain</code> as the domain in :link.',
|
||||
'apple_pay_not_supported' => 'Sorry, Apple/Google Pay isn\'t supported',
|
||||
'optional_payment_methods' => 'Optional Payment Methods',
|
||||
'add_subscription' => 'Add Subscription',
|
||||
'target_url' => 'Target URL',
|
||||
'event' => 'Event',
|
||||
'event_create_client' => 'Created Client',
|
||||
'event_create_invoice' => 'Created Invoice',
|
||||
'event_create_quote' => 'Created Quote',
|
||||
'event_create_payment' => 'Created Payment',
|
||||
'event_create_vendor' => 'Created Vendor',
|
||||
'event_update_quote' => 'Updated Quote',
|
||||
'event_delete_quote' => 'Deleted Quote',
|
||||
'event_update_invoice' => 'Updated Invoice',
|
||||
'event_delete_invoice' => 'Deleted Invoice',
|
||||
'subscriptions' => 'Subscriptions',
|
||||
'updated_subscription' => 'Successfully updated subscription',
|
||||
'created_subscription' => 'Successfully created subscription',
|
||||
|
||||
);
|
||||
|
||||
|
@ -29,6 +29,30 @@
|
||||
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[2]]])
|
||||
->render('datatable') !!}
|
||||
|
||||
<p> </p>
|
||||
|
||||
<div class="pull-right">
|
||||
@if (Utils::hasFeature(FEATURE_API))
|
||||
{!! Button::primary(trans('texts.add_subscription'))->asLinkTo(URL::to('/subscriptions/create'))->appendIcon(Icon::create('plus-sign')) !!}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@include('partials.bulk_form', ['entityType' => ENTITY_TOKEN])
|
||||
|
||||
{!! Datatable::table()
|
||||
->addColumn(
|
||||
trans('texts.name'),
|
||||
trans('texts.token'),
|
||||
trans('texts.action'))
|
||||
->setUrl(url('api/tokens/'))
|
||||
->setOptions('sPaginationType', 'bootstrap')
|
||||
->setOptions('bFilter', false)
|
||||
->setOptions('bAutoWidth', false)
|
||||
->setOptions('aoColumns', [[ "sWidth"=> "40%" ], [ "sWidth"=> "40%" ], ["sWidth"=> "20%"]])
|
||||
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[2]]])
|
||||
->render('datatable') !!}
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
window.onDatatableReady = actionListHandler;
|
||||
|
69
resources/views/accounts/subscription.blade.php
Normal file
69
resources/views/accounts/subscription.blade.php
Normal file
@ -0,0 +1,69 @@
|
||||
@extends('header')
|
||||
|
||||
@section('content')
|
||||
@parent
|
||||
@include('accounts.nav', ['selected' => ACCOUNT_API_TOKENS])
|
||||
|
||||
{!! Former::open($url)->method($method)->addClass('warn-on-exit')->rules(array(
|
||||
'event_id' => 'required',
|
||||
'target_url' => 'required|url',
|
||||
)); !!}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{!! trans($title) !!}</h3>
|
||||
</div>
|
||||
<div class="panel-body form-padding-right">
|
||||
|
||||
@if ($subscription)
|
||||
{!! Former::populate($subscription) !!}
|
||||
@endif
|
||||
|
||||
{!! Former::select('event_id')
|
||||
->options([
|
||||
trans('texts.clients') => [
|
||||
EVENT_CREATE_CLIENT => trans('texts.event_create_client'),
|
||||
],
|
||||
trans('texts.invoices') => [
|
||||
EVENT_CREATE_INVOICE => trans('texts.event_create_invoice'),
|
||||
EVENT_UPDATE_INVOICE => trans('texts.event_update_invoice'),
|
||||
EVENT_DELETE_INVOICE => trans('texts.event_delete_invoice'),
|
||||
],
|
||||
trans('texts.payments') => [
|
||||
EVENT_CREATE_PAYMENT => trans('texts.event_create_payment'),
|
||||
],
|
||||
trans('texts.quotes') => [
|
||||
EVENT_CREATE_QUOTE => trans('texts.event_create_quote'),
|
||||
EVENT_UPDATE_QUOTE => trans('texts.event_update_quote'),
|
||||
EVENT_DELETE_QUOTE => trans('texts.event_delete_quote'),
|
||||
]
|
||||
])
|
||||
->label('event') !!}
|
||||
|
||||
{!! Former::text('target_url')
|
||||
->placeholder('https://example.com')!!}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->hasFeature(FEATURE_API))
|
||||
<center class="buttons">
|
||||
{!! Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/api_tokens'))->appendIcon(Icon::create('remove-circle'))->large() !!}
|
||||
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
|
||||
</center>
|
||||
@else
|
||||
<script>
|
||||
$(function() {
|
||||
$('form.warn-on-exit input').prop('disabled', true);
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
|
||||
|
||||
{!! Former::close() !!}
|
||||
|
||||
@stop
|
||||
|
||||
@section('onReady')
|
||||
$('#name').focus();
|
||||
@stop
|
@ -266,6 +266,9 @@ Route::group([
|
||||
Route::get('api/tokens', 'TokenController@getDatatable');
|
||||
Route::resource('tokens', 'TokenController');
|
||||
Route::post('tokens/bulk', 'TokenController@bulk');
|
||||
Route::get('api/subscriptions', 'SubscriptionController@getDatatable');
|
||||
Route::resource('subscriptions', 'SubscriptionController');
|
||||
Route::post('subscriptions/bulk', 'SubscriptionController@bulk');
|
||||
|
||||
Route::get('api/tax_rates', 'TaxRateController@getDatatable');
|
||||
Route::resource('tax_rates', 'TaxRateController');
|
||||
|
Loading…
Reference in New Issue
Block a user