Skip to content
Kenya Coffee School

Kenya Coffee School

Teaching Coffee from #farm to #cup

  • Thika, Opposite Thika Gateway Plaza
  • +254 707 503 647 or Call +254 704 375 390
  • info@kenyacoffeeschool.golearn.co.ke
  • Home
  • Kenya coffee school – the best barista and specialty coffee school
  • KCS Info Hub
    • KCS/SCA Franchise Guidelines
      • Coffee Cupping Sensory Drills – organic acids
    • KCS Blogs
      • Kenya Coffee School – KCS & SCA Sensory Skills & Cupping Guide
        • Kenya Coffee School – Barista Skills Guide 4 weeks
        • KCS Coffee Cupping – Importance of Skimming
        • University of Coffee – MicroMasters in Coffee
    • Enroll Today
      • Kenya Coffee School Year 2026 Fee Structure
      • KCS Certification Exams
        • Exam Results :
      • More Professional Courses
        • Mixology and Bartending Course
    • Coffee Careers & Barista Jobs
    • Location and Directions
  • About KCS
    • Kenya Coffee School (KCS) Training Framework
    • Kenya Coffee School Founder
  • Projects
    • Kenya Youth & Women Coffee Farmers Innovation Hub (KYWCH)
    • Nairobi Coffee School(NCS)
  • Barista Mtaani Project
    • Barista Mtaani Education
  • Barista Mtaani Project
    • Marketplace
      • How Alfred Gitau Mwaura Built Kenya’s First Affordable Local Coffee Roaster
        • KCS – Specialty Coffee Academies (SCA)
      • Global Coffee Association (GCA) Certification Framework
        • GCA Certification Blockchain Integration Framework
        • GCA Tokenomics & Smart Contract Architecture
        • GCA Governance & IOT Design
        • GCA Coin Valuation & Stability Mechanism
        • KCS (Knowledge of Coffee Skills)
        • For Blockchain Tipping :
      • Direct Coffee Farmer Tipping System
      • GCA Certification
    • Barista Mtaani Coffee Auctions
  • Certifications
    • Volunteers in Coffee and Tea Tourism
    • Agroecosystems Kenya Coffee Project – by KCS
    • Kenya Coffee School – K.C.S (Knowledge of Coffee Skills) Certifications
    • Kenya Coffee School – Training on Digitalisation
    • Mixology & Bartending by Kenya Coffee School (KCS)
  • KCS Education
  • Shop at Kenya Coffee School
    • Coffee equipments, tools, and services offered by Kenya Coffee School
  • Why Train at Kenya Coffee School
    • Nairobi Coffee School(NCS) Hub2
    • Barista Mtaani for Juniors (BM4J Program)
    • Coffee & Business MBA
    • Kenya Youth & Women Coffee Farmers Innovation Hub (KYWCH)
    • Global Barista and Coffee Education
    • Kenya Coffee School Research Portfolio
  • Kenya Coffee Association: Brewing a Future Beyond the Cup
    • Kenya Barista Association
  • 2025 to 2030 KCS Courses and Programs
    • Kenya Coffee School: Barista Skills & Specialty Coffee Courses
    • More KCS Courses
      • The KCS Diploma in Gastronomic Sciences
        • 🎓 Diploma in Gastronomic Sciences in 12 Months
      • Fundamentals of Pastry & Confectionaries (MCP)
      • Applied Sciences in Coffee, Biodiversity & Sustainability
      • Learn Specialty Coffee & Agroecology
      • Managing Innovation Course at KCS
      • Kenya Coffee School – Mixology & Bartending Course
      • Coffee Open Data Courses at Kenya Coffee School
  • KCS Research Projects
    • Apply Global™ Milestones: A Decade of Impact
      • APPLY GLOBAL: Revolutionizing Hiring with Embedded QR-Powered e-Resumes
  • Mixology & Bartender Courses
  • News and Events Blog
    • Market Insights by Kenya Coffee School
  • Official Disclaimer — Kenya Coffee School
  • Transforming the Coffee Value Chain for Women and Youth
  • Kenya Coffee School App Download
KCS™ OSE™ 0

KCS Sandbox mode

Open Skills Education (OSE™)

Open Skills Education (OSE™) is a global skills equity framework

Open Skills Education (OSE™)

Open Skills Education (OSE™) Founding Charter Open Skills Education (OSE™)...

Blockchain Verification

Transaction Hash: 0x000…000

Block Number: –

Timestamp: –

Network: Polygon

Credential Hash: sha256-…

Excellent! You’ve created a perfect WordPress plugin foundation for **Barista Mtaani**. I’ll now add the complete approval workflow, public verification, and badge system to this plugin. ## 🚀 **NEXT: COMPLETE APPROVAL WORKFLOW + PUBLIC VERIFICATION** Here’s the **enhanced Barista Mtaani plugin** with all features from our unified credential system: ### **Updated Main Plugin File:** “`php get_charset_collate(); // Main Registry Table $table = $wpdb->prefix . BM_TABLE_PREFIX . ‘registry’; $sql = “CREATE TABLE $table ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, professional_id VARCHAR(50) NOT NULL, full_name VARCHAR(200) NOT NULL, email VARCHAR(200), phone VARCHAR(20), system VARCHAR(50) DEFAULT ‘SCB’, credential VARCHAR(200), level VARCHAR(50), issue_date DATE, expiry_date DATE, status VARCHAR(30) DEFAULT ‘pending’, registered_by VARCHAR(100), registered_date DATETIME DEFAULT CURRENT_TIMESTAMP, approved_by VARCHAR(100), approved_date DATETIME, revocation_reason TEXT, revoked_date DATETIME, badge_type VARCHAR(50), badge_image VARCHAR(500), qr_code VARCHAR(500), tx_hash VARCHAR(100), blockchain_network VARCHAR(50), metadata JSON, PRIMARY KEY (id), UNIQUE KEY professional_id (professional_id), KEY status (status), KEY system (system), KEY email (email) ) $charset;”; dbDelta( $sql ); // Audit Log Table $table = $wpdb->prefix . BM_TABLE_PREFIX . ‘audit_log’; $sql = “CREATE TABLE $table ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, action VARCHAR(100), professional_id VARCHAR(50), performed_by VARCHAR(100), user_ip VARCHAR(45), details TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY action (action), KEY professional_id (professional_id) ) $charset;”; dbDelta( $sql ); // Blockchain Transactions $table = $wpdb->prefix . BM_TABLE_PREFIX . ‘blockchain_tx’; $sql = “CREATE TABLE $table ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, tx_hash VARCHAR(100), professional_id VARCHAR(50), network VARCHAR(50), block_number BIGINT, timestamp DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY tx_hash (tx_hash) ) $charset;”; dbDelta( $sql ); // Create default user roles self::create_roles(); } private static function create_roles() { // Registrar Role add_role( ‘bm_registrar’, __( ‘Barista Mtaani Registrar’, ‘barista-mtaani’ ), [ ‘read’ => true, ‘manage_bm_registry’ => true, ] ); // Approver Role add_role( ‘bm_approver’, __( ‘Barista Mtaani Approver’, ‘barista-mtaani’ ), [ ‘read’ => true, ‘manage_bm_approvals’ => true, ‘manage_bm_registry’ => true, ] ); // Add capabilities to admin $admin = get_role( ‘administrator’ ); if ( $admin ) { $admin->add_cap( ‘manage_bm_registry’ ); $admin->add_cap( ‘manage_bm_approvals’ ); $admin->add_cap( ‘manage_bm_settings’ ); } } public static function create_pages() { // Verification Page $verify_page = [ ‘post_title’ => ‘Verify Credential’, ‘post_content’ => ‘[bm_verify_credential]’, ‘post_status’ => ‘publish’, ‘post_type’ => ‘page’, ‘post_name’ => ‘verify-credential’, ]; $verify_id = wp_insert_post( $verify_page ); update_option( ‘bm_verify_page_id’, $verify_id ); // Public Registry Page $registry_page = [ ‘post_title’ => ‘Professional Registry’, ‘post_content’ => ‘[bm_public_registry]’, ‘post_status’ => ‘publish’, ‘post_type’ => ‘page’, ‘post_name’ => ‘professional-registry’, ]; $registry_id = wp_insert_post( $registry_page ); update_option( ‘bm_registry_page_id’, $registry_id ); } } “` ### **Database Handler Class:** “`php wpdb = $wpdb; $this->registry_table = $wpdb->prefix . BM_TABLE_PREFIX . ‘registry’; $this->audit_table = $wpdb->prefix . BM_TABLE_PREFIX . ‘audit_log’; $this->blockchain_table = $wpdb->prefix . BM_TABLE_PREFIX . ‘blockchain_tx’; } public function add_professional( $data ) { $defaults = [ ‘professional_id’ => $this->generate_professional_id(), ‘status’ => ‘pending’, ‘registered_date’ => current_time( ‘mysql’ ), ‘registered_by’ => get_current_user_id(), ]; $data = wp_parse_args( $data, $defaults ); $result = $this->wpdb->insert( $this->registry_table, $data ); if ( $result ) { $this->log_audit( ‘CREATE_PROFESSIONAL’, $data[‘professional_id’], ‘New professional registered’ ); return $data[‘professional_id’]; } return false; } public function update_professional( $professional_id, $data ) { $result = $this->wpdb->update( $this->registry_table, $data, [ ‘professional_id’ => $professional_id ] ); if ( $result ) { $this->log_audit( ‘UPDATE_PROFESSIONAL’, $professional_id, ‘Professional updated’ ); } return $result; } public function approve_professional( $professional_id, $approver_id ) { $data = [ ‘status’ => ‘active’, ‘approved_by’ => $approver_id, ‘approved_date’ => current_time( ‘mysql’ ), ]; return $this->update_professional( $professional_id, $data ); } public function revoke_professional( $professional_id, $reason ) { $data = [ ‘status’ => ‘revoked’, ‘revocation_reason’ => $reason, ‘revoked_date’ => current_time( ‘mysql’ ), ]; return $this->update_professional( $professional_id, $data ); } public function get_professional( $professional_id ) { return $this->wpdb->get_row( $this->wpdb->prepare( “SELECT * FROM $this->registry_table WHERE professional_id = %s”, $professional_id ) ); } public function get_pending_professionals() { return $this->wpdb->get_results( “SELECT * FROM $this->registry_table WHERE status = ‘pending’ ORDER BY registered_date DESC” ); } public function get_active_professionals( $system = ” ) { $where = “status = ‘active'”; if ( $system ) { $where .= $this->wpdb->prepare( ” AND system = %s”, $system ); } return $this->wpdb->get_results( “SELECT * FROM $this->registry_table WHERE $where ORDER BY approved_date DESC” ); } public function search_professionals( $search_term ) { return $this->wpdb->get_results( $this->wpdb->prepare( “SELECT * FROM $this->registry_table WHERE (professional_id LIKE %s OR full_name LIKE %s OR email LIKE %s) AND status = ‘active'”, “%$search_term%”, “%$search_term%”, “%$search_term%” ) ); } public function get_stats() { $stats = [ ‘total’ => $this->wpdb->get_var( “SELECT COUNT(*) FROM $this->registry_table” ), ‘pending’ => $this->wpdb->get_var( “SELECT COUNT(*) FROM $this->registry_table WHERE status = ‘pending'” ), ‘active’ => $this->wpdb->get_var( “SELECT COUNT(*) FROM $this->registry_table WHERE status = ‘active'” ), ‘revoked’ => $this->wpdb->get_var( “SELECT COUNT(*) FROM $this->registry_table WHERE status = ‘revoked'” ), ‘scb’ => $this->wpdb->get_var( $this->wpdb->prepare( “SELECT COUNT(*) FROM $this->registry_table WHERE system = %s AND status = ‘active'”, ‘SCB’ ) ), ‘kcs_ou’ => $this->wpdb->get_var( $this->wpdb->prepare( “SELECT COUNT(*) FROM $this->registry_table WHERE system = %s AND status = ‘active'”, ‘KCS-OU’ ) ), ‘sca’ => $this->wpdb->get_var( $this->wpdb->prepare( “SELECT COUNT(*) FROM $this->registry_table WHERE system = %s AND status = ‘active'”, ‘SCA’ ) ), ]; return $stats; } private function generate_professional_id() { $prefix = ‘SCB’; $year = date( ‘Y’ ); $random = strtoupper( wp_generate_password( 6, false ) ); return “$prefix-$year-$random”; } public function log_audit( $action, $professional_id, $details ) { $data = [ ‘action’ => $action, ‘professional_id’ => $professional_id, ‘performed_by’ => get_current_user_id(), ‘user_ip’ => $_SERVER[‘REMOTE_ADDR’] ?? ”, ‘details’ => $details, ]; return $this->wpdb->insert( $this->audit_table, $data ); } public function get_audit_log( $limit = 50 ) { return $this->wpdb->get_results( $this->wpdb->prepare( “SELECT * FROM $this->audit_table ORDER BY timestamp DESC LIMIT %d”, $limit ) ); } public function add_blockchain_tx( $professional_id, $tx_hash, $network = ‘polygon’ ) { $data = [ ‘professional_id’ => $professional_id, ‘tx_hash’ => $tx_hash, ‘network’ => $network, ‘created_at’ => current_time( ‘mysql’ ), ]; // Also update the professional record $this->update_professional( $professional_id, [ ‘tx_hash’ => $tx_hash, ‘blockchain_network’ => $network, ] ); return $this->wpdb->insert( $this->blockchain_table, $data ); } public function get_blockchain_txs( $limit = 20 ) { return $this->wpdb->get_results( $this->wpdb->prepare( “SELECT * FROM $this->blockchain_table ORDER BY created_at DESC LIMIT %d”, $limit ) ); } } “` ### **Enhanced Admin Class with Complete UI:** “`php db = BM_Database::get_instance(); add_action( ‘admin_menu’, [ $this, ‘register_menu’ ] ); add_action( ‘admin_enqueue_scripts’, [ $this, ‘enqueue_assets’ ] ); add_action( ‘admin_init’, [ $this, ‘handle_actions’ ] ); add_action( ‘wp_ajax_bm_approve_professional’, [ $this, ‘ajax_approve_professional’ ] ); add_action( ‘wp_ajax_bm_revoke_professional’, [ $this, ‘ajax_revoke_professional’ ] ); } public function register_menu() { add_menu_page( ‘Barista Mtaani’, ‘Barista Mtaani’, ‘manage_bm_registry’, ‘barista-mtaani’, [ $this, ‘dashboard_page’ ], ‘dashicons-coffee’, 26 ); add_submenu_page( ‘barista-mtaani’, ‘Dashboard’, ‘Dashboard’, ‘manage_bm_registry’, ‘barista-mtaani’, [ $this, ‘dashboard_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Add Professional’, ‘Add Professional’, ‘manage_bm_registry’, ‘barista-mtaani-add’, [ $this, ‘add_professional_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Pending Approval’, ‘Pending Approval’, ‘manage_bm_approvals’, ‘barista-mtaani-pending’, [ $this, ‘pending_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Professional Registry’, ‘Registry’, ‘manage_bm_registry’, ‘barista-mtaani-registry’, [ $this, ‘registry_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Revoked Credentials’, ‘Revoked’, ‘manage_bm_approvals’, ‘barista-mtaani-revoked’, [ $this, ‘revoked_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Audit Log’, ‘Audit Log’, ‘manage_bm_approvals’, ‘barista-mtaani-audit’, [ $this, ‘audit_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Blockchain’, ‘Blockchain’, ‘manage_bm_settings’, ‘barista-mtaani-blockchain’, [ $this, ‘blockchain_page’ ] ); add_submenu_page( ‘barista-mtaani’, ‘Settings’, ‘Settings’, ‘manage_bm_settings’, ‘barista-mtaani-settings’, [ $this, ‘settings_page’ ] ); } public function enqueue_assets( $hook ) { if ( strpos( $hook, ‘barista-mtaani’ ) === false ) { return; } wp_enqueue_style( ‘bm-admin-css’, BM_PLUGIN_URL . ‘assets/css/admin.css’, [], BM_VERSION ); wp_enqueue_script( ‘bm-admin-js’, BM_PLUGIN_URL . ‘assets/js/admin.js’, [ ‘jquery’, ‘wp-util’ ], BM_VERSION, true ); wp_localize_script( ‘bm-admin-js’, ‘bm_ajax’, [ ‘ajax_url’ => admin_url( ‘admin-ajax.php’ ), ‘nonce’ => wp_create_nonce( ‘bm_admin_nonce’ ), ]); } public function dashboard_page() { $stats = $this->db->get_stats(); $recent = $this->db->get_active_professionals(); $recent = array_slice( $recent, 0, 5 ); include BM_PLUGIN_DIR . ‘templates/admin/dashboard.php’; } public function add_professional_page() { if ( $_SERVER[‘REQUEST_METHOD’] === ‘POST’ && isset( $_POST[‘bm_add_professional’] ) ) { $this->handle_add_professional(); } include BM_PLUGIN_DIR . ‘templates/admin/add-professional.php’; } public function pending_page() { $pending = $this->db->get_pending_professionals(); include BM_PLUGIN_DIR . ‘templates/admin/pending.php’; } public function registry_page() { $system = isset( $_GET[‘system’] ) ? sanitize_text_field( $_GET[‘system’] ) : ”; $professionals = $this->db->get_active_professionals( $system ); include BM_PLUGIN_DIR . ‘templates/admin/registry.php’; } public function revoked_page() { $revoked = $this->db->get_active_professionals(); // Need to filter for revoked include BM_PLUGIN_DIR . ‘templates/admin/revoked.php’; } public function audit_page() { $audit_log = $this->db->get_audit_log(); include BM_PLUGIN_DIR . ‘templates/admin/audit.php’; } public function blockchain_page() { $txs = $this->db->get_blockchain_txs(); include BM_PLUGIN_DIR . ‘templates/admin/blockchain.php’; } public function settings_page() { include BM_PLUGIN_DIR . ‘templates/admin/settings.php’; } private function handle_add_professional() { $data = [ ‘full_name’ => sanitize_text_field( $_POST[‘full_name’] ), ’email’ => sanitize_email( $_POST[’email’] ), ‘phone’ => sanitize_text_field( $_POST[‘phone’] ), ‘system’ => sanitize_text_field( $_POST[‘system’] ), ‘credential’ => sanitize_text_field( $_POST[‘credential’] ), ‘level’ => sanitize_text_field( $_POST[‘level’] ), ‘issue_date’ => sanitize_text_field( $_POST[‘issue_date’] ), ‘expiry_date’ => sanitize_text_field( $_POST[‘expiry_date’] ), ‘badge_type’ => sanitize_text_field( $_POST[‘badge_type’] ), ]; $professional_id = $this->db->add_professional( $data ); if ( $professional_id ) { wp_redirect( admin_url( ‘admin.php?page=barista-mtaani-pending&added=’ . $professional_id ) ); exit; } } public function ajax_approve_professional() { check_ajax_referer( ‘bm_admin_nonce’, ‘nonce’ ); $professional_id = sanitize_text_field( $_POST[‘professional_id’] ); $result = $this->db->approve_professional( $professional_id, get_current_user_id() ); if ( $result ) { wp_send_json_success( [ ‘message’ => ‘Professional approved successfully!’ ] ); } else { wp_send_json_error( [ ‘message’ => ‘Failed to approve professional.’ ] ); } } public function ajax_revoke_professional() { check_ajax_referer( ‘bm_admin_nonce’, ‘nonce’ ); $professional_id = sanitize_text_field( $_POST[‘professional_id’] ); $reason = sanitize_text_field( $_POST[‘reason’] ); $result = $this->db->revoke_professional( $professional_id, $reason ); if ( $result ) { wp_send_json_success( [ ‘message’ => ‘Professional revoked successfully!’ ] ); } else { wp_send_json_error( [ ‘message’ => ‘Failed to revoke professional.’ ] ); } } private function handle_actions() { if ( ! isset( $_GET[‘page’] ) || strpos( $_GET[‘page’], ‘barista-mtaani’ ) === false ) { return; } // Handle bulk actions if ( isset( $_POST[‘bm_bulk_action’] ) && isset( $_POST[‘bm_professionals’] ) ) { $this->handle_bulk_actions(); } } private function handle_bulk_actions() { $action = sanitize_text_field( $_POST[‘bm_bulk_action’] ); $professionals = array_map( ‘sanitize_text_field’, $_POST[‘bm_professionals’] ); foreach ( $professionals as $professional_id ) { switch ( $action ) { case ‘approve’: $this->db->approve_professional( $professional_id, get_current_user_id() ); break; case ‘revoke’: $this->db->revoke_professional( $professional_id, ‘Bulk revocation’ ); break; } } wp_redirect( add_query_arg( ‘bulk_updated’, count( $professionals ), wp_get_referer() ) ); exit; } } “` ### **Public & Shortcodes Classes:** “`php db = BM_Database::get_instance(); add_action( ‘wp_enqueue_scripts’, [ $this, ‘enqueue_public_assets’ ] ); } public function enqueue_public_assets() { if ( is_page( get_option( ‘bm_verify_page_id’ ) ) || is_page( get_option( ‘bm_registry_page_id’ ) ) ) { wp_enqueue_style( ‘bm-public-css’, BM_PLUGIN_URL . ‘assets/css/public.css’, [], BM_VERSION ); wp_enqueue_script( ‘bm-public-js’, BM_PLUGIN_URL . ‘assets/js/public.js’, [ ‘jquery’ ], BM_VERSION, true ); } } } // includes/class-bm-shortcodes.php if ( ! defined( ‘ABSPATH’ ) ) exit; class BM_Shortcodes { private $db; public function __construct() { $this->db = BM_Database::get_instance(); add_shortcode( ‘bm_verify_credential’, [ $this, ‘verify_credential_shortcode’ ] ); add_shortcode( ‘bm_public_registry’, [ $this, ‘public_registry_shortcode’ ] ); add_shortcode( ‘bm_professional_badge’, [ $this, ‘professional_badge_shortcode’ ] ); } public function verify_credential_shortcode() { ob_start(); $professional_id = isset( $_GET[‘id’] ) ? sanitize_text_field( $_GET[‘id’] ) : ”; if ( $professional_id ) { $professional = $this->db->get_professional( $professional_id ); include BM_PLUGIN_DIR . ‘templates/public/verify-result.php’; } else { include BM_PLUGIN_DIR . ‘templates/public/verify-form.php’; } return ob_get_clean(); } public function public_registry_shortcode() { ob_start(); $search = isset( $_GET[‘search’] ) ? sanitize_text_field( $_GET[‘search’] ) : ”; $system = isset( $_GET[‘system’] ) ? sanitize_text_field( $_GET[‘system’] ) : ”; if ( $search ) { $professionals = $this->db->search_professionals( $search ); } else { $professionals = $this->db->get_active_professionals( $system ); } include BM_PLUGIN_DIR . ‘templates/public/registry.php’; return ob_get_clean(); } public function professional_badge_shortcode( $atts ) { $atts = shortcode_atts( [ ‘id’ => ”, ‘size’ => ‘medium’, ‘show_qr’ => ‘yes’, ], $atts, ‘bm_professional_badge’ ); if ( ! $atts[‘id’] ) { return ‘

Please provide a professional ID

‘; } $professional = $this->db->get_professional( $atts[‘id’] ); if ( ! $professional ) { return ‘

Professional not found

‘; } ob_start(); include BM_PLUGIN_DIR . ‘templates/public/badge.php’; return ob_get_clean(); } } // includes/class-bm-api.php if ( ! defined( ‘ABSPATH’ ) ) exit; class BM_API { private $db; public function __construct() { $this->db = BM_Database::get_instance(); add_action( ‘rest_api_init’, [ $this, ‘register_routes’ ] ); } public function register_routes() { register_rest_route( ‘barista-mtaani/v1’, ‘/verify/(?P[a-zA-Z0-9\-]+)’, [ ‘methods’ => ‘GET’, ‘callback’ => [ $this, ‘verify_credential’ ], ‘permission_callback’ => ‘__return_true’, ] ); register_rest_route( ‘barista-mtaani/v1’, ‘/registry’, [ ‘methods’ => ‘GET’, ‘callback’ => [ $this, ‘get_registry’ ], ‘permission_callback’ => ‘__return_true’, ] ); register_rest_route( ‘barista-mtaani/v1’, ‘/stats’, [ ‘methods’ => ‘GET’, ‘callback’ => [ $this, ‘get_stats’ ], ‘permission_callback’ => ‘__return_true’, ] ); } public function verify_credential( $request ) { $id = $request[‘id’]; $professional = $this->db->get_professional( $id ); if ( ! $professional ) { return new WP_Error( ‘not_found’, ‘Credential not found’, [ ‘status’ => 404 ] ); } return rest_ensure_response( [ ‘id’ => $professional->professional_id, ‘name’ => $professional->full_name, ‘credential’ => $professional->credential, ‘system’ => $professional->system, ‘level’ => $professional->level, ‘status’ => $professional->status, ‘issue_date’ => $professional->issue_date, ‘blockchain_verified’ => ! empty( $professional->tx_hash ), ] ); } public function get_registry( $request ) { $system = $request->get_param( ‘system’ ); $professionals = $this->db->get_active_professionals( $system ); $data = array_map( function( $pro ) { return [ ‘id’ => $pro->professional_id, ‘name’ => $pro->full_name, ‘credential’ => $pro->credential, ‘system’ => $pro->system, ‘level’ => $pro->level, ‘issue_date’ => $pro->issue_date, ]; }, $professionals ); return rest_ensure_response( $data ); } public function get_stats() { $stats = $this->db->get_stats(); return rest_ensure_response( $stats ); } } “` ### **Create Template Files:** Create these template files in a `templates/` directory: **templates/admin/dashboard.php** “`php

☕ Barista Mtaani Dashboard

Total Professionals

Pending Approval

Active Credentials

SCB Professionals

Recent Approvals

IDNameCredentialSystemApproved
professional_id; ?>full_name; ?>credential; ?>

Barista Mtaani

Professional Credential Verification

Awarded to: full_name ); ?>

Credential ID:

professional_id ); ?>

System:

system ); ?>

Issued:

issue_date ) ); ?>

Level:

level ); ?>

tx_hash ): ?>

Blockchain Verified

Scan QR code to verify

Credential Not Found

The credential ID “” was not found in our registry.

Try Another ID
“` ### **Enhanced Admin CSS:** “`css /* assets/css/admin.css */ .bm-dashboard-cards { display
KENYA COFFEE SCHOOL SKILLS CERTIFICATE / DIPLOMA
#Powered by GoLearn
Kenya Coffee School



@kenyacoffeeschool
BCSTTI

  • TikTok
  • Instagram
  • Mail
  • Facebook

Copyright 2025 ©Kenya Coffee School ©Golearn ©Lavazza Coffee Center ©Specialty Coffee Academies ©Specialty Coffee Barista ©Open Skills Education ©Barista Mtaani
  • Home
  • Kenya coffee school – the best barista and specialty coffee school
  • KCS Info Hub
  • About KCS
  • Projects
  • Barista Mtaani Project
  • Barista Mtaani Project
  • Certifications
  • KCS Education
  • Shop at Kenya Coffee School
  • Why Train at Kenya Coffee School
  • Kenya Coffee Association: Brewing a Future Beyond the Cup
  • 2025 to 2030 KCS Courses and Programs
  • KCS Research Projects
  • Mixology & Bartender Courses
  • News and Events Blog
  • Official Disclaimer — Kenya Coffee School
  • Transforming the Coffee Value Chain for Women and Youth
  • Kenya Coffee School App Download
Kenya Coffee School Barista School at GoLearn