diff --git a/app/Http/Controllers/KomuditiController.php b/app/Http/Controllers/KomuditiController.php
index 8c672266..c77afed0 100644
--- a/app/Http/Controllers/KomuditiController.php
+++ b/app/Http/Controllers/KomuditiController.php
@@ -57,43 +57,69 @@ class KomuditiController extends Controller
}
/**
- * Dummy BSAS eCert layout preview (2-page A4).
+ * Dummy BSAS eCert layout preview (bid, OTC, STB, then one commodity schedule).
*/
public function previewBsasEcert()
{
- $cert = [
- 'ecert_no' => 'CPO13OCT26-0000136-025',
- 'seller' => 'KOPERASI PERMODALAN KELANTAN BERHAD',
- 'buyer' => 'WAN MOHAMAD AIMAN',
- 'bid_no' => '1',
- 'report_time' => '13:39:23.751',
- 'report_date' => '13 OCTOBER 2026',
- 'value_date' => '13 OCTOBER 2026',
- 'product' => 'CPO-MSIA-09',
- 'unit' => 'Tonnage',
- 'volume' => '.72562358',
- 'currency' => 'MYR',
- 'price' => '5,256.72',
- 'price_myr' => '5,256.72',
- 'value' => '3,200.00',
- 'txn_type' => '-',
- 'murabaha' => '3,814.40',
- 'lines' => [
- [
- 'supplier' => 'POA RESOURCES BERHAD',
- 'volume' => '.72562358',
- ],
- ],
+ $line = [
+ ['SUPPLIER' => 'FGV TRADING SDN BHD', 'VOLUME' => '0.75276406'],
];
- return view('print.bsas_ecert', [
- 'cert' => $cert,
- 'isDummy' => true,
- ]);
+ 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 eCert from stored bsas_orders.ecert_response.
+ * Live BSAS eCerts from stored bid, OTC and STB payloads.
*/
public function showBsasEcert($uuid)
{
@@ -109,32 +135,152 @@ class KomuditiController extends Controller
}
$payload = $response->json();
- $ecert = $payload['ecert'] ?? null;
+ if (!is_array($payload)) {
+ abort(502, 'Gagal memuatkan eCert BSAS.');
+ }
- if (!is_array($ecert) || empty($ecert)) {
+ $presented = $this->presentBsasCertificates($payload, false);
+ if ($presented['certificates'] === []) {
abort(404, 'eCert belum tersedia untuk order ini.');
}
- return view('print.bsas_ecert', [
- 'cert' => $this->mapBsasEcertToView($ecert, $payload),
- 'isDummy' => false,
- ]);
+ return view('print.bsas_ecert', $presented);
}
/**
- * Map stored otcXML / eCert JSON into print view fields.
+ * Bid, OTC and STB pages, plus one shared commodity schedule.
*/
- protected function mapBsasEcertToView(array $ecert, array $orderMeta = []): array
+ protected function presentBsasCertificates(array $payload, bool $isDummy): array
{
- $reporting = trim((string) ($ecert['REPORTINGTIMEDATE'] ?? ''));
- $reportTime = '-';
- $reportDate = '-';
- if ($reporting !== '') {
- $parts = explode(' ', $reporting, 2);
- $reportTime = $parts[0] ?? '-';
- $reportDate = isset($parts[1]) ? strtoupper($parts[1]) : '-';
+ $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 Bid',
+ 'This is to certify that the following bid transaction has been executed
through the Bursa Suq Al-Sila\' in accordance with the
Rules of Bursa Suq Al-Sila\'.',
+ 'Generated for Ar-Rahn / Koperasi Permodalan Kelantan Berhad · BSAS Bid Certificate',
+ $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 Purchase',
+ 'This is to certify that the following transaction has been executed
through the Bursa Suq Al-Sila\' in accordance with the
Rules of Bursa Suq Al-Sila\'.',
+ 'Generated for Ar-Rahn / Koperasi Permodalan Kelantan Berhad · BSAS OTC Certificate',
+ $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
through the Bursa Suq Al-Sila\' in accordance with the
Rules of Bursa Suq Al-Sila\'.',
+ 'Generated for Ar-Rahn / Koperasi Permodalan Kelantan Berhad · BSAS STB Certificate',
+ $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, string $footerNote, array $ecert, array $orderMeta, array $rows): array
+ {
+ return [
+ 'title' => $title,
+ 'statement' => $statement,
+ 'footer_note' => $footerNote,
+ '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)) {
@@ -146,31 +292,28 @@ class KomuditiController extends Controller
];
}
- if (empty($lines)) {
+ 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 [
- 'ecert_no' => $ecert['ECERTNO'] ?? ($orderMeta['e_cert_no'] ?? '-'),
- 'seller' => $ecert['SELLER'] ?? 'KOPERASI PERMODALAN KELANTAN BERHAD',
- 'buyer' => $ecert['BUYER'] ?? ($orderMeta['otc_counter_party'] ?? '-'),
- 'bid_no' => $orderMeta['serial_number'] ?? '1',
- 'report_time' => $reportTime,
- 'report_date' => $reportDate,
- 'value_date' => isset($ecert['VALUEDATE']) ? strtoupper((string) $ecert['VALUEDATE']) : '-',
- 'product' => $ecert['PNAME'] ?? ($orderMeta['product_code'] ?? '-'),
- 'unit' => 'Tonnage',
- 'volume' => $ecert['PVOLUME'] ?? '-',
- 'currency' => $ecert['CURRENCY'] ?? 'MYR',
- 'price' => $ecert['PRICE'] ?? '-',
- 'price_myr' => $ecert['PRICE_MYR_EQUIVALENT'] ?? ($ecert['PRICE'] ?? '-'),
- 'value' => $ecert['TOTALVALUE'] ?? '-',
- 'txn_type' => '-',
- 'murabaha' => $ecert['MURABAHAVALUE'] ?? ($orderMeta['otc_murabaha_value'] ?? '-'),
- 'lines' => $lines,
+ $parts[0] ?? '-',
+ isset($parts[1]) ? strtoupper($parts[1]) : '-',
];
}
}
diff --git a/resources/views/gadaian/v2/index.blade.php b/resources/views/gadaian/v2/index.blade.php
index d346d649..cb4f3119 100644
--- a/resources/views/gadaian/v2/index.blade.php
+++ b/resources/views/gadaian/v2/index.blade.php
@@ -1579,7 +1579,7 @@
'' +
'