chore: add spec-kit and standardize signatures
- Added GitHub spec-kit for development workflow - Standardized file signatures to Descomplicar® format - Updated development configuration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
804
src/includes/models/class-prescription.php
Normal file
804
src/includes/models/class-prescription.php
Normal file
@@ -0,0 +1,804 @@
|
||||
/**
|
||||
* Descomplicar® Crescimento Digital
|
||||
* https://descomplicar.pt
|
||||
*/
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Prescription Model
|
||||
*
|
||||
* Handles prescription operations and medication management
|
||||
*
|
||||
* @package KiviCare_API
|
||||
* @subpackage Models
|
||||
* @version 1.0.0
|
||||
* @author Descomplicar® <dev@descomplicar.pt>
|
||||
* @link https://descomplicar.pt
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
namespace KiviCare_API\Models;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Prescription
|
||||
*
|
||||
* Model for handling patient prescriptions and medication management
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Prescription {
|
||||
|
||||
/**
|
||||
* Database table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $table_name = 'kc_prescription';
|
||||
|
||||
/**
|
||||
* Prescription ID
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* Prescription data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $data = array();
|
||||
|
||||
/**
|
||||
* Required fields for prescription creation
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $required_fields = array(
|
||||
'encounter_id',
|
||||
'patient_id',
|
||||
'name',
|
||||
'frequency',
|
||||
'duration'
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int|array $prescription_id_or_data Prescription ID or data array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct( $prescription_id_or_data = null ) {
|
||||
if ( is_numeric( $prescription_id_or_data ) ) {
|
||||
$this->id = (int) $prescription_id_or_data;
|
||||
$this->load_data();
|
||||
} elseif ( is_array( $prescription_id_or_data ) ) {
|
||||
$this->data = $prescription_id_or_data;
|
||||
$this->id = isset( $this->data['id'] ) ? (int) $this->data['id'] : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load prescription data from database
|
||||
*
|
||||
* @return bool True on success, false on failure
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function load_data() {
|
||||
if ( ! $this->id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prescription_data = self::get_prescription_full_data( $this->id );
|
||||
|
||||
if ( $prescription_data ) {
|
||||
$this->data = $prescription_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new prescription
|
||||
*
|
||||
* @param array $prescription_data Prescription data
|
||||
* @return int|WP_Error Prescription ID on success, WP_Error on failure
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function create( $prescription_data ) {
|
||||
// Validate required fields
|
||||
$validation = self::validate_prescription_data( $prescription_data );
|
||||
if ( is_wp_error( $validation ) ) {
|
||||
return $validation;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
// Prepare data for insertion
|
||||
$insert_data = array(
|
||||
'encounter_id' => (int) $prescription_data['encounter_id'],
|
||||
'patient_id' => (int) $prescription_data['patient_id'],
|
||||
'name' => sanitize_textarea_field( $prescription_data['name'] ),
|
||||
'frequency' => sanitize_text_field( $prescription_data['frequency'] ),
|
||||
'duration' => sanitize_text_field( $prescription_data['duration'] ),
|
||||
'instruction' => isset( $prescription_data['instruction'] ) ? sanitize_textarea_field( $prescription_data['instruction'] ) : '',
|
||||
'added_by' => get_current_user_id(),
|
||||
'created_at' => current_time( 'mysql' ),
|
||||
'is_from_template' => isset( $prescription_data['is_from_template'] ) ? (int) $prescription_data['is_from_template'] : 0
|
||||
);
|
||||
|
||||
$result = $wpdb->insert( $table, $insert_data );
|
||||
|
||||
if ( $result === false ) {
|
||||
return new \WP_Error(
|
||||
'prescription_creation_failed',
|
||||
'Failed to create prescription: ' . $wpdb->last_error,
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
return $wpdb->insert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update prescription data
|
||||
*
|
||||
* @param int $prescription_id Prescription ID
|
||||
* @param array $prescription_data Updated prescription data
|
||||
* @return bool|WP_Error True on success, WP_Error on failure
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function update( $prescription_id, $prescription_data ) {
|
||||
if ( ! self::exists( $prescription_id ) ) {
|
||||
return new \WP_Error(
|
||||
'prescription_not_found',
|
||||
'Prescription not found',
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
// Prepare update data
|
||||
$update_data = array();
|
||||
$allowed_fields = array(
|
||||
'name', 'frequency', 'duration', 'instruction', 'is_from_template'
|
||||
);
|
||||
|
||||
foreach ( $allowed_fields as $field ) {
|
||||
if ( isset( $prescription_data[ $field ] ) ) {
|
||||
$value = $prescription_data[ $field ];
|
||||
|
||||
switch ( $field ) {
|
||||
case 'name':
|
||||
case 'instruction':
|
||||
$update_data[ $field ] = sanitize_textarea_field( $value );
|
||||
break;
|
||||
case 'is_from_template':
|
||||
$update_data[ $field ] = (int) $value;
|
||||
break;
|
||||
default:
|
||||
$update_data[ $field ] = sanitize_text_field( $value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $update_data ) ) {
|
||||
return new \WP_Error(
|
||||
'no_data_to_update',
|
||||
'No valid data provided for update',
|
||||
array( 'status' => 400 )
|
||||
);
|
||||
}
|
||||
|
||||
$result = $wpdb->update(
|
||||
$table,
|
||||
$update_data,
|
||||
array( 'id' => $prescription_id ),
|
||||
null,
|
||||
array( '%d' )
|
||||
);
|
||||
|
||||
if ( $result === false ) {
|
||||
return new \WP_Error(
|
||||
'prescription_update_failed',
|
||||
'Failed to update prescription: ' . $wpdb->last_error,
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a prescription
|
||||
*
|
||||
* @param int $prescription_id Prescription ID
|
||||
* @return bool|WP_Error True on success, WP_Error on failure
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function delete( $prescription_id ) {
|
||||
if ( ! self::exists( $prescription_id ) ) {
|
||||
return new \WP_Error(
|
||||
'prescription_not_found',
|
||||
'Prescription not found',
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$result = $wpdb->delete(
|
||||
$table,
|
||||
array( 'id' => $prescription_id ),
|
||||
array( '%d' )
|
||||
);
|
||||
|
||||
if ( $result === false ) {
|
||||
return new \WP_Error(
|
||||
'prescription_deletion_failed',
|
||||
'Failed to delete prescription: ' . $wpdb->last_error,
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prescription by ID
|
||||
*
|
||||
* @param int $prescription_id Prescription ID
|
||||
* @return array|null Prescription data or null if not found
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_by_id( $prescription_id ) {
|
||||
return self::get_prescription_full_data( $prescription_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all prescriptions with optional filtering
|
||||
*
|
||||
* @param array $args Query arguments
|
||||
* @return array Array of prescription data
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_all( $args = array() ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$defaults = array(
|
||||
'encounter_id' => null,
|
||||
'patient_id' => null,
|
||||
'search' => '',
|
||||
'limit' => 50,
|
||||
'offset' => 0,
|
||||
'orderby' => 'created_at',
|
||||
'order' => 'DESC'
|
||||
);
|
||||
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
$where_clauses = array( '1=1' );
|
||||
$where_values = array();
|
||||
|
||||
// Encounter filter
|
||||
if ( ! is_null( $args['encounter_id'] ) ) {
|
||||
$where_clauses[] = 'p.encounter_id = %d';
|
||||
$where_values[] = $args['encounter_id'];
|
||||
}
|
||||
|
||||
// Patient filter
|
||||
if ( ! is_null( $args['patient_id'] ) ) {
|
||||
$where_clauses[] = 'p.patient_id = %d';
|
||||
$where_values[] = $args['patient_id'];
|
||||
}
|
||||
|
||||
// Search filter
|
||||
if ( ! empty( $args['search'] ) ) {
|
||||
$where_clauses[] = '(p.name LIKE %s OR p.frequency LIKE %s OR p.instruction LIKE %s OR pt.first_name LIKE %s OR pt.last_name LIKE %s)';
|
||||
$search_term = '%' . $wpdb->esc_like( $args['search'] ) . '%';
|
||||
$where_values = array_merge( $where_values, array_fill( 0, 5, $search_term ) );
|
||||
}
|
||||
|
||||
$where_sql = implode( ' AND ', $where_clauses );
|
||||
|
||||
// Build query
|
||||
$query = "SELECT p.*,
|
||||
CONCAT(pt.first_name, ' ', pt.last_name) as patient_name,
|
||||
pt.user_email as patient_email,
|
||||
CONCAT(ab.first_name, ' ', ab.last_name) as added_by_name,
|
||||
e.encounter_date
|
||||
FROM {$table} p
|
||||
LEFT JOIN {$wpdb->prefix}users pt ON p.patient_id = pt.ID
|
||||
LEFT JOIN {$wpdb->prefix}users ab ON p.added_by = ab.ID
|
||||
LEFT JOIN {$wpdb->prefix}kc_patient_encounters e ON p.encounter_id = e.id
|
||||
WHERE {$where_sql}";
|
||||
|
||||
$query .= sprintf( ' ORDER BY p.%s %s',
|
||||
sanitize_sql_orderby( $args['orderby'] ),
|
||||
sanitize_sql_orderby( $args['order'] )
|
||||
);
|
||||
|
||||
$query .= $wpdb->prepare( ' LIMIT %d OFFSET %d', $args['limit'], $args['offset'] );
|
||||
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
|
||||
$prescriptions = $wpdb->get_results( $query, ARRAY_A );
|
||||
|
||||
return array_map( array( self::class, 'format_prescription_data' ), $prescriptions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prescription full data with related entities
|
||||
*
|
||||
* @param int $prescription_id Prescription ID
|
||||
* @return array|null Full prescription data or null if not found
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_prescription_full_data( $prescription_id ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$prescription = $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
"SELECT p.*,
|
||||
CONCAT(pt.first_name, ' ', pt.last_name) as patient_name,
|
||||
pt.user_email as patient_email,
|
||||
CONCAT(ab.first_name, ' ', ab.last_name) as added_by_name,
|
||||
e.encounter_date,
|
||||
CONCAT(d.first_name, ' ', d.last_name) as doctor_name
|
||||
FROM {$table} p
|
||||
LEFT JOIN {$wpdb->prefix}users pt ON p.patient_id = pt.ID
|
||||
LEFT JOIN {$wpdb->prefix}users ab ON p.added_by = ab.ID
|
||||
LEFT JOIN {$wpdb->prefix}kc_patient_encounters e ON p.encounter_id = e.id
|
||||
LEFT JOIN {$wpdb->prefix}users d ON e.doctor_id = d.ID
|
||||
WHERE p.id = %d",
|
||||
$prescription_id
|
||||
),
|
||||
ARRAY_A
|
||||
);
|
||||
|
||||
if ( ! $prescription ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::format_prescription_data( $prescription );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prescriptions by encounter
|
||||
*
|
||||
* @param int $encounter_id Encounter ID
|
||||
* @return array Array of prescriptions
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_by_encounter( $encounter_id ) {
|
||||
return self::get_all( array( 'encounter_id' => $encounter_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prescriptions by patient
|
||||
*
|
||||
* @param int $patient_id Patient ID
|
||||
* @param array $args Additional query arguments
|
||||
* @return array Array of prescriptions
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_by_patient( $patient_id, $args = array() ) {
|
||||
$args['patient_id'] = $patient_id;
|
||||
return self::get_all( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Search medications (for autocomplete)
|
||||
*
|
||||
* @param string $search_term Search term
|
||||
* @param int $limit Limit results
|
||||
* @return array Array of medication names
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function search_medications( $search_term, $limit = 20 ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
if ( empty( $search_term ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$medications = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT DISTINCT name, COUNT(*) as usage_count
|
||||
FROM {$table}
|
||||
WHERE name LIKE %s
|
||||
GROUP BY name
|
||||
ORDER BY usage_count DESC, name ASC
|
||||
LIMIT %d",
|
||||
'%' . $wpdb->esc_like( $search_term ) . '%',
|
||||
$limit
|
||||
),
|
||||
ARRAY_A
|
||||
);
|
||||
|
||||
return array_map( function( $med ) {
|
||||
return array(
|
||||
'name' => $med['name'],
|
||||
'usage_count' => (int) $med['usage_count']
|
||||
);
|
||||
}, $medications );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get most prescribed medications
|
||||
*
|
||||
* @param array $args Query arguments
|
||||
* @return array Array of top medications
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_top_medications( $args = array() ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$defaults = array(
|
||||
'limit' => 10,
|
||||
'date_from' => null,
|
||||
'date_to' => null,
|
||||
'doctor_id' => null,
|
||||
'patient_id' => null
|
||||
);
|
||||
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
$where_clauses = array( '1=1' );
|
||||
$where_values = array();
|
||||
|
||||
// Date range filters
|
||||
if ( ! is_null( $args['date_from'] ) ) {
|
||||
$where_clauses[] = 'p.created_at >= %s';
|
||||
$where_values[] = $args['date_from'] . ' 00:00:00';
|
||||
}
|
||||
|
||||
if ( ! is_null( $args['date_to'] ) ) {
|
||||
$where_clauses[] = 'p.created_at <= %s';
|
||||
$where_values[] = $args['date_to'] . ' 23:59:59';
|
||||
}
|
||||
|
||||
// Doctor filter (through encounter)
|
||||
if ( ! is_null( $args['doctor_id'] ) ) {
|
||||
$where_clauses[] = 'e.doctor_id = %d';
|
||||
$where_values[] = $args['doctor_id'];
|
||||
}
|
||||
|
||||
// Patient filter
|
||||
if ( ! is_null( $args['patient_id'] ) ) {
|
||||
$where_clauses[] = 'p.patient_id = %d';
|
||||
$where_values[] = $args['patient_id'];
|
||||
}
|
||||
|
||||
$where_sql = implode( ' AND ', $where_clauses );
|
||||
|
||||
$query = "SELECT p.name,
|
||||
COUNT(*) as prescription_count,
|
||||
COUNT(DISTINCT p.patient_id) as unique_patients,
|
||||
MAX(p.created_at) as last_prescribed
|
||||
FROM {$table} p";
|
||||
|
||||
if ( ! is_null( $args['doctor_id'] ) ) {
|
||||
$query .= " LEFT JOIN {$wpdb->prefix}kc_patient_encounters e ON p.encounter_id = e.id";
|
||||
}
|
||||
|
||||
$query .= " WHERE {$where_sql}
|
||||
GROUP BY p.name
|
||||
ORDER BY prescription_count DESC
|
||||
LIMIT %d";
|
||||
|
||||
$where_values[] = $args['limit'];
|
||||
|
||||
$medications = $wpdb->get_results(
|
||||
$wpdb->prepare( $query, $where_values ),
|
||||
ARRAY_A
|
||||
);
|
||||
|
||||
return array_map( function( $med ) {
|
||||
return array(
|
||||
'name' => $med['name'],
|
||||
'prescription_count' => (int) $med['prescription_count'],
|
||||
'unique_patients' => (int) $med['unique_patients'],
|
||||
'last_prescribed' => $med['last_prescribed']
|
||||
);
|
||||
}, $medications );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prescription templates
|
||||
*
|
||||
* @param array $args Query arguments
|
||||
* @return array Array of prescription templates
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_templates( $args = array() ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$defaults = array(
|
||||
'limit' => 50,
|
||||
'doctor_id' => null
|
||||
);
|
||||
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
$where_clauses = array( 'is_from_template = 1' );
|
||||
$where_values = array();
|
||||
|
||||
// Doctor filter
|
||||
if ( ! is_null( $args['doctor_id'] ) ) {
|
||||
$where_clauses[] = 'added_by = %d';
|
||||
$where_values[] = $args['doctor_id'];
|
||||
}
|
||||
|
||||
$where_sql = implode( ' AND ', $where_clauses );
|
||||
|
||||
$query = "SELECT name, frequency, duration, instruction,
|
||||
COUNT(*) as usage_count,
|
||||
MAX(created_at) as last_used
|
||||
FROM {$table}
|
||||
WHERE {$where_sql}
|
||||
GROUP BY name, frequency, duration, instruction
|
||||
ORDER BY usage_count DESC, last_used DESC
|
||||
LIMIT %d";
|
||||
|
||||
$where_values[] = $args['limit'];
|
||||
|
||||
$templates = $wpdb->get_results(
|
||||
empty( $where_values ) ?
|
||||
$wpdb->prepare( $query, $args['limit'] ) :
|
||||
$wpdb->prepare( $query, $where_values ),
|
||||
ARRAY_A
|
||||
);
|
||||
|
||||
return array_map( function( $template ) {
|
||||
return array(
|
||||
'name' => $template['name'],
|
||||
'frequency' => $template['frequency'],
|
||||
'duration' => $template['duration'],
|
||||
'instruction' => $template['instruction'],
|
||||
'usage_count' => (int) $template['usage_count'],
|
||||
'last_used' => $template['last_used']
|
||||
);
|
||||
}, $templates );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if prescription exists
|
||||
*
|
||||
* @param int $prescription_id Prescription ID
|
||||
* @return bool True if exists, false otherwise
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function exists( $prescription_id ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$count = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM {$table} WHERE id = %d",
|
||||
$prescription_id
|
||||
)
|
||||
);
|
||||
|
||||
return (int) $count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate prescription data
|
||||
*
|
||||
* @param array $prescription_data Prescription data to validate
|
||||
* @return bool|WP_Error True if valid, WP_Error if invalid
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function validate_prescription_data( $prescription_data ) {
|
||||
$errors = array();
|
||||
|
||||
// Check required fields
|
||||
foreach ( self::$required_fields as $field ) {
|
||||
if ( empty( $prescription_data[ $field ] ) ) {
|
||||
$errors[] = "Field '{$field}' is required";
|
||||
}
|
||||
}
|
||||
|
||||
// Validate entities exist
|
||||
if ( ! empty( $prescription_data['encounter_id'] ) &&
|
||||
! Encounter::exists( $prescription_data['encounter_id'] ) ) {
|
||||
$errors[] = 'Encounter not found';
|
||||
}
|
||||
|
||||
if ( ! empty( $prescription_data['patient_id'] ) &&
|
||||
! Patient::exists( $prescription_data['patient_id'] ) ) {
|
||||
$errors[] = 'Patient not found';
|
||||
}
|
||||
|
||||
// Validate medication name
|
||||
if ( ! empty( $prescription_data['name'] ) ) {
|
||||
if ( strlen( $prescription_data['name'] ) > 500 ) {
|
||||
$errors[] = 'Medication name is too long (max 500 characters)';
|
||||
}
|
||||
}
|
||||
|
||||
// Validate frequency format
|
||||
if ( ! empty( $prescription_data['frequency'] ) ) {
|
||||
if ( strlen( $prescription_data['frequency'] ) > 199 ) {
|
||||
$errors[] = 'Frequency is too long (max 199 characters)';
|
||||
}
|
||||
}
|
||||
|
||||
// Validate duration format
|
||||
if ( ! empty( $prescription_data['duration'] ) ) {
|
||||
if ( strlen( $prescription_data['duration'] ) > 199 ) {
|
||||
$errors[] = 'Duration is too long (max 199 characters)';
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $errors ) ) {
|
||||
return new \WP_Error(
|
||||
'prescription_validation_failed',
|
||||
'Prescription validation failed',
|
||||
array(
|
||||
'status' => 400,
|
||||
'errors' => $errors
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format prescription data for API response
|
||||
*
|
||||
* @param array $prescription_data Raw prescription data
|
||||
* @return array Formatted prescription data
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function format_prescription_data( $prescription_data ) {
|
||||
if ( ! $prescription_data ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$formatted = array(
|
||||
'id' => (int) $prescription_data['id'],
|
||||
'name' => $prescription_data['name'],
|
||||
'frequency' => $prescription_data['frequency'],
|
||||
'duration' => $prescription_data['duration'],
|
||||
'instruction' => $prescription_data['instruction'],
|
||||
'is_from_template' => (bool) $prescription_data['is_from_template'],
|
||||
'created_at' => $prescription_data['created_at'],
|
||||
'encounter' => array(
|
||||
'id' => (int) $prescription_data['encounter_id'],
|
||||
'encounter_date' => $prescription_data['encounter_date'] ?? null
|
||||
),
|
||||
'patient' => array(
|
||||
'id' => (int) $prescription_data['patient_id'],
|
||||
'name' => $prescription_data['patient_name'] ?? '',
|
||||
'email' => $prescription_data['patient_email'] ?? ''
|
||||
),
|
||||
'added_by' => array(
|
||||
'id' => (int) $prescription_data['added_by'],
|
||||
'name' => $prescription_data['added_by_name'] ?? ''
|
||||
),
|
||||
'doctor_name' => $prescription_data['doctor_name'] ?? ''
|
||||
);
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prescription statistics
|
||||
*
|
||||
* @param array $filters Optional filters
|
||||
* @return array Prescription statistics
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function get_statistics( $filters = array() ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . self::$table_name;
|
||||
|
||||
$where_clauses = array( '1=1' );
|
||||
$where_values = array();
|
||||
|
||||
if ( ! empty( $filters['patient_id'] ) ) {
|
||||
$where_clauses[] = 'patient_id = %d';
|
||||
$where_values[] = $filters['patient_id'];
|
||||
}
|
||||
|
||||
if ( ! empty( $filters['doctor_id'] ) ) {
|
||||
$where_clauses[] = 'added_by = %d';
|
||||
$where_values[] = $filters['doctor_id'];
|
||||
}
|
||||
|
||||
$where_sql = implode( ' AND ', $where_clauses );
|
||||
|
||||
$stats = array(
|
||||
'total_prescriptions' => 0,
|
||||
'unique_medications' => 0,
|
||||
'prescriptions_today' => 0,
|
||||
'prescriptions_this_week' => 0,
|
||||
'prescriptions_this_month' => 0,
|
||||
'template_prescriptions' => 0,
|
||||
'avg_prescriptions_per_encounter' => 0
|
||||
);
|
||||
|
||||
// Total prescriptions
|
||||
$query = "SELECT COUNT(*) FROM {$table} WHERE {$where_sql}";
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
$stats['total_prescriptions'] = (int) $wpdb->get_var( $query );
|
||||
|
||||
// Unique medications
|
||||
$query = "SELECT COUNT(DISTINCT name) FROM {$table} WHERE {$where_sql}";
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
$stats['unique_medications'] = (int) $wpdb->get_var( $query );
|
||||
|
||||
// Prescriptions today
|
||||
$today_where = array_merge( $where_clauses, array( 'DATE(created_at) = CURDATE()' ) );
|
||||
$query = "SELECT COUNT(*) FROM {$table} WHERE " . implode( ' AND ', $today_where );
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
$stats['prescriptions_today'] = (int) $wpdb->get_var( $query );
|
||||
|
||||
// Prescriptions this week
|
||||
$week_where = array_merge( $where_clauses, array(
|
||||
'WEEK(created_at) = WEEK(CURDATE())',
|
||||
'YEAR(created_at) = YEAR(CURDATE())'
|
||||
) );
|
||||
$query = "SELECT COUNT(*) FROM {$table} WHERE " . implode( ' AND ', $week_where );
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
$stats['prescriptions_this_week'] = (int) $wpdb->get_var( $query );
|
||||
|
||||
// Prescriptions this month
|
||||
$month_where = array_merge( $where_clauses, array(
|
||||
'MONTH(created_at) = MONTH(CURDATE())',
|
||||
'YEAR(created_at) = YEAR(CURDATE())'
|
||||
) );
|
||||
$query = "SELECT COUNT(*) FROM {$table} WHERE " . implode( ' AND ', $month_where );
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
$stats['prescriptions_this_month'] = (int) $wpdb->get_var( $query );
|
||||
|
||||
// Template prescriptions
|
||||
$template_where = array_merge( $where_clauses, array( 'is_from_template = 1' ) );
|
||||
$query = "SELECT COUNT(*) FROM {$table} WHERE " . implode( ' AND ', $template_where );
|
||||
if ( ! empty( $where_values ) ) {
|
||||
$query = $wpdb->prepare( $query, $where_values );
|
||||
}
|
||||
$stats['template_prescriptions'] = (int) $wpdb->get_var( $query );
|
||||
|
||||
// Average prescriptions per encounter
|
||||
if ( $stats['total_prescriptions'] > 0 ) {
|
||||
$unique_encounters = $wpdb->get_var(
|
||||
"SELECT COUNT(DISTINCT encounter_id) FROM {$table} WHERE {$where_sql}"
|
||||
);
|
||||
if ( $unique_encounters > 0 ) {
|
||||
$stats['avg_prescriptions_per_encounter'] = round( $stats['total_prescriptions'] / $unique_encounters, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user