Explore/ismail #12
@@ -22,3 +22,9 @@ docker exec -i api_arrahn_staging_mysql mysql -uroot -proot erahn_test < erahn_t
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Disable the cawangan in arrahn_master_db
|
## Disable the cawangan in arrahn_master_db
|
||||||
|
|
||||||
|
## Feature Flag
|
||||||
|
1. Register the flag in api_arrahn/app/Feature.php
|
||||||
|
2. Block the real work in the API
|
||||||
|
3. Hide the UI in kaunter from the
|
||||||
|
4. Enable a pilot from Admin → Ciri Cawangan (or SQL):
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class CawanganFeature extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'cawangan_feature';
|
||||||
|
protected $connection = 'mysql7';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'kodcaw',
|
||||||
|
'feature',
|
||||||
|
'enabled',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'enabled' => 'integer',
|
||||||
|
];
|
||||||
|
}
|
||||||
+147
@@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
class Feature
|
||||||
|
{
|
||||||
|
const PEMBIAYAAN_ONLINE = 'pembiayaan_online';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Known flag keys. New features: add a constant here, then INSERT rows for pilot kodcaw.
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public static function keys()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
self::PEMBIAYAAN_ONLINE,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string,int>
|
||||||
|
*/
|
||||||
|
public static function defaults()
|
||||||
|
{
|
||||||
|
$map = [];
|
||||||
|
foreach (self::keys() as $key) {
|
||||||
|
$map[$key] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display labels for admin UI. New features: add a label here.
|
||||||
|
*
|
||||||
|
* @return array<string,string>
|
||||||
|
*/
|
||||||
|
public static function labels()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
self::PEMBIAYAAN_ONLINE => 'Pembiayaan Online',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Missing row is off (fail closed).
|
||||||
|
*
|
||||||
|
* @param string $kodcaw
|
||||||
|
* @param string $feature
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function enabled($kodcaw, $feature)
|
||||||
|
{
|
||||||
|
return CawanganFeature::on('mysql7')
|
||||||
|
->where('kodcaw', $kodcaw)
|
||||||
|
->where('feature', $feature)
|
||||||
|
->where('enabled', 1)
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $kodcaw
|
||||||
|
* @return array<string,int>
|
||||||
|
*/
|
||||||
|
public static function mapFor($kodcaw)
|
||||||
|
{
|
||||||
|
$map = self::defaults();
|
||||||
|
|
||||||
|
$rows = CawanganFeature::on('mysql7')
|
||||||
|
->where('kodcaw', $kodcaw)
|
||||||
|
->get(['feature', 'enabled']);
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$map[$row->feature] = ((int) $row->enabled) === 1 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $kodcaws
|
||||||
|
* @return array<string,array<string,int>>
|
||||||
|
*/
|
||||||
|
public static function mapForMany(array $kodcaws)
|
||||||
|
{
|
||||||
|
$defaults = self::defaults();
|
||||||
|
$result = [];
|
||||||
|
foreach ($kodcaws as $kodcaw) {
|
||||||
|
$result[$kodcaw] = $defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($kodcaws) === 0) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = CawanganFeature::on('mysql7')
|
||||||
|
->whereIn('kodcaw', $kodcaws)
|
||||||
|
->get(['kodcaw', 'feature', 'enabled']);
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$result[$row->kodcaw][$row->feature] = ((int) $row->enabled) === 1 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $kodcaw
|
||||||
|
* @param string $feature
|
||||||
|
* @param bool|int $enabled
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function setEnabled($kodcaw, $feature, $enabled)
|
||||||
|
{
|
||||||
|
if (!in_array($feature, self::keys(), true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CawanganFeature::on('mysql7')->updateOrCreate(
|
||||||
|
[
|
||||||
|
'kodcaw' => $kodcaw,
|
||||||
|
'feature' => $feature,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'enabled' => $enabled ? 1 : 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $message
|
||||||
|
* @return array{ok:bool,status:int,payload:array}
|
||||||
|
*/
|
||||||
|
public static function denied($message = null)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'ok' => false,
|
||||||
|
'status' => 403,
|
||||||
|
'payload' => [
|
||||||
|
'message' => $message ?: 'Ciri ini tidak diaktifkan untuk cawangan ini',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Cawangan;
|
use App\Cawangan;
|
||||||
|
use App\Feature;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class CawanganController extends Controller
|
class CawanganController extends Controller
|
||||||
@@ -18,7 +19,15 @@ class CawanganController extends Controller
|
|||||||
$cawangan = Cawangan::on('mysql7')
|
$cawangan = Cawangan::on('mysql7')
|
||||||
->where('kodcaw','=',$code_cawangan)
|
->where('kodcaw','=',$code_cawangan)
|
||||||
->first();
|
->first();
|
||||||
return response()->json($cawangan);
|
|
||||||
|
if (!$cawangan) {
|
||||||
|
return response()->json($cawangan);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $cawangan->toArray();
|
||||||
|
$data['features'] = Feature::mapFor($code_cawangan);
|
||||||
|
|
||||||
|
return response()->json($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Cawangan;
|
||||||
|
use App\Feature;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class FeatureController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'keys' => Feature::keys(),
|
||||||
|
'labels' => Feature::labels(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cawangan()
|
||||||
|
{
|
||||||
|
$cawangan = Cawangan::on('mysql7')
|
||||||
|
->orderBy('kodcaw')
|
||||||
|
->get(['kodcaw', 'details_caw']);
|
||||||
|
|
||||||
|
$maps = Feature::mapForMany($cawangan->pluck('kodcaw')->all());
|
||||||
|
|
||||||
|
$data = $cawangan->map(function ($c) use ($maps) {
|
||||||
|
return [
|
||||||
|
'kodcaw' => $c->kodcaw,
|
||||||
|
'details_caw' => $c->nama_cawangan,
|
||||||
|
'features' => $maps[$c->kodcaw] ?? Feature::defaults(),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update($kodcaw, $feature, Request $request)
|
||||||
|
{
|
||||||
|
$cawangan = Cawangan::on('mysql7')->where('kodcaw', $kodcaw)->first();
|
||||||
|
if (!$cawangan) {
|
||||||
|
return response()->json(['message' => 'Cawangan tidak dijumpai'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($feature, Feature::keys(), true)) {
|
||||||
|
return response()->json(['message' => 'Ciri tidak sah'], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$enabled = (int) $request->input('enabled') ? 1 : 0;
|
||||||
|
Feature::setEnabled($kodcaw, $feature, $enabled);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'kodcaw' => $kodcaw,
|
||||||
|
'feature' => $feature,
|
||||||
|
'enabled' => $enabled,
|
||||||
|
'features' => Feature::mapFor($kodcaw),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Services\PembiayaanOnline;
|
namespace App\Services\PembiayaanOnline;
|
||||||
|
|
||||||
use App\Cawangan;
|
use App\Cawangan;
|
||||||
|
use App\Feature;
|
||||||
use App\ModalOnline;
|
use App\ModalOnline;
|
||||||
use App\RequestModalOnline;
|
use App\RequestModalOnline;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -208,6 +209,10 @@ class ModalOnlineService
|
|||||||
return $resolved;
|
return $resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Feature::enabled($kodcaw, Feature::PEMBIAYAAN_ONLINE)) {
|
||||||
|
return Feature::denied('Pembiayaan online tidak diaktifkan untuk cawangan ini');
|
||||||
|
}
|
||||||
|
|
||||||
$mysql = $resolved['mysql'];
|
$mysql = $resolved['mysql'];
|
||||||
$amaun = round((float) $amaun, 2);
|
$amaun = round((float) $amaun, 2);
|
||||||
|
|
||||||
@@ -294,6 +299,10 @@ class ModalOnlineService
|
|||||||
}
|
}
|
||||||
$mysql = $resolved['mysql'];
|
$mysql = $resolved['mysql'];
|
||||||
|
|
||||||
|
if (!Feature::enabled($kodcaw, Feature::PEMBIAYAAN_ONLINE)) {
|
||||||
|
return Feature::denied('Pembiayaan online tidak diaktifkan untuk cawangan ini');
|
||||||
|
}
|
||||||
|
|
||||||
$amaun = round((float) $amaun, 2);
|
$amaun = round((float) $amaun, 2);
|
||||||
$dimohonOleh = trim((string) $dimohonOleh);
|
$dimohonOleh = trim((string) $dimohonOleh);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Bank;
|
|||||||
use App\BatchPembiayaanOnline;
|
use App\BatchPembiayaanOnline;
|
||||||
use App\Cawangan;
|
use App\Cawangan;
|
||||||
use App\Customer;
|
use App\Customer;
|
||||||
|
use App\Feature;
|
||||||
use App\Gadai;
|
use App\Gadai;
|
||||||
use App\PembiayaanOnline;
|
use App\PembiayaanOnline;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -67,6 +68,10 @@ class PembiayaanOnlineService
|
|||||||
}
|
}
|
||||||
$mysql = $resolved['mysql'];
|
$mysql = $resolved['mysql'];
|
||||||
|
|
||||||
|
if (!Feature::enabled($kodcaw, Feature::PEMBIAYAAN_ONLINE)) {
|
||||||
|
return Feature::denied('Pembiayaan online tidak diaktifkan untuk cawangan ini');
|
||||||
|
}
|
||||||
|
|
||||||
$norujukan = trim((string) ($data['norujukan'] ?? ''));
|
$norujukan = trim((string) ($data['norujukan'] ?? ''));
|
||||||
$nokp = trim((string) ($data['nokp'] ?? ''));
|
$nokp = trim((string) ($data['nokp'] ?? ''));
|
||||||
$pinjaman = round((float) ($data['pinjaman'] ?? 0), 2);
|
$pinjaman = round((float) ($data['pinjaman'] ?? 0), 2);
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateCawanganFeatureTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Master DB (mysql7) — per-cawangan feature flags.
|
||||||
|
*
|
||||||
|
* Missing row = off. Enable a pilot after migrate:
|
||||||
|
*
|
||||||
|
* INSERT INTO cawangan_feature (kodcaw, feature, enabled, created_at, updated_at)
|
||||||
|
* VALUES ('X0301', 'pembiayaan_online', 1, NOW(), NOW())
|
||||||
|
* ON DUPLICATE KEY UPDATE enabled = 1;
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if (!Schema::connection('mysql7')->hasTable('cawangan_feature')) {
|
||||||
|
Schema::connection('mysql7')->create('cawangan_feature', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->string('kodcaw', 20);
|
||||||
|
$table->string('feature', 64);
|
||||||
|
$table->tinyInteger('enabled')->default(0);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->unique(['kodcaw', 'feature'], 'uniq_cawangan_feature');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::connection('mysql7')->dropIfExists('cawangan_feature');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -240,6 +240,10 @@ $router->group(['prefix'=>'api'], function () use ($router){
|
|||||||
$router->get('cawangan/{code_cawangan}',['uses'=>'CawanganController@showOneCawangan']);
|
$router->get('cawangan/{code_cawangan}',['uses'=>'CawanganController@showOneCawangan']);
|
||||||
$router->get('cawangan/detail/{kodcaw}',['uses'=>'CawanganDetailController@getCawanganDetail']);
|
$router->get('cawangan/detail/{kodcaw}',['uses'=>'CawanganDetailController@getCawanganDetail']);
|
||||||
|
|
||||||
|
$router->get('features',['uses'=>'FeatureController@index']);
|
||||||
|
$router->get('features/cawangan',['uses'=>'FeatureController@cawangan']);
|
||||||
|
$router->put('features/{kodcaw}/{feature}',['uses'=>'FeatureController@update']);
|
||||||
|
|
||||||
//Poskod API
|
//Poskod API
|
||||||
$router->post('poskod',['uses'=>'PoskodController@store']);
|
$router->post('poskod',['uses'=>'PoskodController@store']);
|
||||||
$router->put('poskod/{poskod}/update',['uses'=>'PoskodController@update']);
|
$router->put('poskod/{poskod}/update',['uses'=>'PoskodController@update']);
|
||||||
|
|||||||
Reference in New Issue
Block a user