Separated Checkout and Payment controllers, updates to checkout and payments
This commit is contained in:
@@ -3,15 +3,9 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Requests\SiteEdit;
|
||||
use App\Models\{Account,
|
||||
Invoice,
|
||||
Payment,
|
||||
PaymentItem,
|
||||
Service,
|
||||
SiteDetail};
|
||||
use App\Models\SiteDetail;
|
||||
|
||||
/**
|
||||
* The AdminController governs all routes that are prefixed with 'a/'.
|
||||
@@ -20,108 +14,6 @@ use App\Models\{Account,
|
||||
*/
|
||||
class AdminController extends Controller
|
||||
{
|
||||
/**
|
||||
* Record payments on an account.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Payment $o
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
// @todo Move to reseller
|
||||
public function pay_addedit(Request $request,Payment $o)
|
||||
{
|
||||
if ($request->post()) {
|
||||
|
||||
$validation = $request->validate([
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'paid_at' => 'required|date',
|
||||
'checkout_id' => 'required|exists:checkouts,id',
|
||||
'total_amt' => 'required|numeric|min:0.01',
|
||||
'fees_amt' => 'nullable|numeric|lt:total_amt',
|
||||
'source_id' => 'nullable|exists:accounts,id',
|
||||
'pending' => 'nullable|boolean',
|
||||
'notes' => 'nullable|string',
|
||||
'ip' => 'nullable|ip',
|
||||
'invoices' => ['required','array',function ($attribute,$value,$fail) use ($request) {
|
||||
if (collect($value)->sum('id') > $request->post('total_amt'))
|
||||
$fail('Allocation is greater than payment total.');
|
||||
}],
|
||||
'invoices.*.id' => ['required',function ($attribute,$value,$fail) {
|
||||
if (! Invoice::exists(str_replace(str_replace($attribute,'invoice\.','',),'.id','')))
|
||||
$fail('Invoice doesnt exist in DB');
|
||||
}],
|
||||
]);
|
||||
|
||||
if (! $o->exists) {
|
||||
$o->site_id = config('site')->site_id;
|
||||
$o->active = TRUE;
|
||||
}
|
||||
|
||||
$o->forceFill($request->only(['account_id','paid_at','checkout_id','total_amt','fees_amt','source_id','pending','notes','ip']));
|
||||
$o->save();
|
||||
|
||||
foreach ($validation['invoices'] as $id => $amount) {
|
||||
// See if we already have a payment item that we need to update
|
||||
$items = $o->items->filter(function($item) use ($id) { return $item->invoice_id == $id; });
|
||||
|
||||
if ($items->count() == 1) {
|
||||
$oo = $items->pop();
|
||||
if ($amount['id'] == 0) {
|
||||
$oo->delete();
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
$oo = new PaymentItem;
|
||||
$oo->invoice_id = $id;
|
||||
}
|
||||
|
||||
$oo->amount = ($oo->invoice->due >= 0) && ($oo->invoice->due-$amount['id'] >= 0) ? $amount['id'] : 0;
|
||||
|
||||
// If the amount is empty, ignore it.
|
||||
if (! $oo->amount)
|
||||
continue;
|
||||
|
||||
$oo->site_id = config('site')->site_id;
|
||||
$oo->active = TRUE;
|
||||
$o->items()->save($oo);
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success','Payment recorded: '.$o->id);
|
||||
}
|
||||
|
||||
return view('theme.backend.adminlte.a.payment.addedit')
|
||||
->with('o',$o);
|
||||
}
|
||||
|
||||
/**
|
||||
* List unapplied payments
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
// @todo Move to reseller
|
||||
public function pay_unapplied()
|
||||
{
|
||||
return view('theme.backend.adminlte.a.payment.unapplied');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of invoices to apply payments to
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $o
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
// @todo Move to reseller
|
||||
public function pay_invoices(Request $request,Account $o)
|
||||
{
|
||||
return view('theme.backend.adminlte.a.payment.widgets.invoices')
|
||||
->with('pid',$request->pid)
|
||||
->with('o',$o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Site setup
|
||||
*
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
use App\Http\Requests\CheckoutAddEdit;
|
||||
use App\Models\{Checkout,Invoice};
|
||||
@@ -11,31 +11,35 @@ use App\Models\{Checkout,Invoice};
|
||||
class CheckoutController extends Controller
|
||||
{
|
||||
/**
|
||||
* Update a suppliers details
|
||||
* Update a checkout details
|
||||
*
|
||||
* @param CheckoutAddEdit $request
|
||||
* @param Checkout $o
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function addedit(CheckoutAddEdit $request,Checkout $o)
|
||||
public function addedit(CheckoutAddEdit $request,Checkout $o): RedirectResponse
|
||||
{
|
||||
$this->middleware(['auth','wholesaler']);
|
||||
|
||||
foreach ($request->except(['_token','active','submit']) as $key => $item)
|
||||
foreach ($request->validated() as $key => $item)
|
||||
$o->{$key} = $item;
|
||||
|
||||
$o->active = (bool)$request->active;
|
||||
$o->active = (bool)$request->validated('active',FALSE);
|
||||
|
||||
try {
|
||||
$o->save();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->back()->withErrors($e->getMessage())->withInput();
|
||||
return redirect()
|
||||
->back()
|
||||
->withErrors($e->getMessage())->withInput();
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success','Payment saved');
|
||||
return $o->wasRecentlyCreated
|
||||
? redirect()
|
||||
->to('a/checkout/'.$o->id)
|
||||
->with('success','Checkout added')
|
||||
: redirect()
|
||||
->back()
|
||||
->with('success','Checkout saved');
|
||||
}
|
||||
|
||||
public function cart_invoice(Request $request,Invoice $o=NULL)
|
||||
@@ -57,29 +61,8 @@ class CheckoutController extends Controller
|
||||
return $o->fee($request->post('total',0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a specific invoice for the user
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function home(): View
|
||||
{
|
||||
return view('theme.backend.adminlte.payment.home');
|
||||
}
|
||||
|
||||
public function pay(Request $request,Checkout $o)
|
||||
{
|
||||
return redirect('pay/paypal/authorise');
|
||||
}
|
||||
|
||||
/**
|
||||
* View details on a specific payment method
|
||||
*
|
||||
* @param Checkout $o
|
||||
* @return View
|
||||
*/
|
||||
public function view(Checkout $o): View
|
||||
{
|
||||
return view('theme.backend.adminlte.payment.view',['o'=>$o]);
|
||||
}
|
||||
}
|
@@ -4,10 +4,11 @@ namespace App\Http\Controllers;
|
||||
|
||||
use Clarkeash\Doorman\Exceptions\{ExpiredInviteCode,InvalidInviteCode,NotYourInviteCode};
|
||||
use Clarkeash\Doorman\Facades\Doorman;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
use Barryvdh\Snappy\Facades\SnappyPdf as PDF;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Models\{Account,Invoice};
|
||||
|
||||
/**
|
||||
* Class InvoiceController
|
||||
@@ -19,6 +20,21 @@ use App\Models\Invoice;
|
||||
*/
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show a list of invoices to apply payments to
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function api_account_invoices(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
session()->flashInput($request->post('old',[]));
|
||||
|
||||
return view('theme.backend.adminlte.payment.widget.invoices')
|
||||
->with('pid',$request->post('pid'))
|
||||
->with('o',Account::findOrFail($request->post('aid')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the invoice in PDF format, ready to download
|
||||
*
|
||||
|
73
app/Http/Controllers/PaymentController.php
Normal file
73
app/Http/Controllers/PaymentController.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
use App\Http\Requests\PaymentAddEdit;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Models\{Payment,PaymentItem};
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Record payments on an account.
|
||||
*
|
||||
* @param PaymentAddEdit $request
|
||||
* @param Payment $o
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function addedit(PaymentAddEdit $request,Payment $o): RedirectResponse
|
||||
{
|
||||
foreach (Arr::except($request->validated(),'invoices') as $k=>$v)
|
||||
$o->{$k} = $v;
|
||||
|
||||
foreach ($request->validated('invoices',[]) as $id => $amount) {
|
||||
// See if we already have a payment item that we need to update
|
||||
$items = $o->items
|
||||
->filter(fn($item)=>$item->invoice_id == $id);
|
||||
|
||||
if ($items->count() === 1) {
|
||||
$oo = $items->pop();
|
||||
|
||||
if ($amount == 0) {
|
||||
$oo->delete();
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
$oo = new PaymentItem;
|
||||
$oo->invoice_id = $id;
|
||||
}
|
||||
|
||||
$oo->amount = ($oo->invoice->due >= 0) && ($oo->invoice->due-$amount >= 0)
|
||||
? $amount
|
||||
: 0;
|
||||
|
||||
// If the amount is empty, ignore it.
|
||||
if (! $oo->amount)
|
||||
continue;
|
||||
|
||||
$oo->site_id = config('site')->site_id;
|
||||
$oo->active = TRUE;
|
||||
$o->items->push($oo);
|
||||
}
|
||||
|
||||
try {
|
||||
$o->pushNew();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withErrors($e->getMessage())->withInput();
|
||||
}
|
||||
|
||||
return $o->wasRecentlyCreated
|
||||
? redirect()
|
||||
->to('r/payment/'.$o->id)
|
||||
->with('success','Payment added')
|
||||
: redirect()
|
||||
->back()
|
||||
->with('success','Payment saved');
|
||||
}
|
||||
}
|
@@ -90,7 +90,7 @@ class SearchController extends Controller
|
||||
->whereIN('account_id',$account_ids)
|
||||
->limit(10)->get() as $o)
|
||||
{
|
||||
$result->push(['name'=>sprintf('%s: %s $%s',$o->lid,$o->account->name,number_format($o->total,2)),'value'=>'/a/payment/addedit/'.$o->id,'category'=>'Payments']);
|
||||
$result->push(['name'=>sprintf('%s: %s $%s',$o->lid,$o->account->name,number_format($o->total,2)),'value'=>'/r/payment/addedit/'.$o->id,'category'=>'Payments']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
/**
|
||||
* Editing Suppliers
|
||||
@@ -28,7 +29,13 @@ class CheckoutAddEdit extends FormRequest
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|min:2|max:255',
|
||||
'name' => [
|
||||
'required',
|
||||
'string',
|
||||
'min:2',
|
||||
'max:255',
|
||||
Rule::unique('checkouts','name')->ignore($this->route('o')?->id),
|
||||
],
|
||||
'active' => 'sometimes|accepted',
|
||||
'description' => 'nullable|string|min:2|max:255',
|
||||
];
|
||||
|
62
app/Http/Requests/PaymentAddEdit.php
Normal file
62
app/Http/Requests/PaymentAddEdit.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Editing Suppliers
|
||||
*/
|
||||
class PaymentAddEdit extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::user()->isWholesaler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'paid_at' => 'required|date',
|
||||
'checkout_id' => 'required|exists:checkouts,id',
|
||||
'total_amt' => 'required|numeric|min:0.01',
|
||||
'fees_amt' => 'nullable|numeric|lt:total_amt',
|
||||
'source_id' => 'nullable|exists:accounts,id',
|
||||
'pending' => 'nullable|boolean',
|
||||
'notes' => 'nullable|string',
|
||||
'ip' => 'nullable|ip',
|
||||
'invoices' => [
|
||||
'nullable',
|
||||
'array',
|
||||
function($attribute,$value,$fail) {
|
||||
if (($x=collect($value)->sum()) > request()->post('total_amt'))
|
||||
$fail(sprintf('Allocation %3.2f is greater than payment total %3.2f.',$x,request()->post('total_amt')));
|
||||
}
|
||||
],
|
||||
'invoices.*' => [
|
||||
'nullable',
|
||||
function($attribute,$value,$fail) {
|
||||
if (! ($x=Invoice::where('id',$xx=str_replace('invoices.','',$attribute))->first()))
|
||||
$fail(sprintf('Invoice [%d] doesnt exist in DB',$xx));
|
||||
// @todo The due amount may be influenced by this payment (ie: payment edit)
|
||||
elseif($x->due < $value)
|
||||
$fail(sprintf('Invoice [%d] is over allocated by %3.2f',$x->id,$value-$x->due));
|
||||
}
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@@ -6,9 +6,11 @@ use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Leenooks\Traits\ScopeActive;
|
||||
|
||||
use App\Traits\SiteID;
|
||||
|
||||
class Checkout extends Model
|
||||
{
|
||||
use ScopeActive;
|
||||
use ScopeActive,SiteID;
|
||||
|
||||
protected $casts = [
|
||||
'plugin_data'=>'json',
|
||||
|
@@ -300,8 +300,7 @@ class Invoice extends Model implements IDs
|
||||
/**
|
||||
* @param \Leenooks\Carbon $start Start Date
|
||||
* @param Carbon $end End Date
|
||||
* @param int $interval Period End Date
|
||||
* @param bool $strict
|
||||
* @param Collection $period
|
||||
* @return float
|
||||
* @throws \Exception
|
||||
*/
|
||||
@@ -373,7 +372,7 @@ class Invoice extends Model implements IDs
|
||||
public function payments()
|
||||
{
|
||||
return $this->hasManyThrough(Payment::class,PaymentItem::class,NULL,'id',NULL,'payment_id')
|
||||
->where('active',TRUE);
|
||||
->where('payments.active',TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -7,8 +7,7 @@ use Illuminate\Support\Facades\DB;
|
||||
use Leenooks\Traits\ScopeActive;
|
||||
|
||||
use App\Interfaces\IDs;
|
||||
use App\Traits\ProviderRef;
|
||||
use App\Traits\PushNew;
|
||||
use App\Traits\{ProviderRef,PushNew,SiteID};
|
||||
|
||||
/**
|
||||
* Class Payment
|
||||
@@ -25,7 +24,7 @@ use App\Traits\PushNew;
|
||||
*/
|
||||
class Payment extends Model implements IDs
|
||||
{
|
||||
use PushNew,ScopeActive,ProviderRef;
|
||||
use PushNew,ScopeActive,ProviderRef,SiteID;
|
||||
|
||||
protected $casts = [
|
||||
'paid_at'=>'datetime:Y-m-d',
|
||||
@@ -106,7 +105,7 @@ class Payment extends Model implements IDs
|
||||
->select(['payments.id','paid_at','account_id','checkout_id','total_amt',DB::raw("SUM(ABS(amount)) as allocated")])
|
||||
->leftJoin('payment_items',['payment_items.payment_id'=>'payments.id'])
|
||||
->groupBy(['payments.id','paid_at','total_amt','account_id','checkout_id'])
|
||||
->having(DB::raw('ROUND(total_amt-IFNULL(allocated,0),2)'),'>',self::threshold);
|
||||
->having(DB::raw('ROUND(CAST(total_amt-COALESCE(SUM(ABS(amount)),0) AS NUMERIC),2)'),'>',self::threshold);
|
||||
}
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
Reference in New Issue
Block a user