diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 8bf2028..ed569fd 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -67,7 +67,11 @@ class ServiceController extends Controller if (! $o->order_info) $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'; return $o->save(); @@ -91,6 +95,9 @@ class ServiceController extends Controller 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()) { foreach ($this->service_change_charges($request,$o) as $co) $co->save(); @@ -100,12 +107,17 @@ class ServiceController extends Controller $o->order_status = 'ACTIVE'; $o->save(); + $np->pivot->complete = TRUE; + $np->pivot->effective_at = Carbon::now(); + $np->pivot->save(); + return redirect()->to(url('u/service',[$o->id])); } return view('service.change_pending') ->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()) { $request->validate([ + 'product_id'=>'required|exists:products,id', 'change_date'=>'required|date', - 'notes'=>'required|min:10', + 'notes'=>'nullable|min:10', ]); - if (! $o->order_info) - $o->order_info = collect(); + $o->changes()->attach([$o->id=>[ + '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->save(); diff --git a/app/Mail/ChangeRequest.php b/app/Mail/ChangeRequest.php index f5ef620..48c7dbd 100644 --- a/app/Mail/ChangeRequest.php +++ b/app/Mail/ChangeRequest.php @@ -26,7 +26,7 @@ class ChangeRequest extends Mailable public function __construct(Service $o,string $notes='') { $this->service = $o; - $this->notes = $notes; + $this->notes = $notes ?? ''; } /** diff --git a/app/Models/Service.php b/app/Models/Service.php index e090ea0..fe841a6 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -28,6 +28,11 @@ use App\Traits\SiteID; * Class Service * 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: * + 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" @@ -46,14 +51,10 @@ use App\Traits\SiteID; * + sid : System ID for 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 * @todo "Billing Start Date" = "connection date" for sub types?? * @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 { @@ -356,6 +357,14 @@ class Service extends Model implements IDs ->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 public function invoice_items($active=TRUE) { diff --git a/app/Models/ServiceChange.php b/app/Models/ServiceChange.php index a8c55e0..9d18274 100644 --- a/app/Models/ServiceChange.php +++ b/app/Models/ServiceChange.php @@ -12,5 +12,4 @@ use Illuminate\Database\Eloquent\Model; class ServiceChange extends Model { protected $table = 'service__change'; - public $timestamps = FALSE; } \ No newline at end of file diff --git a/database/migrations/2023_05_05_234120_service_change_update.php b/database/migrations/2023_05_05_234120_service_change_update.php new file mode 100644 index 0000000..9f3e4d4 --- /dev/null +++ b/database/migrations/2023_05_05_234120_service_change_update.php @@ -0,0 +1,100 @@ +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'); + } +}; diff --git a/resources/views/theme/backend/adminlte/service/change_pending.blade.php b/resources/views/theme/backend/adminlte/service/change_pending.blade.php index 75c34ad..5b88081 100644 --- a/resources/views/theme/backend/adminlte/service/change_pending.blade.php +++ b/resources/views/theme/backend/adminlte/service/change_pending.blade.php @@ -14,7 +14,7 @@ {{ $o->sid }} @endsection - + @section('main-content')