Files
wticreatorstudio/Modules/StaffPayroll/Entities/Invoice.php
T
Leonard Biano a716188e5b StaffPayroll Module Update
Remove downline bonus on reprocess
2024-06-05 23:18:00 +08:00

286 lines
9.4 KiB
PHP

<?php
namespace Modules\StaffPayroll\Entities;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\JobPortal\Entities\VendorPayout;
use Modules\StaffPayroll\Services\InvoiceService;
use Modules\StudioPlus\Traits\ScopeTrait;
use Modules\StudioPlus\Traits\ThisMonthTrait;
use Modules\StudioPlusWtiiabaddon\Entities\StudioPlusIncentive;
use Modules\StudioPlusWtiiabaddon\Entities\StudioPlusIncentiveCategory;
class Invoice extends Model
{
use HasFactory;
use ScopeTrait;
use ThisMonthTrait;
protected $fillable = [
'invoice_number',
'user_id',
'total_amount',
'issue_date',
'note',
'created_by',
'status',
'due_date',
'discount_type',
'discount',
'terms',
'is_approved'
];
protected $appends = [
'paid',
'stamp',
'month_stamp'
];
public const STATUS_UNPAID = 'UNPAID';
public const STATUS_PAID = 'PAID';
public const STATUS_PARTIALLY_PAID = 'PARTIALLY PAID';
public const STATUS_OVERDUE = 'OVERDUE';
public const DISCOUNT_TYPE_NONE = 'NONE';
public const DISCOUNT_TYPE_FIXED = 'FIXED';
public const DISCOUNT_TYPE_PERCENTAGE = 'PERCENTAGE';
public static function statuses()
{
return [
self::STATUS_UNPAID => self::STATUS_UNPAID,
self::STATUS_PAID => self::STATUS_PAID,
self::STATUS_PARTIALLY_PAID => self::STATUS_PARTIALLY_PAID,
self::STATUS_OVERDUE => self::STATUS_OVERDUE,
];
}
public static function discountTypes()
{
return [
self::DISCOUNT_TYPE_NONE => self::DISCOUNT_TYPE_NONE,
self::DISCOUNT_TYPE_FIXED => self::DISCOUNT_TYPE_FIXED,
self::DISCOUNT_TYPE_PERCENTAGE => self::DISCOUNT_TYPE_PERCENTAGE,
];
}
public function items()
{
return $this->hasMany(InvoiceItem::class)->orderBy('description');
}
public function payout()
{
return $this->hasOne(VendorPayout::class);
}
public function user()
{
return $this->belongsTo(StaffPayrollUser::class);
}
public function getPaidAttribute()
{
if($this->status = self::STATUS_PAID){
return true;
} else {
return false;
}
}
public function getStampAttribute()
{
if ($this->created_at) {
return $this->created_at->format('F j, Y g:i A');
}
return $this->created_at;
}
public function getMonthStampAttribute()
{
/*if ($this->created_at) {
return $this->created_at->format('M Y');
}*/
if ($this->issue_date) {
return Carbon::parse($this->issue_date)->format('M Y');
}
return null;
}
public function reprocessedItems()
{
return $this->hasMany(InvoiceReprocessedItem::class, 'invoice_id', 'id')->orderBy('description');
}
public function addVideoUploadPayout($video, $mode = 'official')
{
if ($mode == 'reprocessed') {
$item_no = $this->reprocessedItems()->count() + 1;
}
else {
$item_no = $this->items()->count() + 1;
}
$video->load('asinData','channel.user');
$applied = false;
$apply_default_incentive = true;
$invoice_service = new InvoiceService();
if($video->videoType->vertical_video){
$incentives = StudioPlusIncentive::whereHas('videoTypes', function ($query) use($video) {
$query->where('studio_plus_video_type_id', $video->studio_plus_video_type_id);
})->doesntHave('asins')->whereHas('roles', function ($query) use($video) {
$query->where('role_id', $video->channel->user->role_id);
})->where('target_rule',1)->get();
} else {
$incentives = StudioPlusIncentive::whereHas('videoTypes', function ($query) use($video) {
$query->where('studio_plus_video_type_id', $video->studio_plus_video_type_id);
})->whereHas('asins', function ($query) use($video) {
$query->where('studio_plus_asin_id', $video->studio_plus_asin_id);
})->whereHas('roles', function ($query) use($video) {
$query->where('role_id', $video->channel->user->role_id);
})->where('target_rule',1)->where('incentive_category_id','!=',5)->get();
}
if (count($incentives) > 0) {
$apply_default_incentive = false;
}
foreach ($incentives as $incentive) {
// if ($invoice_service->isIncentiveApplicable($incentive, $video)) {
$published_track = $video->tracks()->where('name','Published')->first();
$data = [
'studio_plus_video_id' => $video->id,
'item_no' => $item_no,
'name' => 'Video upload payout',
'description' => $video->videoType->need_asin ? "ASIN {$video->asin} ({$incentive->description})" : $incentive->description,
'amount' => $incentive->amount_value_earned,
'quantity' => 1,
'issue_date' => $published_track ? $published_track->created_at->toDateString() : $video->created_at->toDateString(),
'type' => InvoiceItem::TYPE_VIDEO_UPLOAD_PAYOUT,
'range_amount' => $video->asinData != null ? $video->asinData->range_amount : null,
'created_at' => $published_track ? $published_track->created_at : $video->created_at
];
if ($mode == 'reprocessed') {
$this->reprocessedItems()->create($data);
} else {
$this->items()->create($data);
}
$applied = true;
// }
}
if ($apply_default_incentive || !$applied) {
$amount = 0;
if($video->videoType->need_job_request == 1){
//based on a job incentive
$incentive = StudioPlusIncentive::where('incentive_category_id', 15)->where('target_rule',1)->first();
if($incentive){
$amount = $incentive->amount_value_earned;
}
} elseif(!$video->videoType->vertical_video) {
$amount = $video->asinData->payout_amount;
}
$data = [
'studio_plus_video_id' => $video->id,
'item_no' => $item_no,
'name' => 'Video upload payout',
'description' => "ASIN {$video->asin}",
'amount' => $amount,
'quantity' => 1,
'issue_date' => $video->created_at->toDateString(),
'type' => InvoiceItem::TYPE_VIDEO_UPLOAD_PAYOUT,
'range_amount' => $video->asinData->range_amount,
'created_at' => $video->created_at
];
if ($mode == 'reprocessed') {
$this->reprocessedItems()->create($data);
}
else {
$this->items()->create($data);
}
}
// Add incentive for video with over 5k ratings
$rating_bonus = StudioPlusIncentive::where('code', 'asin-ratings')->first();
if ($rating_bonus) {
if ($invoice_service->isIncentiveApplicable($rating_bonus, $video)) {
if ($video->amazon_total_reviews > $rating_bonus->target_rule) {
$data['item_no'] = ++$item_no;
$data['studio_plus_video_id'] = $video->id;
$data['name'] = 'Rating Incentive Bonus';
$data['description'] = $rating_bonus->description;
$data['amount'] = $rating_bonus->amount_value_earned;
$data['type'] = 'INCENTIVE BONUS';
$data['studio_plus_incentive_id'] = $rating_bonus->id;
if ($mode == 'reprocessed') {
$this->reprocessedItems()->create($data);
}
else {
$this->items()->create($data);
}
}
}
}
}
public function addIncentive($incentive, $mode = 'official', $params = null)
{
if ($mode == 'reprocessed') {
$item_no = $this->reprocessedItems()->count() + 1;
}
else {
$item_no = $this->items()->count() + 1;
}
$data = [
'item_no' => $item_no,
'name' => $incentive->title,
'description' => $incentive->description,
'amount' => $incentive->amount_value_earned,
'quantity' => 1,
'issue_date' => $this->created_at->toDateString(),
'type' => 'INCENTIVE BONUS',
'created_at' => $this->created_at,
'studio_plus_incentive_id' => $incentive->id
];
if (is_array($params)) {
$data = array_merge($data, $params);
}
if ($mode == 'reprocessed') {
$this->reprocessedItems()->create($data);
} else {
$this->items()->create($data);
}
}
public function applyReprocessedItems()
{
$reprocessed_items = $this->reprocessedItems;
$this->items()->delete();
foreach ($reprocessed_items as $item) {
$this->items()->create($item->toArray());
}
}
}