# Add-on Request Communication Flow Documentation

## Overview

The Add-on Request Communication System enables structured communication between Sales, Department, and Customer throughout the add-on request lifecycle. This system tracks all conversations, quotes, responses, and decisions in a centralized timeline.

## Communication Flow

### 1. Initial Request Creation
```
Sales → Creates Add-on Request
System → Auto-assigns to Department
System → Creates initial communication log
```

### 2. Sales Inquiry to Department
```
Sales → Sends inquiry with details
Department → Receives notification
System → Logs internal communication
```

### 3. Department Quote Response
```
Department → Provides quote with price
Sales → Receives notification
System → Logs internal quote communication
```

### 4. Sales Forward to Customer
```
Sales → Forwards quote to customer (public communication)
Customer → Receives quote with deadline
System → Creates customer response requirement
```

### 5. Customer Response
```
Customer → Responds (Accept/Reject/Negotiate)
Sales & Department → Receive notification
System → Logs customer response
System → Auto-generates follow-up actions
```

### 6. Sales Confirmation with Department
```
Sales → Confirms customer response with department
Department → Receives customer feedback
System → Logs internal confirmation
```

### 7. Department Final Action
```
Department → Completes/Modifies/Cancels request
Sales → Receives final confirmation
System → Updates request status
System → Logs completion
```

## Database Structure

### Communication Table Fields

| Field | Type | Description |
|-------|------|-------------|
| `addon_request_id` | Foreign Key | Links to main request |
| `user_id` | Foreign Key | Who sent the message |
| `sender_type` | Enum | sales/department/customer/system |
| `message_type` | Enum | inquiry/quote/confirmation/rejection/etc |
| `message` | Text | Message content |
| `quoted_price` | Decimal | Price if applicable |
| `customer_response` | Enum | pending/accepted/rejected/negotiating |
| `is_internal` | Boolean | Internal vs customer-visible |
| `requires_customer_response` | Boolean | Needs customer action |
| `customer_response_deadline` | DateTime | Response deadline |
| `attachments` | JSON | File attachments |

### Enums

#### SenderType
- `sales` - 業務
- `department` - 部門 (票務/線控/OP)
- `customer` - 客戶
- `system` - 系統自動訊息

#### MessageType
- `inquiry` - 詢問
- `quote` - 報價
- `confirmation` - 確認
- `rejection` - 拒絕
- `modification` - 修改
- `approval` - 核准
- `completion` - 完成
- `cancellation` - 取消
- `note` - 一般備註

#### CustomerResponse
- `pending` - 待回覆
- `accepted` - 接受
- `rejected` - 拒絕
- `negotiating` - 議價中

## API Endpoints

### Communication Management

```javascript
// Get communication timeline
GET /api/addon-requests/{id}/communications?include_internal=true

// Add general message
POST /api/addon-requests/{id}/communications
{
  "message": "Message content",
  "message_type": "note",
  "is_internal": false,
  "quoted_price": 1500.00
}

// Sales inquiry to department
POST /api/addon-requests/{id}/communications/sales-inquiry
{
  "message": "客戶無護照，想由旅行社代辦。"
}

// Department provides quote
POST /api/addon-requests/{id}/communications/department-quote
{
  "message": "護照代辦費用如下",
  "quoted_price": 1500.00,
  "customer_response_deadline": "2025-11-15T17:00:00Z"
}

// Sales forwards to customer
POST /api/addon-requests/{id}/communications/sales-forward
{
  "message": "護照代辦服務報價",
  "quoted_price": 1300.00,
  "customer_response_deadline": "2025-11-12T17:00:00Z"
}

// Customer responds
PATCH /api/addon-requests/communications/{id}/customer-response
{
  "customer_response": "accepted",
  "response_message": "客戶同意報價"
}

// Sales confirms with department
POST /api/addon-requests/{id}/communications/sales-confirm
{
  "message": "客戶已同意報價，請安排護照代辦",
  "customer_response": "accepted"
}

// Department final confirmation
POST /api/addon-requests/{id}/communications/department-final
{
  "message": "護照代辦已安排，預計3個工作天完成",
  "final_price": 1300.00
}
```

### Monitoring & Reports

```javascript
// Get pending customer responses
GET /api/addon-requests/communications/pending-responses

// Get communication statistics
GET /api/addon-requests/communications/stats?request_id=123

// Mark communication as read
PATCH /api/addon-requests/communications/{id}/mark-read
```

## Frontend Implementation

### Communication Timeline Component

```vue
<template>
  <div class="communication-timeline">
    <div class="timeline-header">
      <h3>溝通記錄</h3>
      <div class="timeline-actions">
        <button @click="showAddMessage = true" class="btn btn-primary">
          新增訊息
        </button>
        <label class="toggle">
          <input type="checkbox" v-model="showInternal">
          顯示內部訊息
        </label>
      </div>
    </div>
    
    <div class="timeline-content">
      <div 
        v-for="comm in communications" 
        :key="comm.id"
        class="timeline-item"
        :class="[
          `sender-${comm.sender_type}`,
          `message-${comm.message_type}`,
          { 'internal': comm.is_internal }
        ]"
      >
        <!-- Timeline marker -->
        <div class="timeline-marker">
          <i :class="`fas fa-${getSenderIcon(comm.sender_type)}`"></i>
        </div>
        
        <!-- Message content -->
        <div class="timeline-card">
          <div class="card-header">
            <div class="sender-info">
              <span class="sender-type">{{ comm.sender_label }}</span>
              <span class="user-name">{{ comm.user?.name }}</span>
              <span class="message-type" :class="`type-${comm.message_type}`">
                {{ comm.message_type_label }}
              </span>
            </div>
            <div class="timestamp">{{ comm.formatted_date }}</div>
          </div>
          
          <div class="card-body">
            <p class="message-text">{{ comm.message }}</p>
            
            <!-- Quote information -->
            <div v-if="comm.quoted_price" class="quote-info">
              <strong>報價: {{ comm.formatted_quoted_price }}</strong>
            </div>
            
            <!-- Customer response section -->
            <div v-if="comm.requires_customer_response" class="customer-response-section">
              <div class="response-status">
                <span class="label">客戶回覆狀態:</span>
                <span 
                  class="status-badge" 
                  :class="`status-${comm.customer_response}`"
                >
                  {{ comm.customer_response_label }}
                </span>
              </div>
              
              <div v-if="comm.customer_response_deadline" class="deadline">
                <span class="label">回覆期限:</span>
                <span 
                  class="deadline-date"
                  :class="{ 'overdue': comm.is_overdue }"
                >
                  {{ formatDateTime(comm.customer_response_deadline) }}
                </span>
              </div>
              
              <!-- Customer response actions -->
              <div 
                v-if="comm.can_customer_respond && canRespondAsCustomer" 
                class="response-actions"
              >
                <button 
                  @click="respondToMessage(comm, 'accepted')" 
                  class="btn btn-success btn-sm"
                >
                  接受
                </button>
                <button 
                  @click="respondToMessage(comm, 'rejected')" 
                  class="btn btn-danger btn-sm"
                >
                  拒絕
                </button>
                <button 
                  @click="respondToMessage(comm, 'negotiating')" 
                  class="btn btn-warning btn-sm"
                >
                  議價
                </button>
              </div>
            </div>
            
            <!-- Attachments -->
            <div v-if="comm.attachments?.length" class="attachments">
              <div class="attachment-list">
                <div 
                  v-for="attachment in comm.attachments" 
                  :key="attachment.id"
                  class="attachment-item"
                >
                  <i class="fas fa-paperclip"></i>
                  <a :href="attachment.url" target="_blank">
                    {{ attachment.name }}
                  </a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- Add Message Modal -->
    <communication-form-modal
      v-if="showAddMessage"
      :request="request"
      @close="showAddMessage = false"
      @message-sent="onMessageSent"
    />
    
    <!-- Customer Response Modal -->
    <customer-response-modal
      v-if="showResponseModal"
      :communication="selectedCommunication"
      :response-type="selectedResponseType"
      @close="showResponseModal = false"
      @response-sent="onResponseSent"
    />
  </div>
</template>

<script>
export default {
  name: 'CommunicationTimeline',
  props: {
    request: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      communications: [],
      showInternal: true,
      showAddMessage: false,
      showResponseModal: false,
      selectedCommunication: null,
      selectedResponseType: null,
      loading: false
    }
  },
  computed: {
    canRespondAsCustomer() {
      // This would be determined by user role/permissions
      return this.$auth.user.hasRole('customer') || this.$auth.user.hasRole('admin');
    }
  },
  async mounted() {
    await this.loadCommunications();
  },
  methods: {
    async loadCommunications() {
      this.loading = true;
      try {
        const response = await this.$http.get(
          `/api/addon-requests/${this.request.id}/communications`,
          {
            params: {
              include_internal: this.showInternal
            }
          }
        );
        this.communications = response.data.data;
      } catch (error) {
        this.$toast.error('載入溝通記錄失敗');
      } finally {
        this.loading = false;
      }
    },
    
    getSenderIcon(senderType) {
      const icons = {
        sales: 'user-tie',
        department: 'building',
        customer: 'user',
        system: 'robot'
      };
      return icons[senderType] || 'comment';
    },
    
    respondToMessage(communication, responseType) {
      this.selectedCommunication = communication;
      this.selectedResponseType = responseType;
      this.showResponseModal = true;
    },
    
    async onMessageSent() {
      this.showAddMessage = false;
      await this.loadCommunications();
      this.$toast.success('訊息已發送');
    },
    
    async onResponseSent() {
      this.showResponseModal = false;
      await this.loadCommunications();
      this.$toast.success('回覆已發送');
    },
    
    formatDateTime(date) {
      return new Date(date).toLocaleString('zh-TW');
    }
  },
  watch: {
    showInternal() {
      this.loadCommunications();
    }
  }
}
</script>
```

### Quick Action Buttons

```vue
<template>
  <div class="communication-quick-actions">
    <!-- Sales Actions -->
    <div v-if="isSales" class="action-group">
      <h4>業務操作</h4>
      <button @click="sendInquiry" class="btn btn-primary">
        詢問部門
      </button>
      <button @click="forwardToCustomer" class="btn btn-success">
        轉發給客戶
      </button>
      <button @click="confirmWithDepartment" class="btn btn-info">
        確認客戶回覆
      </button>
    </div>
    
    <!-- Department Actions -->
    <div v-if="isDepartment" class="action-group">
      <h4>部門操作</h4>
      <button @click="provideQuote" class="btn btn-warning">
        提供報價
      </button>
      <button @click="finalConfirmation" class="btn btn-success">
        最終確認
      </button>
    </div>
    
    <!-- Customer Actions -->
    <div v-if="isCustomer && hasPendingResponse" class="action-group">
      <h4>客戶回覆</h4>
      <button @click="acceptQuote" class="btn btn-success">
        接受報價
      </button>
      <button @click="rejectQuote" class="btn btn-danger">
        拒絕報價
      </button>
      <button @click="negotiateQuote" class="btn btn-warning">
        議價
      </button>
    </div>
  </div>
</template>
```

## Workflow Examples

### Example 1: Passport Service Request

1. **Sales creates request**: "客戶需要護照代辦服務"
2. **Sales inquiry**: "客戶無護照，想由旅行社代辦，請提供報價"
3. **Department quote**: "護照代辦費用 $1,500，包含所有手續費"
4. **Sales forward**: "護照代辦服務報價 $1,300，請於3天內回覆"
5. **Customer accepts**: "客戶同意報價"
6. **Sales confirm**: "客戶已同意，請安排護照代辦"
7. **Department complete**: "護照代辦已安排，預計5個工作天完成"

### Example 2: Flight Upgrade Request

1. **Sales creates request**: "客戶希望升等商務艙"
2. **Department quote**: "商務艙升等費用 $15,000 per person"
3. **Sales forward**: "商務艙升等報價 $14,000 per person"
4. **Customer negotiates**: "價格太高，能否優惠？"
5. **Sales confirm**: "客戶希望議價，請評估是否可調整"
6. **Department final**: "最終價格 $13,500 per person，不可再議"
7. **Customer accepts**: "客戶接受最終報價"

## Benefits

### 1. **Complete Audit Trail**
- Every communication is logged with timestamp
- Clear sender identification and message type
- Full history of price negotiations

### 2. **Structured Workflow**
- Predefined message types guide communication
- Automatic notifications keep everyone informed
- Customer response tracking with deadlines

### 3. **Internal vs External Communication**
- Internal messages for sales-department coordination
- Public messages visible to customers
- Flexible privacy controls

### 4. **Real-time Monitoring**
- Pending customer responses dashboard
- Overdue response alerts
- Communication statistics and analytics

### 5. **Integration with Request Lifecycle**
- Communication automatically updates request status
- Price changes reflected in request records
- Completion triggers final cost calculation

This communication system provides a complete solution for managing the complex interactions between sales, departments, and customers throughout the add-on request process, ensuring nothing falls through the cracks and maintaining a professional, organized approach to customer service.
