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
|
||||
|
||||
## 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;
|
||||
|
||||
use App\Cawangan;
|
||||
use App\Feature;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CawanganController extends Controller
|
||||
@@ -18,7 +19,15 @@ class CawanganController extends Controller
|
||||
$cawangan = Cawangan::on('mysql7')
|
||||
->where('kodcaw','=',$code_cawangan)
|
||||
->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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
use App\Cawangan;
|
||||
use App\Feature;
|
||||
use App\ModalOnline;
|
||||
use App\RequestModalOnline;
|
||||
use Carbon\Carbon;
|
||||
@@ -208,6 +209,10 @@ class ModalOnlineService
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
if (!Feature::enabled($kodcaw, Feature::PEMBIAYAAN_ONLINE)) {
|
||||
return Feature::denied('Pembiayaan online tidak diaktifkan untuk cawangan ini');
|
||||
}
|
||||
|
||||
$mysql = $resolved['mysql'];
|
||||
$amaun = round((float) $amaun, 2);
|
||||
|
||||
@@ -294,6 +299,10 @@ class ModalOnlineService
|
||||
}
|
||||
$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);
|
||||
$dimohonOleh = trim((string) $dimohonOleh);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Bank;
|
||||
use App\BatchPembiayaanOnline;
|
||||
use App\Cawangan;
|
||||
use App\Customer;
|
||||
use App\Feature;
|
||||
use App\Gadai;
|
||||
use App\PembiayaanOnline;
|
||||
use Carbon\Carbon;
|
||||
@@ -67,6 +68,10 @@ class PembiayaanOnlineService
|
||||
}
|
||||
$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'] ?? ''));
|
||||
$nokp = trim((string) ($data['nokp'] ?? ''));
|
||||
$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/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
|
||||
$router->post('poskod',['uses'=>'PoskodController@store']);
|
||||
$router->put('poskod/{poskod}/update',['uses'=>'PoskodController@update']);
|
||||
|
||||
Reference in New Issue
Block a user