mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-23 06:24:03 +00:00
E-Invoice - API, Sales Invoice Report
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
});
|
||||
})
|
||||
->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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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
|
||||
|
||||
$query = $this->listsBookings->execute($this->listsBookings->deserializeFilters($request->input('filters')));
|
||||
|
||||
return $this->collectionResponse(AutocountSalesInvoiceBookingResource::collection($query));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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,35 @@
|
||||
<?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'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?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 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)
|
||||
{
|
||||
$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();
|
||||
|
||||
$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->currency_rate;
|
||||
$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');
|
||||
|
||||
$firstItem = true;
|
||||
$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 ? '<<New>>' : '',
|
||||
'DocDate' => $formattedDocumentDate,
|
||||
'DebtorCode' => $company->debtor,
|
||||
'Ref' => $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') : '',
|
||||
];
|
||||
$details->push($detail);
|
||||
|
||||
if($firstItem) {
|
||||
$firstItem = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Service Charge - Starts
|
||||
$serviceCharge = 0;
|
||||
if (!$totalPayment) {
|
||||
$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->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' => '',
|
||||
];
|
||||
$details->push($detail);
|
||||
// Service Charge - Ends
|
||||
|
||||
// Adjustment - Starts
|
||||
$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' => '',
|
||||
];
|
||||
$details->push($detail);
|
||||
// Adjustment - Ends
|
||||
|
||||
return AutocountSalesInvoiceBookingDetailsResource::collection(
|
||||
collect($details)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Bookings\ListBookingsSalesInvoiceController;
|
||||
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', [ListBookingsSalesInvoiceController::class, 'list'])->name('booking.sales-invoice.list');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user