Complete Guide to Multi-Warehouse Pharmacy & Floor Stock Setup in SIMRS
T
Kembali ke Blog

Complete Guide to Multi-Warehouse Pharmacy & Floor Stock Setup in SIMRS

Industri Kesehatan
Tim Pilar Inovasi 11 Sep 2026 15 min baca 3,496 kata 130
Manage hospital drug stock more efficiently with this guide to multi-warehouse pharmacy and floor stock setup in SIMRS. This article covers the concepts, technical implementation, and best practices for optimizing pharmacy inventory.

Pharmaceutical inventory management in hospitals, especially large-scale ones with hundreds of beds and various service units, is often a complex operational challenge. Problems such as unused drug stock piling up, expired drugs that burden finances, stockouts of critical drugs that endanger patients, and inefficiencies in the distribution process can cause significant losses reaching tens or even hundreds of millions of rupiah each year. Without a well-integrated and well-structured information system, recording errors, data inaccuracies, and slow movement of goods become unavoidable. A modern SIMRS must be able to address this complexity with robust multi-warehouse and floor stock features. This article will guide you practically, from understanding basic concepts, technical architecture with references to specific tools, code implementation examples, to best practices to ensure efficiency, data accuracy, and regulatory compliance in managing your hospital pharmacy.

Understanding the Concept of Multi-Warehouse Pharmacy and Floor Stock

To achieve maximum efficiency in hospital pharmacy management, it is important to understand the differences and functions of the central pharmacy warehouse, satellite warehouses, and floor stock. These three concepts work synergistically in a SIMRS to ensure the availability of the right drugs in the right place at the right time.

Central Pharmacy Warehouse is the hospital's main storage facility. This is where all drugs and medical devices (alkes) are received from distributors, stored in large quantities, and become the main source of distribution to satellite warehouses or other care units. Its functions include receiving, bulk storage, quality control, and initial distribution. A concrete example is the Pharmacy Installation on the ground floor of the hospital, which has a large storage room for all types of drugs, from generics to patented drugs, vaccines, and laboratory reagents.

Satellite Pharmacy Warehouse is a smaller storage unit scattered in strategic areas of the hospital, such as in the Emergency Department (IGD), Outpatient Polyclinic, or Inpatient Installation. Its main purpose is to accelerate drug access for specific service areas without always having to take from the central warehouse. Satellite warehouses usually have pharmacy staff fully responsible for stock management in that area. For example, the Emergency Pharmacy Warehouse will store emergency and fast-moving drugs commonly used in the Emergency Department for rapid patient handling.

Floor Stock refers to drug or medical device stock stored directly in patient care units, such as in wards, ICU, or operating rooms (OK), and managed directly by nurses or medical staff in that unit. Its purpose is for immediate use on patients in that unit without requiring individual requests to the pharmacy each time. This is very important for essential drugs needed quickly. For example, stock of paracetamol, infusion fluids, or standard first-aid drugs available at the Nurses Station of each ward.

The benefits of implementing multi-warehouse and floor stock include increased service time efficiency because drugs are accessed more quickly, reduced risk of errors because stock is more decentralized and specific, increased patient satisfaction, and optimized use of storage space. However, the challenge is ensuring stock data accuracy at each location, strict expiry date monitoring, effective stock rotation (FIFO/FEFO), and periodic stock reconciliation. As an example, "Medika Sejahtera" Hospital with 350 beds implements this system. They have a Central Pharmacy Warehouse, two Satellite Pharmacy Warehouses (in the Emergency Department and Outpatient), as well as floor stock in 15 inpatient wards. Their SIMRS must be able to track drug movement from the Central Warehouse to Satellite Warehouses, then to Floor Stock, and finally recorded as dispensed to patients, ensuring full visibility at every stage of the supply chain.

Technical Architecture and Implementation in SIMRS

The implementation of multi-warehouse pharmacy and floor stock in SIMRS requires a solid technical architecture to support data complexity and workflows. The selection of appropriate technology and database design is crucial for scalability and performance.

On the Database Schema Design side, we need several core tables. First, a locations table to define each drug storage location: id (primary key), name (location name, e.g., 'Central Pharmacy Warehouse', 'Floor Stock Ward A'), type (enum: 'central', 'satellite', 'floor'), and possibly parent_id (for hierarchy, e.g., floor stock has a satellite warehouse parent). Second, an items table for drug/medical device master data: id, name, unit (tablet, bottle), min_stock, max_stock (for alerts). Third, a stocks table that is the core of inventory: id, item_id, location_id, batch_number, expiry_date, quantity, and cost_price. The stock_transactions table is also important for recording every stock movement: id, item_id, from_location_id, to_location_id, quantity, transaction_type (receive, transfer, dispense), transaction_date, user_id.

For Frameworks and Tools, common and robust choices are: For the backend, we can use Laravel 11.x (with PHP 8.2+) or Node.js 20 LTS (with Express.js or NestJS). Laravel is very suitable for rapid development and has a mature ecosystem for database management. The recommended database is PostgreSQL 16, known for its reliability, JSONB features for storing flexible metadata, and partitioning capabilities that are very useful for large transaction tables. For API standards, RESTful API is the primary choice, but integration with healthcare standards such as FHIR R4 (Fast Healthcare Interoperability Resources) for resources like SupplyRequest, SupplyDelivery, or MedicationDispense can greatly improve interoperability, especially if the hospital plans to integrate with the SatuSehat ecosystem. If there is a need for more legacy integration, HL7 v2.5.1 is still relevant for ADT (Admission, Discharge, Transfer) messages that may trigger changes in floor stock requirements.

Business Logic that must be implemented includes: the goods receiving process which ideally only occurs at the central warehouse, requests and distribution between warehouses (from central to satellite, or satellite to floor stock) which must be recorded as stock transfers, dispensing of medications to patients recorded from satellite warehouses or floor stock, as well as automatic or manual stock reconciliation. The system must also have alerting features for notifications of minimum stock, maximum stock, and medications approaching their expiration date. For example, if the stock of Paracetamol in Floor Stock Ward A drops below 10 strips, the SIMRS must automatically create a replenishment request to the nearest Satellite Pharmacy Warehouse.

Example API & Logic Implementation Code

To provide a concrete picture, let's look at a simple implementation example using Laravel 11.x and PostgreSQL 16. We will focus on the database migration structure and the stock transfer logic between locations.

First, we define migrations for the locations and stocks tables. This is important to ensure a consistent database structure.

<?php namespace DatabaseMigrations; use IlluminateDatabaseMigrationsMigration; use IlluminateDatabaseSchemaBlueprint; use IlluminateSupportFacadesSchema; class CreateInventoryTables extends Migration { public function up(): void { Schema::create('locations', function (Blueprint $table) { $table->id(); $table->string('name'); $table->enum('type', ['central', 'satellite', 'floor_stock']); $table->foreignId('parent_location_id')->nullable()->constrained('locations')->onDelete('set null'); $table->timestamps(); }); Schema::create('items', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('unit')->default('pcs'); $table->integer('min_stock')->default(0); $table->integer('max_stock')->default(0); $table->timestamps(); }); Schema::create('stocks', function (Blueprint $table) { $table->id(); $table->foreignId('item_id')->constrained('items')->onDelete('cascade'); $table->foreignId('location_id')->constrained('locations')->onDelete('cascade'); $table->string('batch_number')->nullable(); $table->date('expiry_date')->nullable(); $table->integer('quantity')->default(0); $table->decimal('cost_price', 10, 2)->default(0.00); $table->timestamps(); $table->unique(['item_id', 'location_id', 'batch_number'], 'item_location_batch_unique'); }); Schema::create('stock_transactions', function (Blueprint $table) { $table->id(); $table->foreignId('item_id')->constrained('items')->onDelete('cascade'); $table->foreignId('from_location_id')->nullable()->constrained('locations')->onDelete('set null'); $table->foreignId('to_location_id')->nullable()->constrained('locations')->onDelete('set null'); $table->integer('quantity'); $table->enum('transaction_type', ['receive', 'transfer_out', 'transfer_in', 'dispense', 'adjustment_in', 'adjustment_out']); $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); $table->text('notes')->nullable(); $table->timestamps(); }); } public function down(): void { Schema::dropIfExists('stock_transactions'); Schema::dropIfExists('stocks'); Schema::dropIfExists('items'); Schema::dropIfExists('locations'); } }

The migration above defines four tables: locations to store warehouse and floor stock information, items for medication master data, stocks for actual inventory per location and batch, and stock_transactions to track every movement. The parent_location_id column in the locations table allows us to create a hierarchy, for example Floor Stock Ward A is under the Inpatient Satellite Warehouse. The batch_number and expiry_date columns in the stocks table are very important for implementing FEFO (First-Expired, First-Out) and batch tracking.

Next, let's create an example controller method in Laravel to perform stock transfers between locations. This is one of the core functionalities in multi-warehouse management.

<?php namespace AppHttpControllers; use AppModelsItem; use AppModelsLocation; use AppModelsStock; use AppModelsStockTransaction; use IlluminateHttpRequest; use IlluminateSupportFacadesDB; use IlluminateValidationValidationException; class InventoryController extends Controller { public function transferStock(Request $request) { $request->validate([ 'item_id' => 'required|exists:items,id', 'from_location_id' => 'required|exists:locations,id', 'to_location_id' => 'required|exists:locations,id|different:from_location_id', 'quantity' => 'required|integer|min:1', 'batch_number' => 'nullable|string', ]); try { DB::beginTransaction(); $itemId = $request->item_id; $fromLocationId = $request->from_location_id; $toLocationId = $request->to_location_id; $quantity = $request->quantity; $batchNumber = $request->batch_number; // Get stock from source location $fromStock = Stock::where('item_id', $itemId) ->where('location_id', $fromLocationId) ->when($batchNumber, fn($query) => $query->where('batch_number', $batchNumber)) ->first(); if (!$fromStock || $fromStock->quantity < $quantity) { throw ValidationException::withMessages(['quantity' => 'Insufficient stock or batch not found in source location.']); } // Deduct from source $fromStock->quantity -= $quantity; $fromStock->save(); // Add to destination $toStock = Stock::firstOrCreate( [ 'item_id' => $itemId, 'location_id' => $toLocationId, 'batch_number' => $batchNumber ], [ 'expiry_date' => $fromStock->expiry_date, 'cost_price' => $fromStock->cost_price, 'quantity' => 0 ] ); $toStock->quantity += $quantity; $toStock->save(); // Record transactions StockTransaction::create([ 'item_id' => $itemId, 'from_location_id' => $fromLocationId, 'to_location_id' => $toLocationId, 'quantity' => $quantity, 'transaction_type' => 'transfer_out', 'user_id' => auth()->id(), 'notes' => 'Stock transferred to another location.' ]); StockTransaction::create([ 'item_id' => $itemId, 'from_location_id' => $fromLocationId, // Still from source for tracking 'to_location_id' => $toLocationId, 'quantity' => $quantity, 'transaction_type' => 'transfer_in', 'user_id' => auth()->id(), 'notes' => 'Stock received from another location.' ]); DB::commit(); return response()->json(['message' => 'Stock transferred successfully.']); } catch (ValidationException $e) { DB::rollBack(); return response()->json(['errors' => $e->errors()], 422); } catch (Exception $e) { DB::rollBack(); return response()->json(['message' => 'An error occurred during stock transfer.', 'error' => $e->getMessage()], 500); } } }

The transferStock method handles the process of transferring medications from one location to another. This includes input validation, checking stock availability at the source location, deducting stock at the source location, adding stock at the destination location (by creating a new entry if one does not already exist for that item and batch at the destination location), and recording two separate transactions (transfer_out and transfer_in) for audit purposes. The use of database transactions (DB::beginTransaction() and DB::commit()) is crucial for maintaining data integrity; if any step fails, all changes are rolled back (DB::rollBack()), preventing stock inconsistencies. Note how we search for stock based on batch_number; this allows tracking of specific batches for FEFO purposes.

Data Integration and Error Handling

Seamless data integration and robust error handling are the foundation of a reliable pharmaceutical inventory system. Without both, data can become inaccurate and the system is vulnerable to operational failures. For integration, we can use a standard JSON payload or follow the FHIR R4 standard for broader interoperability.

The following is an example of a realistic JSON payload for a stock transfer request from the Central Pharmacy Warehouse to Ward A Floor Stock, for example for the drug Paracetamol 500mg:

{ "item_id": 101, "item_name": "Paracetamol 500mg Tablet", "batch_number": "PCMTL202305A", "expiry_date": "2025-12-31", "quantity_to_transfer": 50, "from_location_id": 1, "from_location_name": "Central Pharmacy Warehouse", "to_location_id": 15, "to_location_name": "Ward A Floor Stock", "requested_by_user_id": 203, "requested_by_user_name": "Nurse Ani", "notes": "Daily floor stock replenishment" }

This payload includes all the important information for a stock transfer: drug identity, batch number, expiry date, quantity, source and destination locations, and requester information. When this payload is sent to the transferStock API, the system will process it and update the stock data in the database.

However, in any system, errors are an unavoidable part. Good error handling is very important. An example of an error message that may occur:

"Insufficient stock for item [Paracetamol 500mg Tablet] with batch [PCMTL202305A] in location [Central Pharmacy Warehouse] to transfer 50 units. Available: 30 units."

This error occurs when the quantity requested for transfer exceeds the stock available at the source location for a specific batch. Handling this error must be done on the backend API side with strict validation before making changes to the database. Several crucial error handling steps include:

  1. Input Validation: Before processing a request, all incoming data must be validated. This includes quantity (must be positive), location (must be valid and different), item (must exist), and date format (for expiration). Laravel, for example, provides a robust validation system.
  2. Database Transactions (ACID): As shown in the code example, every operation that modifies stock data (reduction in one place, addition in another) must be wrapped in a database transaction. This guarantees the ACID properties (Atomicity, Consistency, Isolation, Durability). If any part of the transaction fails (for example, the stock at the destination cannot be updated), the entire transaction will be rolled back, preventing data inconsistency.
  3. Error Logging: Every error that occurs, whether validation, database failure, or external issue, must be logged in detail. This log should include the time of occurrence, error message, request details (payload), and the ID of the user who triggered the error. This is very helpful for debugging and auditing.
  4. Notifications: For critical errors (for example, system failure or highly inconsistent stock), the system should send automatic notifications to the IT administrator or pharmacy head via email or internal messaging system.
  5. Informative Error Messages: Error messages returned to the user must be clear, specific, and help the user understand what went wrong and how to fix it, without exposing sensitive internal technical details.

Adopting standards such as FHIR R4 for resources like Medication, Location, and SupplyRequest can facilitate integration with other systems in the healthcare ecosystem. For example, using HAPI FHIR 6.8 as a FHIR server can provide appropriate endpoints for inventory management, ensuring data is structured according to industry standards.

Best Practices in Multi-Warehouse & Floor Stock Pharmacy Management

  1. Standardization of Drug Master Data: Ensure every drug item has a unique code, standard name, and clear smallest unit across the system. This prevents duplication, recording errors, and ensures data consistency across all warehouses and floor stock. Using standards such as SNOMED CT or local KFA will be very helpful.
  2. Clear Definition of Stock Locations: Classify each storage location (central, satellite, floor stock) with a unique ID and defined type in the SIMRS. Implement a location hierarchy, for example floor stock under satellite warehouse, to facilitate tracking and tiered inventory reporting.
  3. Automation of Stock Transfers and Issues: Utilize SIMRS automation features to record every stock movement between locations or issue to patients in real-time. This drastically reduces manual work, minimizes potential human error, and ensures stock data is always up-to-date.
  4. Implementation of Early Warning Systems: Configure automatic notifications for minimum stock, maximum stock, and drugs approaching expiration date (for example 3-6 months before expiry). This is very helpful in purchase planning, stock rotation (FEFO), and preventing losses due to expired drugs.
  5. Periodic Stock Audits and Reconciliation: Conduct physical stock opname periodically (for example monthly for floor stock, quarterly for satellite warehouses, and semi-annually for central warehouse) and compare with SIMRS data. Discrepancies found must be thoroughly investigated and adjusted in the system after approval.
  6. Comprehensive Staff Training: Ensure all pharmacy staff, nurses, and IT involved understand the workflow, standard operating procedures (SOP), and how to use SIMRS for stock management. Continuous training and refreshers are essential to maintain competence and compliance.
  7. Utilization of Analytical Reports: Use SIMRS reporting modules to analyze stock movements, consumption patterns per unit/ward, and distribution efficiency. This data is crucial for strategic decision-making regarding procurement, determining optimal stock levels, and identifying slow-moving or fast-moving drugs.
  8. Data Security and Access Control: Implement strict Role-Based Access Control (RBAC) to ensure only authorized personnel can perform certain stock transactions. For example, nurses can only issue floor stock, while pharmacy staff can perform transfers between warehouses.
  9. Data Backup and Recovery: Perform regular SIMRS data backups (daily or even real-time) and prepare a Disaster Recovery Plan (DRP) to prevent loss of crucial inventory data due to system failure or natural disasters.
  10. Integration with Other Modules: Ensure the pharmacy module is well integrated with patient registration, electronic medical records, billing, and procurement modules. This integration creates a seamless workflow and prevents data duplication and input errors.

FAQ

  1. Q: What is the difference between a satellite warehouse and floor stock?

    A: A satellite warehouse is a pharmaceutical storage unit that is smaller than the central warehouse, usually has pharmacy staff, and serves several surrounding treatment units or outpatient clinics. Stock in a satellite warehouse still requires a formal request and issuance process. Meanwhile, floor stock is stock of drugs or medical supplies stored directly in the treatment unit (for example, wards, ICU) and managed by nurses for the immediate needs of patients in that unit, without requiring repeated requests to the pharmacy. Both aim to improve service speed, but with different levels of control and procedures.

  2. Q: How can stock discrepancies between physical and system records be prevented?

    A: Preventing stock discrepancies requires a combination of strict processes and technology. First, ensure that every transaction (receipt, issuance, transfer) is recorded in real-time in the SIMRS immediately after the event. Second, implement a barcode or RFID system to minimize manual input errors and speed up the process. Third, conduct regular physical stock audits and reconcile SIMRS data, and investigate the cause of every discrepancy found for process improvement.

  3. Q: Should SIMRS support FIFO/FEFO for floor stock?

    A: Yes, it is highly recommended. FIFO (First-In, First-Out) and FEFO (First-Expired, First-Out) are crucial principles in pharmaceutical management to reduce the risk of expired drugs and waste. SIMRS must be able to track the batch number and expiration date of each item, and provide recommendations or even automate issuance based on the FEFO principle, especially for floor stock that turns over quickly and is prone to expiration if not managed properly.

  4. Q: How should floor stock for narcotic/psychotropic drugs be managed?

    A: The management of narcotic and psychotropic drugs in floor stock requires very strict control in accordance with applicable regulations, such as those stipulated in Permenkes RI No. 2 of 2022 concerning the Management of Drugs, Drug Materials, and Medical Devices in Health Service Facilities. SIMRS must have a special module with dual authentication, very detailed recording for every issuance (patient name, doctor, dose, time), and audit reports that cannot be manipulated. The key to the floor stock cabinet must also be managed with strict security protocols, and daily physical checks are mandatory.

  5. Q: What is the ideal frequency for floor stock replenishment?

    A: The frequency of floor stock replenishment depends greatly on the average consumption rate of drugs in that unit and the available storage capacity. For fast-moving drugs, replenishment can be daily. For slow-moving drugs, it can be weekly or even monthly. A good SIMRS will have an algorithm to predict needs based on historical consumption data and the established minimum/maximum stock levels, then automate replenishment requests.

  6. Q: What is the impact if the multi-warehouse and floor stock setup is not optimal?

    A: The impact is very significant and detrimental. There can be stock-outs of critical drugs that endanger patient safety, accumulation of expired drugs that causes large financial losses, operational inefficiency due to time-consuming manual searching or transfers, and difficulty in audits and reporting to regulators. Ultimately, this will reduce the quality of patient care, increase hospital operational costs, and potentially create legal problems if negligence occurs.

Implementing an effective multi-warehouse and floor stock pharmacy system in SIMRS is not merely an operational necessity, but a strategic investment to improve the quality of patient care, operational efficiency, and regulatory compliance. With the right architectural design, solid technical implementation, and adherence to best practices, hospitals can optimize their pharmaceutical inventory management, reduce waste, and ensure consistent drug availability. This success depends greatly on the capabilities of the SIMRS and the competence of the IT team supporting it. If you need further consultation, custom module development, or reliable SIMRS integration to implement this multi-warehouse and floor stock pharmacy system, do not hesitate to contact Nugroho Setiawan. With our experience in SIMRS, BPJS/SatuSehat integration, and custom development, we are ready to help your hospital achieve the highest operational efficiency. Visit nugrohosetiawan.com or email us at info@nugrohosetiawan.com for further discussion and the right technology solution.

Related solutions by PT Pilar Inovasi Informatika (Pilar Inovasi IT products): SIMRS (Hospital Information System) BPJS & SatuSehat Integration. Need a free consultation?

Terakhir diperbarui 18 Oct 2026

Komentar

Komentar ditinjau sebelum tampil.

Belum ada komentar. Jadilah yang pertama!