mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-19 04:23:55 +00:00
Merge branch 'dillon/90-e-invoice-g-0' into vapor/staging
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class DateRange implements Filter
|
||||
{
|
||||
/**
|
||||
* Apply the filter to the query.
|
||||
*
|
||||
* @param Builder $builder
|
||||
* @param mixed $value
|
||||
* @return Builder
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
$dt1 = $value[0];
|
||||
$dt2 = $value[1];
|
||||
|
||||
$startDate = isset($dt1) && $dt1
|
||||
? Carbon::createFromFormat('Y-m-d', $dt1)->startOfDay()
|
||||
: Carbon::now()->subMonth()->startOfDay();
|
||||
|
||||
$endDate = isset($dt2) && $dt2
|
||||
? Carbon::createFromFormat('Y-m-d', $dt2)->endOfDay()
|
||||
: Carbon::now()->endOfDay();
|
||||
|
||||
$minAllowedDate = Carbon::createFromFormat('Y-m-d', '2025-07-01')->startOfDay();
|
||||
if ($startDate->lt($minAllowedDate) || $endDate->lt($minAllowedDate)) {
|
||||
$startDate = Carbon::createFromFormat('Y-m-d', '1970-01-01')->startOfDay();
|
||||
$endDate = Carbon::createFromFormat('Y-m-d', '1970-01-01')->startOfDay();
|
||||
}
|
||||
|
||||
// return $builder->with([
|
||||
// 'company',
|
||||
// 'transactions.transactionDetails',
|
||||
// 'transactions.voucherRedemption',
|
||||
// ])
|
||||
// ->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
// $query->payments()
|
||||
// ->complete()
|
||||
// ->whereBetween('created_at', [$startDate, $endDate])
|
||||
// ->latest('created_at');
|
||||
// })
|
||||
// ->whereDoesntHave('transactions', function ($query) use ($startDate, $endDate) {
|
||||
// $query->payments()
|
||||
// ->complete()
|
||||
// ->where(function ($q) use ($startDate, $endDate) {
|
||||
// $q->where('created_at', '<', $startDate)
|
||||
// ->orWhere('created_at', '>', $endDate);
|
||||
// });
|
||||
// });
|
||||
|
||||
return $builder->whereIn('status', [
|
||||
ApprovalStatus::APPROVED,
|
||||
ApprovalStatus::COMPLETED,
|
||||
ApprovalStatus::SUSPENDED,
|
||||
])
|
||||
->where(function ($q) use ($startDate, $endDate) {
|
||||
$q->where(function ($q) {
|
||||
$q->whereDoesntHave('company', function ($query) {
|
||||
$query->where('debtor', 'N/A NO NEED TO IMPORT');
|
||||
});
|
||||
})
|
||||
// Bookings without refunds
|
||||
->where(function ($q1) use ($startDate, $endDate) {
|
||||
$q1->where('status', ApprovalStatus::COMPLETED)
|
||||
->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
$query->payments()
|
||||
->complete()
|
||||
->whereBetween('created_at', [$startDate, $endDate]);
|
||||
})
|
||||
->whereDoesntHave('transactions', function ($query) {
|
||||
$query->payments()
|
||||
->complete()
|
||||
->where(function ($q) {
|
||||
$q->where('created_at', '<', '2025-07-01 00:00:00');
|
||||
});
|
||||
});
|
||||
})
|
||||
// OR bookings with refunds
|
||||
->orWhere(function ($q2) use ($startDate, $endDate) {
|
||||
$q2->whereHas('transactions', function ($query) use ($startDate, $endDate) {
|
||||
$query->payments()
|
||||
->whereBetween('created_at', [$startDate, $endDate])
|
||||
->whereHas('transactions', function ($refundQuery) {
|
||||
$refundQuery->refunds()
|
||||
->whereIn('status', [ApprovalStatus::APPROVED]);
|
||||
});
|
||||
})
|
||||
->whereDoesntHave('transactions', function ($query) {
|
||||
$query->payments()
|
||||
->complete()
|
||||
->where(function ($q) {
|
||||
$q->where('created_at', '<', '2025-07-01 00:00:00');
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
->with([
|
||||
'company',
|
||||
'transactions.transactionDetails',
|
||||
'transactions.voucherRedemption',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\KVPKey;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class DateRangeNoData implements Filter
|
||||
{
|
||||
/**
|
||||
* Apply the filter to the query.
|
||||
*
|
||||
* @param Builder $builder
|
||||
* @param mixed $value
|
||||
* @return Builder
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
$dt1 = $value[0];
|
||||
$dt2 = $value[1];
|
||||
|
||||
$startDate = isset($dt1) && $dt1
|
||||
? Carbon::createFromFormat('Y-m-d', $dt1)->startOfDay()
|
||||
: Carbon::now()->subMonth()->startOfDay();
|
||||
|
||||
$endDate = isset($dt2) && $dt2
|
||||
? Carbon::createFromFormat('Y-m-d', $dt2)->endOfDay()
|
||||
: Carbon::now()->endOfDay();
|
||||
|
||||
$minAllowedDate = Carbon::createFromFormat('Y-m-d', '2025-07-01')->startOfDay();
|
||||
if ($startDate->lt($minAllowedDate) || $endDate->lt($minAllowedDate)) {
|
||||
$startDate = Carbon::createFromFormat('Y-m-d', '1970-01-01')->startOfDay();
|
||||
$endDate = Carbon::createFromFormat('Y-m-d', '1970-01-01')->startOfDay();
|
||||
}
|
||||
|
||||
// return $builder->with([
|
||||
// 'company',
|
||||
// 'transactions.transactionDetails',
|
||||
// 'transactions.voucherRedemption',
|
||||
// ])
|
||||
|
||||
// // ->whereHas('company', function ($query) {
|
||||
// // $query->where('debtor', '!=', 'N/A NO NEED TO IMPORT');
|
||||
// // })
|
||||
// ->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
// $query->payments()
|
||||
// ->complete()
|
||||
// ->whereBetween('created_at', [$startDate, $endDate])
|
||||
// ->latest('created_at');
|
||||
// })
|
||||
// ->whereDoesntHave('transactions', function ($query) use ($startDate, $endDate) {
|
||||
// $query->payments()
|
||||
// ->complete()
|
||||
// ->where(function ($q) use ($startDate, $endDate) {
|
||||
// $q->where('created_at', '<', $startDate)
|
||||
// ->orWhere('created_at', '>', $endDate);
|
||||
// });
|
||||
// })
|
||||
// ->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
// $query->where('type', TransactionType::INVOICE)
|
||||
// ->latest('created_at')
|
||||
// ->whereDoesntHave('attributesKVP', function ($invoiceQuery) {
|
||||
// $invoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
// });
|
||||
// })
|
||||
// ->whereDoesntHave('attributesKVP', function ($invoiceQuery) {
|
||||
// $invoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
// });
|
||||
|
||||
return $builder->whereIn('status', [
|
||||
ApprovalStatus::APPROVED,
|
||||
ApprovalStatus::COMPLETED,
|
||||
ApprovalStatus::SUSPENDED,
|
||||
])
|
||||
->where(function ($q) use ($startDate, $endDate) {
|
||||
$q->where(function ($q) {
|
||||
$q->whereDoesntHave('company', function ($query) {
|
||||
$query->where('debtor', 'N/A NO NEED TO IMPORT');
|
||||
});
|
||||
})
|
||||
// Bookings without refunds
|
||||
->where(function ($q1) use ($startDate, $endDate) {
|
||||
$q1->where('status', ApprovalStatus::COMPLETED)
|
||||
->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
$query->payments()
|
||||
->complete()
|
||||
->whereBetween('created_at', [$startDate, $endDate]);
|
||||
})
|
||||
->whereDoesntHave('transactions', function ($query) {
|
||||
$query->payments()
|
||||
->complete()
|
||||
->where(function ($q) {
|
||||
$q->where('created_at', '<', '2025-07-01 00:00:00');
|
||||
});
|
||||
})
|
||||
->where(function ($query){
|
||||
$query
|
||||
->whereDoesntHave('transactions.attributesKVP', function ($subQuery) {
|
||||
$subQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
})
|
||||
->whereDoesntHave('attributesKVP', function ($subQuery) {
|
||||
$subQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
});
|
||||
});
|
||||
})
|
||||
// OR bookings with refunds
|
||||
->orWhere(function ($q2) use ($startDate, $endDate) {
|
||||
$q2->whereHas('transactions', function ($query) use ($startDate, $endDate) {
|
||||
$query->payments()
|
||||
->whereBetween('created_at', [$startDate, $endDate])
|
||||
->whereHas('transactions', function ($refundQuery) {
|
||||
$refundQuery->refunds()
|
||||
->whereIn('status', [ApprovalStatus::APPROVED]);
|
||||
});
|
||||
})
|
||||
->whereDoesntHave('transactions', function ($query) {
|
||||
$query->payments()
|
||||
->complete()
|
||||
->where(function ($q) {
|
||||
$q->where('created_at', '<', '2025-07-01 00:00:00');
|
||||
});
|
||||
})
|
||||
->where(function ($query){
|
||||
$query
|
||||
->whereDoesntHave('transactions.attributesKVP', function ($subQuery) {
|
||||
$subQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
})
|
||||
|
||||
->whereDoesntHave('attributesKVP', function ($subQuery) {
|
||||
$subQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
->with([
|
||||
'company',
|
||||
'transactions.transactionDetails',
|
||||
'transactions.voucherRedemption',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\KVPKey;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class DateRangeWithData implements Filter
|
||||
{
|
||||
/**
|
||||
* Apply the filter to the query.
|
||||
*
|
||||
* @param Builder $builder
|
||||
* @param mixed $value
|
||||
* @return Builder
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
$dt1 = $value[0];
|
||||
$dt2 = $value[1];
|
||||
|
||||
$startDate = isset($dt1) && $dt1
|
||||
? Carbon::createFromFormat('Y-m-d', $dt1)->startOfDay()
|
||||
: Carbon::now()->subMonth()->startOfDay();
|
||||
|
||||
$endDate = isset($dt2) && $dt2
|
||||
? Carbon::createFromFormat('Y-m-d', $dt2)->endOfDay()
|
||||
: Carbon::now()->endOfDay();
|
||||
|
||||
$minAllowedDate = Carbon::createFromFormat('Y-m-d', '2025-07-01')->startOfDay();
|
||||
if ($startDate->lt($minAllowedDate) || $endDate->lt($minAllowedDate)) {
|
||||
$startDate = Carbon::createFromFormat('Y-m-d', '1970-01-01')->startOfDay();
|
||||
$endDate = Carbon::createFromFormat('Y-m-d', '1970-01-01')->startOfDay();
|
||||
}
|
||||
|
||||
// return $builder->with([
|
||||
// 'company',
|
||||
// 'transactions.transactionDetails',
|
||||
// 'transactions.voucherRedemption',
|
||||
// ])
|
||||
|
||||
// // ->whereHas('company', function ($query) {
|
||||
// // $query->where('debtor', '!=', 'N/A NO NEED TO IMPORT');
|
||||
// // })
|
||||
// ->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
// $query->payments()
|
||||
// ->complete()
|
||||
// ->whereBetween('created_at', [$startDate, $endDate])
|
||||
// ->latest('created_at');
|
||||
// })
|
||||
// ->whereDoesntHave('transactions', function ($query) use ($startDate, $endDate) {
|
||||
// $query->payments()
|
||||
// ->complete()
|
||||
// ->where(function ($q) use ($startDate, $endDate) {
|
||||
// $q->where('created_at', '<', $startDate)
|
||||
// ->orWhere('created_at', '>', $endDate);
|
||||
// });
|
||||
// })
|
||||
// ->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
// $query->where('type', TransactionType::INVOICE)
|
||||
// ->latest('created_at')
|
||||
// ->whereHas('attributesKVP', function ($invoiceQuery) {
|
||||
// $invoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
// });
|
||||
// });
|
||||
// // ->WhereHas('attributesKVP', function ($invoiceQuery) {
|
||||
// // $invoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
// // });
|
||||
|
||||
|
||||
return $builder->whereIn('status', [
|
||||
ApprovalStatus::APPROVED,
|
||||
ApprovalStatus::COMPLETED,
|
||||
ApprovalStatus::SUSPENDED,
|
||||
])
|
||||
->where(function ($q) use ($startDate, $endDate) {
|
||||
$q->where(function ($q) {
|
||||
$q->whereDoesntHave('company', function ($query) {
|
||||
$query->where('debtor', 'N/A NO NEED TO IMPORT');
|
||||
});
|
||||
})
|
||||
// Bookings without refunds
|
||||
->where(function ($q1) use ($startDate, $endDate) {
|
||||
$q1->where('status', ApprovalStatus::COMPLETED)
|
||||
->whereHas('transactions', function ($query) use ($startDate, $endDate){
|
||||
$query->payments()
|
||||
->complete()
|
||||
->whereBetween('created_at', [$startDate, $endDate]);
|
||||
})
|
||||
->whereDoesntHave('transactions', function ($query) {
|
||||
$query->payments()
|
||||
->complete()
|
||||
->where(function ($q) {
|
||||
$q->where('created_at', '<', '2025-07-01 00:00:00');
|
||||
});
|
||||
})
|
||||
->where(function ($subQuery){
|
||||
$subQuery
|
||||
->whereHas('transactions', function ($query) {
|
||||
$query->where('type', TransactionType::INVOICE)
|
||||
->whereHas('attributesKVP', function ($invoiceQuery) {
|
||||
$invoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
});
|
||||
})
|
||||
->orWhereHas('attributesKVP', function ($noInvoiceQuery) {
|
||||
$noInvoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
});
|
||||
});
|
||||
})
|
||||
// OR bookings with refunds
|
||||
->orWhere(function ($q2) use ($startDate, $endDate) {
|
||||
$q2->whereHas('transactions', function ($query) use ($startDate, $endDate) {
|
||||
$query->payments()
|
||||
->whereBetween('created_at', [$startDate, $endDate])
|
||||
->whereHas('transactions', function ($refundQuery) {
|
||||
$refundQuery->refunds()
|
||||
->whereIn('status', [ApprovalStatus::APPROVED]);
|
||||
});
|
||||
})
|
||||
->whereDoesntHave('transactions', function ($query) {
|
||||
$query->payments()
|
||||
->complete()
|
||||
->where(function ($q) {
|
||||
$q->where('created_at', '<', '2025-07-01 00:00:00');
|
||||
});
|
||||
})
|
||||
->where(function ($subQuery){
|
||||
$subQuery
|
||||
->whereHas('transactions', function ($query) {
|
||||
$query->where('type', TransactionType::INVOICE)
|
||||
->whereHas('attributesKVP', function ($invoiceQuery) {
|
||||
$invoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
});
|
||||
})
|
||||
->orWhereHas('attributesKVP', function ($noInvoiceQuery) {
|
||||
$noInvoiceQuery->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
->with([
|
||||
'company',
|
||||
'transactions.transactionDetails',
|
||||
'transactions.voucherRedemption',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Classes\Modules\Bookings\ControllersLogic;
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractControllerLogic;
|
||||
use App\Classes\Modules\Bookings\Services\ListsBookings;
|
||||
use App\Classes\Modules\Bookings\Standards\Rules\CanListBookings;
|
||||
use App\Http\Resources\AutocountSalesInvoiceBookingResource;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ListBookingsSalesInvoiceLogic extends AbstractControllerLogic
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function notification():array {
|
||||
return [
|
||||
'title' => 'Retrieved Bookings with Sales Invoice',
|
||||
'message' => 'You have successfully retrieved a list of Bookings with Sales Invoice'
|
||||
];
|
||||
}
|
||||
|
||||
/** @var CanListBookings */
|
||||
private $canListBookings;
|
||||
|
||||
/** @var ListsBookings */
|
||||
private $listsBookings;
|
||||
|
||||
/**
|
||||
* ListBookingsSalesInvoiceLogic constructor.
|
||||
* @param CanListBookings $canListBookings
|
||||
* @param ListsBookings $listsBookings
|
||||
*/
|
||||
public function __construct(CanListBookings $canListBookings, ListsBookings $listsBookings)
|
||||
{
|
||||
$this->canListBookings = $canListBookings;
|
||||
$this->listsBookings = $listsBookings;
|
||||
}
|
||||
|
||||
public function logic(Request $request) : JsonResponse
|
||||
{
|
||||
// $this->canListBookings->passes(); //cief todo: 90 - apipub
|
||||
|
||||
$filters = $request->input('filters');
|
||||
if (is_string($filters)) {
|
||||
$filters = json_decode($filters, true);
|
||||
}
|
||||
|
||||
if (!is_array($filters)) {
|
||||
return response()->json([
|
||||
'message' => 'Invalid filters format. Expected JSON object.',
|
||||
'payload' => new \stdClass(),
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Only these filters are allowed
|
||||
$allowedKeys = ['per_page', 'status', 'order_by', 'date_range', 'date_range_no_data', 'date_range_with_data'];
|
||||
|
||||
$extra = array_diff(array_keys($filters), $allowedKeys);
|
||||
if (!empty($extra)) {
|
||||
return response()->json([
|
||||
'message' => 'Invalid filter(s) provided: ' . implode(', ', $extra),
|
||||
'payload' => new \stdClass(),
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Required filters that must always exist
|
||||
$alwaysRequired = ['per_page', 'status'];
|
||||
|
||||
$missing = array_diff($alwaysRequired, array_keys($filters));
|
||||
if (!empty($missing)) {
|
||||
return response()->json([
|
||||
'message' => 'Missing required filter(s): ' . implode(', ', $missing),
|
||||
'payload' => new \stdClass(),
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ((int) $filters['status'] !== 3) {
|
||||
return response()->json([
|
||||
'message' => 'Invalid status value.',
|
||||
'payload' => new \stdClass(),
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Required at least one of: date_range or date_range_no_data
|
||||
if (!isset($filters['date_range']) && !isset($filters['date_range_no_data']) && !isset($filters['date_range_with_data'])) {
|
||||
return response()->json([
|
||||
'message' => 'Either "date_range" or "date_range_no_data" or "date_range_with_data" filter is required.',
|
||||
'payload' => new \stdClass(),
|
||||
], 400);
|
||||
}
|
||||
$filters = $request->input('filters');
|
||||
if (is_string($filters)) {
|
||||
$decoded = json_decode($filters, true) ?? [];
|
||||
unset($decoded['status']);
|
||||
$decoded['order_by'] = ['column' => 'id', 'DESC' => false];
|
||||
$request->merge(['filters' => json_encode($decoded)]);
|
||||
}
|
||||
|
||||
$query = $this->listsBookings->execute($this->listsBookings->deserializeFilters($request->input('filters')));
|
||||
|
||||
return $this->collectionResponse(AutocountSalesInvoiceBookingResource::collection($query));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Bookings\ControllersLogic;
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractControllerLogic;
|
||||
use App\Classes\Jobs\Commands\V2\ProcessSalesInvoiceReportV2CommandJob;
|
||||
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingSalesInvoiceDTO;
|
||||
use App\Classes\Modules\Bookings\Standards\Rules\CanUpdateBookingSalesInvoice;
|
||||
use ErrorException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdateBatchBookingSalesInvoiceLogic extends AbstractControllerLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function notification(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'Updated Bookings with Sales Invoices',
|
||||
'message' => 'You have successfully updated multiple bookings with Sales Invoices',
|
||||
];
|
||||
}
|
||||
|
||||
/** @var CanUpdateBookingSalesInvoice */
|
||||
private $canUpdateBookingSalesInvoice;
|
||||
|
||||
/**
|
||||
* UpdateBatchBookingSalesInvoiceLogic constructor.
|
||||
* @param CanUpdateBookingSalesInvoice $canUpdateBookingSalesInvoice
|
||||
*/
|
||||
public function __construct(
|
||||
CanUpdateBookingSalesInvoice $canUpdateBookingSalesInvoice
|
||||
) {
|
||||
$this->canUpdateBookingSalesInvoice = $canUpdateBookingSalesInvoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles batch update for multiple booking sales invoices
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
* @throws ErrorException
|
||||
*/
|
||||
public function logic(Request $request): JsonResponse
|
||||
{
|
||||
$collections = $request->input('collections', []);
|
||||
|
||||
if (!is_array($collections) || empty($collections)) {
|
||||
return response()->json([
|
||||
'error' => 'Invalid or empty collections array provided.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$jobs = [];
|
||||
$processed = [];
|
||||
|
||||
foreach ($collections as $index => $bookingData) {
|
||||
try {
|
||||
$data = [
|
||||
'docno' => $bookingData['docno'] ?? $bookingData['DocNo'] ?? null,
|
||||
'docdate' => $bookingData['docdate'] ?? $bookingData['DocDate'] ?? null,
|
||||
'debtorcode' => $bookingData['debtorcode'] ?? $bookingData['DebtorCode'] ?? null,
|
||||
'ref' => $bookingData['ref'] ?? $bookingData['Ref'] ?? null,
|
||||
'shipinfo' => $bookingData['shipinfo'] ?? $bookingData['ShipInfo'] ?? null,
|
||||
'accno' => $bookingData['accno'] ?? $bookingData['AccNo'] ?? null,
|
||||
'detaildescription' => $bookingData['detaildescription'] ?? $bookingData['DetailDescription'] ?? null,
|
||||
'furtherdescription' => $bookingData['furtherdescription'] ?? $bookingData['FurtherDescription'] ?? null,
|
||||
'classification' => $bookingData['classification'] ?? $bookingData['Classification'] ?? null,
|
||||
'deptno' => $bookingData['deptno'] ?? $bookingData['DeptNo'] ?? null,
|
||||
'qty' => $bookingData['qty'] ?? $bookingData['Qty'] ?? null,
|
||||
'unitprice' => $bookingData['unitprice'] ?? $bookingData['UnitPrice'] ?? null,
|
||||
'submiteinvoice' => $bookingData['submiteinvoice'] ?? $bookingData['SubmitEinvoice'] ?? null,
|
||||
'consolidatedeinvoice' => $bookingData['consolidatedeinvoice'] ?? $bookingData['ConsolidatedEinvoice'] ?? null,
|
||||
'einvoicevalidationlink' => $bookingData['einvoicevalidationlink'] ?? $bookingData['EInvoiceValidationLink'] ?? null,
|
||||
];
|
||||
|
||||
$dto = new UpdateBookingSalesInvoiceDTO($data);
|
||||
$this->canUpdateBookingSalesInvoice->passes($dto);
|
||||
|
||||
ProcessSalesInvoiceReportV2CommandJob::dispatch($dto->toArray());
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
Log::error("Failed to process booking at index {$index}: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->response([]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Bookings\ControllersLogic;
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractControllerLogic;
|
||||
use App\Classes\Jobs\Commands\V2\ProcessSalesInvoiceReportV2CommandJob;
|
||||
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingSalesInvoiceDTO;
|
||||
use App\Classes\Modules\Bookings\Standards\Rules\CanUpdateBookingSalesInvoice;
|
||||
use ErrorException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdateBookingSalesInvoiceLogic extends AbstractControllerLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function notification():array {
|
||||
return [
|
||||
'title' => 'Updated Booking with Sales Invoice',
|
||||
'message' => 'You have successfully updated Booking with Sales Invoice'
|
||||
];
|
||||
}
|
||||
|
||||
/** @var CanUpdateBookingSalesInvoice */
|
||||
private $canUpdateBookingSalesInvoice;
|
||||
|
||||
|
||||
/**
|
||||
* UpdateBookingSalesInvoiceLogic constructor.
|
||||
* @param CanUpdateBookingSalesInvoice $canUpdateBookingSalesInvoice
|
||||
*/
|
||||
public function __construct(
|
||||
CanUpdateBookingSalesInvoice $canUpdateBookingSalesInvoice
|
||||
)
|
||||
{
|
||||
$this->canUpdateBookingSalesInvoice = $canUpdateBookingSalesInvoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
* @throws ErrorException
|
||||
*/
|
||||
public function logic(Request $request) : JsonResponse
|
||||
{
|
||||
$data = [
|
||||
'docno' => $request->input('docno', $request->input('DocNo')),
|
||||
'docdate' => $request->input('docdate', $request->input('DocDate')),
|
||||
'debtorcode' => $request->input('debtorcode', $request->input('DebtorCode')),
|
||||
'ref' => $request->input('ref', $request->input('Ref')),
|
||||
'shipinfo' => $request->input('shipinfo', $request->input('ShipInfo')),
|
||||
'accno' => $request->input('accno', $request->input('AccNo')),
|
||||
'detaildescription' => $request->input('detaildescription', $request->input('DetailDescription')),
|
||||
'furtherdescription' => $request->input('furtherdescription', $request->input('FurtherDescription')),
|
||||
'classification' => $request->input('classification', $request->input('Classification')),
|
||||
'deptno' => $request->input('deptno', $request->input('DeptNo')),
|
||||
'qty' => $request->input('qty', $request->input('Qty')),
|
||||
'unitprice' => $request->input('unitprice', $request->input('UnitPrice')),
|
||||
'submiteinvoice' => $request->input('submiteinvoice', $request->input('SubmitEinvoice')),
|
||||
'consolidatedeinvoice' => $request->input('consolidatedeinvoice', $request->input('ConsolidatedEinvoice')),
|
||||
'einvoicevalidationlink' => $request->input('einvoicevalidationlink', $request->input('EInvoiceValidationLink')),
|
||||
];
|
||||
|
||||
$dto = new UpdateBookingSalesInvoiceDTO($data);
|
||||
$this->canUpdateBookingSalesInvoice->passes($dto);
|
||||
|
||||
ProcessSalesInvoiceReportV2CommandJob::dispatch($dto->toArray());
|
||||
|
||||
return $this->response([]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Bookings\DataTransferObjects;
|
||||
|
||||
use App\Classes\General\Interfaces\DataTransferObject;
|
||||
|
||||
class UpdateBookingSalesInvoiceDTO implements DataTransferObject
|
||||
{
|
||||
private ?string $docNo;
|
||||
private ?string $docDate;
|
||||
private ?string $debtorCode;
|
||||
private ?string $ref;
|
||||
private ?string $shipInfo;
|
||||
private ?string $accNo;
|
||||
private ?string $detailDescription;
|
||||
private ?string $furtherDescription;
|
||||
private ?string $classification;
|
||||
private ?string $deptNo;
|
||||
private float $qty;
|
||||
private float $unitPrice;
|
||||
private bool $submitEinvoice;
|
||||
private bool $consolidatedEinvoice;
|
||||
private ?string $einvoiceValidationLink;
|
||||
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->docNo = $data['docno'];
|
||||
$this->docDate = $data['docdate'];
|
||||
$this->debtorCode = $data['debtorcode'];
|
||||
$this->ref = $data['ref'] ?? null;
|
||||
$this->shipInfo = $data['shipinfo'] ?? null;
|
||||
$this->accNo = $data['accno'] ?? null;
|
||||
$this->detailDescription = $data['detaildescription'] ?? null;
|
||||
$this->furtherDescription = $data['furtherdescription'] ?? null;
|
||||
$this->classification = $data['classification'] ?? null;
|
||||
$this->deptNo = $data['deptno'] ?? null;
|
||||
$this->qty = (float) ($data['qty'] ?? 0);
|
||||
$this->unitPrice = (float) ($data['unitprice'] ?? 0);
|
||||
$this->submitEinvoice = filter_var($data['submiteinvoice'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
$this->consolidatedEinvoice = filter_var($data['consolidatedeinvoice'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
$this->einvoiceValidationLink = $data['einvoicevalidationlink'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDocNo(): ?string
|
||||
{
|
||||
return $this->docNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDocDate(): ?string
|
||||
{
|
||||
return $this->docDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDebtorCode(): ?string
|
||||
{
|
||||
return $this->debtorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRef(): ?string
|
||||
{
|
||||
return $this->ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getShipInfo(): ?string
|
||||
{
|
||||
return $this->shipInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAccNo(): ?string
|
||||
{
|
||||
return $this->accNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDetailDescription(): ?string
|
||||
{
|
||||
return $this->detailDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFurtherDescription(): ?string
|
||||
{
|
||||
return $this->furtherDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getClassification(): ?string
|
||||
{
|
||||
return $this->classification;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDeptNo(): ?string
|
||||
{
|
||||
return $this->deptNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getQty(): float
|
||||
{
|
||||
return $this->qty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getUnitPrice(): float
|
||||
{
|
||||
return $this->unitPrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getSubmitEinvoice(): bool
|
||||
{
|
||||
return $this->submitEinvoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getConsolidatedEinvoice(): bool
|
||||
{
|
||||
return $this->consolidatedEinvoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getEinvoiceValidationLink(): ?string
|
||||
{
|
||||
return $this->einvoiceValidationLink;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'docno' => $this->docNo,
|
||||
'docdate' => $this->docDate,
|
||||
'debtorcode' => $this->debtorCode,
|
||||
'ref' => $this->ref,
|
||||
'shipinfo' => $this->shipInfo,
|
||||
'accno' => $this->accNo,
|
||||
'detaildescription' => $this->detailDescription,
|
||||
'furtherdescription' => $this->furtherDescription,
|
||||
'classification' => $this->classification,
|
||||
'deptno' => $this->deptNo,
|
||||
'qty' => $this->qty,
|
||||
'unitprice' => $this->unitPrice,
|
||||
'submiteinvoice' => $this->submitEinvoice,
|
||||
'consolidatedeinvoice' => $this->consolidatedEinvoice,
|
||||
'einvoicevalidationlink' => $this->einvoiceValidationLink,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Classes\Modules\Bookings\Standards\Rules;
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractRule;
|
||||
use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject;
|
||||
|
||||
|
||||
class CanListBookingsSalesInvoice extends AbstractRule
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function authorized($object): bool
|
||||
{
|
||||
// TODO Set Authorization rules
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BookingObject $object
|
||||
* @return bool
|
||||
*/
|
||||
protected function validators($object): bool
|
||||
{
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BookingObject $object
|
||||
* @return bool
|
||||
*/
|
||||
protected function criteria($object): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Bookings\Standards\Rules;
|
||||
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractRule;
|
||||
use App\Classes\Modules\Bookings\Standards\Validators\BookingSalesInvoiceValidation;
|
||||
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingSalesInvoiceDTO;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CanUpdateBookingSalesInvoice extends AbstractRule
|
||||
{
|
||||
|
||||
/** @var BookingSalesInvoiceValidation */
|
||||
private $bookingSalesInvoiceValidation;
|
||||
|
||||
|
||||
/**
|
||||
* CanUpdateBookingSalesInvoice constructor.
|
||||
* @param UpdateBookingSalesInvoiceDTO $bookingSalesInvoiceValidation
|
||||
*/
|
||||
public function __construct(BookingSalesInvoiceValidation $bookingSalesInvoiceValidation)
|
||||
{
|
||||
$this->bookingSalesInvoiceValidation = $bookingSalesInvoiceValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function authorized($object): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UpdateBookingSalesInvoiceDTO $object
|
||||
* @return bool
|
||||
* @throws \App\Classes\Exceptions\RequestValidationException
|
||||
*/
|
||||
protected function validators($object): bool
|
||||
{
|
||||
return $this->bookingSalesInvoiceValidation->validate($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UpdateBookingSalesInvoiceDTO $object
|
||||
* @return bool
|
||||
*/
|
||||
protected function criteria($object): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Bookings\Standards\Validators;
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractValidation;
|
||||
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingSalesInvoiceDTO;
|
||||
|
||||
class BookingSalesInvoiceValidation extends AbstractValidation
|
||||
{
|
||||
/**
|
||||
* @param UpdateBookingSalesInvoiceDTO $object
|
||||
* @return array
|
||||
*/
|
||||
protected function data($object): array
|
||||
{
|
||||
return [
|
||||
'docno' => $object->getDocNo(),
|
||||
'docdate' => $object->getDocDate(),
|
||||
'debtorcode' => $object->getDebtorCode(),
|
||||
'ref' => $object->getRef(),
|
||||
'shipinfo' => $object->getShipInfo(),
|
||||
'accno' => $object->getAccNo(),
|
||||
'detaildescription' => $object->getDetailDescription(),
|
||||
'furtherdescription' => $object->getFurtherDescription(),
|
||||
'classification' => $object->getClassification(),
|
||||
'deptno' => $object->getDeptNo(),
|
||||
'qty' => $object->getQty(),
|
||||
'unitprice' => $object->getUnitPrice(),
|
||||
'submiteinvoice' => $object->getSubmitEinvoice(),
|
||||
'consolidatedeinvoice' => $object->getConsolidatedEinvoice(),
|
||||
'einvoicevalidationlink' => $object->getEinvoiceValidationLink(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function rules(): array
|
||||
{
|
||||
return [
|
||||
'docno' => 'required|string',
|
||||
'docdate' => 'required|date',
|
||||
'debtorcode' => 'required|string',
|
||||
'ref' => 'required|string',
|
||||
'shipinfo' => 'required|string',
|
||||
'einvoicevalidationlink' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function messages(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,11 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
|
||||
});
|
||||
}
|
||||
|
||||
public function getRecordCount(): int
|
||||
{
|
||||
return $this->query()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Booking $booking
|
||||
* @return array
|
||||
|
||||
@@ -84,6 +84,11 @@ class ExportsSalesInvoiceWithRefundReport implements FromQuery, WithHeadings, Wi
|
||||
});
|
||||
}
|
||||
|
||||
public function getRecordCount(): int
|
||||
{
|
||||
return $this->query()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Booking $booking
|
||||
* @return array
|
||||
|
||||
+14
-5
@@ -111,10 +111,6 @@ class CreateInvoiceTransactionV2Processor
|
||||
// Log::info('CreateInvoiceTransactionV2Processor generateEInvoiceRefund: ' . json_encode($generateEInvoiceRefund));
|
||||
// Log::info('CreateInvoiceTransactionV2Processor bookingOriginalStatus: ' . json_encode($bookingOriginalStatus));
|
||||
|
||||
if($generateEInvoiceRefund){
|
||||
$generateEInvoice = true; //With or without refund, these 2 flags are meant to Generate E-Invoice, so cannot have opposite indicator
|
||||
}
|
||||
|
||||
if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoiceRefund) {
|
||||
Log::info('CreateInvoiceTransactionV2Processor Check 1 Bypass New Business Logic Update for booking ' . $booking->id);
|
||||
// return;
|
||||
@@ -124,7 +120,7 @@ class CreateInvoiceTransactionV2Processor
|
||||
$refund_amount = $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id);
|
||||
$booking_amount = $booking->fix_amount;
|
||||
|
||||
if ((float) $booking_amount === (float) $refund_amount && !$generateEInvoice) {
|
||||
if ((float) $booking_amount === (float) $refund_amount && !$generateEInvoiceRefund) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,6 +253,19 @@ class CreateInvoiceTransactionV2Processor
|
||||
|
||||
$voucherRedemption = $transaction->voucherRedemption;
|
||||
|
||||
if($generateEInvoiceRefund){
|
||||
$metadata = $booking->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
|
||||
if($metadata){
|
||||
$generateEInvoice = true;
|
||||
}
|
||||
else{
|
||||
$metadata = $transaction->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
|
||||
if($metadata){
|
||||
$generateEInvoice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($purchaseOrder){
|
||||
// purchase order
|
||||
if(!$generateEInvoiceRefund){
|
||||
|
||||
+16
-1
@@ -46,6 +46,9 @@ class UpdateRefundTransactionStatusProcessor
|
||||
/** @var CanUpdateRefundTransactionStatus */
|
||||
private $canUpdateRefundTransactionStatus;
|
||||
|
||||
/** @var CreateInvoiceTransactionV2Processor */
|
||||
private $createInvoiceTransactionV2Processor;
|
||||
|
||||
/**
|
||||
* UpdateRefundTransactionStatusProcessor constructor.
|
||||
* @param FetchesCompany $fetchesCompany
|
||||
@@ -57,8 +60,9 @@ class UpdateRefundTransactionStatusProcessor
|
||||
* @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount
|
||||
* @param UpdateBookingAmountLogic $updateBookingAmountLogic
|
||||
* @param CanUpdateRefundTransactionStatus $canUpdateRefundTransactionStatus
|
||||
* @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionV2Processor
|
||||
*/
|
||||
public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdateBookingAmountLogic $updateBookingAmountLogic, CanUpdateRefundTransactionStatus $canUpdateRefundTransactionStatus)
|
||||
public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdateBookingAmountLogic $updateBookingAmountLogic, CanUpdateRefundTransactionStatus $canUpdateRefundTransactionStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionV2Processor)
|
||||
{
|
||||
$this->fetchesCompany = $fetchesCompany;
|
||||
$this->fetchesTransaction = $fetchesTransaction;
|
||||
@@ -69,6 +73,7 @@ class UpdateRefundTransactionStatusProcessor
|
||||
$this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount;
|
||||
$this->updateBookingAmountLogic = $updateBookingAmountLogic;
|
||||
$this->canUpdateRefundTransactionStatus = $canUpdateRefundTransactionStatus;
|
||||
$this->createInvoiceTransactionV2Processor = $createInvoiceTransactionV2Processor;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,5 +130,15 @@ class UpdateRefundTransactionStatusProcessor
|
||||
if (!$paidAmount > 0) {
|
||||
$this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED);
|
||||
}
|
||||
|
||||
//A full refund will need invoice generated
|
||||
if($refundAmount === $booking->fix_amount){
|
||||
$this->createInvoiceTransactionV2Processor->execute($booking, "", null, [
|
||||
'generateEInvoice' => false,
|
||||
'generateEInvoiceWithNormalInvoiceTemplate' => false,
|
||||
'generateEInvoiceRefund' => true,
|
||||
'bookingOriginalStatus' => $booking->status
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Controllers\Bookings;
|
||||
|
||||
use App\Classes\Modules\Bookings\ControllersLogic\ListBookingsSalesInvoiceLogic;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
class ListBookingsSalesInvoiceController
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function list(Request $request, ListBookingsSalesInvoiceLogic $logic) : JsonResponse {
|
||||
return $logic->execute($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Controllers\Bookings;
|
||||
|
||||
use App\Classes\Modules\Bookings\ControllersLogic\UpdateBookingSalesInvoiceLogic;
|
||||
use App\Classes\Modules\Bookings\ControllersLogic\UpdateBatchBookingSalesInvoiceLogic;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
class UpdateBookingSalesInvoiceController
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(Request $request, UpdateBookingSalesInvoiceLogic $logic) : JsonResponse {
|
||||
return $logic->execute($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function updateBatch(Request $request, UpdateBatchBookingSalesInvoiceLogic $logic) : JsonResponse {
|
||||
return $logic->execute($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class AutocountSalesInvoiceBookingDetailsResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'DocNo' => $this['DocNo'],
|
||||
'DocDate' => $this['DocDate'],
|
||||
'DebtorCode' => $this['DebtorCode'],
|
||||
'Ref' => $this['Ref'],
|
||||
'ShipInfo' => $this['ShipInfo'],
|
||||
'AccNo' => $this['AccNo'],
|
||||
'DetailDescription' => $this['DetailDescription'],
|
||||
'FurtherDescription' => $this['FurtherDescription'],
|
||||
'Classification' => $this['Classification'],
|
||||
'DeptNo' => $this['DeptNo'],
|
||||
'Qty' => $this['Qty'],
|
||||
'UnitPrice' => $this['UnitPrice'],
|
||||
'SubmitEinvoice' => $this['SubmitEinvoice'],
|
||||
'ConsolidatedEinvoice' => $this['ConsolidatedEinvoice'],
|
||||
'InvoiceStatus' => $this['InvoiceStatus'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Models\Booking;
|
||||
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
|
||||
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundServiceCharge;
|
||||
use App\Classes\ValueObjects\Constants\KVPKey;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AutocountSalesInvoiceBookingResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$booking = $this;
|
||||
$details = collect();
|
||||
$purchaseOrder = $this->transactions->where('type', TransactionType::PURCHASE_ORDER)->first();
|
||||
$company = $this->company;
|
||||
|
||||
$lastPaymentTransaction = $this->transactions
|
||||
->where('type', TransactionType::PAYMENT)
|
||||
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
|
||||
->sortByDesc('created_at')
|
||||
->first();
|
||||
|
||||
if(!$lastPaymentTransaction){
|
||||
$lastPaymentTransaction = $this->transactions()->payments()->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED])->latest()->first();
|
||||
}
|
||||
$documentDate = Carbon::parse($lastPaymentTransaction->created_at);
|
||||
|
||||
// if ($documentDate < $this->startDate || $documentDate > $this->endDate) {
|
||||
// return [];
|
||||
// }
|
||||
|
||||
if($company->e_invoice === 1){
|
||||
$documentDate = $documentDate->copy()->endOfMonth();
|
||||
}
|
||||
|
||||
$invoiceTransaction = $this->transactions->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first();
|
||||
|
||||
$currencyId = $this->fix_currency_id;
|
||||
|
||||
$subtotal = 0;
|
||||
$displayedSubtotal = 0;
|
||||
$totalPayment = 0;
|
||||
$averageCurrencyRate = $invoiceTransaction ? $invoiceTransaction->currency_rate : 0;
|
||||
$paymentSum = $this->transactions
|
||||
->where('type', TransactionType::PAYMENT)
|
||||
->where('status', ApprovalStatus::COMPLETED)
|
||||
->sum(function ($transaction) {
|
||||
return round($transaction->amount, 2);
|
||||
});
|
||||
if ($paymentSum){
|
||||
$averageCurrencyRate = $this->transactions
|
||||
->where('type', TransactionType::PAYMENT)
|
||||
->where('status', ApprovalStatus::COMPLETED)
|
||||
->sum(function ($transaction) {
|
||||
return $transaction->currency_rate;
|
||||
}) / $this->transactions
|
||||
->where('type', TransactionType::PAYMENT)
|
||||
->where('status', ApprovalStatus::COMPLETED)
|
||||
->count();
|
||||
|
||||
$booking = Booking::where('id', $this->id)->first();
|
||||
$refundedAmount = (App()->make(CalculatesBookingRefundAmount::class))->execute($booking, 1);
|
||||
$refundedServiceCharge = (App()->make(CalculatesBookingRefundServiceCharge::class))->execute($booking, 1);
|
||||
|
||||
$totalPayment = $paymentSum - $refundedAmount - $refundedServiceCharge;
|
||||
}
|
||||
|
||||
$formattedDocumentDate = Carbon::parse($documentDate)->format('m/d/Y');
|
||||
|
||||
$docNo = '<<New>>';
|
||||
$firstItem = true;
|
||||
if($invoiceTransaction){
|
||||
$invoiceTransactionKVP = $invoiceTransaction->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
|
||||
if($invoiceTransactionKVP){
|
||||
$docNo = $invoiceTransactionKVP->value;
|
||||
}
|
||||
else {
|
||||
$bookingKVP = $booking->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
|
||||
$docNo = $bookingKVP ? $bookingKVP->value :'<<New>>';
|
||||
}
|
||||
}
|
||||
|
||||
$transactionDetails = $purchaseOrder->transactionDetails;
|
||||
foreach ($transactionDetails as $detail) {
|
||||
$displayUnitPrice = 0;
|
||||
if($averageCurrencyRate && $currencyId){
|
||||
$exactUnitPrice = ($currencyId) === 1 ? $detail->price : bcdiv($detail->price, $averageCurrencyRate, 7);
|
||||
$displayUnitPrice = round($exactUnitPrice, 2);
|
||||
$itemTotal = bcmul($exactUnitPrice, $detail->quantity, 5);
|
||||
$displayedItemTotal = round(bcmul($displayUnitPrice, $detail->quantity, 7), 2);
|
||||
$displayedSubtotal = bcadd($displayedSubtotal, $displayedItemTotal, 2);
|
||||
$subtotal = bcadd($subtotal, $itemTotal, 5);
|
||||
}
|
||||
|
||||
$detail = [
|
||||
'DocNo' => $firstItem ? $docNo : '',
|
||||
'DocDate' => $formattedDocumentDate,
|
||||
'DebtorCode' => $company->debtor,
|
||||
'Ref' => $invoiceTransaction ? $invoiceTransaction->bill_no : '',
|
||||
'ShipInfo' => $this->marking,
|
||||
'AccNo' => '500-0000',
|
||||
'DetailDescription' => 'PRODUCT NAME :',
|
||||
'FurtherDescription' => $detail->product_name,
|
||||
'Classification' => '022',
|
||||
'DeptNo' => 'C',
|
||||
'Qty' => number_format($detail->quantity, 0),
|
||||
'UnitPrice' => $displayUnitPrice ? number_format($displayUnitPrice, 2) : '0',
|
||||
'SubmitEinvoice' => $firstItem ? 'T' : '',
|
||||
'ConsolidatedEinvoice' => $firstItem ? ($company->e_invoice ? 'F' : 'T') : '',
|
||||
'InvoiceStatus' => (string) $this->invoice_status,
|
||||
];
|
||||
$details->push($detail);
|
||||
|
||||
if($firstItem) {
|
||||
$firstItem = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Voucherify - Starts
|
||||
$voucherRedemption = $lastPaymentTransaction->voucherRedemption;
|
||||
if($voucherRedemption){
|
||||
$voucherDiscount = $voucherRedemption ? bcmul((string)$voucherRedemption->value, "-1", 2) : "0";
|
||||
$voucher = $voucherRedemption->voucher;
|
||||
$category = $voucher->campaign ? $voucher->campaign->category : null;
|
||||
$detail = [
|
||||
'DocNo' => '',
|
||||
'DocDate' => $formattedDocumentDate,
|
||||
'DebtorCode' => $company->debtor,
|
||||
'Ref' => $invoiceTransaction ? $invoiceTransaction->bill_no : '',
|
||||
'ShipInfo' => $this->marking,
|
||||
'AccNo' => $category === 'Compensation Voucher' ? '1000-000' : '949-2000',
|
||||
'DetailDescription' => 'PRODUCT NAME :',
|
||||
'FurtherDescription' => $voucher->code,
|
||||
'Classification' => '022',
|
||||
'DeptNo' => 'C',
|
||||
'Qty' => '1',
|
||||
'UnitPrice' => $voucherDiscount ? number_format($voucherDiscount, 2): '0',
|
||||
'SubmitEinvoice' => '',
|
||||
'ConsolidatedEinvoice' => '',
|
||||
'InvoiceStatus' => (string) $this->invoice_status,
|
||||
];
|
||||
$details->push($detail);
|
||||
}
|
||||
// Voucherify - Ends
|
||||
|
||||
// Service Charge - Starts
|
||||
$serviceCharge = 0;
|
||||
if (!$totalPayment && $invoiceTransaction) {
|
||||
$serviceCharge = $invoiceTransaction->service_charge;
|
||||
}
|
||||
else {
|
||||
$serviceCharge = $this->transactions
|
||||
->where('type', TransactionType::PAYMENT)
|
||||
->where('status', ApprovalStatus::COMPLETED)
|
||||
->sum(function ($transaction) {
|
||||
return $transaction->service_charge;
|
||||
});
|
||||
}
|
||||
|
||||
$detail = [
|
||||
'DocNo' => '',
|
||||
'DocDate' => $formattedDocumentDate,
|
||||
'DebtorCode' => $company->debtor,
|
||||
'Ref' => $invoiceTransaction ? $invoiceTransaction->bill_no : '',
|
||||
'ShipInfo' => $this->marking,
|
||||
'AccNo' => '500-0000',
|
||||
'DetailDescription' => 'PRODUCT NAME :',
|
||||
'FurtherDescription' => 'Service Charge',
|
||||
'Classification' => '022',
|
||||
'DeptNo' => 'C',
|
||||
'Qty' => '1',
|
||||
'UnitPrice' => $serviceCharge ? number_format($serviceCharge, 2) : '0',
|
||||
'SubmitEinvoice' => '',
|
||||
'ConsolidatedEinvoice' => '',
|
||||
'InvoiceStatus' => (string) $this->invoice_status,
|
||||
];
|
||||
$details->push($detail);
|
||||
// Service Charge - Ends
|
||||
|
||||
// Adjustment - Starts
|
||||
if($invoiceTransaction){
|
||||
$adjustment = 0;
|
||||
$voucherRedemption = $invoiceTransaction->voucherRedemption;
|
||||
$voucherDiscount = $voucherRedemption ? bcmul((string)$voucherRedemption->value, "-1", 2) : "0";
|
||||
|
||||
$displayedSubtotal = is_numeric($displayedSubtotal) ? sprintf('%F', $displayedSubtotal) : '0';
|
||||
$serviceCharge = is_numeric($serviceCharge) ? sprintf('%F', $serviceCharge) : '0';
|
||||
$tax = is_numeric($invoiceTransaction->tax) ? sprintf('%F', $invoiceTransaction->tax) : '0';
|
||||
$voucherDiscount = is_numeric($voucherDiscount) ? sprintf('%F', $voucherDiscount) : '0';
|
||||
|
||||
$displayedTotal = bcadd(
|
||||
bcadd(
|
||||
bcadd($displayedSubtotal, $serviceCharge, 5),
|
||||
$tax,
|
||||
5
|
||||
),
|
||||
$voucherDiscount,
|
||||
5
|
||||
);
|
||||
|
||||
$expectedTotal = bcadd(bcadd(bcadd($subtotal, $serviceCharge, 5), $invoiceTransaction->tax, 5), $voucherDiscount, 5);
|
||||
$adjustment = bcsub($expectedTotal, $displayedTotal, 5);
|
||||
|
||||
if ($totalPayment) {
|
||||
$expectedTotal = $totalPayment;
|
||||
$adjustment = bcsub($expectedTotal, $displayedTotal, 5);
|
||||
}
|
||||
|
||||
$detail = [
|
||||
'DocNo' => '',
|
||||
'DocDate' => $formattedDocumentDate,
|
||||
'DebtorCode' => $company->debtor,
|
||||
'Ref' => $invoiceTransaction->bill_no,
|
||||
'ShipInfo' => $this->marking,
|
||||
'AccNo' => '500-0000',
|
||||
'DetailDescription' => 'PRODUCT NAME :',
|
||||
'FurtherDescription' => 'Adjustment',
|
||||
'Classification' => '022',
|
||||
'DeptNo' => 'C',
|
||||
'Qty' => '1',
|
||||
'UnitPrice' => $adjustment ? number_format($adjustment, 2) : '0',
|
||||
'SubmitEinvoice' => '',
|
||||
'ConsolidatedEinvoice' => '',
|
||||
'InvoiceStatus' => (string) $this->invoice_status,
|
||||
];
|
||||
$details->push($detail);
|
||||
}
|
||||
// Adjustment - Ends
|
||||
|
||||
return AutocountSalesInvoiceBookingDetailsResource::collection(
|
||||
collect($details)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
<!-- Approve and Edit Purchase Order -->
|
||||
<div class="row" v-if="submitted">
|
||||
<div class="col-12 col-md-5 pr-md-0" v-if="submitted && data.status !== 3">
|
||||
<div class="col-12 col-md-5 pr-md-0" v-if="submitted">
|
||||
<div class="row m-b-15" v-if="($store.getters.isAdmin && data.purchase_order.status === 1) || ($store.getters.isCustomer && data.purchase_order.status === 1 && $store.getters.getCompanyId === 199)" >
|
||||
<div class="col">
|
||||
<button class="btn btn-sm btn-block btn-success b-rad-none" :disabled="poProcessing" @click="handleRepprove()">Approve Purchase Order</button>
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col" v-else>
|
||||
<div class="col" v-else> <!-- Show only single E-Invoice button-->
|
||||
<div class="row m-b-50">
|
||||
<div class="col no-padding">
|
||||
<div class="row m-t-20">
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Bookings\ListBookingsSalesInvoiceController;
|
||||
use App\Http\Controllers\Bookings\UpdateBookingSalesInvoiceController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group(['middleware' => 'apipub', 'prefix' => 'v1', 'as' => 'apipub.'], function () {
|
||||
Route::group(['middleware' => 'token.check'], function () {
|
||||
Route::get('transactions/mappable/query', 'Transactions\ListMappableTransactionsController@list')->name('transaction.mappable.list');
|
||||
|
||||
Route::group(['prefix' => 'booking', 'as' => 'booking.'], function () {
|
||||
Route::get('/sales-invoice/list', [ListBookingsSalesInvoiceController::class, 'list'])->name('booking.sales-invoice.list');
|
||||
Route::post('/sales-invoice', [UpdateBookingSalesInvoiceController::class, 'update'])->name('booking.sales-invoice.update');
|
||||
Route::post('/sales-invoice/batch', [UpdateBookingSalesInvoiceController::class, 'updateBatch'])->name('booking.sales-invoice.batch.update');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user