Reimplmement service changes going to the service__change table
This commit is contained in:
parent
691180b3f0
commit
013bb632d3
@ -67,7 +67,11 @@ class ServiceController extends Controller
|
|||||||
if (! $o->order_info)
|
if (! $o->order_info)
|
||||||
$o->order_info = collect();
|
$o->order_info = collect();
|
||||||
|
|
||||||
$o->order_info->put('change_cancel',Carbon::now()->format('Y-m-d H:i:s'));
|
// @todo add some validation if this doesnt return a result
|
||||||
|
$np = $o->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->get()->pop();
|
||||||
|
$np->pivot->active = FALSE;
|
||||||
|
$np->pivot->save();
|
||||||
|
|
||||||
$o->order_status = 'ACTIVE';
|
$o->order_status = 'ACTIVE';
|
||||||
|
|
||||||
return $o->save();
|
return $o->save();
|
||||||
@ -91,6 +95,9 @@ class ServiceController extends Controller
|
|||||||
|
|
||||||
public function change_pending(ServiceChangeRequest $request,Service $o)
|
public function change_pending(ServiceChangeRequest $request,Service $o)
|
||||||
{
|
{
|
||||||
|
// @todo add some validation if this doesnt return a result
|
||||||
|
$np = $o->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->get()->pop();
|
||||||
|
|
||||||
if ($request->post()) {
|
if ($request->post()) {
|
||||||
foreach ($this->service_change_charges($request,$o) as $co)
|
foreach ($this->service_change_charges($request,$o) as $co)
|
||||||
$co->save();
|
$co->save();
|
||||||
@ -100,12 +107,17 @@ class ServiceController extends Controller
|
|||||||
$o->order_status = 'ACTIVE';
|
$o->order_status = 'ACTIVE';
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
|
$np->pivot->complete = TRUE;
|
||||||
|
$np->pivot->effective_at = Carbon::now();
|
||||||
|
$np->pivot->save();
|
||||||
|
|
||||||
return redirect()->to(url('u/service',[$o->id]));
|
return redirect()->to(url('u/service',[$o->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('service.change_pending')
|
return view('service.change_pending')
|
||||||
->with('breadcrumb',collect()->merge($o->account->breadcrumb))
|
->with('breadcrumb',collect()->merge($o->account->breadcrumb))
|
||||||
->with('o',$o);
|
->with('o',$o)
|
||||||
|
->with('np',$np);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,16 +230,22 @@ class ServiceController extends Controller
|
|||||||
{
|
{
|
||||||
if ($request->post()) {
|
if ($request->post()) {
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
'product_id'=>'required|exists:products,id',
|
||||||
'change_date'=>'required|date',
|
'change_date'=>'required|date',
|
||||||
'notes'=>'required|min:10',
|
'notes'=>'nullable|min:10',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! $o->order_info)
|
$o->changes()->attach([$o->id=>[
|
||||||
$o->order_info = collect();
|
'site_id'=> $o->site_id,
|
||||||
|
'ordered_by' => Auth::id(),
|
||||||
|
'ordered_at' => Carbon::now(),
|
||||||
|
'effective_at' => $request->change_date,
|
||||||
|
'product_id' => $request->product_id,
|
||||||
|
'notes' => $request->notes,
|
||||||
|
'active' => TRUE,
|
||||||
|
'complete' => FALSE,
|
||||||
|
]]);
|
||||||
|
|
||||||
$o->order_info->put('change_note',$request->notes);
|
|
||||||
$o->order_info->put('change_date',$request->change_date);
|
|
||||||
$o->order_info->put('change_product_id',$request->product_id);
|
|
||||||
$o->order_status = 'CHANGE-REQUEST';
|
$o->order_status = 'CHANGE-REQUEST';
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class ChangeRequest extends Mailable
|
|||||||
public function __construct(Service $o,string $notes='')
|
public function __construct(Service $o,string $notes='')
|
||||||
{
|
{
|
||||||
$this->service = $o;
|
$this->service = $o;
|
||||||
$this->notes = $notes;
|
$this->notes = $notes ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +28,11 @@ use App\Traits\SiteID;
|
|||||||
* Class Service
|
* Class Service
|
||||||
* Services that belong to an account
|
* Services that belong to an account
|
||||||
*
|
*
|
||||||
|
* So each service attribute has:
|
||||||
|
* - Offering, what product we supply (we make offerings from supplier's supplied products) - in the DB these are products/*
|
||||||
|
* - Supplied, our supplier's product that is providing the service - in the DB these are supplier/*
|
||||||
|
* - Type, what service we are providing, made up of a product we supply - in the DB these are service/*
|
||||||
|
*
|
||||||
* Attributes for services:
|
* Attributes for services:
|
||||||
* + additional_cost : Pending additional charges for this service (excluding setup) //@todo check all these are still valid
|
* + additional_cost : Pending additional charges for this service (excluding setup) //@todo check all these are still valid
|
||||||
* + billing_charge : Charge for this service each invoice period // @todo change to "charge"
|
* + billing_charge : Charge for this service each invoice period // @todo change to "charge"
|
||||||
@ -46,14 +51,10 @@ use App\Traits\SiteID;
|
|||||||
* + sid : System ID for service
|
* + sid : System ID for service
|
||||||
* + supplied : The model of the supplier's product used for this service.
|
* + supplied : The model of the supplier's product used for this service.
|
||||||
*
|
*
|
||||||
* = Terminology:
|
|
||||||
* - Offering, what product we supply (we make offerings from supplier's supplied products) - in the DB these are products/*
|
|
||||||
* - Supplied, our supplier's product that is providing the service - in the DB these are supplier/*
|
|
||||||
* - Type, what service we are providing, made up of a product we supply - in the DB these are service/*
|
|
||||||
*
|
|
||||||
* @package App\Models
|
* @package App\Models
|
||||||
* @todo "Billing Start Date" = "connection date" for sub types??
|
* @todo "Billing Start Date" = "connection date" for sub types??
|
||||||
* @todo Add min_charge
|
* @todo Add min_charge
|
||||||
|
* @todo deprecate price_override, and if price < what would be billed, show it striked through, otherwise show it as if it was the price
|
||||||
*/
|
*/
|
||||||
class Service extends Model implements IDs
|
class Service extends Model implements IDs
|
||||||
{
|
{
|
||||||
@ -356,6 +357,14 @@ class Service extends Model implements IDs
|
|||||||
->orderBy('created_at');
|
->orderBy('created_at');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function changes()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Product::class,'service__change','service_id','product_id','id','id')
|
||||||
|
->where('service__change.site_id',$this->site_id)
|
||||||
|
->withPivot(['ordered_at','effective_at','ordered_by','active','complete','notes'])
|
||||||
|
->withTimestamps();
|
||||||
|
}
|
||||||
|
|
||||||
// @todo changed to invoiced_items
|
// @todo changed to invoiced_items
|
||||||
public function invoice_items($active=TRUE)
|
public function invoice_items($active=TRUE)
|
||||||
{
|
{
|
||||||
|
@ -12,5 +12,4 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
class ServiceChange extends Model
|
class ServiceChange extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'service__change';
|
protected $table = 'service__change';
|
||||||
public $timestamps = FALSE;
|
|
||||||
}
|
}
|
100
database/migrations/2023_05_05_234120_service_change_update.php
Normal file
100
database/migrations/2023_05_05_234120_service_change_update.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
DB::statement('ALTER TABLE service__change RENAME COLUMN ordered_at TO ordered_at_old');
|
||||||
|
DB::statement('ALTER TABLE service__change RENAME COLUMN effective_at TO effective_at_old');
|
||||||
|
|
||||||
|
Schema::table('service__change', function (Blueprint $table) {
|
||||||
|
$table->dateTime('created_at')->nullable()->after('id');
|
||||||
|
$table->dateTime('updated_at')->nullable()->after('created_at');
|
||||||
|
$table->date('ordered_at')->nullable()->after('ordered_by');
|
||||||
|
$table->date('effective_at')->nullable()->after('ordered_at');
|
||||||
|
$table->text('notes')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
DB::statement('ALTER TABLE service__change MODIFY service_id int unsigned NOT NULL');
|
||||||
|
DB::statement('ALTER TABLE service__change MODIFY product_id int unsigned NOT NULL');
|
||||||
|
DB::statement('ALTER TABLE service__change MODIFY ordered_by int unsigned NOT NULL');
|
||||||
|
|
||||||
|
DB::statement('ALTER TABLE service__change MODIFY active tinyint(1) NOT NULL');
|
||||||
|
DB::statement('ALTER TABLE service__change MODIFY complete tinyint(1) NOT NULL');
|
||||||
|
|
||||||
|
// Convert out dates
|
||||||
|
foreach (\App\Models\ServiceChange::withoutGlobalScope(\App\Models\Scopes\SiteScope::class)->cursor() as $o) {
|
||||||
|
// If we are running again
|
||||||
|
if ($o->created_at)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ($o->ordered_at_old)
|
||||||
|
$o->created_at = \Carbon\Carbon::create(substr($o->ordered_at_old,0,4),substr($o->ordered_at_old,4,2),substr($o->ordered_at_old,6,2));
|
||||||
|
|
||||||
|
$o->updated_at = $o->created_at;
|
||||||
|
$o->ordered_at = $o->created_at;
|
||||||
|
|
||||||
|
if ($o->effective_at_old)
|
||||||
|
$o->effective_at = \Carbon\Carbon::create(substr($o->effective_at_old,0,4),substr($o->effective_at_old,4,2),substr($o->effective_at_old,6,2));
|
||||||
|
|
||||||
|
$o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::table('service__change', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['ordered_at_old','effective_at_old']);
|
||||||
|
});
|
||||||
|
|
||||||
|
DB::statement('ALTER TABLE service__change MODIFY ordered_at date NOT NULL');
|
||||||
|
|
||||||
|
foreach (\App\Models\Service::where('order_info','LIKE','%change%')->withoutGlobalScope(\App\Models\Scopes\SiteScope::class)->cursor() as $o) {
|
||||||
|
if ($o->order_info->only(['change_note','change_product_id','change_date'])->count() !== 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$o->changes()->attach([$o->id => [
|
||||||
|
'site_id'=> $o->site_id,
|
||||||
|
'ordered_by' => 1,
|
||||||
|
'ordered_at' => $x=\Carbon\Carbon::createFromDate(\Illuminate\Support\Arr::get($o->order_info,'change_date')),
|
||||||
|
'effective_at' => $x,
|
||||||
|
'product_id' => \Illuminate\Support\Arr::get($o->order_info,'change_product_id'),
|
||||||
|
'notes' => \Illuminate\Support\Arr::get($o->order_info,'change_note'),
|
||||||
|
'active' => true,
|
||||||
|
'complete' => true,
|
||||||
|
]]);
|
||||||
|
|
||||||
|
$o->order_info->forget(['change_note','change_product_id','change_date']);
|
||||||
|
$o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional cleanup
|
||||||
|
foreach (\App\Models\Service::whereNotNull('order_info')->withoutGlobalScope(\App\Models\Scopes\SiteScope::class)->cursor() as $o) {
|
||||||
|
foreach (['notes','provision_notes','cancel_note'] as $key) {
|
||||||
|
if ($o->order_info && ((is_array($o->order_info) && array_key_exists($key,$o->order_info)) || ($o->order_info->has($key))) && is_null(\Illuminate\Support\Arr::get($o->order_info,$key)))
|
||||||
|
$o->order_info->forget($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
$o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final cleanup
|
||||||
|
DB::statement("UPDATE services set order_info=null WHERE order_info='[]'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
abort(500,'cant go back');
|
||||||
|
}
|
||||||
|
};
|
@ -14,7 +14,7 @@
|
|||||||
{{ $o->sid }}
|
{{ $o->sid }}
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
<!-- $o = App\Models\Service::class -->
|
<!-- $o = Service::class, $np = Product::class -->
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-lg-4">
|
<div class="col-12 col-lg-4">
|
||||||
@ -56,7 +56,7 @@
|
|||||||
<!-- @todo TO DO LIMIT THIS TO OF THE SAME OFFERING TYPE AND SORT BY NAME -->
|
<!-- @todo TO DO LIMIT THIS TO OF THE SAME OFFERING TYPE AND SORT BY NAME -->
|
||||||
@foreach (\App\Models\Product::get() as $po)
|
@foreach (\App\Models\Product::get() as $po)
|
||||||
@if (! $po->category || ($po->category !== $o->product->category)) @continue @endif
|
@if (! $po->category || ($po->category !== $o->product->category)) @continue @endif
|
||||||
<option value="{{ $po->id }}" {{ $po->id == old('broadband.product_id',$po->exists ? Arr::get($o->order_info,'change_product_id') : NULL) ? 'selected' : '' }}>{{ $po->name }}</option>
|
<option value="{{ $po->id }}" {{ $po->id == old('broadband.product_id',$np->id) ? 'selected' : '' }}>{{ $po->name }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
<span class="invalid-feedback" role="alert">
|
<span class="invalid-feedback" role="alert">
|
||||||
@ -81,7 +81,7 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="date" class="form-control @error('broadband.start_at') is-invalid @enderror" id="start_at" name="broadband[start_at]" value="{{ \Illuminate\Support\Arr::get($o->order_info,'change_date') ?? '' }}" required>
|
<input type="date" class="form-control @error('broadband.start_at') is-invalid @enderror" id="start_at" name="broadband[start_at]" value="{{ $np->pivot->effective_at ?? $np->pivot->ordered_at }}" required>
|
||||||
<span class="invalid-feedback" role="alert">
|
<span class="invalid-feedback" role="alert">
|
||||||
@error('broadband.start_at')
|
@error('broadband.start_at')
|
||||||
{{ $message }}
|
{{ $message }}
|
||||||
@ -153,7 +153,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@include('service.widget.internal',['o'=>$o,'p'=>\App\Models\Product::where('id',Arr::get($o->order_info,'change_product_id'))->singleOrFail()])
|
@include('service.widget.internal',['o'=>$o,'p'=>$np])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -170,13 +170,14 @@
|
|||||||
var pid = $('#product_id').val();
|
var pid = $('#product_id').val();
|
||||||
var start = $('#start_at').val();
|
var start = $('#start_at').val();
|
||||||
var fee = $('#change_fee').val();
|
var fee = $('#change_fee').val();
|
||||||
|
var price = $('#price').val();
|
||||||
|
|
||||||
$("div[id=transactions]").empty();
|
$("div[id=transactions]").empty();
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
dataType: 'html',
|
dataType: 'html',
|
||||||
data: {broadband: {product_id: pid,start_at: start,change_fee: fee}},
|
data: {broadband: {product_id: pid,start_at: start,change_fee: fee,price: price}},
|
||||||
cache: false,
|
cache: false,
|
||||||
url: '{{ url('r/service_change_charges',[$o->id]) }}',
|
url: '{{ url('r/service_change_charges',[$o->id]) }}',
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
@ -205,6 +206,10 @@
|
|||||||
pendingtrans();
|
pendingtrans();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#price').on('change',function() {
|
||||||
|
pendingtrans();
|
||||||
|
});
|
||||||
|
|
||||||
pendingtrans();
|
pendingtrans();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -89,7 +89,11 @@
|
|||||||
</div>
|
</div>
|
||||||
@can('wholesaler')
|
@can('wholesaler')
|
||||||
<div class="tab-pane fade" id="internal" role="tabpanel">
|
<div class="tab-pane fade" id="internal" role="tabpanel">
|
||||||
|
@if(($x=$o->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->get()->pop()))
|
||||||
|
@include('service.widget.internal',['o'=>$o,'p'=>$x])
|
||||||
|
@else
|
||||||
@include('service.widget.internal',['o'=>$o,'p'=>new \App\Models\Product()])
|
@include('service.widget.internal',['o'=>$o,'p'=>new \App\Models\Product()])
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade {{ session()->pull('service_update') ? 'active show' : '' }}" id="update" role="tabpanel">
|
<div class="tab-pane fade {{ session()->pull('service_update') ? 'active show' : '' }}" id="update" role="tabpanel">
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<!-- @todo -->
|
<!-- @todo -->
|
||||||
<tr>
|
<tr>
|
||||||
<th>Traffic</th>
|
<th>Traffic</th>
|
||||||
<td>{{ $o->service->offering->allowance_string() }} GB @if(FALSE)(YY GB used month)@endif</td>
|
<td>{{ $o->service->offering->allowance_string() }} GB</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>IP4 Address</th>
|
<th>IP4 Address</th>
|
||||||
@ -73,6 +73,23 @@
|
|||||||
<th>Cancel Notice</th>
|
<th>Cancel Notice</th>
|
||||||
<td>1 month @if($o->inContract())<small>(after {{ $o->service_expire->subMonth()->format('Y-m-d') }})</small>@endif</td>
|
<td>1 month @if($o->inContract())<small>(after {{ $o->service_expire->subMonth()->format('Y-m-d') }})</small>@endif</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@if(($x=$o->service->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->get()->pop()))
|
||||||
|
<tr>
|
||||||
|
<th>Pending Plan Change</th>
|
||||||
|
<td>{{ $x->name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Pending Submitted</th>
|
||||||
|
<td>{{ $x->pivot->ordered_at }}</td>
|
||||||
|
</tr>
|
||||||
|
@if($x->pivot->effective_at)
|
||||||
|
<tr>
|
||||||
|
<th>Pending Active</th>
|
||||||
|
<td>{{ $x->pivot->effective_at }}</td>
|
||||||
|
</tr>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -11,12 +11,14 @@
|
|||||||
@if ($o->setup_charge)
|
@if ($o->setup_charge)
|
||||||
<tr>
|
<tr>
|
||||||
<th>Setup Charges <sup>*</sup></th>
|
<th>Setup Charges <sup>*</sup></th>
|
||||||
<td class="text-right">${{ number_format($user->exists ? $user->taxed($o->setup_charge) : Config::get('site')->taxed($o->setup_charge),2) }}</td>
|
{{-- @todo this should use account::taxed() when the user is known --}}
|
||||||
|
<td class="text-right">${{ number_format($user->exists ? Config::get('site')->taxed($o->setup_charge) : Config::get('site')->taxed($o->setup_charge),2) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
<tr>
|
<tr>
|
||||||
<th>Cost <sup>+</sup></th>
|
<th>Cost <sup>+</sup></th>
|
||||||
<td class="text-right">${{ number_format($user->exists ? $user->taxed($o->base_charge) : Config::get('site')->taxed($o->base_charge),2) }}</td>
|
{{-- @todo this should use account::taxed() when the user is known --}}
|
||||||
|
<td class="text-right">${{ number_format($user->exists ? Config::get('site')->taxed($o->base_charge) : Config::get('site')->taxed($o->base_charge),2) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Default Billing</th>
|
<th>Default Billing</th>
|
||||||
@ -28,7 +30,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Minimum Costs <sup>+*</sup></th>
|
<th>Minimum Costs <sup>+*</sup></th>
|
||||||
<td class="text-right">${{ number_format($user->exists ? $user->taxed($o->min_charge) : Config::get('site')->taxed($o->min_charge),2) }}</td>
|
{{-- @todo this should use account::taxed() when the user is known --}}
|
||||||
|
<td class="text-right">${{ number_format($user->exists ? Config::get('site')->taxed($o->min_charge) : Config::get('site')->taxed($o->min_charge),2) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tfoot>
|
<tfoot>
|
||||||
|
Loading…
Reference in New Issue
Block a user