
1. **Transaction Reception**: IncomingMessageProcessor receives ISO8583 message
2. **Pipeline Processing**: Goes through ValidationProcessor, EnrichmentProcessor, BusinessLogic
3. **YSP Detection**: Checks if DE-24 = "782" for YSP routing
4. **Terminal Validation**: Validates DE-41 (terminal ID) against database
5. **Temp Transaction Creation**: Creates pos_temp_transaction record
6. **Upstream Processing**: Routes to YSP network


## Complete Transaction Flow Analysis: Terminal Validation (DE-41) and pos_temp_transaction Creation

Based on my examination of your codebase, here's the **complete flow** from transaction receipt to database save:

### 1. **Transaction Reception** → IncomingMessageProcessor
```elixir
# lib/da_product_app/switch/incoming_message_processor.ex
def process_message(iso_message, channel_context) do
  # Entry point - receives ISO8583 message with DE-41 (Terminal ID)
```

### 2. **Pipeline Processing** → ValidationProcessor
```elixir
# config/processor_pipelines.exs (Port 8583 Primary)
{DaProductApp.MercuryISO8583.Processors.ValidationProcessor, %{
  strict_mode: false,
  required_fields: [3, 4, 11, 41, 42],  # ← DE-41 (Terminal ID) is REQUIRED
  validate_amounts: true,
  validate_dates: true,
  max_amount: 1_000_000,
  allowed_mtis: ["0200", "0220", "0400", "0420", "0800", "0810"]
}}
```

**Validation Flow:**
```elixir
# ValidationProcessor validates DE-41 presence
defp validate_required_fields(iso_message, _channel_context, config) do
  required_fields = Map.get(config, :required_fields, [])
  missing_fields = Enum.filter(required_fields, fn field ->
    ISOMsg.get_field(iso_message, field) == nil  # Checks DE-41 exists
  end)
end
```

### 3. **YSP Message Detection** → BusinessLogic
```elixir
# lib/da_product_app/switch/incoming_message_processor.ex:188
case DaProductApp.YSP.MessageProcessor.ysp_message?(iso_message) do
  true ->
    Logger.info("Detected YSP message (DE24=782), applying YSP-specific processing")
    apply_ysp_business_logic(iso_message)
```

### 4. **YSP Message Processing** → Terminal Validation
```elixir
# lib/da_product_app/acquirer/ysp/message_processor.ex
def validate_ysp_message(%ISOMsg{} = iso_message) do
  with :ok <- validate_mti(iso_message),
       :ok <- validate_required_fields(iso_message),  # ← Validates DE-41
       :ok <- validate_ysp_routing(iso_message) do
    :ok
```

**Required Fields by MTI:**
```elixir
# config/upstream_networks.exs:299
required_fields_by_mti: %{
  "0100" => [2, 3, 4, 11],              # Authorization request
  "0200" => [2, 3, 4, 11],              # Purchase request - DE-41 implied in processing
  "0220" => [2, 3, 4, 11],              # Completion request
  "0400" => [3, 4, 11],                 # Reversal - no PAN required
  "0800" => [11]                        # Network management
}
```

### 5. **Terminal Database Lookup** → Acquirer Context
```elixir
# lib/da_product_app/acquirer.ex:169
def get_terminal_by_switch_ids(switch_tid, switch_mid) do
  AcquirerTerminal.find_by_switch_ids(switch_tid, switch_mid)
end

# lib/da_product_app/acquirer/schemas/acquirer_terminal.ex:118
def find_by_switch_ids(switch_tid, switch_mid) do
  from(t in __MODULE__,
    where: t.tid == ^switch_tid and    # ← DE-41 Terminal ID lookup
           t.mid == ^switch_mid and    # ← DE-42 Merchant ID lookup  
           t.status == "ACTIVE"
  )
  |> Repo.one()
end
```

### 6. **pos_temp_transaction Creation** → Database Insert
```elixir
# lib/da_product_app/acquirer.ex:32
def create_temp_transaction(attrs \\ %{}) do
  now = DateTime.utc_now()
  attrs = Map.merge(attrs, %{created_dateTime: now, updated_dateTime: now})
  
  %PosTempTransaction{}
  |> PosTempTransaction.changeset(attrs)
  |> Repo.insert()  # ← Database INSERT into pos_temp_transaction
end
```

**PosTempTransaction Schema Fields:**
```elixir
# lib/da_product_app/transactions/pos_temp_transaction.ex:25
schema "pos_temp_transaction" do
  # Switch-side identifiers (from original request - includes DE-41)
  field :s_tid, :string               # Switch Terminal ID (DE-41)
  field :s_mid, :string               # Switch Merchant ID (DE-42)
  field :s_tid_stan, :string          # Switch STAN (DE-11)
  
  # Backend-side identifiers (what we're sending to acquirer)
  field :b_tid, :string               # Backend Terminal ID
  field :b_mid, :string               # Backend Merchant ID
  field :b_tid_stan, :string          # Backend STAN
  
  # Transaction data
  field :mti, :string                 # MTI (0200, etc.)
  field :proc_code, :string           # Processing code (DE-3)
  field :total_amount, :decimal       # Amount (DE-4)
  field :processing_state, :string    # "CREATED", "VALIDATED", etc.
  
  # Association to terminal configuration
  belongs_to :acquirer_terminal, AcquirerTerminal, foreign_key: :acquirer_id
end
```

### 7. **Complete Flow Sequence**

```mermaid
sequenceDiagram
    participant T as Terminal
    participant IMP as IncomingMessageProcessor  
    participant VP as ValidationProcessor
    participant YSP as YSP.MessageProcessor
    participant ACQ as Acquirer Context
    participant DB as Database
    
    T->>IMP: ISO8583 Message (DE-41=Terminal ID)
    IMP->>VP: validate_required_fields([41, 42])
    VP-->>IMP: ✅ DE-41 present and valid
    
    IMP->>YSP: ysp_message?(DE-24=782?)
    YSP-->>IMP: ✅ YSP message detected
    
    IMP->>ACQ: get_terminal_by_switch_ids(DE-41, DE-42)
    ACQ->>DB: SELECT * FROM acquirer_terminal WHERE tid=? AND mid=?
    DB-->>ACQ: Terminal record (or nil)
    ACQ-->>IMP: Terminal validation result
    
    alt Terminal Found & Active
        IMP->>ACQ: create_temp_transaction(attrs)
        ACQ->>DB: INSERT INTO pos_temp_transaction (s_tid=DE-41, ...)
        DB-->>ACQ: pos_temp_transaction.id
        ACQ-->>IMP: ✅ Transaction created
    else Terminal Not Found
        IMP-->>T: ❌ Invalid Terminal (Response Code 03)
    end
```

### 8. **Key Validation Points**

1. **DE-41 Presence Check**: ValidationProcessor ensures DE-41 exists in required_fields
2. **Terminal Active Status**: Database query includes `t.status == "ACTIVE"`  
3. **YSP Network Routing**: DE-24 = "782" triggers YSP-specific processing
4. **Temp Transaction State**: Initial state = "CREATED", progresses through lifecycle
5. **Database Constraints**: Foreign key to acquirer_terminal ensures valid terminal association

### 9. **Error Handling**

```elixir
# If DE-41 missing
{:error, {:missing_required_fields, [41]}}

# If terminal not found/inactive  
{:error, :terminal_not_found}

# If database constraint violation
{:error, %Ecto.Changeset{errors: [acquirer_id: {"does not exist", ...}]}}
```

This flow ensures that every transaction **validates the terminal ID (DE-41) against the database** before creating the initial `pos_temp_transaction` record, exactly as your Java implementation would do with the three-phase approach (validate → create temp → process).