Files
wticreatorstudio/Modules/StaffPayroll/Services/InvoiceService.php
T
2024-06-04 23:51:40 +08:00

215 lines
7.6 KiB
PHP

<?php
namespace Modules\StaffPayroll\Services;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Modules\StaffPayroll\Entities\Invoice;
use Modules\StaffPayroll\Entities\InvoiceSetting;
use Modules\StaffPayroll\Transformers\InvoiceResource;
use Modules\StudioPlus\Entities\StudioPlusVideo;
use Modules\StudioPlusWtiiabaddon\Entities\StudioPlusIncentive;
class InvoiceService
{
public function getInvoiceAmount(Invoice $invoice): float
{
$amount = 0;
$items = $invoice->items;
foreach ($items as $item) {
$amount += $item->quantity * $item->amount;
}
return $amount;
}
public function getUserInvoiceOfMonth(User $user): Invoice
{
$latestInvoice = Invoice::query()
->where('user_id', $user->id)
->latest()
->first();
if (!$latestInvoice) {
$invoiceSetting = InvoiceSetting::query()
->where('name', 'start_invoice_number')
->first()
->value ?? 1;
}
$latestInvoiceNumber = $latestInvoice
? $latestInvoice->invoice_number
: $invoiceSetting;
return Invoice::query()
->whereBetween(DB::raw('created_at'), [now()->startOfMonth()->toDateString(), now()->lastOfMonth()->toDateString()])
->firstOrCreate(
[
'user_id' => $user->id,
],
[
'invoice_number' => $latestInvoiceNumber,
'issue_date' => now()->toDateString(),
'created_by' => Auth::check() ? auth()->id() : null,
]
);
}
public function reprocess($invoice, $apply = false)
{
$user = $invoice->user;
$downlines = $user->downlines;
//$start_date = $invoice->created_at->firstOfMonth();
//$end_date = $invoice->created_at->lastOfMonth();
$start_date = Carbon::parse("{$invoice->issue_date}")->firstOfMonth()->startOfDay();
$end_date = Carbon::parse("{$invoice->issue_date}")->lastOfMonth()->endOfDay();
$video_upload_count = 0;
/*$videos = StudioPlusVideo::whereHas('channel.user', function($query) use($user) {
$query->where('id', $user->id);
})
->whereBetween('created_at', [$start_date, $end_date])
->where('status', StudioPlusVideo::STATUS_PUBLISHED_TO_AMAZON)
->get();*/
$videos = $user->getPublishedVideos($start_date, $end_date);
$invoice->reprocessedItems()->delete();
// Add 10/25/50 incentive bonus
$bonus10_incentive = StudioPlusIncentive::where('code', 'bonus-10')->first();
$bonus25_incentive = StudioPlusIncentive::where('code', 'bonus-25')->first();
$bonus50_incentive = StudioPlusIncentive::where('code', 'bonus-50')->first();
$video_upload_count_b10 = 0;
$video_upload_count_b25 = 0;
$video_upload_count_b50 = 0;
foreach ($videos as $video) {
$video_upload_count++;
$invoice->addVideoUploadPayout($video, 'reprocessed');
if ($this->isIncentiveApplicable($bonus10_incentive, $video) && ($video->videoType->vertical_video || $video->asinData->payout_amount > 0)) {
$video_upload_count_b10++;
}
if ($this->isIncentiveApplicable($bonus25_incentive, $video) && ($video->videoType->vertical_video || $video->asinData->payout_amount > 0)) {
$video_upload_count_b25++;
}
if ($this->isIncentiveApplicable($bonus50_incentive, $video) && ($video->videoType->vertical_video || $video->asinData->payout_amount > 0)) {
$video_upload_count_b50++;
}
}
if ($bonus10_incentive) {
if ($video_upload_count_b10 >= $bonus10_incentive->target_rule) {
$invoice->addIncentive($bonus10_incentive, 'reprocessed');
}
}
if ($bonus25_incentive) {
if ($video_upload_count_b25 >= $bonus25_incentive->target_rule) {
$invoice->addIncentive($bonus25_incentive, 'reprocessed');
}
}
if ($bonus50_incentive) {
if ($video_upload_count_b50 >= $bonus50_incentive->target_rule) {
$invoice->addIncentive($bonus50_incentive, 'reprocessed');
}
}
$downline_incentive = StudioPlusIncentive::with('roles')->where('code', 'vcm-downline-bonus')->first();
if ($downline_incentive && in_array($user->role_id, $downline_incentive->roles->pluck('id')->toArray())) {
foreach ($downlines as $downline) {
$videos = $downline->getPublishedVideos($start_date, $end_date);
foreach ($videos as $video) {
if ($this->isIncentiveApplicable($downline_incentive, $video)) {
$invoice->addIncentive($downline_incentive, 'reprocessed', [
'name' => 'Downline Incentives',
'description' => "Downline bonus ({$downline->first_name})",
]);
}
}
}
}
//add incentives manually added
foreach($invoice->items()->whereNull('type')->get() as $incentive){
$invoice->reprocessedItems()->firstOrCreate(
[
'description' => $incentive->description
],
[
'item_no' => $invoice->reprocessedItems()->count() + 1,
'name' => $incentive->name,
'amount' => $incentive->amount,
'quantity' => $incentive->quantity,
'issue_date' => $incentive->created_at->toDateString(),
'created_at' => $incentive->created_at
]
);
}
if ($apply) {
$invoice->applyReprocessedItems();
}
return response()->json([
'invoice' => InvoiceResource::make($invoice->load(['payout', 'user', 'items', 'reprocessedItems']))
]);
}
public function reprocessAllPending()
{
$invoices = Invoice::where('is_approved', false)->get();
foreach ($invoices as $invoice) {
$this->reprocess($invoice, true);
}
}
public function isUserIncentiveQualified($user, $incentive)
{
$role = $incentive->roles()->where('id', $user->role->id)->first();
if ($role) {
return true;
}
return false;
}
public function isIncentiveApplicable($incentive, $video)
{
if ($incentive) {
$video_types = $incentive->videoTypes()->pluck('studio_plus_video_type_id');
if ($video_types->count() > 0) {
return $video_types->contains($video->studio_plus_video_type_id);
}
return true;
}
return false;
}
protected function toVideoVariants($variants)
{
return array_map(function($variant) {
if ($variant == 'based-on-a-job') {
return 'VIDEO BASED ON A JOB';
} else if ($variant == 'reach-out') {
return 'REACH OUT';
} else if ($variant == 'sponsored-product') {
return 'SPONSORED PRODUCT';
}
}, $variants);
}
}