mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-19 04:23:55 +00:00
E-Invoice - Project 27: Import Tax Entity, Customers Data Report
This commit is contained in:
@@ -87,4 +87,71 @@ class Helper
|
||||
return strtoupper('ringgit ' . $ringgitWords . ' and ' . $centsWords . ' cents only');
|
||||
}
|
||||
|
||||
public static function getStateCodeByName($name)
|
||||
{
|
||||
$path = resource_path('data/lhdn/StateCodes.json');
|
||||
|
||||
if (!file_exists($path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$json = file_get_contents($path);
|
||||
$data = json_decode($json, true);
|
||||
|
||||
if (!is_array($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
// Step 1: Try exact match
|
||||
foreach ($data as $item) {
|
||||
if (
|
||||
isset($item['State']) &&
|
||||
strtolower(trim($item['State'])) === $name
|
||||
) {
|
||||
return $item['Code'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Try partial match
|
||||
foreach ($data as $item) {
|
||||
if (
|
||||
isset($item['State']) &&
|
||||
str_contains(strtolower($item['State']), $name)
|
||||
) {
|
||||
return $item['Code'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getMsicDescriptionByCode($code)
|
||||
{
|
||||
$path = resource_path('data/lhdn/MSICSubCategoryCodes.json');
|
||||
|
||||
if (!file_exists($path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$json = file_get_contents($path);
|
||||
$data = json_decode($json, true);
|
||||
|
||||
if (!is_array($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($data as $item) {
|
||||
if (
|
||||
isset($item['Code']) &&
|
||||
$item['Code'] === $code
|
||||
) {
|
||||
return $item['Description'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Exports\Services;
|
||||
|
||||
use App\Classes\General\Helper;
|
||||
use App\Classes\ValueObjects\Constants\DocumentType;
|
||||
use App\Models\Company;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Concerns\Exportable;
|
||||
use Maatwebsite\Excel\Concerns\FromQuery;
|
||||
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
|
||||
class ExportsCompanies implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
|
||||
{
|
||||
use Exportable;
|
||||
|
||||
protected $startDate;
|
||||
protected $endDate;
|
||||
|
||||
public function __construct($startDate = null, $endDate = null) {
|
||||
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1);
|
||||
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'TIN',
|
||||
'IdentityNo',
|
||||
'Name',
|
||||
'IdentityType',
|
||||
'TaxClassification',
|
||||
'MSICCode',
|
||||
'BusinessActivityDesc',
|
||||
'DebtorCode',
|
||||
'TradeName',
|
||||
'Address',
|
||||
'PostCode',
|
||||
'Phone',
|
||||
'EmailAddress',
|
||||
'City',
|
||||
'CountryCode',
|
||||
'StateCode'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Support\Collection|mixed
|
||||
*/
|
||||
public function query()
|
||||
{
|
||||
return Company::whereBetween('created_at', [$this->startDate, $this->endDate]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Company $company
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function map($company): array
|
||||
{
|
||||
$employee = $company->employees()->first();
|
||||
$lastBooking = $company->bookings()->orderByDesc('id')->first();
|
||||
$identityNo = $company->documents->where('document_type', DocumentType::IDENTITY_CARD)->first();
|
||||
$identityType = DocumentType::IDENTITY_CARD;
|
||||
if(!$identityNo){
|
||||
$identityNo = $company->documents->where('document_type', DocumentType::SSM_REGISTRATION)->first();
|
||||
$identityType = DocumentType::SSM_REGISTRATION;
|
||||
}
|
||||
$address = $company->addresses()->where('e_invoice', '=', true)->latest()->first();
|
||||
if(!$address){
|
||||
$address = $company->addresses()->where('billing', '=', true)->first();
|
||||
}
|
||||
|
||||
return [
|
||||
$company->tin, // 'TIN',
|
||||
$identityNo ? $identityNo->reference: '', // 'IdentityNo',
|
||||
$employee ? $employee->name : '', // 'Name',
|
||||
$identityType === DocumentType::IDENTITY_CARD ? 'MyKad' : '', // 'IdentityType',
|
||||
$company->type !== null ? (string) $company->type : '0', // 'TaxClassification',
|
||||
$company->msic_code, // 'MSICCode',
|
||||
$company->msic_code ? Helper::getMsicDescriptionByCode($company->msic_code) : '', // 'BusinessActivityDesc',
|
||||
$company->debtor, // 'DebtorCode',
|
||||
$company->name, // 'TradeName',
|
||||
$address ? $address->street_one . ',' . $address->street_two : '',// 'Address',
|
||||
$address ? $address->postcode : '', // 'PostCode',
|
||||
$company->contacts()->first() ? $company->contacts()->first()->phone : '', // 'Phone',
|
||||
$employee ? $employee->email : '', // 'EmailAddress',
|
||||
$address ? $address->district()->first()->name : '', // 'City',
|
||||
'MYS', // 'CountryCode',
|
||||
$address ? Helper::getStateCodeByName($address->state()->first()->name) : '', // 'StateCode'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,12 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
|
||||
{
|
||||
use Exportable;
|
||||
|
||||
private $request;
|
||||
protected $startDate;
|
||||
protected $endDate;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
public function __construct($startDate = null, $endDate = null) {
|
||||
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1);
|
||||
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
@@ -53,25 +54,6 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
|
||||
*/
|
||||
public function query()
|
||||
{
|
||||
$start_date = $this->request->input('startDate', null);
|
||||
if ($start_date) {
|
||||
$start_date = Carbon::parse($this->request->input('startDate'))->format('Y-m-d');
|
||||
}
|
||||
|
||||
$end_date = $this->request->input('endDate', null);
|
||||
if ($end_date) {
|
||||
$end_date = Carbon::parse($this->request->input('endDate'))->format('Y-m-d');
|
||||
}
|
||||
|
||||
if (!$start_date) {
|
||||
$start_date = Carbon::now()->subMonths(1)->startOfDay();
|
||||
}
|
||||
if (!$end_date) {
|
||||
$end_date = Carbon::now()->endOfDay();
|
||||
}
|
||||
|
||||
$query = Booking::where('status', ApprovalStatus::COMPLETED);
|
||||
|
||||
// $query = Transaction::query();
|
||||
// $query->where('type', TransactionType::PAYMENT)->where('payment_method', '!=', PaymentMethodType::WALLET);
|
||||
// $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
|
||||
@@ -79,20 +61,7 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
|
||||
// $query->where('type', TransactionType::PURCHASE_ORDER)->complete();
|
||||
// });
|
||||
|
||||
if($start_date && $end_date) {
|
||||
$query->whereBetween('created_at', [
|
||||
Carbon::parse($start_date)->format('Y-m-d 0:00:00'),
|
||||
Carbon::parse($end_date)->format('Y-m-d 23:59:59')
|
||||
]);
|
||||
}
|
||||
elseif($start_date && !$end_date) {
|
||||
$query->where('created_at', '>=', Carbon::parse($start_date)->format('Y-m-d 0:00:00'));
|
||||
}
|
||||
elseif(!$start_date && $end_date) {
|
||||
$query->where('created_at', '<=', Carbon::parse($end_date)->format('Y-m-d 23:59:59'));
|
||||
}
|
||||
|
||||
return $query;
|
||||
return Booking::where('status', ApprovalStatus::COMPLETED)->whereBetween('created_at', [$this->startDate, $this->endDate]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,11 +70,15 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
|
||||
*/
|
||||
public function map($booking): array
|
||||
{
|
||||
// $transaction = $booking->transactions()->payments()->complete()->first();
|
||||
$records = [];
|
||||
|
||||
$purchaseOrder = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first();
|
||||
$company = $booking->company()->first();
|
||||
|
||||
$lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->latest()->first();
|
||||
if(!$lastPaymentTransaction){
|
||||
return $records;
|
||||
}
|
||||
$documentDate = $lastPaymentTransaction->created_at;
|
||||
if(Carbon::parse($booking->updated_at)->isAfter($lastPaymentTransaction->created_at)){
|
||||
$documentDate = $booking->updated_at;
|
||||
@@ -113,11 +86,7 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
|
||||
$formattedDocumentDate = Carbon::parse($documentDate)->format('m/d/Y');
|
||||
|
||||
$firstItem = true;
|
||||
$records = [];
|
||||
|
||||
$transactionDetails = $purchaseOrder->transactionDetails;
|
||||
|
||||
|
||||
foreach ($transactionDetails as $detail) {
|
||||
$records[] = [
|
||||
$firstItem ? '<<New>>' : '',
|
||||
|
||||
@@ -8,11 +8,35 @@ use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Excel;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Classes\General\AWSS3Helper;
|
||||
use App\Classes\Modules\Exports\Services\ExportsCompanies;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ExportController
|
||||
{
|
||||
public function salesInvoices(Request $request){
|
||||
$exportsTransactions = new ExportsSalesInvoiceReport($request);
|
||||
$validated = $request->validate([
|
||||
'startDate' => 'nullable|date_format:d-m-Y',
|
||||
'endDate' => 'nullable|date_format:d-m-Y|after_or_equal:startDate',
|
||||
]);
|
||||
|
||||
$startDate = null;
|
||||
$endDate = null;
|
||||
|
||||
if (isset($validated['startDate']) && $validated['startDate']) {
|
||||
$startDate = Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay();
|
||||
} else {
|
||||
$startDate = Carbon::now()->subMonths(1)->startOfDay();
|
||||
}
|
||||
|
||||
if (isset($validated['endDate']) && $validated['endDate']) {
|
||||
$endDate = Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay();
|
||||
} else {
|
||||
$endDate = Carbon::now()->endOfDay();
|
||||
}
|
||||
|
||||
|
||||
$exportsTransactions = new ExportsSalesInvoiceReport($startDate, $endDate);
|
||||
|
||||
$exportFileName = 'Exchange - Sales Invoice Report.xls';
|
||||
$filesystemDriver = Storage::getDefaultDriver();
|
||||
if($filesystemDriver === 's3'){
|
||||
@@ -24,4 +48,39 @@ class ExportController
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function companies(Request $request){
|
||||
$validated = $request->validate([
|
||||
'startDate' => 'nullable|date_format:d-m-Y',
|
||||
'endDate' => 'nullable|date_format:d-m-Y|after_or_equal:startDate',
|
||||
]);
|
||||
|
||||
$startDate = null;
|
||||
$endDate = null;
|
||||
|
||||
if (isset($validated['startDate']) && $validated['startDate']) {
|
||||
$startDate = Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay();
|
||||
} else {
|
||||
$startDate = Carbon::now()->subMonths(1)->startOfDay();
|
||||
}
|
||||
|
||||
if (isset($validated['endDate']) && $validated['endDate']) {
|
||||
$endDate = Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay();
|
||||
} else {
|
||||
$endDate = Carbon::now()->endOfDay();
|
||||
}
|
||||
|
||||
$exportsCompanies = new ExportsCompanies($startDate, $endDate);
|
||||
|
||||
$exportFileName = 'Exchange - Customers Data Report.xls';
|
||||
$filesystemDriver = Storage::getDefaultDriver();
|
||||
if($filesystemDriver === 's3'){
|
||||
return response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $exportsCompanies) ]);
|
||||
}
|
||||
else{
|
||||
$response = $exportsCompanies->download($exportFileName, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
|
||||
ob_end_clean();
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ export default {
|
||||
options() {
|
||||
return [
|
||||
'Sales Invoice Report',
|
||||
'Customers Report',
|
||||
];
|
||||
},
|
||||
handleClick(){
|
||||
@@ -90,7 +91,8 @@ export default {
|
||||
const reportType = this.parameters.reportType;
|
||||
|
||||
const routesMap = {
|
||||
'Sales Invoice Report': route('api.export.transaction.sales-invoices'),
|
||||
'Sales Invoice Report': route('api.export.transactions.sales-invoices'),
|
||||
'Customers Report': route('api.export.companies.customers-data'),
|
||||
};
|
||||
|
||||
let url = `${routesMap[reportType]}?startDate=${this.parameters.startDate}&endDate=${this.parameters.endDate}`;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
[
|
||||
{
|
||||
"Code": "01",
|
||||
"State": "Johor"
|
||||
},
|
||||
{
|
||||
"Code": "02",
|
||||
"State": "Kedah"
|
||||
},
|
||||
{
|
||||
"Code": "03",
|
||||
"State": "Kelantan"
|
||||
},
|
||||
{
|
||||
"Code": "04",
|
||||
"State": "Melaka"
|
||||
},
|
||||
{
|
||||
"Code": "05",
|
||||
"State": "Negeri Sembilan"
|
||||
},
|
||||
{
|
||||
"Code": "06",
|
||||
"State": "Pahang"
|
||||
},
|
||||
{
|
||||
"Code": "07",
|
||||
"State": "Pulau Pinang"
|
||||
},
|
||||
{
|
||||
"Code": "08",
|
||||
"State": "Perak"
|
||||
},
|
||||
{
|
||||
"Code": "09",
|
||||
"State": "Perlis"
|
||||
},
|
||||
{
|
||||
"Code": "10",
|
||||
"State": "Selangor"
|
||||
},
|
||||
{
|
||||
"Code": "11",
|
||||
"State": "Terengganu"
|
||||
},
|
||||
{
|
||||
"Code": "12",
|
||||
"State": "Sabah"
|
||||
},
|
||||
{
|
||||
"Code": "13",
|
||||
"State": "Sarawak"
|
||||
},
|
||||
{
|
||||
"Code": "14",
|
||||
"State": "Wilayah Persekutuan Kuala Lumpur"
|
||||
},
|
||||
{
|
||||
"Code": "15",
|
||||
"State": "Wilayah Persekutuan Labuan"
|
||||
},
|
||||
{
|
||||
"Code": "16",
|
||||
"State": "Wilayah Persekutuan Putrajaya"
|
||||
},
|
||||
{
|
||||
"Code": "17",
|
||||
"State": "Not Applicable"
|
||||
}
|
||||
]
|
||||
+4
-1
@@ -5,7 +5,10 @@ use Illuminate\Support\Facades\Route;
|
||||
|
||||
|
||||
Route::group(['prefix' => 'export', 'as' => 'export.', 'namespace' => 'Exports'], function () {
|
||||
Route::group(['prefix' => 'transactions', 'as' => 'transaction.'], function () {
|
||||
Route::group(['prefix' => 'transactions', 'as' => 'transactions.'], function () {
|
||||
Route::get('/sales-invoices', [ExportController::class, 'salesInvoices'])->name('sales-invoices');
|
||||
});
|
||||
Route::group(['prefix' => 'companies', 'as' => 'companies.'], function () {
|
||||
Route::get('/customers-data', [ExportController::class, 'companies'])->name('customers-data');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user