npm package: @rashidazarang/propertyware-adapter
Description: PropertyWare SOAP API adapter for property management integrations
Author: Rashid Azarang
Latest version: 1.0.0

# PropertyWare Adapter

[![npm version](https://img.shields.io/npm/v/@pmip/propertyware-adapter)](https://www.npmjs.com/package/@pmip/propertyware-adapter)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/)

A TypeScript/JavaScript adapter for integrating with PropertyWare's SOAP API. This adapter provides a clean, promise-based interface for property management operations.

## 🚀 Features

- **Full CRUD Operations** for portfolios, buildings, work orders, leases, and tenants
- **Built-in Rate Limiting** (2 requests/second as per PropertyWare limits)
- **Automatic Retry Logic** with exponential backoff
- **Batch Operations Support** for efficient data processing
- **TypeScript Support** with full type definitions
- **Comprehensive Error Handling** with detailed error messages
- **Connection Pooling** for optimal performance

## 📦 Installation

```bash
npm install @pmip/propertyware-adapter
```

or

```bash
yarn add @pmip/propertyware-adapter
```

## 🔧 Configuration

```typescript
import { PropertyWareAdapter } from '@pmip/propertyware-adapter';

const adapter = new PropertyWareAdapter({
  username: 'your-username',
  password: 'your-password',
  url: 'https://api.propertyware.com',
  wsdl: 'https://api.propertyware.com/services?wsdl',
  options: {
    rateLimit: 2, // requests per second (default: 2)
    retryAttempts: 3, // number of retry attempts (default: 3)
    timeout: 30000, // request timeout in ms (default: 30000)
    batchSize: 100 // batch operation size (default: 100)
  }
});

// Initialize the connection
await adapter.connect();
```

## 📖 Usage Examples

### Basic Operations

#### Get All Portfolios
```typescript
const portfolios = await adapter.getPortfolios();
console.log(`Found ${portfolios.length} portfolios`);
```

#### Get Portfolio by ID
```typescript
const portfolio = await adapter.getPortfolio('4550688770');
console.log(portfolio.name);
```

#### Create Work Order
```typescript
const workOrder = await adapter.createWorkOrder({
  portfolioId: '4550688770',
  buildingId: '5031395333',
  unitId: '6789',
  type: 'Maintenance',
  priority: 'High',
  description: 'Fix leaking faucet',
  tenantId: '12345'
});
console.log(`Created work order: ${workOrder.id}`);
```

### Batch Operations

```typescript
// Batch fetch with automatic pagination
const allWorkOrders = await adapter.getWorkOrders({
  portfolioIds: ['4550688770', '4550688772'],
  status: 'Open',
  batchSize: 50
});

// Batch update
const updates = workOrders.map(wo => ({
  id: wo.id,
  status: 'In Progress'
}));
await adapter.batchUpdateWorkOrders(updates);
```

### Advanced Filtering

```typescript
// Get work orders with filters
const workOrders = await adapter.getWorkOrders({
  portfolioId: '4550688770',
  status: 'Open',
  priority: 'High',
  dateFrom: new Date('2025-01-01'),
  dateTo: new Date('2025-12-31')
});

// Get leases expiring soon
const expiringLeases = await adapter.getLeases({
  expiresWithin: 90, // days
  portfolioId: '4550688770'
});
```

### Error Handling

```typescript
try {
  const portfolio = await adapter.getPortfolio('invalid-id');
} catch (error) {
  if (error.code === 'PORTFOLIO_NOT_FOUND') {
    console.error('Portfolio not found');
  } else if (error.code === 'RATE_LIMIT_EXCEEDED') {
    console.error('Rate limit exceeded, please retry later');
  } else {
    console.error('Unexpected error:', error.message);
  }
}
```

## 🏗️ API Reference

### Portfolio Operations

- `getPortfolios(options?: PaginationOptions): Promise<Portfolio[]>`
- `getPortfolio(id: string): Promise<Portfolio>`
- `createPortfolio(data: PortfolioInput): Promise<Portfolio>`
- `updatePortfolio(id: string, data: Partial<PortfolioInput>): Promise<Portfolio>`
- `deletePortfolio(id: string): Promise<void>`

### Building Operations

- `getBuildings(portfolioId?: string): Promise<Building[]>`
- `getBuilding(id: string): Promise<Building>`
- `createBuilding(data: BuildingInput): Promise<Building>`
- `updateBuilding(id: string, data: Partial<BuildingInput>): Promise<Building>`
- `deleteBuilding(id: string): Promise<void>`

### Work Order Operations

- `getWorkOrders(filters?: WorkOrderFilters): Promise<WorkOrder[]>`
- `getWorkOrder(id: string): Promise<WorkOrder>`
- `createWorkOrder(data: WorkOrderInput): Promise<WorkOrder>`
- `updateWorkOrder(id: string, data: Partial<WorkOrderInput>): Promise<WorkOrder>`
- `batchUpdateWorkOrders(updates: WorkOrderUpdate[]): Promise<void>`

### Lease Operations

- `getLeases(filters?: LeaseFilters): Promise<Lease[]>`
- `getLease(id: string): Promise<Lease>`
- `createLease(data: LeaseInput): Promise<Lease>`
- `updateLease(id: string, data: Partial<LeaseInput>): Promise<Lease>`

### Tenant Operations

- `getTenants(options?: PaginationOptions): Promise<Tenant[]>`
- `getTenant(id: string): Promise<Tenant>`
- `createTenant(data: TenantInput): Promise<Tenant>`
- `updateTenant(id: string, data: Partial<TenantInput>): Promise<Tenant>`

## 🔒 Rate Limiting

PropertyWare enforces a rate limit of 2 requests per second. This adapter automatically handles rate limiting with:

- Built-in request queuing
- Automatic throttling
- Configurable rate limits
- Retry logic with exponential backoff

```typescript
// Configure custom rate limiting
const adapter = new PropertyWareAdapter({
  // ... credentials
  options: {
    rateLimit: 1, // More conservative: 1 request per second
    retryAttempts: 5,
    retryDelay: 2000 // Initial retry delay in ms
  }
});
```

## 🧪 Testing

```bash
# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run with coverage
npm run test:coverage
```

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📝 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🆘 Support

- **Documentation**: [Full API Documentation](https://github.com/rashidazarang/propertyware-adapter/wiki)
- **Issues**: [GitHub Issues](https://github.com/rashidazarang/propertyware-adapter/issues)
- **Discussions**: [GitHub Discussions](https://github.com/rashidazarang/propertyware-adapter/discussions)

## 🔗 Related Projects

- [PMIP Core](https://github.com/rashidazarang/property-management-integration-platform) - The main integration platform
- [ServiceFusion Adapter](https://github.com/rashidazarang/servicefusion-adapter) - ServiceFusion REST API adapter

## 📈 Roadmap

- [ ] Support for custom fields
- [ ] Webhook support
- [ ] File upload/download operations
- [ ] Report generation
- [ ] Bulk import/export
- [ ] GraphQL wrapper (optional)

## ⚠️ Disclaimer

This adapter is not officially affiliated with or endorsed by PropertyWare. PropertyWare is a registered trademark of RealPage, Inc.