Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

inventory-control-delphi-2016

Delphi 7 Inventory Control System - Stock Management, Warehousing & Reporting (2016)

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

Inventory Control System - Delphi 7

Legacy Project 2016

📋 Project Description

Multi-warehouse inventory control system developed in Delphi 7 with FirebirdSQL. Manages products, warehouses, stock movements (entries, exits, transfers, and adjustments), with role-based access control and complete operation auditing.

🎯 Key Features

Product Management

  • ✅ Create, update, and delete products
  • ✅ Categorization (Food, Beverages, Cleaning, Technology, Clothing)
  • ✅ Automatic EAN-13 barcode generation
  • ✅ Minimum and maximum stock control
  • ✅ Automatic price calculation with 30% margin
  • ✅ Search by name, code, or barcode
  • ✅ Barcode label printing

Warehouse Management

  • ✅ Multiple warehouses with detailed information
  • ✅ Geographic location control
  • ✅ Manager assignment per warehouse
  • ✅ Active/inactive status

Inventory Movements

  • ✅ Entries: Purchases, customer returns
  • ✅ Exits: Sales, supplier returns
  • ✅ Transfers: Between warehouses
  • ✅ Adjustments: Inventory corrections
  • ✅ Available stock validation
  • ✅ Automatic inventory updates
  • ✅ Cost tracking per movement
  • ✅ Complete history with date and type filters

Security

  • ✅ Authentication with encrypted password (XOR)
  • ✅ Role-based access control:
    • Admin: Full access
    • Supervisor: Product and movement management
    • Warehouse Worker: Entry/exit movements only
  • ✅ All operations audited
  • ✅ Last connection logging

Reporting

  • ✅ General inventory report (all warehouses)
  • ✅ Inventory report by warehouse
  • ✅ Low stock alerts report
  • ✅ Detailed movement history by date range
  • ✅ FastReport 4.0 integration for printing
  • ✅ Export to PDF and Excel

🛠 Technologies Used

Component Technology Version Purpose
Language Object Pascal Delphi 7 Main development language
Database FirebirdSQL 2.5 Multi-user embedded database
Components IBX Native Delphi 7 InterBase/Firebird connectivity
Reports FastReport 4.0 Report generation
Barcodes Barcode Studio Built-in EAN-13 generation
UI VCL Native Windows user interface

📁 Project Structure

pascal
Delphi_InventoryControl_Implementation/
???
????????? README.md                           # This documentation
???
????????? Source/                             # Application source code
???   ????????? InventoryControl.dpr            # Main project file
???   ????????? InventoryControl.dproj          # Project configuration
???   ???
???   ????????? Forms/                          # Application forms
???   ???   ????????? ULogin.pas/dfm              # Login authentication
???   ???   ????????? UMainMenu.pas/dfm           # Main application menu
???   ???   ????????? UProducts.pas/dfm           # Product CRUD
???   ???   ????????? UWarehouses.pas/dfm         # Warehouse management
???   ???   ????????? UStockMovements.pas/dfm     # Stock movements
???   ???   ????????? UReports.pas/dfm            # Reports and queries
???   ???
???   ????????? DataModules/                    # Data modules
???   ???   ????????? DMDatabase.pas/dfm          # Database connections and queries
???   ???
???   ????????? Units/                          # Utility units
???       ????????? UGlobals.pas                # Global variables and constants
???
????????? Database/                           # Database configuration
???   ????????? INVENTORY.FDB                   # FirebirdSQL database
???   ????????? CreateDatabase.sql              # Database creation script
???
????????? Reports/                            # Report templates
???   ????????? RptInventario.fr3               # General inventory report
???   ????????? RptStockBajo.fr3                # Low stock report
???   ????????? RptMovimientos.fr3              # Movement history report
???
????????? Documentation/                      # Technical documentation
???   ????????? UserManual.pdf                  # End-user manual
???   ????????? TechnicalGuide.pdf              # Technical specifications
???   ????????? ERD.png                         # Entity-Relationship Diagram
???
????????? Screenshots/                        # Application screenshots
    ????????? login.png                       # Login screen
    ????????? main_menu.png                   # Main menu
    ????????? products.png                    # Product management
    ????????? movements.png                   # Stock movements
    ????????? reports.png                     # Reports interface

🚀 Installation

1. Prerequisites

  • Operating System: Windows XP/Vista/7/8/10 (32-bit or 64-bit)
  • RAM: 512 MB minimum, 1 GB recommended
  • Disk Space: 50 MB for application, 500 MB for database
  • Delphi 7: Required for compilation (Enterprise or Professional)
  • FirebirdSQL: Version 2.5 (embedded mode - included)

2. Database Configuration

sql
-- Run CreateDatabase.sql in Firebird SQL Editor (ISQL)
-- Default credentials:
-- User: SYSDBA
-- Password: masterkey

-- Database path: .\Database\INVENTORY.FDB
-- Character set: WIN1252
-- Page size: 4096

3. FirebirdSQL Setup

pascal
1. Embedded mode (included):
   - Copy fbclient.dll to application folder
   - Copy gds32.dll to application folder
   - No service installation required

2. Server mode (optional):
   - Install Firebird 2.5 server
   - Configure database path in DMDatabase.pas:
     IBDatabase1.DatabaseName := 'localhost:C:\Path\INVENTORY.FDB';

4. Compilation

pascal
1. Open InventoryControl.dpr in Delphi 7
2. Configure library paths:
   - Tools ??? Environment Options ??? Library
   - Add FastReport 4.0 components path
   - Add IBX components path (usually included)
3. Project ??? Build All
4. Check for successful compilation in Messages window

5. Initial Execution

pascal
Default admin credentials:
Username: admin
Password: admin123

Important: Change admin password on first login!

📊 Database Structure

Main Tables

USERS

  • User_ID (INTEGER, PK): User identifier
  • Username (VARCHAR(50)): Login username
  • Password (VARCHAR(100)): Encrypted password (XOR)
  • FullName (VARCHAR(100)): User full name
  • Email (VARCHAR(100)): Contact email
  • Role (VARCHAR(20)): Admin / Supervisor / Warehouse Worker
  • Active (SMALLINT): Active status (1/0)
  • LastLogin (TIMESTAMP): Last connection timestamp
  • CreatedAt (TIMESTAMP): Account creation date

PRODUCTS

  • Product_ID (INTEGER, PK, Auto): Product identifier
  • Code (VARCHAR(20)): Internal product code
  • Barcode (VARCHAR(50)): EAN-13 barcode
  • Name (VARCHAR(100)): Product name
  • Description (VARCHAR(255)): Detailed description
  • Category (VARCHAR(50)): Product category
  • Cost (DECIMAL(12,2)): Unit cost
  • Price (DECIMAL(12,2)): Sale price (cost × 1.30)
  • MinStock (DECIMAL(10,2)): Minimum stock threshold
  • MaxStock (DECIMAL(10,2)): Maximum stock level
  • Active (SMALLINT): Active status
  • CreatedAt (TIMESTAMP): Registration date

WAREHOUSES

  • Warehouse_ID (INTEGER, PK, Auto): Warehouse identifier
  • Code (VARCHAR(20)): Warehouse code
  • Name (VARCHAR(100)): Warehouse name
  • Location (VARCHAR(255)): Physical address
  • Manager (VARCHAR(100)): Responsible person
  • Active (SMALLINT): Operational status
  • CreatedAt (TIMESTAMP): Creation date

INVENTORY

  • Inventory_ID (INTEGER, PK, Auto): Inventory record identifier
  • Product_ID (INTEGER, FK): Product reference
  • Warehouse_ID (INTEGER, FK): Warehouse reference
  • Quantity (DECIMAL(10,2)): Current stock quantity
  • LastUpdated (TIMESTAMP): Last stock update
  • UNIQUE: (Product_ID, Warehouse_ID)

STOCK_MOVEMENTS

  • Movement_ID (INTEGER, PK, Auto): Movement identifier
  • MovementType (VARCHAR(20)): Entry / Exit / Transfer / Adjustment
  • MovementDate (TIMESTAMP): Movement timestamp
  • Product_ID (INTEGER, FK): Product reference
  • SourceWarehouse_ID (INTEGER, FK): Source warehouse (exits/transfers)
  • DestWarehouse_ID (INTEGER, FK): Destination warehouse (entries/transfers)
  • Quantity (DECIMAL(10,2)): Movement quantity
  • Cost (DECIMAL(12,2)): Unit cost for movement
  • Notes (VARCHAR(255)): Additional notes
  • User_ID (INTEGER, FK): User who performed the operation
  • CreatedAt (TIMESTAMP): Registration date

🔐 Security Features

1. Password Encryption

pascal
// XOR encryption function in UGlobals.pas
function EncryptPassword(const APassword: string): string;
const
  XOR_KEY = 'DELPHI7KEY2016';
var
  i: Integer;
begin
  Result := '';
  for i := 1 to Length(APassword) do
    Result := Result + Chr(Ord(APassword[i]) xor
              Ord(XOR_KEY[((i-1) mod Length(XOR_KEY)) + 1]));
  Result := EncodeBASE64(Result);
end;

2. Role-Based Access Control (RBAC)

  • Admin: Full system access
    • User management (create, edit, delete)
    • All product and warehouse operations
    • All movement types
    • Report generation and export
  • Supervisor: Management operations
    • View users (no edit)
    • Full product management
    • All movement types
    • Report generation
  • Warehouse Worker: Basic operations
    • View products only
    • Entry and exit movements only
    • Limited reports

3. Audit Trail

pascal
// All operations logged in STOCK_MOVEMENTS table
// Tracks: Who, What, When, Where, How Much
procedure LogMovement(AType: string; AProduct, AWarehouse: Integer;
                      AQuantity: Double; AUser: Integer);

💻 Usage Guide

1. User Authentication

pascal
1. Launch InventoryControl.exe
2. Enter credentials:
   - Username: admin
   - Password: admin123 (first time)
3. Click "Login"
4. System validates credentials and loads main menu

2. Product Management

pascal
Create New Product:
1. Main Menu ??? Products
2. Click "New" button
3. Fill form:
   - Code: Manual or auto-generated
   - Name: Product description
   - Category: Select from dropdown
   - Cost: Purchase cost
   - Price: Auto-calculated (Cost ?? 1.30)
   - Min/Max Stock: Threshold values
4. Click "Generate Barcode" for EAN-13
5. Save

Edit Product:
1. Search product (by code/name/barcode)
2. Select from grid
3. Modify fields
4. Save changes

Delete Product:
1. Select product
2. Click "Delete"
3. Confirm action (soft delete - sets Active=0)

3. Warehouse Operations

pascal
Add Warehouse:
1. Main Menu ??? Warehouses
2. Click "New"
3. Enter:
   - Code: Warehouse identifier
   - Name: Descriptive name
   - Location: Full address
   - Manager: Responsible person name
4. Save

Activate/Deactivate:
1. Select warehouse
2. Toggle "Active" checkbox
3. Save

4. Stock Movements

pascal
Entry Movement (Purchase):
1. Main Menu ??? Movements
2. Select "Entry" type
3. Choose destination warehouse
4. Select product
5. Enter quantity and cost
6. Add notes (optional)
7. Save ??? Inventory auto-updated

Exit Movement (Sale):
1. Select "Exit" type
2. Choose source warehouse
3. Select product
4. Enter quantity
5. System validates available stock
6. Save ??? Inventory decremented

Transfer Between Warehouses:
1. Select "Transfer" type
2. Choose source warehouse
3. Choose destination warehouse
4. Select product and quantity
5. Save ??? Stock updated in both warehouses

Adjustment (Correction):
1. Select "Adjustment" type
2. Choose warehouse
3. Select product
4. Enter correction quantity (+ or -)
5. Add reason in notes
6. Save

5. Report Generation

pascal
Inventory Report:
1. Main Menu ??? Reports
2. Select "General Inventory" or "By Warehouse"
3. Choose warehouse (if applicable)
4. Click "Generate"
5. Preview in FastReport viewer
6. Export to PDF/Excel or Print

Low Stock Report:
1. Reports ??? Low Stock Alerts
2. System shows products below MinStock
3. Grouped by warehouse
4. Export or print

Movement History:
1. Reports ??? Movement History
2. Set date range (From/To)
3. Select movement type (optional filter)
4. Select warehouse (optional filter)
5. Generate report

🔧 Troubleshooting

1. Database Connection Error

Error: Unable to complete network request to host "localhost"

Solutions:

pascal
1. Embedded mode:
   - Verify fbclient.dll exists in app folder
   - Check database path in DMDatabase.pas
   - Ensure INVENTORY.FDB has read/write permissions

2. Server mode:
   - Start Firebird service:
     NET START FirebirdServerDefaultInstance
   - Verify server is listening on port 3050:
     netstat -an | findstr 3050
   - Check firewall rules allow port 3050

2. Login Failed

Error: Invalid username or password

Solutions:

pascal
1. Reset admin password:
   - Connect to database with ISQL
   - Update USERS set Password = (SELECT ENCRYPT_PASS('admin123')
     FROM RDB$DATABASE) WHERE Username = 'admin';

2. Check database connection:
   - Verify INVENTORY.FDB exists
   - Check IBDatabase1.Connected property
   - Review DMDatabase error messages

3. Insufficient Stock Error

Error: Insufficient stock in warehouse

Solutions:

pascal
1. Verify current inventory:
   - Reports ??? Inventory by Warehouse
   - Check actual quantities

2. Process pending entries:
   - Complete any pending purchase movements
   - Apply inventory adjustments if needed

3. Check data integrity:
   SELECT Product_ID, Warehouse_ID, SUM(Quantity)
   FROM INVENTORY
   GROUP BY Product_ID, Warehouse_ID;

4. Report Not Loading

Error: Cannot load report template

Solutions:

pascal
1. Verify FastReport files:
   - Check *.fr3 files exist in Reports folder
   - Ensure FastReport 4.0 components installed
   - Verify frReport1.LoadFromFile path

2. Component registration:
   - Component ??? Install Packages
   - Enable FastReport 4.0 package
   - Rebuild application

5. Barcode Generation Failed

Error: Invalid barcode format

Solutions:

pascal
1. EAN-13 validation:
   - Code must be exactly 12 digits
   - System calculates 13th check digit
   - Function: GenerateEAN13CheckDigit

2. Manual entry:
   - Ensure numeric input only
   - Use full 13-digit code if pre-generated

📝 Technical Notes

IBX Components

pascal
// Core Firebird connectivity in DMDatabase.pas

IBDatabase1: TIBDatabase
  - DatabaseName: Path to INVENTORY.FDB
  - SQLDialect: 3 (Firebird 2.5 default)
  - CharSet: WIN1252
  - Connected: True at runtime

IBTransaction1: TIBTransaction
  - DefaultDatabase: IBDatabase1
  - Params: read_committed, rec_version, nowait
  - AutoCommit: False (explicit transaction control)

IBQuery/IBDataSet: Data access components
  - Transaction: IBTransaction1
  - Database: IBDatabase1
  - CachedUpdates: False

Transaction Management

pascal
// Standard transaction pattern
procedure TDMDatabase.ExecuteTransaction(const ASQL: string);
begin
  IBTransaction1.StartTransaction;
  try
    IBQuery1.SQL.Text := ASQL;
    IBQuery1.ExecSQL;
    IBTransaction1.Commit;
  except
    on E: Exception do
    begin
      IBTransaction1.Rollback;
      raise Exception.Create('Transaction failed: ' + E.Message);
    end;
  end;
end;

Data Validation

pascal
// Product validation before save
function TFormProducts.ValidateProduct: Boolean;
begin
  Result := False;

  if Trim(edtName.Text) = '' then
  begin
    ShowMessage('Product name is required');
    edtName.SetFocus;
    Exit;
  end;

  if edtCost.Value <= 0 then
  begin
    ShowMessage('Cost must be greater than zero');
    edtCost.SetFocus;
    Exit;
  end;

  // Auto-calculate price
  edtPrice.Value := edtCost.Value * 1.30;

  Result := True;
end;

Stock Update Logic

pascal
// Inventory update on movement
procedure TDMDatabase.UpdateInventory(AProduct, AWarehouse: Integer;
                                      AQuantity: Double;
                                      AMovementType: string);
var
  CurrentQty: Double;
begin
  // Get current stock
  CurrentQty := GetInventoryQty(AProduct, AWarehouse);

  // Calculate new quantity based on movement type
  case AMovementType of
    'Entry', 'Adjustment+':
      CurrentQty := CurrentQty + AQuantity;
    'Exit', 'Adjustment-':
    begin
      if CurrentQty < AQuantity then
        raise Exception.Create('Insufficient stock');
      CurrentQty := CurrentQty - AQuantity;
    end;
  end;

  // Update or insert inventory record
  if InventoryExists(AProduct, AWarehouse) then
    UpdateInventoryQty(AProduct, AWarehouse, CurrentQty)
  else
    InsertInventory(AProduct, AWarehouse, CurrentQty);
end;

🎨 Customization Examples

1. Add New Product Category

pascal
// In UGlobals.pas, update categories constant
const
  PRODUCT_CATEGORIES: array[0..5] of string =
    ('Food', 'Beverages', 'Cleaning', 'Technology', 'Clothing', 'Pharmaceuticals');

// In UProducts.pas, refresh combobox
procedure TFormProducts.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  cmbCategory.Items.Clear;
  for i := Low(PRODUCT_CATEGORIES) to High(PRODUCT_CATEGORIES) do
    cmbCategory.Items.Add(PRODUCT_CATEGORIES[i]);
end;

2. Change Price Calculation Margin

pascal
// In UProducts.pas, modify calculation
const
  PRICE_MARGIN = 1.35; // 35% instead of 30%

procedure TFormProducts.edtCostChange(Sender: TObject);
begin
  if edtCost.Value > 0 then
    edtPrice.Value := edtCost.Value * PRICE_MARGIN;
end;

3. Add Email Notifications for Low Stock

pascal
// In DMDatabase.pas, add notification procedure
uses
  IdSMTP, IdMessage;

procedure TDMDatabase.CheckLowStockAndNotify;
var
  qryLowStock: TIBQuery;
  EmailMsg: TIdMessage;
begin
  qryLowStock := TIBQuery.Create(nil);
  try
    qryLowStock.Database := IBDatabase1;
    qryLowStock.SQL.Text :=
      'SELECT p.Name, w.Name AS Warehouse, i.Quantity, p.MinStock ' +
      'FROM INVENTORY i ' +
      'JOIN PRODUCTS p ON i.Product_ID = p.Product_ID ' +
      'JOIN WAREHOUSES w ON i.Warehouse_ID = w.Warehouse_ID ' +
      'WHERE i.Quantity < p.MinStock AND p.Active = 1';
    qryLowStock.Open;

    if not qryLowStock.IsEmpty then
    begin
      // Send email to admin
      EmailMsg := TIdMessage.Create(nil);
      try
        EmailMsg.From.Address := 'inventory@company.com';
        EmailMsg.Recipients.EMailAddresses := 'admin@company.com';
        EmailMsg.Subject := 'Low Stock Alert';
        EmailMsg.Body.Add('Products below minimum stock:');

        while not qryLowStock.Eof do
        begin
          EmailMsg.Body.Add(Format('%s in %s: %.2f (Min: %.2f)',
            [qryLowStock.FieldByName('Name').AsString,
             qryLowStock.FieldByName('Warehouse').AsString,
             qryLowStock.FieldByName('Quantity').AsFloat,
             qryLowStock.FieldByName('MinStock').AsFloat]));
          qryLowStock.Next;
        end;

        // Configure and send via SMTP
        // IdSMTP1.Send(EmailMsg);
      finally
        EmailMsg.Free;
      end;
    end;
  finally
    qryLowStock.Free;
  end;
end;

Note: This is a Legacy 2016 project maintained for historical and compatibility purposes. The system remains in production use in environments requiring Delphi 7 and FirebirdSQL 2.5 compatibility. For new development, consider modern alternatives such as Delphi 11 Alexandria with Firebird 4.0 or PostgreSQL.

Last Updated: 2016
Maintained By: Legacy Systems Team