Frosty — Cold Storage ERP
A specialized enterprise resource planning system built for cold storage operations, supporting allocation, billing, stock tracking, and controls.
Lead System Developer
Anand, Gujarat, India
2024 Release

90%
Manual billing overhead cut
0%
Allocation discrepancy rate
Daily
Rent generation automation
Executive Summary
Perishable logistics operations represent a high-stakes segment of supply chain management. In major agricultural and exporting hubs across Gujarat, warehouses require precise space mapping, temperature audits, and variable billing rules to handle bulk goods. When managing tons of agricultural yields, simple inventory spreadsheets fail to coordinate spatial availability, leading to rotting stock or wasted space.
Akshar KaPatel designed the Frosty Cold Storage ERP to replace paper registers with a dynamic digital grid. The system maps warehouse capacity across chambers, rows, and bays in real time, automatically compiles daily storage-rent accruals, and coordinates batch allocations. Deployed in cold storage environments, it reduced manual billing compile times by 90% and reduced inventory allocation errors to zero.
The Challenge
Cold storage warehousing carries specific physical constraints:
- Spatial Dynamics: Crops are deposited, merged, split, and released in small batches. Tracking the specific physical location (Chamber to Row to Bay) of each client lot requires a hierarchical data structure that calculates capacity constraints in real time.
- Temperature Compliance: Different items (e.g. potatoes, onions, spices, pulp) require different temperature zones. Storing a lot in a room with incompatible temperatures will ruin the stock, causing huge business losses.
- High-Density Billing Calculations: Client billing is dynamic: clients accrue rent daily based on weight, bag count, or pallet volume. Generating monthly billing ledgers across millions of historic transactions often chokes memory limits and blocks web servers.
Architectural Solutions & Code Mappings
1. Grid Mapping Database Schema
To map a warehouse into a queryable structure, we configured relational coordinates mapping chambers down to individual storage bays:
CREATE TABLE chambers (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL, -- e.g., 'Chamber A'
temperature_min DECIMAL(4,2) NOT NULL,
temperature_max DECIMAL(4,2) NOT NULL,
created_at TIMESTAMP NULL,
updated_at TIMESTAMP NULL
);
CREATE TABLE rows_sectors (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
chamber_id BIGINT UNSIGNED NOT NULL,
name VARCHAR(50) NOT NULL, -- e.g., 'Row 12'
FOREIGN KEY (chamber_id) REFERENCES chambers(id) ON DELETE CASCADE
);
CREATE TABLE bays (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
sector_id BIGINT UNSIGNED NOT NULL,
name VARCHAR(50) NOT NULL, -- e.g., 'Bay B-10'
max_pallet_capacity INT UNSIGNED DEFAULT 10,
current_pallet_count INT UNSIGNED DEFAULT 0,
status ENUM('active', 'maintenance', 'full') DEFAULT 'active',
FOREIGN KEY (sector_id) REFERENCES rows_sectors(id) ON DELETE CASCADE
);2. Concurrency-Safe Bay Allocation
When multiple operators assign incoming pallets at the same time, we must prevent double-booking. We write Laravel transaction handlers using explicit lockForUpdate() blocks to isolate the bay query during placement checks:
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Bay;
use App\Models\Lot;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class BayAllocationController extends Controller
{
public function allocatePallets(Request $request)
{
$validated = $request->validate([
'bay_id' => 'required|exists:bays,id',
'lot_id' => 'required|exists:lots,id',
'pallet_count' => 'required|integer|min:1',
]);
return DB::transaction(function () use ($validated) {
// Apply row lock to prevent simultaneous updates
$bay = Bay::where('id', $validated['bay_id'])
->lockForUpdate()
->firstOrFail();
$lot = Lot::findOrFail($validated['lot_id']);
// Validate temperature zones matching
$chamber = $bay->sector->chamber;
if ($lot->required_temp < $chamber->temperature_min ||
$lot->required_temp > $chamber->temperature_max) {
return response()->json(['error' => 'Chamber temperature invalid for crop type.'], 422);
}
// Capacity validation
if (($bay->current_pallet_count + $validated['pallet_count']) > $bay->max_pallet_capacity) {
return response()->json(['error' => 'Insufficient space in selected bay.'], 422);
}
// Assign stock and increment counter
$bay->increment('current_pallet_count', $validated['pallet_count']);
$lot->update([
'bay_id' => $bay->id,
'allocated_at' => now(),
]);
return response()->json([
'success' => true,
'allocated_bay' => $bay->name,
'occupancy' => "{$bay->current_pallet_count}/{$bay->max_pallet_capacity}"
]);
});
}
}3. Memory-Safe Storage Rent Calculations
Rent compiles daily. To avoid memory depletion, calculations run via queued background processes. This decouples daily logs compiling from active user requests:
namespace App\Jobs;
use App\Models\Lot;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessLotRent implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $lot;
public function __construct(Lot $lot)
{
$this->lot = $lot;
}
public function handle()
{
$activeDays = now()->diffInDays($this->lot->created_at);
$dailyRate = $this->lot->client->billingRules->rate_per_day;
$totalRentAccrued = $activeDays * $dailyRate;
$this->lot->update([
'rent_accrued' => $totalRentAccrued,
'last_calculated_at' => now(),
]);
}
}Logistics Allocation Flow
Results & Metrics
Performance analysis comparison showing manual spreadsheets audits vs the Frosty ERP platform:
| Process Variable | Excel-Based Audits | Frosty ERP Platform |
|---|---|---|
| Daily Invoicing Compilation | 6-8 hours / cycle | Instant generation (Queued Job) |
| Pallet Allocation Discrepancy | 3.5% / month | 0.00% (Real-time locked coordinates) |
| Room Temp Audit Compliance | Manual Checklist | Automated logs & alarms |
| Client Inventory Access | Email requests | Real-Time Client Dashboard |
Billing Autopilot: Running daily rent calculations via background queue workers removes administrative delay, converting hours of spreadsheet auditing into a dynamic background operation.
Bay Allocation Precision: Using SELECT FOR UPDATE locks on specific coordinate records prevents double-pallet allocations, resulting in 0.00% discrepancies in warehouse planning.
Environmental Security: Digital temperature checks replace manual compliance sheets, logging hourly temperature changes and firing automatic alerts if chambers exceed configured limits.
Client Transparency: Merchants and clients view active holdings directly via secure web portals, eliminating telephone checking cycles and shipping delays.
Interested in launching similar digital systems?
Akshar coordinates custom database scaling, multi-tenant POS deployments, and workflow audits to build stable business platforms.
Discuss your project