# Employee-User Binding API Documentation

This document explains how to use the employee API endpoints to bind a Django User object to an Employee object, either during creation or update operations. It also includes information about the UserProfile model which extends the Django User model with merchant association.

## 1. Model Relationship Overview

### 1.1 Core Model Relationships
The system has three key models related to user management:
- `django.contrib.auth.models.User`: Django's built-in user model for authentication
- `Employee`: Represents an employee in the system
- `UserProfile`: Extends the User model with additional information (merchant association)

### 1.2 Field Relationships
- `Employee` has a **one-to-one** field `sys_user` that references `django.contrib.auth.models.User`
  - Field name: `sys_user`
  - It accepts the User ID as input
  - It's a nullable field, so an Employee can exist without being bound to a User initially

- `UserProfile` has a **one-to-one** field `user` that references `django.contrib.auth.models.User`
  - Field name: `user`
  - It also has a `merchant` field that links the user to a specific merchant
  - A User can have only one UserProfile, and a UserProfile belongs to only one merchant

### 1.3 Relationship Diagram
```
+------------------------+       +------------------------+
| django.contrib.auth.User|       | Employee               |
+------------------------+       +------------------------+
| id                     |       | id                     |
| username               |<----->| sys_user               | (one-to-one)
| email                  |       | name                   |
| password               |       | position               |
+------------------------+       +------------------------+

+------------------------+       +------------------------+
| django.contrib.auth.User|       | UserProfile            |
+------------------------+       +------------------------+
| id                     |<----->| user                   | (one-to-one)
| username               |       | merchant               |
| email                  |       | description            |
| password               |       +------------------------+
+------------------------+
```

## 2. API Endpoints

### 2.1 Employee API Endpoints
Base URL: `/api_man/employees/`

| Method | URL Pattern | Action |
|--------|-------------|--------|
| GET | `/api_man/employees/` | List all employees |
| GET | `/api_man/employees/{id}/` | Retrieve a single employee |
| POST | `/api_man/employees/` | Create a new employee |
| PUT | `/api_man/employees/{id}/` | Update an existing employee |
| PATCH | `/api_man/employees/{id}/` | Partially update an existing employee |
| DELETE | `/api_man/employees/{id}/` | Delete an employee |

### 2.2 UserProfile API Endpoints
Base URL: `/api_man/user-profiles/`

| Method | URL Pattern | Action |
|--------|-------------|--------|
| GET | `/api_man/user-profiles/` | List all user profiles |
| GET | `/api_man/user-profiles/{id}/` | Retrieve a single user profile |
| POST | `/api_man/user-profiles/` | Create a new user profile |
| PUT | `/api_man/user-profiles/{id}/` | Update an existing user profile |
| PATCH | `/api_man/user-profiles/{id}/` | Partially update an existing user profile |
| DELETE | `/api_man/user-profiles/{id}/` | Delete a user profile |

### 2.3 User Creation API Endpoint
Base URL: `/api_v1/users/`

| Method | URL Pattern | Action |
|--------|-------------|--------|
| POST | `/api_v1/users/create/` | Create a new User and associated UserProfile |

## 3. Binding User to Employee

### 3.1 During Employee Creation
When creating a new Employee, you can directly include the `sys_user` field with the User ID to bind them immediately.

#### Request Body Example:
```json
{
  "name": "张三",
  "position": 1,  // EmployeeType ID
  "mobile": "13800138000",
  "status": "在职",
  "sys_user": 123  // User ID to bind
}
```

#### Response Example:
```json
{
  "id": 456,
  "name": "张三",
  "position": { "id": 1, "name": "仓库管理员" },
  "mobile": "13800138000",
  "status": "在职",
  "sys_user": 123,  // User ID is now bound
  // Other fields...
}
```

### 3.2 During Employee Update
To bind an existing User to an existing Employee, use the PUT or PATCH method and include the `sys_user` field.

#### PUT Request Body Example (Full Update):
```json
{
  "name": "张三",
  "position": 1,
  "mobile": "13800138000",
  "status": "在职",
  "sys_user": 123  // New User ID to bind
}
```

#### PATCH Request Body Example (Partial Update):
```json
{
  "sys_user": 123  // User ID to bind
}
```

#### Response Example:
```json
{
  "id": 456,
  "name": "张三",
  "position": { "id": 1, "name": "仓库管理员" },
  "mobile": "13800138000",
  "status": "在职",
  "sys_user": 123,  // User ID is now bound
  // Other fields...
}
```

### 3.3 Unbinding User from Employee
To unbind a User from an Employee, set the `sys_user` field to `null` using PUT or PATCH.

#### PATCH Request Body Example:
```json
{
  "sys_user": null
}
```

#### Response Example:
```json
{
  "id": 456,
  "name": "张三",
  "position": { "id": 1, "name": "仓库管理员" },
  "mobile": "13800138000",
  "status": "在职",
  "sys_user": null,  // User is now unbound
  // Other fields...
}
```

## 4. UserProfile Management

### 4.1 Creating a UserProfile
When creating a new UserProfile, you need to provide the User ID and Merchant ID.

#### Request Body Example:
```json
{
  "user": 123,  // User ID
  "merchant": 1,  // Merchant ID
  "description": "User profile for system access"
}
```

#### Response Example:
```json
{
  "id": 789,
  "user": {
    "id": 123,
    "username": "system_user",
    "email": "user@example.com",
    "is_active": true,
    "is_superuser": false,
    "last_login": "2025-11-24T12:34:56Z"
  },
  "merchant": 1,
  "description": "User profile for system access",
  "created_at": "2025-11-24T13:00:00Z",
  "updated_at": "2025-11-24T13:00:00Z"
}
```

### 4.2 Updating a UserProfile
To update an existing UserProfile, use the PUT or PATCH method.

#### PATCH Request Body Example (Partial Update):
```json
{
  "description": "Updated user profile for system access"
}
```

#### Response Example:
```json
{
  "id": 789,
  "user": {
    "id": 123,
    "username": "system_user",
    "email": "user@example.com",
    "is_active": true,
    "is_superuser": false,
    "last_login": "2025-11-24T12:34:56Z"
  },
  "merchant": 1,
  "description": "Updated user profile for system access",
  "created_at": "2025-11-24T13:00:00Z",
  "updated_at": "2025-11-24T13:30:00Z"
}
```

## 5. Creating User with Profile

### 5.1 User and Profile Creation
This API creates a new Django User and associated UserProfile in a single request. The UserProfile links the User to a specific Merchant.

#### Request Body Example:
```json
{
  "username": "newuser",
  "email": "newuser@example.com",
  "password": "securepass123",
  "is_staff": false,
  "description": "New user account",
  "merchant_id": 1
}
```

#### Request Parameters:
- `username` (required): The username for the new user account
- `email` (optional): The email address for the user
- `password` (required): The password for the user account (minimum 6 characters)
- `is_staff` (optional, default: false): Whether the user should have staff privileges
- `description` (optional): Description for the UserProfile
- `merchant_id` (required): ID of the merchant to associate with the user

#### Response Example:
```json
{
  "user": {
    "id": 124,
    "username": "newuser",
    "email": "newuser@example.com",
    "is_staff": false,
    "is_active": true,
    "date_joined": "2025-11-24T14:00:00Z"
  },
  "profile": {
    "id": 790,
    "user": {
      "id": 124,
      "username": "newuser",
      "email": "newuser@example.com",
      "is_staff": false,
      "is_active": true,
      "date_joined": "2025-11-24T14:00:00Z"
    },
    "merchant": 1,
    "description": "New user account",
    "created_at": "2025-11-24T14:00:00Z",
    "updated_at": "2025-11-24T14:00:00Z"
  }
}
```

### 5.2 Authentication Requirements
- The request must be authenticated with a valid user session
- The authenticated user must have appropriate permissions to create new users

### 5.3 Validation Rules
- Username must be unique across the system
- Password must be at least 6 characters long
- merchant_id must correspond to an existing merchant in the system

## 6. Validation Rules

### 5.1 Employee-User Binding Rules
1. **One-to-one constraint**: A User can only be bound to one Employee at a time.
2. **Permission check**: Only super users or users with appropriate permissions can perform binding operations.
3. **User existence**: The provided User ID must exist in the system.
4. **Merchant isolation**: Both the User (via UserProfile) and Employee must belong to the same Merchant.

### 5.2 UserProfile Rules
1. **One-to-one constraint**: A User can only have one UserProfile at a time.
2. **Permission check**: Only users with appropriate permissions can access UserProfiles from the same merchant.
3. **User existence**: The provided User ID must exist in the system.
4. **Merchant existence**: The provided Merchant ID must exist in the system.

## 6. Error Handling

### User already bound to another Employee
```json
{
  "sys_user": [
    "User with id 123 is already bound to an existing employee."
  ]
}
```

### User already has a UserProfile
```json
{
  "user": [
    "User with id 123 already has a UserProfile."
  ]
}
```

### 6.1 User Creation API Errors

#### Username already exists
```json
{
  "username": [
    "用户名已存在"
  ]
}
```

#### Merchant does not exist
```json
{
  "merchant_id": [
    "商户不存在"
  ]
}
```

#### Password too short
```json
{
  "password": [
    "Ensure this field has at least 6 characters."
  ]
}
```

#### Unauthenticated request
```json
{
  "error": "未授权"
}
```

#### Server error during creation
```json
{
  "error": "创建用户失败: [detailed error message]"
}
```

## 7. Usage Examples

### 7.1 Creating a Complete User Flow
```bash
# 1. Create a new user with profile
curl -X POST http://localhost/api/v1/users/create/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer [token]" \
  -d '{
    "username": "john_doe",
    "email": "john@example.com",
    "password": "securepass123",
    "description": "Store employee",
    "merchant_id": 1
  }'

# Response will contain both user and profile IDs
# Use the user ID to create an Employee record and bind the user
curl -X POST http://localhost/api_man/employees/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer [token]" \
  -d '{
    "name": "John Doe",
    "position": 1,
    "mobile": "1234567890",
    "sys_user": 124  # User ID from the previous response
  }'
```

### Invalid User ID
```json
{
  "sys_user": [
    "Invalid pk \"999\" - object does not exist."
  ]
}
```

### Permission denied
```json
{
  "detail": "无权限创建该对象"
}
```

## 7. Front-End Implementation Tips

1. **User selection flow**: 
   - First fetch the list of available Users with active UserProfiles
   - Then allow users to select from this list when binding to an Employee
   
2. **State management**: 
   - After binding, update the UI to reflect the bound status
   - Ensure consistency between User, UserProfile, and Employee data

3. **Error handling**: 
   - Implement proper error messages based on the API responses
   - Distinguish between binding errors and UserProfile management errors

4. **Data consistency**: 
   - Ensure that the User and Employee belong to the same Merchant
   - Verify that a User has a UserProfile before attempting to bind to an Employee

## 8. Example Workflow

### Full Workflow (Creating User, UserProfile, and Bound Employee)
1. **Create User**: First create a User via Django's authentication system.
2. **Fetch User ID**: Retrieve the User ID from the response.
3. **Create UserProfile**: Create a UserProfile and include the User ID and Merchant ID.
4. **Create Employee**: Create an Employee and include the User ID in the `sys_user` field to bind them.
5. **Verify binding**: Retrieve the Employee to confirm the User is bound.

### Partial Workflow (Binding Existing User to Existing Employee)
1. **Fetch existing User**: Retrieve User IDs that have active UserProfiles.
2. **Fetch existing Employee**: Retrieve the Employee to bind to.
3. **Update Employee**: Update the Employee with the User ID to bind them.
4. **Verify binding**: Retrieve the Employee to confirm the User is bound.
