# Priority Community Node - Usage Guide and Examples

## Table of Contents
1. [Introduction](#introduction)
2. [Installation and Setup](#installation-and-setup)
3. [Authentication](#authentication)
4. [Available Resources](#available-resources)
5. [Detailed Usage Examples](#detailed-usage-examples)
6. [Tips and Tricks](#tips-and-tricks)
7. [Troubleshooting](#troubleshooting)

## Introduction

The Priority Community Node provides complete integration with Priority ERP systems through a comprehensive REST API based on OData v4.0. This node supports all Priority functionality including CRUD operations, advanced queries, attachments, text operations, batch operations, webhooks, and metadata management.

### Key Features:
- ✅ **Full Authentication**: Basic, PAT, OAuth2 with PKCE
- ✅ **CRUD Operations**: Create, Read, Update, Delete with validation
- ✅ **Advanced Queries**: $filter, $orderby, $select, $expand, $since, $top, $skip
- ✅ **Attachments**: Upload and download with Data URI support (v21.0+)
- ✅ **Text Operations**: HTML support with append/signature options
- ✅ **Batch Operations**: Multiple operations with dependencies
- ✅ **Webhooks**: Event notifications (requires Webhooks module)
- ✅ **Metadata**: System and version information
- ✅ **Composite Keys**: Support for multi-field entity keys
- ✅ **Incremental Sync**: $since parameter for efficient data synchronization
- ✅ **Performance Optimized**: Built-in pagination and query optimization

### Demo Environment
For testing, you can use the free demo environment:
- **URL**: `https://t.eu.priority-connect.online/odata/Priority/tabbtd38.ini/usdemo`
- **Username**: `apidemo`
- **Password**: `123`
- **Version**: 25.0

## Installation and Setup

### 1. Install the Node
```bash
npm install n8n-nodes-priority
```

### 2. Configure Credentials

#### Basic Authentication
```
Service Root URL: https://your-priority-server.com/odata/Priority/tabula.ini/your-company
Authentication: Basic
Username: your-username
Password: your-password
Application ID: (optional)
Application Key: (optional)
Language Code: 3 (US English)
```

#### Personal Access Token (PAT)
```
Service Root URL: https://your-priority-server.com/odata/Priority/tabula.ini/your-company
Authentication: Personal Access Token (PAT)
Access Token: your-pat-token
Application ID: (optional)
Application Key: (optional)
Language Code: 3 (US English)
```

#### OAuth2
```
Service Root URL: https://your-priority-server.com/odata/Priority/tabula.ini/your-company
Authentication: OAuth2
Client ID: your-client-id
Client Secret: your-client-secret
Auth URL: https://your-priority-server.com/accounts/connect/authorize
Access Token URL: https://your-priority-server.com/accounts/connect/token
Scope: openid rest_api
```

## Available Resources

### 1. Entity - Entity Operations
- **Get**: Retrieve single entity
- **Get Many**: Retrieve entity list with queries
- **Create**: Create new entity
- **Update**: Update existing entity
- **Delete**: Delete entity
- **Get Attachment**: Retrieve attachments
- **Upload Attachment**: Upload attachments

### 2. Metadata - System Information
- **Get Service Root**: Get available entities list
- **Get Metadata**: Get full system metadata
- **Get Entity Metadata**: Get specific entity metadata (v23.0+)
- **Get Priority Version**: Get Priority version
- **Get OData Version**: Get OData version
- **Refresh Metadata**: Refresh metadata (v22.0+)

### 3. Text - Text Operations
- **Get Text**: Retrieve text content
- **Set Text**: Set text content (HTML support)

### 4. Attachment - File Attachments
- **Get Attachments**: Get attachments list
- **Upload Attachment**: Upload new file
- **Download Attachment**: Download specific file

### 5. Batch - Multiple Operations
- **Execute Batch**: Execute multiple operations together

### 6. Webhook - Event Notifications
- **Subscribe**: Subscribe to events
- **Unsubscribe**: Unsubscribe from events
- **List Subscriptions**: List active subscriptions

## Detailed Usage Examples

### Example 1: Get Customer List with Advanced Filtering

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: CUSTOMERS  
**Query Options**:
```json
{
  "$select": "CUSTNAME,CUSTDES,EMAIL,PHONE,ADDRESS,STATENAME",
  "$filter": "STATENAME eq 'CA' and CUSTNAME ne 'T000001'",
  "$orderby": "CUSTDES asc",
  "$top": 100,
  "$expand": "CUSTNOTESA_SUBFORM($select=NOTE,CURDATE)"
}
```

**Result**:
```json
{
  "@odata.context": "serviceRoot/$metadata#CUSTOMERS",
  "value": [
    {
      "CUSTNAME": "C000001",
      "CUSTDES": "Acme Corporation",
      "EMAIL": "contact@acme.com",
      "PHONE": "+1-555-0123",
      "ADDRESS": "123 Main St",
      "STATENAME": "CA",
      "CUSTNOTESA_SUBFORM": [
        {
          "NOTE": "VIP Customer",
          "CURDATE": "2024-10-19T00:00:00+02:00"
        }
      ]
    }
  ]
}
```

### Example 1.1: Incremental Customer Sync

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: CUSTOMERS  
**Query Options**:
```json
{
  "$since": "2024-10-01T00:00:00Z",
  "$select": "CUSTNAME,CUSTDES,EMAIL,PHONE",
  "$orderby": "CUSTNAME"
}
```

**Use Case**: Sync only customers modified since a specific date (requires BPM module)

### Example 2: Create Order with Items

**Resource**: Entity  
**Operation**: Create  
**Collection**: ORDERS  
**JSON Body**:
```json
{
  "CUSTNAME": "C000001",
  "ORDERITEMS_SUBFORM": [
    {
      "PARTNAME": "P001",
      "TQUANT": 5,
      "DUEDATE": "2024-12-31T00:00:00+02:00"
    },
    {
      "PARTNAME": "P002", 
      "TQUANT": 3,
      "DUEDATE": "2024-12-31T00:00:00+02:00"
    }
  ]
}
```

### Example 2.1: Add Order Notes and Attachments

**Step 1 - Add Order Notes:**
**Resource**: Text  
**Operation**: Set  
**Collection**: ORDERS  
**Entity ID**: SO24001234  
**Text Field**: ORDERSTEXT_SUBFORM  
**Text Content**: 
```html
<p><strong>Important Order Notes:</strong></p>
<ul>
  <li>Rush delivery required</li>
  <li>Special packaging needed</li>
  <li>Contact customer before delivery</li>
</ul>
<p><em>Created via API on 2024-10-19</em></p>
```
**Append**: false  
**Signature**: false

**Step 2 - Upload Order Contract:**
**Resource**: Attachment  
**Operation**: Upload  
**Collection**: ORDERS  
**Entity ID**: SO24001234  
**JSON Body**:
```json
{
  "EXTFILEDES": "Order Contract",
  "EXTFILENAME": "data:application/pdf;base64,JVBERi0xLjQK...",
  "SUFFIX": ".pdf"
}
```

### Example 3: Advanced Query with Date Filtering

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: ORDERS  
**Query Options**:
```json
{
  "$filter": "CURDATE ge 2024-01-01T00:00:00+02:00 and TOTPRICE gt 1000",
  "$expand": "ORDERITEMS_SUBFORM($select=PARTNAME,TQUANT,PRICE)",
  "$select": "ORDNAME,CUSTNAME,CURDATE,TOTPRICE",
  "$orderby": "CURDATE desc",
  "$top": 20
}
```

### Example 4: Using $since for Incremental Sync

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: ORDERS  
**Query Options**:
```json
{
  "$since": "2024-01-15T06:00:00Z",
  "$select": "ORDNAME,CUSTNAME,CURDATE",
  "$expand": "ORDERITEMS_SUBFORM($select=PARTNAME,TQUANT)"
}
```
Use UTC (`Z`) for `$since` to avoid DST-related sync gaps.

### Example 5: Upload Attachment

**Resource**: Attachment  
**Operation**: Upload Attachment  
**Collection**: ORDERS  
**Entity ID**: SO200001  
**Attachment Subform**: EXTFILES_SUBFORM  
**File Description**: "Contract Document"  
**File Data**: "data:application/pdf;base64,JVBERi0xLjQKJcOkw7zDtsO..."  
**File Extension**: ".pdf"

### Example 6: Add Text with HTML

**Resource**: Text  
**Operation**: Set Text  
**Collection**: ORDERS  
**Entity ID**: SO200001  
**Text Field**: ORDERSTEXT_SUBFORM  
**Text Content**: "<p>Important Order</p><p><strong>Note:</strong> Please handle this order urgently</p>"  
**Append Mode**: true  
**Include Signature**: false

### Example 7: Batch Operations - Multiple Operations

**Resource**: Batch  
**Operation**: Execute Batch  
**Batch Operations**:
```json
[
  {
    "id": "1",
    "method": "POST",
    "url": "ORDERS",
    "body": {
      "CUSTNAME": "C000001"
    }
  },
  {
    "id": "2",
    "method": "POST", 
    "url": "$1/ORDERITEMS_SUBFORM",
    "dependsOn": ["1"],
    "body": {
      "PARTNAME": "P001",
      "TQUANT": 10
    }
  },
  {
    "id": "3",
    "method": "POST",
    "url": "$1/ORDERITEMS_SUBFORM", 
    "dependsOn": ["1"],
    "body": {
      "PARTNAME": "P002",
      "TQUANT": 5
    }
  }
]
```

### Example 8: Get System Information

**Resource**: Metadata  
**Operation**: Get Priority Version  

**Result**:
```json
{
  "@odata.context": "serviceRoot/$metadata#Edm.String",
  "value": "22.0-20.0.0.119"
}
```

### Example 9: Webhook - Subscribe to Events

**Resource**: Webhook  
**Operation**: Subscribe  
**Webhook URL**: "https://your-app.com/webhook"  
**Events**: ["created", "updated", "deleted"]  
**Entity Types**: "CUSTOMERS,ORDERS"

### Example 10: Query with Composite Keys

**Resource**: Entity  
**Operation**: Get  
**Collection**: AINVOICES  
**Entity ID**: "IVNUM='T9696',IVTYPE='A',DEBIT='D'"

### Example 11: Inventory Monitoring with Low Stock Alert

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: LOGPART  
**Query Options**:
```json
{
  "$filter": "ONHAND lt 10 and TYPE eq 'P'",
  "$select": "PARTNAME,PARTDES,ONHAND,MINBAL,LASTPRICE,FAMILYNAME",
  "$orderby": "ONHAND asc",
  "$top": 100
}
```

**Use Case**: Monitor inventory levels and alert when stock is below minimum balance

### Example 12: Daily Sales Report Generation

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: ORDERS  
**Query Options**:
```json
{
  "$filter": "CURDATE ge 2024-10-19T00:00:00+02:00 and CURDATE le 2024-10-19T23:59:59+02:00",
  "$select": "ORDNAME,CUSTNAME,CDES,CURDATE,TOTPRICE,ORDSTATUSDES",
  "$expand": "ORDERITEMS_SUBFORM($select=PARTNAME,PDES,TQUANT,PRICE,TOTPRICE)",
  "$orderby": "CURDATE desc"
}
```

**Use Case**: Generate comprehensive daily sales reports with product breakdown

### Example 13: Customer Sync with Incremental Updates

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: CUSTOMERS  
**Query Options**:
```json
{
  "$since": "2024-10-01T00:00:00Z",
  "$select": "CUSTNAME,CUSTDES,EMAIL,PHONE,ADDRESS,STATENAME",
  "$expand": "CUSTNOTESA_SUBFORM($select=NOTE,CURDATE)",
  "$orderby": "CUSTNAME"
}
```

**Use Case**: Efficiently sync only customers that have been modified since last sync

### Example 14: Complex Order Query with Multiple Filters

**Resource**: Entity  
**Operation**: Get Many  
**Collection**: ORDERS  
**Query Options**:
```json
{
  "$filter": "CUSTNAME eq 'C001' and CURDATE ge 2024-01-01T00:00:00+02:00 and TOTPRICE gt 500",
  "$select": "ORDNAME,CURDATE,TOTPRICE,ORDSTATUSDES",
  "$expand": "ORDERITEMS_SUBFORM($filter=PRICE gt 50;$select=PARTNAME,TQUANT,PRICE)",
  "$orderby": "CURDATE desc",
  "$top": 20
}
```

**Use Case**: Find high-value orders from specific customer with expensive items

### Example 15: Batch Operations with Dependencies

**Resource**: Batch  
**Operation**: Execute Batch  
**JSON Body**:
```json
{
  "requests": [
    {
      "id": "1",
      "method": "POST",
      "url": "ORDERS",
      "body": {
        "CUSTNAME": "C001"
      }
    },
    {
      "id": "2",
      "method": "POST",
      "url": "$1/ORDERITEMS_SUBFORM",
      "dependsOn": ["1"],
      "body": {
        "PARTNAME": "ITEM001",
        "TQUANT": 5,
        "DUEDATE": "2024-11-20T00:00:00+02:00"
      }
    },
    {
      "id": "3",
      "method": "POST",
      "url": "$1/ORDERSTEXT_SUBFORM",
      "dependsOn": ["1"],
      "body": {
        "TEXT": "<p>Order created via API</p>",
        "APPEND": false,
        "SIGNATURE": false
      }
    }
  ]
}
```

**Use Case**: Create order with items and notes in a single atomic operation

## Tips and Tricks

### 1. Performance Optimization
```json
// ❌ Bad - gets all fields
{
  "Collection": "CUSTOMERS"
}

// ✅ Good - gets only needed fields
{
  "Collection": "CUSTOMERS",
  "Query Options": {
    "$select": "CUSTNAME,CUSTDES,EMAIL"
  }
}
```

### 2. Smart $expand Usage
```json
// ❌ Bad - too deep expand
{
  "$expand": "ORDERITEMS_SUBFORM($expand=DEEP_SUBFORM($expand=DEEPER_SUBFORM))"
}

// ✅ Good - 2-3 levels max
{
  "$expand": "ORDERITEMS_SUBFORM($select=PARTNAME,TQUANT,PRICE)"
}
```

### 3. Correct Date Filtering
```json
// ❌ Bad - wrong date format
{
  "$filter": "CURDATE ge 2024-01-01"
}

// ✅ Good - ISO format with timezone
{
  "$filter": "CURDATE ge 2024-01-01T00:00:00+02:00"
}
```

### 4. Using $since for Sync
```json
// Instead of getting all data every time
{
  "Collection": "ORDERS"
}

// Use $since to get only changes
{
  "Collection": "ORDERS",
  "Query Options": {
    "$since": "2024-01-15T06:00:00Z"
  }
}
```

### 5. Batch Operations for Multiple Actions
```json
// Instead of 3 separate requests
// POST /ORDERS
// POST /ORDERS('SO001')/ORDERITEMS_SUBFORM
// POST /ORDERS('SO001')/ORDERITEMS_SUBFORM

// Use one Batch Operation
{
  "requests": [
    {"id": "1", "method": "POST", "url": "ORDERS", "body": {...}},
    {"id": "2", "method": "POST", "url": "$1/ORDERITEMS_SUBFORM", "dependsOn": ["1"], "body": {...}},
    {"id": "3", "method": "POST", "url": "$1/ORDERITEMS_SUBFORM", "dependsOn": ["1"], "body": {...}}
  ]
}
```

### 6. Composite Key Handling
```json
// For entities with multiple key fields (like AINVOICES)
{
  "Collection": "AINVOICES",
  "Entity ID": "IVNUM='INV001',IVTYPE='A',DEBIT='D'"
}
```

### 7. Advanced Filtering Patterns
```json
// Date range with multiple conditions
{
  "$filter": "CURDATE ge 2024-01-01T00:00:00+02:00 and CURDATE le 2024-12-31T23:59:59+02:00 and TOTPRICE gt 1000"
}

// String operations
{
  "$filter": "startswith(CUSTDES, 'ACME') or contains(CUSTDES, 'Corp')"
}

// Numeric comparisons
{
  "$filter": "ONHAND lt MINBAL and TYPE eq 'P'"
}
```

### 8. Demo Environment Testing
Use the free demo environment for testing:
- **URL**: `https://t.eu.priority-connect.online/odata/Priority/tabbtd38.ini/usdemo`
- **Username**: `apidemo`
- **Password**: `123`
- **Version**: 25.0

### 9. Performance Monitoring
```json
// Monitor response times and optimize queries
{
  "Collection": "ORDERS",
  "Query Options": {
    "$select": "ORDNAME,CURDATE,TOTPRICE",  // Only needed fields
    "$top": 100,  // Limit results
    "$orderby": "CURDATE desc"  // Use indexed fields
  }
}
```

## Troubleshooting

### Common Errors

#### 1. Authentication Error (401)
```
Error: Unauthorized
```
**Solution**: Check credentials and authentication settings

#### 2. Entity Not Found (404)
```
Error: Not Found
```
**Solution**: Verify Entity ID is correct and collection exists

#### 3. Validation Error (400)
```
Error: Bad Request
```
**Solution**: Check JSON Body and required parameters

#### 4. Permission Error (403)
```
Error: Forbidden
```
**Solution**: Check user permissions in Priority system

### Debugging

#### 1. Test Connection
```json
{
  "Resource": "Metadata",
  "Operation": "Get Service Root"
}
```

#### 2. Check Version
```json
{
  "Resource": "Metadata", 
  "Operation": "Get Priority Version"
}
```

#### 3. Check Metadata
```json
{
  "Resource": "Metadata",
  "Operation": "Get Entity Metadata",
  "Entity Name": "CUSTOMERS"
}
```

### Logging and Monitoring

1. **Enable detailed logs** in n8n
2. **Check the Response** for each request
3. **Use Error Handling** nodes
4. **Monitor performance** with $top and $skip

## Advanced Examples

### Example 1: Customer Sync with External CRM
```json
{
  "Resource": "Entity",
  "Operation": "Get Many", 
  "Collection": "CUSTOMERS",
  "Query Options": {
    "$since": "2024-01-01T00:00:00Z",
    "$select": "CUSTNAME,CUSTDES,EMAIL,PHONE,ADDRESS",
    "$expand": "CUSTNOTESA_SUBFORM($select=NOTE,CURDATE)",
    "$orderby": "CUSTNAME"
  }
}
```

### Example 2: Daily Sales Report
```json
{
  "Resource": "Entity",
  "Operation": "Get Many",
  "Collection": "ORDERS", 
  "Query Options": {
    "$filter": "CURDATE ge 2024-01-15T00:00:00+02:00 and CURDATE le 2024-01-15T23:59:59+02:00",
    "$select": "ORDNAME,CUSTNAME,CURDATE,TOTPRICE,ORDSTATUSDES",
    "$expand": "ORDERITEMS_SUBFORM($select=PARTNAME,TQUANT,PRICE)",
    "$orderby": "CURDATE desc"
  }
}
```

### Example 3: Low Stock Check
```json
{
  "Resource": "Entity",
  "Operation": "Get Many",
  "Collection": "LOGPART",
  "Query Options": {
    "$filter": "ONHAND lt 10 and TYPE eq 'P'",
    "$select": "PARTNAME,PARTDES,ONHAND,MINBAL,LASTPRICE",
    "$orderby": "ONHAND asc",
    "$top": 50
  }
}
```

### Example 4: Complex Order Creation
```json
{
  "Resource": "Batch",
  "Operation": "Execute Batch",
  "Batch Operations": [
    {
      "id": "1",
      "method": "POST",
      "url": "ORDERS",
      "body": {
        "CUSTNAME": "C000001",
        "CURDATE": "2024-01-15T00:00:00+02:00"
      }
    },
    {
      "id": "2", 
      "method": "POST",
      "url": "$1/ORDERITEMS_SUBFORM",
      "dependsOn": ["1"],
      "body": {
        "PARTNAME": "P001",
        "TQUANT": 10,
        "DUEDATE": "2024-02-01T00:00:00+02:00"
      }
    },
    {
      "id": "3",
      "method": "POST", 
      "url": "$1/ORDERSTEXT_SUBFORM",
      "dependsOn": ["1"],
      "body": {
        "TEXT": "<p>Special Order - Please handle urgently</p>",
        "APPEND": false,
        "SIGNATURE": true
      }
    }
  ]
}
```

## Summary

The Priority Community Node provides complete and comprehensive access to all Priority system functionality. With support for all authentication types, advanced CRUD operations, full OData queries, and advanced features like batch operations and webhooks, the node enables seamless and efficient integration with Priority systems.

### Useful Links:
- **npm Package**: https://www.npmjs.com/package/n8n-nodes-priority
- **GitHub Repository**: https://github.com/HirezRa/n8n-nodes-priority
- **Priority REST API Documentation**: https://prioritysoftware.github.io/restapi/
- **n8n Documentation**: https://docs.n8n.io/

---

*Created for n8n-nodes-priority v0.3.1*
