Rework service, removed redundant code, service invoicing improvements
This commit is contained in:
@@ -16,7 +16,7 @@ use Leenooks\Casts\LeenooksCarbon;
|
||||
|
||||
use App\Models\Product\Type;
|
||||
use App\Interfaces\IDs;
|
||||
use App\Traits\ScopeServiceUserAuthorised;
|
||||
use App\Traits\{ScopeServiceActive,ScopeServiceUserAuthorised};
|
||||
|
||||
/**
|
||||
* Class Service
|
||||
@@ -29,10 +29,10 @@ use App\Traits\ScopeServiceUserAuthorised;
|
||||
*
|
||||
* 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"
|
||||
* + billing_charge : Charge for this service each invoice period
|
||||
* + billing_interval : The period that this service is billed for by default
|
||||
* + billing_interval_string : The period that this service is billed for by default as a name
|
||||
* + billed_to : When this service has been billed to // @todo rename all references to invoice_to
|
||||
* + invoiced_to : When this service has been billed to
|
||||
* + category : The type of service this is, eg: broadband, phone
|
||||
* + category_name : The type of service this is, eg: Broadband, Telephone (in human friendly)
|
||||
* + contract_term : The term that this service must be active
|
||||
@@ -54,7 +54,7 @@ use App\Traits\ScopeServiceUserAuthorised;
|
||||
*/
|
||||
class Service extends Model implements IDs
|
||||
{
|
||||
use HasFactory,ScopeServiceUserAuthorised;
|
||||
use HasFactory,ScopeServiceActive,ScopeServiceUserAuthorised;
|
||||
|
||||
protected $casts = [
|
||||
'order_info' => AsCollection::class,
|
||||
@@ -281,8 +281,8 @@ class Service extends Model implements IDs
|
||||
public static function movements(User $uo): Collection
|
||||
{
|
||||
return (new self)
|
||||
->active()
|
||||
->serviceUserAuthorised($uo)
|
||||
->ServiceActive()
|
||||
->ServiceUserAuthorised($uo)
|
||||
->where('order_status','!=','ACTIVE')
|
||||
->with(['account','product'])
|
||||
->get();
|
||||
@@ -343,7 +343,7 @@ class Service extends Model implements IDs
|
||||
public function charges_active()
|
||||
{
|
||||
return $this->charges()
|
||||
->active();
|
||||
->ServiceActive();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,6 +371,7 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function invoice_items($active=TRUE)
|
||||
{
|
||||
Log::alert('Call to deprecated functon '.__METHOD__);
|
||||
return $this->invoiced_items_active();
|
||||
}
|
||||
|
||||
@@ -418,6 +419,7 @@ class Service extends Model implements IDs
|
||||
{
|
||||
return $this->hasMany(InvoiceItem::class)
|
||||
->where('item_type','=',0)
|
||||
->whereNotNull('start_at')
|
||||
->orderBy('start_at','desc');
|
||||
}
|
||||
|
||||
@@ -464,9 +466,11 @@ class Service extends Model implements IDs
|
||||
|
||||
/**
|
||||
* Only query active categories
|
||||
* @deprecated use ScopeServiceActive
|
||||
*/
|
||||
public function scopeActive($query)
|
||||
{
|
||||
throw new \Exception('deprecated');
|
||||
return $query->where(
|
||||
fn($query)=>
|
||||
$query->where($this->getTable().'.active',TRUE)
|
||||
@@ -479,9 +483,11 @@ class Service extends Model implements IDs
|
||||
*
|
||||
* @param $query
|
||||
* @return mixed
|
||||
* @deprecated use ScopeServiceInactive
|
||||
*/
|
||||
public function scopeInActive($query)
|
||||
public function scopeInactive($query)
|
||||
{
|
||||
dd('deprecated');
|
||||
return $query->where(
|
||||
fn($query)=>
|
||||
$query->where($this->getTable().'.active',FALSE)
|
||||
@@ -527,15 +533,7 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function getBillingChargeAttribute(): float
|
||||
{
|
||||
// If recur_schedule is null, then we only bill this item once
|
||||
if (is_null($this->recur_schedule) && $this->getInvoiceToAttribute())
|
||||
$this->price = 0;
|
||||
|
||||
return $this->account->taxed(
|
||||
is_null($this->price)
|
||||
? $this->product->getBaseChargeAttribute($this->recur_schedule,$this->account->group)
|
||||
: $this->price
|
||||
);
|
||||
return $this->account->taxed($this->billing_charge());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -546,7 +544,7 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function getBillingChargeNormalisedAttribute(): float
|
||||
{
|
||||
return number_format($this->getBillingChargeAttribute()*Invoice::billing_change($this->recur_schedule,$this->offering->billing_interval),2);
|
||||
return number_format($this->getBillingChargeAttribute()*Invoice::billing_change($this->getBillingIntervalAttribute(),$this->offering->billing_interval),2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,39 +567,6 @@ class Service extends Model implements IDs
|
||||
return Invoice::billing_name($this->getBillingIntervalAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a monthly price for a service, even if it is billed at a different frequency
|
||||
*
|
||||
* @return float
|
||||
* @throws Exception
|
||||
* @deprecated use class::billing_charge_normalised()
|
||||
*/
|
||||
public function getBillingMonthlyPriceAttribute(): float
|
||||
{
|
||||
Log::alert('SMO:! Deprecated function getBillingMonthlyPriceAttribute()');
|
||||
return $this->getBillingChargeNormalisedAttribute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Category ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCategoryAttribute(): string
|
||||
{
|
||||
return $this->product->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Category Name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCategoryNameAttribute(): string
|
||||
{
|
||||
return $this->product->category_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The date the contract ends
|
||||
*
|
||||
@@ -652,155 +617,19 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function getInvoiceNextAttribute(): Carbon
|
||||
{
|
||||
$last = $this->getInvoiceToAttribute();
|
||||
$last = $this->getInvoicedToAttribute();
|
||||
|
||||
return $last
|
||||
? $last->addDay()
|
||||
: (min($this->start_at,$this->invoice_next_at) ?: Carbon::now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the end date for the next invoice
|
||||
*
|
||||
* @return Carbon
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getInvoiceNextEndAttribute(): Carbon
|
||||
{
|
||||
switch ($this->recur_schedule) {
|
||||
case Invoice::BILL_WEEKLY:
|
||||
$date = $this->product->price_recur_strict
|
||||
? $this->getInvoiceNextAttribute()->endOfWeek()
|
||||
: $this->getInvoiceNextAttribute()->addWeek()->subDay();
|
||||
break;
|
||||
|
||||
case Invoice::BILL_MONTHLY:
|
||||
$date = $this->product->price_recur_strict
|
||||
? $this->getInvoiceNextAttribute()->endOfMonth()
|
||||
: $this->getInvoiceNextAttribute()->addMonth()->subDay();
|
||||
break;
|
||||
|
||||
case Invoice::BILL_QUARTERLY:
|
||||
$date = $this->product->price_recur_strict
|
||||
? $this->getInvoiceNextAttribute()->endOfQuarter()
|
||||
: $this->getInvoiceNextAttribute()->addQuarter()->subDay();
|
||||
break;
|
||||
|
||||
case Invoice::BILL_SEMI_YEARLY:
|
||||
$date = $this->product->price_recur_strict
|
||||
? $this->getInvoiceNextAttribute()->endOfHalf()
|
||||
: $this->getInvoiceNextAttribute()->addQuarters(2)->subDay();
|
||||
break;
|
||||
|
||||
case Invoice::BILL_YEARLY:
|
||||
$date = $this->product->price_recur_strict
|
||||
? $this->getInvoiceNextAttribute()->endOfYear()
|
||||
: $this->getInvoiceNextAttribute()->addYear()->subDay();
|
||||
break;
|
||||
|
||||
case Invoice::BILL_TWOYEARS:
|
||||
if (! $this->product->price_recur_strict) {
|
||||
$date = $this->getInvoiceNextAttribute()->addYears(2)->subDay();
|
||||
|
||||
} else {
|
||||
$date = $this->getInvoiceNextAttribute()->addYears(2)->subDay()->endOfYear();
|
||||
|
||||
// Make sure we end on an even year
|
||||
if ($date->clone()->addDay()->year%2)
|
||||
$date = $date->subYear();
|
||||
}
|
||||
break;
|
||||
|
||||
// NOTE: price_recur_strict ignored
|
||||
case Invoice::BILL_THREEYEARS:
|
||||
$date = $this->getInvoiceNextAttribute()->addYears(3)->subDay();
|
||||
break;
|
||||
|
||||
// NOTE: price_recur_strict ignored
|
||||
case Invoice::BILL_FOURYEARS:
|
||||
$date = $this->getInvoiceNextAttribute()->addYears(4)->subDay();
|
||||
break;
|
||||
|
||||
// NOTE: price_recur_strict ignored
|
||||
case Invoice::BILL_FIVEYEARS:
|
||||
$date = $this->getInvoiceNextAttribute()->addYears(5)->subDay();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown recur_schedule');
|
||||
}
|
||||
|
||||
// If the invoice has an end date, our invoice period shouldnt be greater than that (might be terminating).
|
||||
if ($this->stop_at && ($this->stop_at < $date))
|
||||
$date = $this->stop_at;
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine how much quantity (at the charge rate) is required for the next invoice
|
||||
*
|
||||
* @return float
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getInvoiceNextQuantityAttribute(): float
|
||||
{
|
||||
// If we are not rounding to the first day of the cycle, then it is always a full cycle
|
||||
if (! $this->product->price_recur_strict)
|
||||
return 1;
|
||||
|
||||
$n = $this->invoice_next->diffInDays($this->invoice_next_end);
|
||||
|
||||
switch ($this->recur_schedule) {
|
||||
case Invoice::BILL_WEEKLY:
|
||||
$d = $this->invoice_next_end->addWeek()->startOfWeek()->diffInDays($this->invoice_next->startOfWeek());
|
||||
break;
|
||||
|
||||
case Invoice::BILL_MONTHLY:
|
||||
$d = $this->invoice_next_end->addMonth()->startOfMonth()->diffInDays($this->invoice_next->startOfMonth());
|
||||
break;
|
||||
|
||||
case Invoice::BILL_QUARTERLY:
|
||||
$d = $this->invoice_next_end->startOfQuarter()->diffInDays($this->invoice_next->addQuarter()->startOfQuarter());
|
||||
break;
|
||||
|
||||
case Invoice::BILL_SEMI_YEARLY:
|
||||
$d = $this->invoice_next_end->addQuarter(2)->startOfHalf()->diffInDays($this->invoice_next->startOfHalf());
|
||||
break;
|
||||
|
||||
case Invoice::BILL_YEARLY:
|
||||
$d = $this->invoice_next_end->addYear()->startOfYear()->diffInDays($this->invoice_next->startOfYear());
|
||||
break;
|
||||
|
||||
case Invoice::BILL_TWOYEARS:
|
||||
$d = $this->invoice_next_end->addYear(2)->startOfYear()->diffInDays($this->invoice_next->subyear(2))-1;
|
||||
break;
|
||||
|
||||
case Invoice::BILL_THREEYEARS:
|
||||
$d = $this->invoice_next_end->addYear(3)->startOfYear()->diffInDays($this->invoice_next->subyear(3))-1;
|
||||
break;
|
||||
|
||||
case Invoice::BILL_FOURYEARS:
|
||||
$d = $this->invoice_next_end->addYear(3)->startOfYear()->diffInDays($this->invoice_next->subyear(4))-1;
|
||||
break;
|
||||
|
||||
case Invoice::BILL_FIVEYEARS:
|
||||
$d = $this->invoice_next_end->addYear(3)->startOfYear()->diffInDays($this->invoice_next->subyear(5))-1;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown recur_schedule');
|
||||
}
|
||||
|
||||
return round($n/$d,2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date that the service has been invoiced to
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getInvoiceToAttribute(): ?Carbon
|
||||
public function getInvoicedToAttribute(): ?Carbon
|
||||
{
|
||||
return ($x=$this->invoiced_service_items_active_recent)->count()
|
||||
? $x->first()->stop_at
|
||||
@@ -826,7 +655,9 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function getNameShortAttribute()
|
||||
{
|
||||
return $this->type->getServiceNameAttribute() ? $this->type->getServiceNameAttribute() : 'SID:'.$this->sid;
|
||||
return $this->type->getServiceNameAttribute()
|
||||
? $this->type->getServiceNameAttribute()
|
||||
: 'SID:'.$this->sid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -841,7 +672,9 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function getNameDetailAttribute()
|
||||
{
|
||||
return ($this->type->getServiceDescriptionAttribute() !== NULL) ? $this->type->getServiceDescriptionAttribute() : 'No Description';
|
||||
return ($this->type->getServiceDescriptionAttribute() !== NULL)
|
||||
? $this->type->getServiceDescriptionAttribute()
|
||||
: 'No Description';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -878,22 +711,13 @@ class Service extends Model implements IDs
|
||||
->last();
|
||||
|
||||
return $lastpaid
|
||||
? $this->invoiced_service_items_active->where('invoice_id',$lastpaid->id)->where('type',0)->max('stop_at')
|
||||
? $this->invoiced_service_items_active
|
||||
->where('invoice_id',$lastpaid->id)
|
||||
->where('type',0)
|
||||
->max('stop_at')
|
||||
: NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the billing recurring configuration for this service
|
||||
*
|
||||
* @param $value
|
||||
* @return int
|
||||
*/
|
||||
public function xgetRecurScheduleAttribute($value): int
|
||||
{
|
||||
// If recur_schedule not set, default to quarterly
|
||||
return $value ?? Invoice::BILL_QUARTERLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Service Status
|
||||
*
|
||||
@@ -1033,6 +857,7 @@ class Service extends Model implements IDs
|
||||
public function actions(): Collection
|
||||
{
|
||||
$next = $this->getStageParameters($this->order_status)->get('next');
|
||||
|
||||
return $next
|
||||
? $next->map(function($item,$key) {
|
||||
$authorized = FALSE;
|
||||
@@ -1050,6 +875,22 @@ class Service extends Model implements IDs
|
||||
: collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* This service billing charge, pre-taxes
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function billing_charge(): float
|
||||
{
|
||||
// If recur_schedule is null, then we only bill this item once
|
||||
if (is_null($this->getBillingIntervalAttribute()) && $this->getInvoicedToAttribute())
|
||||
$this->price = 0;
|
||||
|
||||
return is_null($this->price)
|
||||
? $this->product->getBaseChargeAttribute($this->getBillingIntervalAttribute(),$this->account->group)
|
||||
: $this->price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stage parameters
|
||||
*
|
||||
@@ -1108,7 +949,8 @@ class Service extends Model implements IDs
|
||||
*/
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->attributes['active'] || ($this->order_status && (! in_array($this->order_status,self::INACTIVE_STATUS)));
|
||||
return $this->attributes['active']
|
||||
|| ($this->order_status && (! in_array($this->order_status,self::INACTIVE_STATUS)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1180,17 +1022,6 @@ class Service extends Model implements IDs
|
||||
return ! is_null($this->price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this service be invoiced soon
|
||||
*
|
||||
* @param int $days
|
||||
* @return bool
|
||||
*/
|
||||
public function isInvoiceDueSoon($days=30): bool
|
||||
{
|
||||
return $this->isBilled() AND $this->getInvoiceNextAttribute()->lessThan(now()->addDays($days));
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify if a service is being ordered, ie: not active yet nor cancelled
|
||||
*
|
||||
@@ -1206,95 +1037,88 @@ class Service extends Model implements IDs
|
||||
/**
|
||||
* Generate a collection of invoice_item objects that will be billed for the next invoice
|
||||
*
|
||||
* @param bool $future Next item to be billed (not in the next x days)
|
||||
* @param Carbon|null $billdate
|
||||
* @return Collection
|
||||
* @throws Exception
|
||||
* @todo This query is expensive.
|
||||
*/
|
||||
public function next_invoice_items(bool $future,Carbon $billdate=NULL): Collection
|
||||
public function next_invoice_items(Carbon $billdate=NULL): Collection
|
||||
{
|
||||
if ($this->wasCancelled() OR (! $this->isBilled()) OR (! $future AND ! $this->active))
|
||||
if ($this->wasCancelled() || (! $this->isBilled()))
|
||||
return collect();
|
||||
|
||||
if (is_null($billdate))
|
||||
$billdate = Carbon::now()->addDays(30);
|
||||
$o = collect();
|
||||
$invoiced_to = $this->getInvoiceNextAttribute();
|
||||
|
||||
// If pending, add any connection charges
|
||||
// Connection charges are only charged once
|
||||
if ((! $this->invoice_items->filter(function($item) { return $item->item_type==4; })->sum('total'))
|
||||
AND ($this->isPending() OR is_null($this->invoice_to))
|
||||
AND $this->product->getSetupChargeAttribute($this->recur_schedule,$this->account->group))
|
||||
// Connection charges are only charged once, so ignore if if we have already billed them
|
||||
if ((! $this->invoiced_items()->where('item_type',InvoiceItem::INVOICEITEM_SETUP)->count())
|
||||
&& (InvoiceItem::distinct('invoice_id')->where('service_id',$this->id)->count() < 2)
|
||||
&& $this->product->getSetupChargeAttribute($this->getBillingIntervalAttribute(),$this->account->group))
|
||||
{
|
||||
$o = new InvoiceItem;
|
||||
$ii = new InvoiceItem;
|
||||
|
||||
$o->active = TRUE;
|
||||
$o->service_id = $this->id;
|
||||
$o->product_id = $this->product_id;
|
||||
$o->item_type = 4; // @todo change to const or something
|
||||
$o->price_base = $this->product->getSetupChargeAttribute($this->recur_schedule,$this->account->group);
|
||||
//$o->recurring_schedule = $this->recur_schedule;
|
||||
$o->start_at = $this->invoice_next;
|
||||
$o->stop_at = $this->invoice_next;
|
||||
$o->quantity = 1;
|
||||
$o->site_id = 1; // @todo
|
||||
$ii->active = TRUE;
|
||||
$ii->service_id = $this->id;
|
||||
$ii->product_id = $this->product_id;
|
||||
$ii->item_type = InvoiceItem::INVOICEITEM_SETUP;
|
||||
$ii->price_base = $this->product->getSetupChargeAttribute($this->getBillingIntervalAttribute(),$this->account->group);
|
||||
$ii->start_at = $this->invoice_next;
|
||||
$ii->stop_at = $this->invoice_next;
|
||||
$ii->quantity = 1;
|
||||
$ii->site_id = 1; // @todo
|
||||
|
||||
$o->addTaxes($this->account->country->taxes);
|
||||
$this->invoice_items->push($o);
|
||||
$ii->addTaxes($this->account->country->taxes);
|
||||
$o->push($ii);
|
||||
}
|
||||
|
||||
// If the service is active, there will be service charges
|
||||
if ((! $this->invoice_items->filter(function($item) { return $item->item_type==0 AND ! $item->exists; })->count())
|
||||
AND ($this->active OR $this->isPending())
|
||||
AND (
|
||||
(($future == TRUE) AND $this->invoice_next < $this->invoice_next_end) OR
|
||||
(($future == FALSE) AND ($this->invoice_to < ($this->stop_at ?: $billdate)))
|
||||
))
|
||||
{
|
||||
do {
|
||||
$o = new InvoiceItem;
|
||||
$o->active = TRUE;
|
||||
$o->service_id = $this->id;
|
||||
$o->product_id = $this->product_id;
|
||||
$o->item_type = 0;
|
||||
$o->price_base = is_null($this->price)
|
||||
? (is_null($this->price) ? $this->product->getBaseChargeAttribute($this->recur_schedule,$this->account->group) : $this->price)
|
||||
: $this->price; // @todo change to a method in this class
|
||||
$o->recur_schedule = $this->recur_schedule;
|
||||
$o->start_at = $this->invoice_next;
|
||||
$o->stop_at = $this->invoice_next_end;
|
||||
$o->quantity = $this->invoice_next_quantity;
|
||||
$o->site_id = 1; // @todo
|
||||
// The service charges
|
||||
if (is_null($billdate))
|
||||
$billdate = $invoiced_to->clone()->addDays(config('osb.invoice_days'));
|
||||
|
||||
$o->addTaxes($this->account->country->taxes);
|
||||
$this->invoice_items->push($o);
|
||||
} while ($future == FALSE AND ($this->invoice_to < ($this->stop_at ?: $billdate)));
|
||||
while ($invoiced_to < ($this->stop_at ?: $billdate)) {
|
||||
$ii = new InvoiceItem;
|
||||
$period = Invoice::invoice_period($invoiced_to,$this->getBillingIntervalAttribute(),$this->product->price_recur_strict);
|
||||
|
||||
$ii->active = TRUE;
|
||||
$ii->service_id = $this->id;
|
||||
$ii->product_id = $this->product_id;
|
||||
$ii->item_type = InvoiceItem::INVOICEITEM_SERVICE;
|
||||
$ii->price_base = $this->billing_charge();
|
||||
$ii->recur_schedule = $this->getBillingIntervalAttribute();
|
||||
$ii->start_at = $invoiced_to;
|
||||
$ii->stop_at = ($this->stop_at && ($this->stop_at < Arr::get($period,'end'))) ? $this->stop_at : Arr::get($period,'end');
|
||||
$ii->quantity = Invoice::invoice_quantity($ii->start_at,$ii->stop_at,$period);
|
||||
$ii->site_id = 1; // @todo
|
||||
|
||||
$ii->addTaxes($this->account->country->taxes);
|
||||
$o->push($ii);
|
||||
|
||||
$invoiced_to = $ii->stop_at
|
||||
->clone()
|
||||
->addDay()
|
||||
->startOfDay();
|
||||
}
|
||||
|
||||
// Add additional charges
|
||||
if ((($future == TRUE) OR (($future == FALSE) AND ($this->invoice_to >= $billdate)))
|
||||
AND ! $this->invoice_items->filter(function($item) { return $item->module_id == 30 AND ! $item->exists; })->count())
|
||||
{
|
||||
foreach ($this->charges->filter(function($item) { return $item->unprocessed; }) as $oo) {
|
||||
$o = new InvoiceItem;
|
||||
$o->active = TRUE;
|
||||
$o->service_id = $oo->service_id;
|
||||
$o->product_id = $this->product_id;
|
||||
$o->quantity = $oo->quantity;
|
||||
$o->item_type = $oo->type;
|
||||
$o->price_base = $oo->amount;
|
||||
$o->start_at = $oo->start_at;
|
||||
$o->stop_at = $oo->stop_at;
|
||||
$o->module_id = 30; // @todo This shouldnt be hard coded
|
||||
$o->module_ref = $oo->id;
|
||||
$o->site_id = 1; // @todo
|
||||
foreach ($this->charges->filter(function($item) { return $item->unprocessed; }) as $oo) {
|
||||
$ii = new InvoiceItem;
|
||||
|
||||
$o->addTaxes($this->account->country->taxes);
|
||||
$this->invoice_items->push($o);
|
||||
}
|
||||
$ii->active = TRUE;
|
||||
$ii->service_id = $oo->service_id;
|
||||
$ii->product_id = $this->product_id;
|
||||
$ii->quantity = $oo->quantity;
|
||||
$ii->item_type = $oo->type;
|
||||
$ii->price_base = $oo->amount;
|
||||
$ii->start_at = $oo->start_at;
|
||||
$ii->stop_at = $oo->stop_at;
|
||||
$ii->module_id = 30; // @todo This shouldnt be hard coded
|
||||
$ii->module_ref = $oo->id;
|
||||
$ii->site_id = 1; // @todo
|
||||
|
||||
$ii->addTaxes($this->account->country->taxes);
|
||||
$o->push($ii);
|
||||
}
|
||||
|
||||
return $this->invoice_items->filter(function($item) { return ! $item->exists; });
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user