Feature/bsas integration (#31)
Reviewed-on: #31 Co-authored-by: ISMAIL MASSERAN <ismail@koppkb.com> Co-committed-by: ISMAIL MASSERAN <ismail@koppkb.com>
This commit was merged in pull request #31.
This commit is contained in:
@@ -298,7 +298,7 @@ class GadaianController extends Controller
|
||||
}
|
||||
|
||||
if ($caraTerima === 'ONLINE' && !$this->hasMatchingBorangOnlinePrint($request)) {
|
||||
return redirect()->back()->with('error', 'Sila cetak borang pengesahan pelanggan sebelum tekan Terima.');
|
||||
return $this->gadaiStoreResult($request, false, 'Sila cetak borang pengesahan pelanggan sebelum tekan Terima.');
|
||||
}
|
||||
|
||||
//$total_nilai_marhun = $request->total_nilai_marhun;
|
||||
@@ -320,6 +320,27 @@ class GadaianController extends Controller
|
||||
$keuntungan12bulan = $keuntungan_sebln * 12;
|
||||
|
||||
$hargajualan = $request->pinjaman + $keuntungan12bulan;
|
||||
|
||||
// BSAS commodity order must succeed before finalizing gadai.
|
||||
$bsas = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->timeout(60)
|
||||
->post(config('api.url') . '/api/komuditi/bsas/order', [
|
||||
'norujukan' => $request->norujukan_gadai,
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'pinjaman' => round((float) $request->pinjaman, 2),
|
||||
'hargajualan' => round((float) $hargajualan, 2),
|
||||
'nama_pelanggan' => $request->nama_pelanggan ?: $request->nama_akaun,
|
||||
'teller' => $auth_user['name'],
|
||||
]);
|
||||
|
||||
if (!$bsas->successful()) {
|
||||
$body = $bsas->json();
|
||||
$msg = is_array($body) && isset($body['message'])
|
||||
? $body['message']
|
||||
: 'Gagal pembelian komoditi BSAS. Sila cuba lagi.';
|
||||
return $this->gadaiStoreResult($request, false, $msg);
|
||||
}
|
||||
|
||||
//Log::info('DEBUG NOKP:' . $request->nokp);
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/gadai/norujukan/' . $auth_user['cawangan'] . '/' . $request->norujukan_gadai, [
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
@@ -344,14 +365,6 @@ class GadaianController extends Controller
|
||||
'rebate' => $this->parseMoney($request->rebate),
|
||||
])->json();
|
||||
|
||||
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/komuditi/transaksi', [
|
||||
'unit_komuditi' => round($request->pinjaman, 2),
|
||||
'norujukan' => $request->norujukan_gadai,
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'teller' => $auth_user['name']
|
||||
]);
|
||||
|
||||
if ($caraTerima === 'ONLINE') {
|
||||
$online = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->asForm()
|
||||
@@ -374,7 +387,7 @@ class GadaianController extends Controller
|
||||
$msg = is_array($body) && isset($body['message'])
|
||||
? $body['message']
|
||||
: 'Gagal daftar pembiayaan online. Sila cuba lagi.';
|
||||
return redirect()->back()->with('error', $msg);
|
||||
return $this->gadaiStoreResult($request, false, $msg);
|
||||
}
|
||||
|
||||
$this->notifyPcPembiayaanOnlinePending($auth_user, $request, $pinjamanAmt);
|
||||
@@ -392,6 +405,33 @@ class GadaianController extends Controller
|
||||
$request->session()->flash('message', 'Gadai berjaya. Pembiayaan online menunggu semakan PC.');
|
||||
}
|
||||
|
||||
return $this->gadaiStoreResult($request, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON for AJAX Terima (BSAS progress UI); normal redirect otherwise.
|
||||
*/
|
||||
protected function gadaiStoreResult(Request $request, bool $ok, string $message = null)
|
||||
{
|
||||
if ($request->ajax() || $request->wantsJson()) {
|
||||
if (!$ok) {
|
||||
return response()->json([
|
||||
'ok' => false,
|
||||
'message' => $message ?: 'Gadai tidak berjaya.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'message' => $message ?: 'Gadai berjaya.',
|
||||
'redirect' => route('customer_info'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$ok) {
|
||||
return redirect()->back()->with('error', $message ?: 'Gadai tidak berjaya.');
|
||||
}
|
||||
|
||||
return redirect()->route('customer_info');
|
||||
}
|
||||
|
||||
@@ -671,13 +711,31 @@ class GadaianController extends Controller
|
||||
// $pembayaran_segera = "https://spare.arrahn.com.my/pembayaransegera";
|
||||
$pembayaran_segera = "https://pay.arrahn.com.my";
|
||||
|
||||
$komoditi = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/check')
|
||||
->json();
|
||||
$product = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/description', ['kodproduk' => $komoditi['kodproduct']])
|
||||
->json();
|
||||
$kuantiti = $gadai_detail['pinjaman'] / $komoditi['nilai'];
|
||||
$bsasSag = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/bsas/order/norujukan/' . urlencode($norujukan));
|
||||
|
||||
$komoditi = [];
|
||||
$product = [];
|
||||
$kuantiti = 0;
|
||||
|
||||
if ($bsasSag->successful() && is_array($bsasSag->json())) {
|
||||
$bsasPayload = $bsasSag->json();
|
||||
$komoditi = $bsasPayload['komoditi'] ?? [];
|
||||
$product = $bsasPayload['product'] ?? [];
|
||||
$kuantiti = (float) ($bsasPayload['kuantiti'] ?? 0);
|
||||
}
|
||||
|
||||
if (!is_array($komoditi)) {
|
||||
$komoditi = [];
|
||||
}
|
||||
if (!is_array($product)) {
|
||||
$product = [
|
||||
'product_code' => $komoditi['kodproduct'] ?? '',
|
||||
'kodproduk' => $komoditi['kodproduct'] ?? '',
|
||||
'description' => '',
|
||||
'unit' => 'TAN',
|
||||
];
|
||||
}
|
||||
|
||||
if ($gadai_detail['tagbaru'] == 1) {
|
||||
$cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
|
||||
@@ -55,4 +55,274 @@ class KomuditiController extends Controller
|
||||
|
||||
return redirect()->route('komuditi');
|
||||
}
|
||||
|
||||
/**
|
||||
* Khazanah branch list of BSAS commodity orders.
|
||||
*/
|
||||
public function khazanahBsas()
|
||||
{
|
||||
$auth_user = Auth::user();
|
||||
$cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get(config('api.url') . '/api/cawangan/' . $auth_user['cawangan'])
|
||||
->json();
|
||||
|
||||
return view('homepage.khazanah.bsas_komoditi', compact('cawangan_info'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy BSAS eCert layout preview (bid, OTC, STB, then one commodity schedule).
|
||||
*/
|
||||
public function previewBsasEcert()
|
||||
{
|
||||
$line = [
|
||||
['SUPPLIER' => 'FGV TRADING SDN BHD', 'VOLUME' => '0.75276406'],
|
||||
];
|
||||
|
||||
return view('print.bsas_ecert', $this->presentBsasCertificates([
|
||||
'e_cert_no' => 'CPO21OCT26-0000031-000',
|
||||
'serial_number' => '1',
|
||||
'otc_counter_party' => 'ALI BIN ABU',
|
||||
'otc_murabaha_value' => '3,814.40',
|
||||
'product_code' => 'CPO-MSIA-09',
|
||||
'bid_ecert' => [
|
||||
'ECERTNO' => 'CPO21OCT26-0000031-000',
|
||||
'BUYER' => 'KOPERASI PERMODALAN KELANTAN BERHAD',
|
||||
'OWNER' => 'KOPERASI PERMODALAN KELANTAN BERHAD',
|
||||
'BIDNO' => '8',
|
||||
'TOTALVALUE' => '3,200.00',
|
||||
'CURRENCY' => 'MYR',
|
||||
'PRICE' => '4,251.00',
|
||||
'PRICE_MYR_EQUIVALENT' => '4,251.00',
|
||||
'PURCHASETIMEDATE' => '15:11:53.316 21 Oct 2026',
|
||||
'VALUEDATE' => '21 Oct 2026',
|
||||
'PNAME' => 'CPO-MSIA-09',
|
||||
'PVOLUME' => '0.75276406',
|
||||
'LINE' => $line,
|
||||
],
|
||||
'otc_ecert' => [
|
||||
'ECERTNO' => 'CPO21OCT26-0000031-000',
|
||||
'SELLER' => 'KOPERASI PERMODALAN KELANTAN BERHAD',
|
||||
'BUYER' => 'ALI BIN ABU',
|
||||
'REPORTINGTIMEDATE' => '15:11:53.320 21 Oct 2026',
|
||||
'VALUEDATE' => '21 Oct 2026',
|
||||
'PNAME' => 'CPO-MSIA-09',
|
||||
'PVOLUME' => '0.75276406',
|
||||
'CURRENCY' => 'MYR',
|
||||
'PRICE' => '4,251.00',
|
||||
'PRICE_MYR_EQUIVALENT' => '4,251.00',
|
||||
'TOTALVALUE' => '3,200.00',
|
||||
'MURABAHAVALUE' => '3,814.40',
|
||||
'LINE' => $line,
|
||||
],
|
||||
'stb_ecert' => [
|
||||
'ECERTNO' => 'CPO21OCT26-0000031-000',
|
||||
'SELLER' => 'ALI BIN ABU',
|
||||
'BUYER' => 'BURSA MALAYSIA ISLAMIC SERVICES',
|
||||
'TOTALVALUE' => '3,200.00',
|
||||
'CURRENCY' => 'MYR',
|
||||
'PRICE' => '4,251.00',
|
||||
'PRICE_MYR_EQUIVALENT' => '4,251.00',
|
||||
'SELLINGTIMEDATE' => '15:11:53.325 21 Oct 2026',
|
||||
'VALUEDATE' => '21 Oct 2026',
|
||||
'PNAME' => 'CPO-MSIA-09',
|
||||
'PVOLUME' => '0.75276406',
|
||||
'LINE' => $line,
|
||||
],
|
||||
], true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Live BSAS eCerts from stored bid, OTC and STB payloads.
|
||||
*/
|
||||
public function showBsasEcert($uuid)
|
||||
{
|
||||
$response = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get(config('api.url') . '/api/komuditi/bsas/order/' . urlencode($uuid) . '/ecert');
|
||||
|
||||
if ($response->status() === 404) {
|
||||
abort(404, $response->json('message') ?: 'eCert tidak dijumpai.');
|
||||
}
|
||||
|
||||
if (!$response->successful()) {
|
||||
abort(502, 'Gagal memuatkan eCert BSAS.');
|
||||
}
|
||||
|
||||
$payload = $response->json();
|
||||
if (!is_array($payload)) {
|
||||
abort(502, 'Gagal memuatkan eCert BSAS.');
|
||||
}
|
||||
|
||||
$presented = $this->presentBsasCertificates($payload, false);
|
||||
if ($presented['certificates'] === []) {
|
||||
abort(404, 'eCert belum tersedia untuk order ini.');
|
||||
}
|
||||
|
||||
return view('print.bsas_ecert', $presented);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bid, OTC and STB pages, plus one shared commodity schedule.
|
||||
*/
|
||||
protected function presentBsasCertificates(array $payload, bool $isDummy): array
|
||||
{
|
||||
$certificates = [];
|
||||
|
||||
$bid = $payload['bid_ecert'] ?? null;
|
||||
if (is_array($bid) && $bid !== []) {
|
||||
$certificates[] = $this->mapBidCertificate($bid, $payload);
|
||||
}
|
||||
|
||||
$otc = $payload['otc_ecert'] ?? null;
|
||||
if (is_array($otc) && $otc !== []) {
|
||||
$certificates[] = $this->mapOtcCertificate($otc, $payload);
|
||||
}
|
||||
|
||||
$stb = $payload['stb_ecert'] ?? null;
|
||||
if (is_array($stb) && $stb !== []) {
|
||||
$certificates[] = $this->mapStbCertificate($stb, $payload);
|
||||
}
|
||||
|
||||
$scheduleSource = [];
|
||||
if (is_array($otc) && $otc !== []) {
|
||||
$scheduleSource = $otc;
|
||||
} elseif (is_array($bid) && $bid !== []) {
|
||||
$scheduleSource = $bid;
|
||||
} elseif (is_array($stb) && $stb !== []) {
|
||||
$scheduleSource = $stb;
|
||||
}
|
||||
|
||||
$ecertNo = $scheduleSource['ECERTNO'] ?? ($payload['e_cert_no'] ?? '-');
|
||||
|
||||
return [
|
||||
'certificates' => $certificates,
|
||||
'ecert_no' => $ecertNo,
|
||||
'lines' => $this->mapBsasLines($scheduleSource),
|
||||
'isDummy' => $isDummy,
|
||||
];
|
||||
}
|
||||
|
||||
protected function mapBidCertificate(array $ecert, array $orderMeta): array
|
||||
{
|
||||
[$time, $date] = $this->splitBsasDateTime((string) ($ecert['PURCHASETIMEDATE'] ?? ''));
|
||||
|
||||
return $this->certificatePage(
|
||||
'Certificate of Purchase',
|
||||
'This is to certify that the following bid transaction has been executed<br>through the Bursa Suq Al-Sila\' in accordance with the<br>Rules of Bursa Suq Al-Sila\'.',
|
||||
$ecert,
|
||||
$orderMeta,
|
||||
array_merge([
|
||||
['label' => 'Buyer', 'value' => $ecert['BUYER'] ?? '-'],
|
||||
['label' => 'Owner', 'value' => $ecert['OWNER'] ?? '-'],
|
||||
['label' => 'Bid No', 'value' => $ecert['BIDNO'] ?? ($orderMeta['serial_number'] ?? '-')],
|
||||
['label' => 'Purchase Time / Date', 'value' => $time . ' / ' . $date],
|
||||
], $this->commodityDetailRows($ecert, $orderMeta))
|
||||
);
|
||||
}
|
||||
|
||||
protected function mapOtcCertificate(array $ecert, array $orderMeta): array
|
||||
{
|
||||
[$time, $date] = $this->splitBsasDateTime((string) ($ecert['REPORTINGTIMEDATE'] ?? ''));
|
||||
|
||||
$page = $this->certificatePage(
|
||||
'Certificate of Murabahah',
|
||||
'This is to certify that the following transaction has been executed<br>through the Bursa Suq Al-Sila\' in accordance with the<br>Rules of Bursa Suq Al-Sila\'.',
|
||||
$ecert,
|
||||
$orderMeta,
|
||||
array_merge([
|
||||
['label' => 'Seller', 'value' => $ecert['SELLER'] ?? 'KOPERASI PERMODALAN KELANTAN BERHAD'],
|
||||
['label' => 'Buyer', 'value' => $ecert['BUYER'] ?? ($orderMeta['otc_counter_party'] ?? '-')],
|
||||
['label' => 'Bid No', 'value' => $orderMeta['serial_number'] ?? '1'],
|
||||
['label' => 'Reporting Time / Date', 'value' => $time . ' / ' . $date],
|
||||
], $this->commodityDetailRows($ecert, $orderMeta), [
|
||||
['label' => 'Transaction Type', 'value' => '-'],
|
||||
])
|
||||
);
|
||||
|
||||
$page['show_murabaha'] = true;
|
||||
$page['murabaha'] = $ecert['MURABAHAVALUE'] ?? ($orderMeta['otc_murabaha_value'] ?? '-');
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
protected function mapStbCertificate(array $ecert, array $orderMeta): array
|
||||
{
|
||||
[$time, $date] = $this->splitBsasDateTime((string) ($ecert['SELLINGTIMEDATE'] ?? ''));
|
||||
|
||||
return $this->certificatePage(
|
||||
'Certificate of Sale',
|
||||
'This is to certify that the following sale transaction has been executed<br>through the Bursa Suq Al-Sila\' in accordance with the<br>Rules of Bursa Suq Al-Sila\'.',
|
||||
$ecert,
|
||||
$orderMeta,
|
||||
array_merge([
|
||||
['label' => 'Seller', 'value' => $ecert['SELLER'] ?? ($orderMeta['otc_counter_party'] ?? '-')],
|
||||
['label' => 'Buyer', 'value' => $ecert['BUYER'] ?? '-'],
|
||||
['label' => 'Selling Time / Date', 'value' => $time . ' / ' . $date],
|
||||
], $this->commodityDetailRows($ecert, $orderMeta))
|
||||
);
|
||||
}
|
||||
|
||||
protected function certificatePage(string $title, string $statement, array $ecert, array $orderMeta, array $rows): array
|
||||
{
|
||||
return [
|
||||
'title' => $title,
|
||||
'statement' => $statement,
|
||||
'ecert_no' => $ecert['ECERTNO'] ?? ($orderMeta['e_cert_no'] ?? '-'),
|
||||
'currency' => $ecert['CURRENCY'] ?? 'MYR',
|
||||
'rows' => $rows,
|
||||
'show_murabaha' => false,
|
||||
'murabaha' => null,
|
||||
];
|
||||
}
|
||||
|
||||
protected function commodityDetailRows(array $ecert, array $orderMeta): array
|
||||
{
|
||||
return [
|
||||
['label' => 'Value Date', 'value' => isset($ecert['VALUEDATE']) ? strtoupper((string) $ecert['VALUEDATE']) : '-'],
|
||||
['label' => 'Product Code / Description', 'value' => $ecert['PNAME'] ?? ($orderMeta['product_code'] ?? '-')],
|
||||
['label' => 'Unit', 'value' => 'Tonnage'],
|
||||
['label' => 'Volume', 'value' => $ecert['PVOLUME'] ?? '-'],
|
||||
['label' => 'Currency', 'value' => $ecert['CURRENCY'] ?? 'MYR'],
|
||||
['label' => 'Price (MYR)', 'value' => $ecert['PRICE'] ?? '-'],
|
||||
['label' => 'Price (MYR Equivalent)', 'value' => $ecert['PRICE_MYR_EQUIVALENT'] ?? ($ecert['PRICE'] ?? '-')],
|
||||
['label' => 'Value', 'value' => $ecert['TOTALVALUE'] ?? '-'],
|
||||
];
|
||||
}
|
||||
|
||||
protected function mapBsasLines(array $ecert): array
|
||||
{
|
||||
$lines = [];
|
||||
foreach (($ecert['LINE'] ?? []) as $line) {
|
||||
if (!is_array($line)) {
|
||||
continue;
|
||||
}
|
||||
$lines[] = [
|
||||
'supplier' => $line['SUPPLIER'] ?? '-',
|
||||
'volume' => $line['VOLUME'] ?? ($ecert['PVOLUME'] ?? '-'),
|
||||
];
|
||||
}
|
||||
|
||||
if ($lines === []) {
|
||||
$lines[] = [
|
||||
'supplier' => '-',
|
||||
'volume' => $ecert['PVOLUME'] ?? '-',
|
||||
];
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
protected function splitBsasDateTime(string $value): array
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
return ['-', '-'];
|
||||
}
|
||||
|
||||
$parts = explode(' ', $value, 2);
|
||||
|
||||
return [
|
||||
$parts[0] ?? '-',
|
||||
isset($parts[1]) ? strtoupper($parts[1]) : '-',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,15 +585,37 @@ class PembiayaanOnlineController extends Controller
|
||||
|
||||
$pembayaran_segera = 'https://pay.arrahn.com.my';
|
||||
|
||||
$komoditi = $this->api()->get($api_url . '/api/komuditi/check')->json();
|
||||
$product = $this->api()
|
||||
->get($api_url . '/api/komuditi/description', [
|
||||
'kodproduk' => is_array($komoditi) ? ($komoditi['kodproduct'] ?? '') : '',
|
||||
])
|
||||
->json();
|
||||
// Prefer per-Terima BSAS order; fall back to legacy daily KomuditiPurchase.
|
||||
$bsasSag = $this->api()
|
||||
->get($api_url . '/api/komuditi/bsas/order/norujukan/' . urlencode($norujukan));
|
||||
|
||||
$nilai = is_array($komoditi) ? (float) ($komoditi['nilai'] ?? 0) : 0;
|
||||
$kuantiti = $nilai > 0 ? ((float) ($gadai_detail['pinjaman'] ?? 0) / $nilai) : 0;
|
||||
if ($bsasSag->successful() && is_array($bsasSag->json())) {
|
||||
$bsasPayload = $bsasSag->json();
|
||||
$komoditi = $bsasPayload['komoditi'] ?? [];
|
||||
$product = $bsasPayload['product'] ?? [];
|
||||
$kuantiti = (float) ($bsasPayload['kuantiti'] ?? 0);
|
||||
} else {
|
||||
$komoditi = $this->api()->get($api_url . '/api/komuditi/check')->json();
|
||||
$product = $this->api()
|
||||
->get($api_url . '/api/komuditi/description', [
|
||||
'kodproduk' => is_array($komoditi) ? ($komoditi['kodproduct'] ?? '') : '',
|
||||
])
|
||||
->json();
|
||||
|
||||
$nilai = is_array($komoditi) ? (float) ($komoditi['nilai'] ?? 0) : 0;
|
||||
$kuantiti = $nilai > 0 ? ((float) ($gadai_detail['pinjaman'] ?? 0) / $nilai) : 0;
|
||||
}
|
||||
|
||||
if (!is_array($komoditi)) {
|
||||
$komoditi = [];
|
||||
}
|
||||
if (!is_array($product)) {
|
||||
$product = [
|
||||
'kodproduk' => $komoditi['kodproduct'] ?? '',
|
||||
'description' => '',
|
||||
'unit' => 'TAN',
|
||||
];
|
||||
}
|
||||
|
||||
if (($gadai_detail['tagbaru'] ?? 0) == 1) {
|
||||
$cawangan_info = $this->api()
|
||||
|
||||
Reference in New Issue
Block a user