From ebd4367975568e62c9abff5c4468f7f979087d66 Mon Sep 17 00:00:00 2001 From: Deon George Date: Thu, 6 Feb 2020 18:31:43 +0900 Subject: [PATCH] Invoice rendering for service, and unit testing for Invoice Item quantity --- app/Models/InvoiceItem.php | 31 +++ app/Models/Service.php | 190 ++++++++++++++---- database/factories/InvoiceItemFactory.php | 77 +++++++ database/factories/ProductFactory.php | 19 ++ database/factories/ServiceFactory.php | 95 +++++++++ .../common/service/widget/invoice.blade.php | 30 ++- .../backend/adminlte/u/service.blade.php | 34 ++-- .../widgets/broadband/details.blade.php | 9 +- .../u/service/widgets/information.blade.php | 51 +++-- .../adminlte/u/widgets/service/info.blade.php | 49 ----- .../u/widgets/service/order/sent.blade.php | 52 ----- tests/Feature/ExampleTest.php | 21 -- tests/Feature/ServiceTest.php | 100 +++++++++ tests/Unit/ExampleTest.php | 19 -- 14 files changed, 541 insertions(+), 236 deletions(-) create mode 100644 database/factories/InvoiceItemFactory.php create mode 100644 database/factories/ProductFactory.php create mode 100644 database/factories/ServiceFactory.php delete mode 100644 resources/theme/backend/adminlte/u/widgets/service/info.blade.php delete mode 100644 resources/theme/backend/adminlte/u/widgets/service/order/sent.blade.php delete mode 100644 tests/Feature/ExampleTest.php create mode 100644 tests/Feature/ServiceTest.php delete mode 100644 tests/Unit/ExampleTest.php diff --git a/app/Models/InvoiceItem.php b/app/Models/InvoiceItem.php index 8fee3a8..6d34d16 100644 --- a/app/Models/InvoiceItem.php +++ b/app/Models/InvoiceItem.php @@ -4,6 +4,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; +use Leenooks\Carbon; class InvoiceItem extends Model { @@ -36,6 +37,36 @@ class InvoiceItem extends Model /** ATTRIBUTES **/ + /** + * Start date for the invoice item line + * + * We need cast this value to a Leenooks\Carbon for access to startOfHalf() endOfHalf() methods + * + * @param $value + * @return Carbon + * @throws \Exception + */ + public function getDateStartAttribute($value) + { + if (! is_null($value)) + return Carbon::createFromTimestamp($value); + } + + /** + * End date for the invoice item line + * + * We need cast this value to a Leenooks\Carbon for access to startOfHalf() endOfHalf() methods + * + * @param $value + * @return Carbon + * @throws \Exception + */ + public function getDateStopAttribute($value) + { + if (! is_null($value)) + return Carbon::createFromTimestamp($value); + } + public function getItemTypeNameAttribute() { $types = [ diff --git a/app/Models/Service.php b/app/Models/Service.php index ff67990..2cd7cfc 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -2,15 +2,18 @@ namespace App\Models; -use Illuminate\Database\Eloquent\Collection; +use Exception; +use Illuminate\Database\Eloquent\Collection as DatabaseCollection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use App\Traits\NextKey; +use Leenooks\Carbon; class Service extends Model { @@ -23,8 +26,11 @@ class Service extends Model protected $dates = [ 'date_last_invoice', - 'date_next_invoice' + 'date_next_invoice'. + 'date_start', + 'date_end', ]; + public $dateFormat = 'U'; protected $table = 'ab_service'; @@ -303,38 +309,124 @@ class Service extends Model * Return the date for the next invoice * * @todo This function negates the need for date_next_invoice - * @return null + * @return Carbon|string */ public function getInvoiceNextAttribute() { $last = $this->getInvoiceToAttribute(); - $date = $last ? $last->addDay() : now(); + $date = $last ? $last->addDay() : Carbon::now(); return request()->wantsJson() ? $date->format('Y-m-d') : $date; } + /** + * Return the end date for the next invoice + * + * @return mixed + * @throws Exception + */ public function getInvoiceNextEndAttribute() { - switch ($this->recur_schedule) - { + switch ($this->recur_schedule) { // Weekly - case 0: $date = $this->getInvoiceNextAttribute()->addWeek(); break; + case 0: $date = $this->product->price_recurr_strict + ? $this->getInvoiceNextAttribute()->endOfWeek() + : $this->getInvoiceNextAttribute()->addWeek()->subDay(); + break; + // Monthly - case 1: $date = $this->getInvoiceNextAttribute()->addMonth(); break; + case 1: + $date = $this->product->price_recurr_strict + ? $this->getInvoiceNextAttribute()->endOfMonth() + : $this->getInvoiceNextAttribute()->addMonth()->subDay(); + break; + // Quarterly - case 2: $date = $this->getInvoiceNextAttribute()->addQuarter(); break; + case 2: + $date = $this->product->price_recurr_strict + ? $this->getInvoiceNextAttribute()->endOfQuarter() + : $this->getInvoiceNextAttribute()->addQuarter()->subDay(); + break; + // Half Yearly - case 3: $date = $this->getInvoiceNextAttribute()->addQuarter(2); break; + case 3: + $date = $this->product->price_recurr_strict + ? $this->getInvoiceNextAttribute()->endOfHalf() + : $this->getInvoiceNextAttribute()->addQuarter(2)->subDay(); + break; + // Yearly - case 4: $date = $this->getInvoiceNextAttribute()->addYear(); break; + case 4: + $date = $this->product->price_recurr_strict + ? $this->getInvoiceNextAttribute()->endOfYear() + : $this->getInvoiceNextAttribute()->addYear()->subDay(); + break; + // Two Yearly - case 5: $date = $this->getInvoiceNextAttribute()->addYear(2); break; + // NOTE: price_recurr_strict ignored + case 5: $date = $this->getInvoiceNextAttribute()->addYear(2)->subDay(); break; + // Three Yearly - case 6: $date = $this->getInvoiceNextAttribute()->addYear(3); break; - default: throw new \Exception('Unknown recur_schedule'); + // NOTE: price_recurr_strict ignored + case 6: $date = $this->getInvoiceNextAttribute()->addYear(3)->subDay(); break; + + default: throw new Exception('Unknown recur_schedule'); } - return $date->subDay(); + return $date; + } + + public function getInvoiceNextQuantityAttribute() + { + // If we are not rounding to the first day of the cycle, then it is always a full cycle + if (! $this->product->price_recurr_strict) + return 1; + + $n = $this->invoice_next->diff($this->invoice_next_end)->days+1; + + switch ($this->recur_schedule) { + // Weekly + case 0: + $d = $this->invoice_next_end->diff($this->invoice_next_end->startOfWeek())->days; + break; + + // Monthly + case 1: + $d = $this->invoice_next_end->diff($this->invoice_next_end->startOfMonth())->days; + break; + + // Quarterly + case 2: + $d = $this->invoice_next_end->diff($this->invoice_next_end->startOfQuarter())->days; + break; + + // Half Yearly + case 3: + $d = $this->invoice_next_end->diff($this->invoice_next_end->startOfHalf())->days; + break; + + // Yearly + case 4: + $d = $this->invoice_next_end->diff($this->invoice_next_end->startOfYear())->days; + break; + + // Two Yearly + case 5: + $d = $this->invoice_next_end->diff($this->invoice_next_end->subyear(2))->days-1; + break; + + // Three Yearly + case 6: + $d = $this->invoice_next_end->diff($this->invoice_next_end->subyear(3))->days-1; + break; + + default: throw new Exception('Unknown recur_schedule'); + } + + // Include the start date and end date. + $d += 1; + + return round($n/$d,2); } /** @@ -541,14 +633,24 @@ class Service extends Model public function getStatusHTMLAttribute(): string { $class = NULL; - switch ($this->status) - { - case 'ACTIVE': - $class = 'badge-success'; - break; - } - return sprintf('%s',$class,$this->status); + if ($this->isPending()) + $class = 'badge-warning'; + + else + switch ($this->status) + { + case 'ACTIVE': + $class = 'badge-success'; + break; + case 'INACTIVE': + $class = 'badge-danger'; + break; + } + + return $class + ? sprintf('%s',$class,$this->status) + : $this->status; } /** @@ -597,7 +699,7 @@ class Service extends Model return round($value*1.1,2); } - public function invoices_due(): Collection + public function invoices_due(): DatabaseCollection { $this->load('invoice_items.invoice'); @@ -635,29 +737,41 @@ class Service extends Model */ public function isPending(): bool { - return ! $this->active AND ! in_array($this->order_status,$this->inactive_status); + return ! $this->active + AND ! is_null($this->order_status) + AND ! in_array($this->order_status,array_merge($this->inactive_status,['INACTIVE'])); } - public function next_invoice_items(): \Illuminate\Support\Collection + /** + * Generate a collection of invoice_item objects that will be billed for the next invoice + * + * @return Collection + * @throws Exception + */ + public function next_invoice_items(): Collection { $result = collect(); $o = new InvoiceItem; - $o->active = TRUE; - $o->service_id = $this->id; - $o->product_id = $this->product_id; - $o->quantity = 1; - $o->item_type = 0; - $o->price_base = $this->price ?: $this->product->price($this->recur_schedule); // @todo change to a method in this class - $o->recurring_schedule = $this->recur_schedule; - $o->date_start = $this->invoice_next; - $o->date_stop = $this->invoice_next_end; - $o->addTaxes(); - $result->push($o); + // If the service is active, there will be service charges + if ($this->active or $this->isPending()) { + $o->active = TRUE; + $o->service_id = $this->id; + $o->product_id = $this->product_id; + $o->item_type = 0; + $o->price_base = $this->price ?: $this->product->price($this->recur_schedule); // @todo change to a method in this class + $o->recurring_schedule = $this->recur_schedule; + $o->date_start = $this->invoice_next; + $o->date_stop = $this->invoice_next_end; + $o->quantity = $this->invoice_next_quantity; - foreach ($this->charges->filter(function($item) { return ! $item->processed; }) as $oo) - { + $o->addTaxes(); + $result->push($o); + } + + // Add additional charges + foreach ($this->charges->filter(function($item) { return ! $item->processed; }) as $oo) { $o = new InvoiceItem; $o->active = TRUE; $o->service_id = $oo->service_id; diff --git a/database/factories/InvoiceItemFactory.php b/database/factories/InvoiceItemFactory.php new file mode 100644 index 0000000..b79e84c --- /dev/null +++ b/database/factories/InvoiceItemFactory.php @@ -0,0 +1,77 @@ +define(App\Models\InvoiceItem::class, function (Faker $faker) { + return [ + 'id'=>1, + ]; +}); + +// Weekly +$factory->state(App\Models\InvoiceItem::class,'week',[ + 'date_start'=>Carbon::now()->startOfWeek(), + 'date_stop'=>Carbon::now()->endOfWeek(), +]); + +$factory->state(App\Models\InvoiceItem::class,'week-mid',[ + 'date_start'=>Carbon::now()->startOfWeek(), + 'date_stop'=>Carbon::now()->endOfWeek()->addDays(3), +]); + +// Monthly +$factory->state(App\Models\InvoiceItem::class,'month',[ + 'date_start'=>Carbon::now()->startOfMonth(), + 'date_stop'=>Carbon::now()->endOfMonth(), +]); + +$factory->state(App\Models\InvoiceItem::class,'month-mid',[ + 'date_start'=>Carbon::now()->startOfMonth(), + 'date_stop'=>Carbon::now()->endOfMonth()->addDays(Carbon::now()->daysInMonth/2+1), +]); + +// Quarterly +$factory->state(App\Models\InvoiceItem::class,'quarter',[ + 'date_start'=>Carbon::now()->startOfQuarter(), + 'date_stop'=>Carbon::now()->endOfQuarter(), +]); + +$factory->state(App\Models\InvoiceItem::class,'quarter-mid',[ + 'date_start'=>Carbon::now()->startOfQuarter(), + 'date_stop'=>Carbon::now()->startOfQuarter()->addDays(45), +]); + +// Half Yearly +$factory->state(App\Models\InvoiceItem::class,'half',[ + 'date_start'=>Carbon::now()->startOfHalf(), + 'date_stop'=>Carbon::now()->endOfHalf(), +]); + +$factory->state(App\Models\InvoiceItem::class,'half-mid',[ + 'date_start'=>Carbon::now()->startOfHalf(), + 'date_stop'=>Carbon::now()->startOfHalf()->addDays(90), +]); + +// Yearly +$factory->state(App\Models\InvoiceItem::class,'year',[ + 'date_start'=>Carbon::now()->startOfYear(), + 'date_stop'=>Carbon::now()->endOfYear(), +]); + +$factory->state(App\Models\InvoiceItem::class,'year-mid',[ + 'date_start'=>Carbon::now()->startOfYear(), + 'date_stop'=>Carbon::now()->startOfYear()->addDays(181), +]); + +// Two Yearly (price_recurr_strict ignored) +$factory->state(App\Models\InvoiceItem::class,'2year',[ + 'date_start'=>Carbon::now()->subyear(), + 'date_stop'=>Carbon::now()->subday(), +]); + +// Three Yearly (price_recurr_strict ignored) +$factory->state(App\Models\InvoiceItem::class,'3year',[ + 'date_start'=>Carbon::now()->subyear(2), + 'date_stop'=>Carbon::now()->subday(), +]); \ No newline at end of file diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php new file mode 100644 index 0000000..817b81f --- /dev/null +++ b/database/factories/ProductFactory.php @@ -0,0 +1,19 @@ +define(App\Models\Product::class, function (Faker $faker) { + return [ + 'id'=>1, + ]; +}); + +$factory->state(App\Models\Product::class,'active',[ + 'active' => '1', +]); +$factory->state(App\Models\Product::class,'strict',[ + 'price_recurr_strict' => '1', +]); +$factory->state(App\Models\Product::class,'notstrict',[ + 'price_recurr_strict' => '0', +]); \ No newline at end of file diff --git a/database/factories/ServiceFactory.php b/database/factories/ServiceFactory.php new file mode 100644 index 0000000..a7002d6 --- /dev/null +++ b/database/factories/ServiceFactory.php @@ -0,0 +1,95 @@ +define(App\Models\Service::class, function (Faker $faker) { + return [ + 'account_id'=>1, + ]; +}); + +$factory->afterMaking(App\Models\Service::class, function ($service,$faker) { + $product = factory(App\Models\Product::class)->make(); + + $service->setRelation('product',$product); + $service->product_id = $product->id; +}); + +// Weekly +$factory->afterMakingState(App\Models\Service::class,'week',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('week')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 0; +}); + +$factory->afterMakingState(App\Models\Service::class,'week-mid',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('week-mid')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 0; +}); + +// Monthly +$factory->afterMakingState(App\Models\Service::class,'month',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('month')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 1; +}); + +$factory->afterMakingState(App\Models\Service::class,'month-mid',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('month-mid')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 1; +}); + +// Quarterly +$factory->afterMakingState(App\Models\Service::class,'quarter',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('quarter')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 2; +}); + +$factory->afterMakingState(App\Models\Service::class,'quarter-mid',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('quarter-mid')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 2; +}); + +// Half Yearly +$factory->afterMakingState(App\Models\Service::class,'half',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('half')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 3; +}); + +$factory->afterMakingState(App\Models\Service::class,'half-mid',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('half-mid')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 3; +}); + +// Yearly +$factory->afterMakingState(App\Models\Service::class,'year',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('year')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 4; +}); + +$factory->afterMakingState(App\Models\Service::class,'year-mid',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('year-mid')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 4; +}); + +// 2 Yearly +$factory->afterMakingState(App\Models\Service::class,'2year',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('2year')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 5; +}); + +// 3 Yearly +$factory->afterMakingState(App\Models\Service::class,'3year',function ($service,$faker) { + $invoice_items = factory(App\Models\InvoiceItem::class,1)->state('3year')->make(); + $service->setRelation('invoice_items',$invoice_items); + $service->recur_schedule = 6; +}); \ No newline at end of file diff --git a/resources/theme/backend/adminlte/common/service/widget/invoice.blade.php b/resources/theme/backend/adminlte/common/service/widget/invoice.blade.php index fcb1421..f3a7e2f 100644 --- a/resources/theme/backend/adminlte/common/service/widget/invoice.blade.php +++ b/resources/theme/backend/adminlte/common/service/widget/invoice.blade.php @@ -1,19 +1,13 @@ -
-
- Next Invoice Details -
+ + + + -
-
{{ $o->name }}${{ number_format($o->next_invoice_items()->sum('total'),2) }}
- - - - - @foreach ($o->next_invoice_items() as $io) - - - - @endforeach -
{{ $o->name }}${{ number_format($o->next_invoice_items()->sum('total'),2) }}
 {{ $io->item_type_name }}${{ number_format($io->total,2) }}
-
- \ No newline at end of file + @foreach ($o->next_invoice_items() as $io) + +   + {{ $io->item_type_name }} + ${{ number_format($io->total,2) }} + + @endforeach + \ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/service.blade.php b/resources/theme/backend/adminlte/u/service.blade.php index e3c4636..e0f9c4b 100644 --- a/resources/theme/backend/adminlte/u/service.blade.php +++ b/resources/theme/backend/adminlte/u/service.blade.php @@ -8,7 +8,7 @@ @endsection @section('contentheader_title') - Service: {{ $o->sid }} NBN-50/20-100 + Service: {{ $o->sid }} {{ $o->product->name }} @endsection @section('contentheader_description') {{ $o->sname }}: {{ $o->sdesc }} @@ -34,20 +34,22 @@ - + @can('update',$o) + + @endcan
@@ -59,7 +61,7 @@ Product.
- Invoice Next. + @include('common.service.widget.invoice')
Invoices. diff --git a/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php b/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php index 263c48f..ed9141c 100644 --- a/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php +++ b/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php @@ -1,11 +1,10 @@
- @if($o->service->isPending()) -
-
- Pending +
+
+ Pending +
-
@endif
diff --git a/resources/theme/backend/adminlte/u/service/widgets/information.blade.php b/resources/theme/backend/adminlte/u/service/widgets/information.blade.php index 98f4aeb..497aed6 100644 --- a/resources/theme/backend/adminlte/u/service/widgets/information.blade.php +++ b/resources/theme/backend/adminlte/u/service/widgets/information.blade.php @@ -2,38 +2,53 @@

Service Information

+
- + - @if ($o->active) + @if ($o->active or $o->isPending()) - - - - - - - - + @if($o->active) + + + + + + + + + @endif - - - - + + + + + + + + + + @else + + + + @endif - - - -
Status{{ $o->status }}{!! $o->status_html !!}
Billed {{ $o->billing_period }}
Invoiced To{{ $o->invoice_to->format('Y-m-d') }}
Paid Until{{ $o->paid_to->format('Y-m-d') }}
Invoiced To{{ $o->invoice_to->format('Y-m-d') }}
Paid Until{{ $o->paid_to->format('Y-m-d') }}
Next Invoice {{ $o->invoice_next->format('Y-m-d') }}
Estimated Invoice${{ number_format($o->billing_price,2) }}
Next Estimated Invoice${{ number_format($o->next_invoice_items()->sum('total'),2) }} *
Payment Method@if ($o->autopay)Direct Debit @else Invoice @endif
Cancelled{!! $o->date_end ? $o->date_end->format('Y-m-d') : $o->paid_to->format('Y-m-d').'*' !!}
Payment Method@if ($o->autopay)Direct Debit @else Invoice @endif
+ + @if($o->active OR $o->isPending()) + + @endif
\ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/widgets/service/info.blade.php b/resources/theme/backend/adminlte/u/widgets/service/info.blade.php deleted file mode 100644 index cd25165..0000000 --- a/resources/theme/backend/adminlte/u/widgets/service/info.blade.php +++ /dev/null @@ -1,49 +0,0 @@ -
-
-

Service Information

-
- - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account{{ $o->account->company }}
Active{{ $o->active }} ({{ $o->order_status }}) [{{ $o->status }}]
Type{{ $o->type->type }}
Product{{ $o->product->name }}: {{ $o->name }}
Billing Period{{ $o->recur_schedule }}
Billing Amount{{ $o->cost }}
Last Invoice{{ $o->date_last_invoice }}
Paid Until{{ 'TBA' }}
Next Invoice{{ $o->date_next_invoice }}
- -
- - {{-- - - --}} -
\ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/widgets/service/order/sent.blade.php b/resources/theme/backend/adminlte/u/widgets/service/order/sent.blade.php deleted file mode 100644 index 5b75791..0000000 --- a/resources/theme/backend/adminlte/u/widgets/service/order/sent.blade.php +++ /dev/null @@ -1,52 +0,0 @@ -
-
-

New Order ({{$o->order_status}})

-
- - -
-
- -
- - - - - - - - @if($o->date_last_invoice) - - - - - - - - - - @endif - - - - @if ($o->date_last) - - - - @endif - - - - - - -
Account{{ $o->account->company }}
Product{{ $o->product->name }}: {{ $o->name }}
Last Invoice{{ $o->date_last_invoice }}
Paid Until{{ 'TBA' }}
Next Invoice{{ $o->date_next_invoice }}
Ordered{{ $o->date_orig->format('Y-m-d') }}
Update{{ $o->date_last->format('Y-m-d') }}
Order Details{!! $o->order_info_details !!}
Reference:{{ \Illuminate\Support\Arr::get($o->order_info,'order_reference','') }}
-
- - {{-- - - --}} -
\ No newline at end of file diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php deleted file mode 100644 index 6eb72b6..0000000 --- a/tests/Feature/ExampleTest.php +++ /dev/null @@ -1,21 +0,0 @@ -get('/login'); - - $response->assertStatus(200); - } -} diff --git a/tests/Feature/ServiceTest.php b/tests/Feature/ServiceTest.php new file mode 100644 index 0000000..3590cd2 --- /dev/null +++ b/tests/Feature/ServiceTest.php @@ -0,0 +1,100 @@ +states('week')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Weekly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Weekly Equals 1'); + + $o = factory(Service::class)->states('week-mid')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Weekly Mid Equals 0.57'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(0.57,$o->invoice_next_quantity,'Weekly Mid Equals 0.57'); + + // Test Monthly Billing + $o = factory(Service::class)->states('month')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Monthly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Monthly Equals 1'); + + $o = factory(Service::class)->states('month-mid')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Monthly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(round(round(Carbon::now()->addMonth()->daysInMonth/2,0)/Carbon::now()->addMonth()->daysInMonth,2),$o->invoice_next_quantity,'Monthly Mid Equals 0.5'); + + // Test Quarterly Billing + $o = factory(Service::class)->states('quarter')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Quarterly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Quarterly Equals 1'); + + $o = factory(Service::class)->states('quarter-mid')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Quarterly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEqualsWithDelta(0.5,$o->invoice_next_quantity,.02,'Quarterly Mid Equals 0.5'); + + // Test Half Year Billing + $o = factory(Service::class)->states('half')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Half Yearly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Half Yearly Equals 1'); + + $o = factory(Service::class)->states('half-mid')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Half Yearly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(0.5,$o->invoice_next_quantity,'Half Yearly Mid Equals 0.5'); + + // Test Year Billing + $o = factory(Service::class)->states('year')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Yearly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Yearly Equals 1'); + + $o = factory(Service::class)->states('year-mid')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Yearly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(0.5,$o->invoice_next_quantity,'Yearly Mid Equals 0.5'); + + // Test 2 Year Billing (price_recurr_strict ignored) + $o = factory(Service::class)->states('2year')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Two Yearly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Two Yearly Equals 1'); + + // Test 3 Year Billing (price_recurr_strict ignored) + $o = factory(Service::class)->states('3year')->make(); + $o->setRelation('product',factory(Product::class)->states('notstrict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Three Yearly Equals 1'); + $o->setRelation('product',factory(Product::class)->states('strict')->make()); + $this->assertEquals(1,$o->invoice_next_quantity,'Three Yearly Equals 1'); + } +} \ No newline at end of file diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php deleted file mode 100644 index e9fe19c..0000000 --- a/tests/Unit/ExampleTest.php +++ /dev/null @@ -1,19 +0,0 @@ -assertTrue(true); - } -}