# Order Management Module - Bulk Buy Orders

## Overview

The Order Management module provides a **Bulk Buy Group** system where multiple members can participate in collective purchasing. An administrator creates bulk buy orders with items, and members can join by adding quantities to items they want. The system handles financial calculations including tax, freight sharing, and tracks member participation and payments.

## Core Concept

- **Admin** creates bulk buy orders with items/products
- **Members** (persons) join orders and specify quantities they want
- System tracks available quantities (Size - ordered quantities)
- Financial calculations: totals, tax (configurable rate), per-unit costs, proportional freight sharing
- Payment tracking per member
- Deadline enforcement prevents adding items after deadline

## Architecture Decisions

### 1. Terminology

#### Entity Naming Discussion

**Member Order vs Bulk Buy Order Request**

We need to decide on the naming for the entity representing a member's participation in a bulk buy order.

##### Option A: `MemberOrder` (Recommended)
```typescript
MemberOrder
├── Represents member's participation
├── Shorter, cleaner name
├── Follows pattern: BulkBuyOrder → MemberOrder
└── Status indicates request state (Pending, Confirmed, Paid)
```

**Pros:**
- ✅ Shorter and cleaner
- ✅ Consistent with naming pattern (BulkBuyOrder, BulkBuyOrderItem)
- ✅ Status field already indicates it's a "request" (Pending status)
- ✅ Matches existing codebase pattern
- ✅ Clear relationship: Member → Order

**Cons:**
- ❌ Less explicit about being a "request" to join

##### Option B: `BulkBuyOrderRequest`
```typescript
BulkBuyOrderRequest
├── More explicit about being a request
├── Clearly indicates relationship to BulkBuyOrder
└── Status indicates request state
```

**Pros:**
- ✅ More descriptive and explicit
- ✅ Clearly indicates it's a request to join a bulk buy order
- ✅ Better for documentation and understanding

**Cons:**
- ❌ Longer name
- ❌ Redundant (it's already a "request" conceptually)
- ❌ Breaks naming pattern consistency

#### Decision: `MemberOrder` (Recommended)

**Rationale:**
1. **Consistency**: Follows the pattern `BulkBuyOrder` → `MemberOrder` (parent → child relationship)
2. **Status Indicates State**: The status field (Pending, Confirmed, Paid) already communicates it's a request
3. **Shorter**: Better for code readability and API usage
4. **Clear Relationship**: `MemberOrder` clearly shows it's a member's order within a bulk buy order
5. **Existing Pattern**: Matches how other modules name related entities

**Final Terminology:**
- **Bulk Buy Order** - Main order created by admin (matches image requirements)
- **Bulk Buy Order Item** - Products/items in the order
- **Member Order** - Member's participation/request in a bulk buy order
- **Member Order Line** - Individual item quantities requested by member

### 2. Entity Relationships

```
BulkBuyOrder (Main Order)
├── supplierId → SupplierManagement.Supplier
├── statusId → Status (Open, Closed, Cancelled)
├── orderNumber (auto-generated via AXPIdentifierRule)
├── title
├── orderDate
├── deadlineDate (enforced - prevents adding items after)
├── freightAmount
└── total (calculated)

BulkBuyOrderItem (Items in Order)
├── bulkBuyOrderId → BulkBuyOrder
├── productId → ProductCatalog.Product
├── size (total quantity available)
├── quantityInOrder (sum of all member quantities)
├── price (per unit)
├── unit (from product or custom)
├── total (calculated: price × quantityInOrder × taxRate)
└── perUnitInclGst (calculated: total / size)

MemberOrder (Member's Participation)
├── bulkBuyOrderId → BulkBuyOrder
├── memberId → PersonManagement.Person (flexible for community participation)
├── statusId → Status (Pending, Confirmed, Paid, Cancelled)
├── productTotal (sum of all line totals)
├── freightShare (calculated: proportional to productTotal)
├── totalOwing (calculated: productTotal + freightShare)
└── paidDate

MemberOrderLine (Member's Item Quantities)
├── memberOrderId → MemberOrder
├── bulkBuyOrderItemId → BulkBuyOrderItem
├── quantity
├── price (from BulkBuyOrderItem)
└── lineTotal (calculated: price × quantity × taxRate)
```

### 3. Member Identification
- **Decision**: Use `PersonManagement.Person` directly
- **Rationale**: More flexible for community participation, doesn't require being a customer first
- **Alternative Considered**: `CustomerManagement.Customer` (rejected - too restrictive)

### 4. Product Relationship
- **Decision**: Reference `ProductCatalog.Product`
- **Rationale**: Consistent with platform architecture, leverages existing product catalog
- **Future**: May allow adding new products on-the-fly (saves back to Items List)

### 5. Other Items
- **Decision**: Skip for now (no `otherItemsTotal` field)
- **Rationale**: Can be added later if needed

## Financial Calculations

### 1. BulkBuyOrderItem Calculations

```typescript
// Total with tax
total = price × quantityInOrder × taxRate

// Per unit including GST
perUnitInclGst = total / size

// Available quantity
quantityAvailable = size - quantityInOrder
```

### 2. MemberOrderLine Calculations

```typescript
// Line total with tax
lineTotal = price × quantity × taxRate
```

### 3. MemberOrder Calculations

```typescript
// Product total (sum of all member order lines)
productTotal = sum(memberOrderLines.lineTotal)

// Freight share (proportional to product total)
freightShare = (productTotal / bulkBuyOrder.total) × freightAmount

// Total owing
totalOwing = productTotal + freightShare
```

### 4. Tax Rate
- **Source**: Settings (configurable per tenant)
- **Default**: 15% (1.15 multiplier)
- **Setting Key**: `OrderManagement:Setting:BulkBuy.TaxRate`
- **Scope**: Tenant-level

## Status Definitions

### BulkBuyOrder Status
- `open` - Accepting member orders
- `closed` - No longer accepting orders (admin closed)
- `cancelled` - Order cancelled

### MemberOrder Status
- `pending` - Created but not confirmed
- `confirmed` - Confirmed by admin
- `paid` - Payment received
- `cancelled` - Cancelled

## Permissions Structure

### Admin Permissions
```
BulkBuyOrders.Management
├── View
├── Create
├── Edit
├── Delete
└── Close
```

### Member Permissions
```
BulkBuyOrders.Member
├── View (open orders only)
├── CreateRequest (create member order)
├── UpdateRequest (update own member order)
└── DeleteRequest (delete own member order)
```

## Settings

### Tax Rate Setting
- **Key**: `OrderManagement:Setting:BulkBuy.TaxRate`
- **Type**: Number (percentage)
- **Default**: 15 (representing 15% = 1.15 multiplier)
- **Scope**: Tenant (T)
- **Widget**: NumberBox with min: 0, max: 100, format: percentage

## Identifier Rules

### Bulk Buy Order Number
- **Rule ID**: `order-management.bulk-buy-order-number`
- **Pattern**: `BBO-{YYYY}-{####}`
- **Example**: `BBO-2024-0001`
- **Scope**: Yearly reset
- **Entity**: `OrderManagement.BulkBuyOrder`

## Deadline Enforcement

- System prevents adding/editing items after `deadlineDate`
- Validation rules check deadline before allowing:
  - Creating new member orders
  - Updating existing member orders
  - Adding new member order lines

## Entity Features

### BulkBuyOrder
- Identifier plugin (auto-generate order number)
- Status plugin
- History plugin
- Lock plugin
- Compare plugin
- Notes plugin
- Related entities:
  - BulkBuyOrderItem (items in order)
  - MemberOrder (member participations)

### BulkBuyOrderItem
- Computed properties:
  - `total` (calculated)
  - `perUnitInclGst` (calculated)
  - `quantityAvailable` (calculated)
- Related to ProductCatalog.Product

### MemberOrder
- Status plugin
- History plugin
- Lock plugin
- Notes plugin
- Computed properties:
  - `productTotal` (sum of lines)
  - `freightShare` (calculated)
  - `totalOwing` (calculated)
- Related entities:
  - MemberOrderLine (item quantities)

### MemberOrderLine
- Simple line item entity
- Links MemberOrder to BulkBuyOrderItem
- Calculated `lineTotal`

## Module Structure

All feature-related providers are organized under a single feature folder `features/bulk-buy-order`:

```
order-management/
├── src/lib/
│   ├── const.ts                          # Module configuration
│   ├── settings.provider.ts              # Settings definitions
│   ├── settings.keys.ts                  # Setting key enums
│   ├── entity.provider.ts                # Entity factory provider
│   ├── permission-definition.provider.ts # Permission definitions
│   ├── permission.keys.ts                # Permission key enums
│   ├── menu.provider.ts                  # Menu definitions
│   ├── menu.keys.ts                      # Menu key enums
│   ├── order-management.module.ts       # Module registration
│   ├── entities/
│   │   ├── bulk-buy-order/
│   │   │   ├── bulk-buy-order.entity.ts
│   │   │   ├── bulk-buy-order.types.ts
│   │   │   └── index.ts
│   │   ├── bulk-buy-order-item/
│   │   │   ├── bulk-buy-order-item.entity.ts
│   │   │   ├── bulk-buy-order-item.types.ts
│   │   │   └── index.ts
│   │   ├── member-order/
│   │   │   ├── member-order.entity.ts
│   │   │   ├── member-order.types.ts
│   │   │   └── index.ts
│   │   └── member-order-line/
│   │       ├── member-order-line.entity.ts
│   │       ├── member-order-line.types.ts
│   │       └── index.ts
│   └── features/
│       └── bulk-buy-order/               # Single feature folder
│           ├── bulk-buy-order-status.provider.ts
│           ├── member-order-status.provider.ts
│           └── identifiers/
│               └── bulk-buy-order-number-identifier-rule.provider.ts
```

## Module Configuration

### Provider Registration with `provideLazyProvider`

The module uses `provideLazyProvider` for lazy-loaded providers to improve initial bundle size and load performance. This pattern is used for all class-based providers:

- **Status Providers**: Lazy loaded status definitions
- **Settings Provider**: Lazy loaded settings configuration
- **Permission Definition Provider**: Lazy loaded permission definitions
- **Menu Provider**: Lazy loaded menu definitions
- **Entity Definition Loader**: Lazy loaded entity provider
- **Feature Definition Provider**: Lazy loaded feature definitions

#### Status Providers

```typescript
provideLazyProvider(
  AXP_STATUS_PROVIDERS,
  () => import('./features/bulk-buy-order/bulk-buy-order-status.provider').then(m => m.AXMBulkBuyOrderStatusProvider)
),
provideLazyProvider(
  AXP_STATUS_PROVIDERS,
  () => import('./features/bulk-buy-order/member-order-status.provider').then(m => m.AXMMemberOrderStatusProvider)
),
```

#### Settings Provider

```typescript
provideLazyProvider(
  AXP_SETTING_DEFINITION_PROVIDER,
  () => import('./settings.provider').then(m => m.AXMOrderManagementSettingProvider)
),
```

#### Other Providers

```typescript
provideLazyProvider(
  AXP_PERMISSION_DEFINITION_PROVIDER,
  () => import('./permission-definition.provider').then(m => m.AXMOrderManagementPermissionDefinitionProvider)
),
provideLazyProvider(
  AXP_MENU_PROVIDER,
  () => import('./menu.provider').then(m => m.AXMOrderManagementMenuProvider)
),
provideLazyProvider(
  AXP_ENTITY_DEFINITION_LOADER,
  () => import('./entity.provider').then(m => m.AXMOrderManagementEntityProvider)
),
provideLazyProvider(
  AXP_FEATURE_DEFINITION_PROVIDER,
  () => import('./feature-definition.provider').then(m => m.AXMOrderManagementFeatureDefinitionProvider)
),
```

**Note:** Identifier rules use `useValue` since they are constants, not classes:

```typescript
{
  provide: AXP_IDENTIFIER_RULES,
  useValue: AXM_BULK_BUY_ORDER_NUMBER_IDENTIFIER_RULE,
  multi: true,
}
```

**Benefits:**
- Reduces initial bundle size
- Providers are only loaded when needed
- Automatic dependency injection context handling
- Cleaner code without manual factory functions

**Note:** Providers using `provideLazyProvider` don't need constructor injection - the platform handles dependency injection automatically.

## Menu Structure

### Final Menu Structure

Based on requirements, the menu structure is:

```
Order Management (Root Menu)
├── Bulk Buy Orders (Priority: 1, Admin only - with permissions)
│   └── Status plugin generates different views (Open, Closed, Cancelled)
│   └── Full CRUD access for admins
│
├── Available Orders (Priority: 2, Member only)
│   └── Read-only view of open bulk buy orders
│   └── Command to create new member-order (join order)
│
└── My Orders (Priority: 3, Member only)
    └── Status plugin generates different views (Pending, Confirmed, Paid, Cancelled)
    └── Member's own member orders across all bulk buy orders
```

### Menu Details

#### 1. Bulk Buy Orders (Admin Only)
- **Access**: Admin users with `BulkBuyOrders.Management` permission
- **Views**: Generated by status plugin (Open, Closed, Cancelled)
- **Actions**: Full CRUD (Create, Edit, Delete, Close)
- **Entity**: `BulkBuyOrder`

#### 2. Available Orders (Member Only)
- **Access**: Member users (any authenticated user)
- **View**: Read-only list of open bulk buy orders
- **Actions**: 
  - View order details
  - Command: "Create Member Order" (join the order)
- **Entity**: Virtual/read-only view of `BulkBuyOrder` filtered by status = "open"
- **Purpose**: Members can browse and join available orders

#### 3. My Orders (Member Only)
- **Access**: Member users (any authenticated user)
- **Views**: Generated by status plugin (Pending, Confirmed, Paid, Cancelled)
- **Actions**: View and update own member orders
- **Entity**: `MemberOrder` filtered by current user's person
- **Purpose**: Members manage their own participation in orders

### Navigation Items (Items, Suppliers, Users)

From the images, these are navigation shortcuts to other modules:
- **Items** → `ProductCatalog.Product` entity (separate module)
- **Suppliers** → `SupplierManagement.Supplier` entity (separate module)
- **Users** → `PersonManagement.Person` or `SecurityManagement.User` (separate modules)

These are likely:
- Related entity links in the entity detail view
- Quick navigation buttons in the admin landing page
- Not separate menu items in this module

### Menu Organization

Based on the requirements, the menu structure should support both admin and member views:

#### Root Menu
- **Title**: `@order-management:module.title` (e.g., "Order Management" or "Bulk Buy Orders")
- **Icon**: Module icon (`fa-light fa-file-invoice` or similar)
- **Priority**: 900050 (unique module priority)

#### Menu Items

**Option 1: Role-Based Menu Items**
```
Order Management (Root)
├── Bulk Buy Orders (Admin: all orders, Member: open orders only)
├── My Orders (Member only: their member orders)
└── Completed Orders (View only: both admin and member)
```

**Option 2: Single Entity with Views**
```
Order Management (Root)
└── Bulk Buy Orders
    ├── All Orders (Admin only)
    ├── Open Orders (Member view)
    ├── My Orders (Member only)
    └── Completed Orders (Both)
```

**Option 3: Based on Images (Admin Landing Page)**
```
Order Management (Root)
├── Bulk Buy Orders (Main entity - admin creates/manages)
├── Available Orders (Member view - open orders to join)
└── Completed Orders (View only - summary list)
```

**Note**: Items, Suppliers, and Users from the images are likely:
- **Items**: Links to `ProductCatalog.Product` (separate module)
- **Suppliers**: Links to `SupplierManagement.Supplier` (separate module)
- **Users**: Links to `SecurityManagement.User` or `PersonManagement.Person` (separate modules)

These are probably navigation shortcuts or related entity links, not separate menu items in this module.

### Recommended Menu Structure

```
Order Management
├── Bulk Buy Orders (Priority: 1)
│   └── Admin: Full CRUD, Member: View open orders only
├── My Orders (Priority: 2, Member only)
│   └── Member's own member orders
└── Completed Orders (Priority: 3, View only)
    └── Read-only view of closed orders
```

### Menu Keys

```typescript
export const AXMOrderManagementMenuKeys = {
  Root: 'OrderManagement:Menu',
  BulkBuyOrders: 'OrderManagement:Menu:BulkBuyOrders',
  AvailableOrders: 'OrderManagement:Menu:AvailableOrders',
  MyOrders: 'OrderManagement:Menu:MyOrders',
} as const;
```

### Menu Titles (i18n)

Translation keys for menu items:
- `@order-management:module.title` - Root menu title
- `@order-management:bulk-buy-orders.entities.bulk-buy-order.plural` - Bulk Buy Orders
- `@order-management:bulk-buy-orders.menus.available-orders.title` - Available Orders
- `@order-management:bulk-buy-orders.menus.my-orders.title` - My Orders

## Translation Structure

Translation keys follow the pattern: `@order-management:bulk-buy-orders.{section}.{key}`

### Sections
- `module` - Module-level metadata
- `entities` - Entity definitions
- `menus` - Menu item titles and descriptions
- `permissions` - Permission definitions
- `settings` - Settings definitions
- `actions` - Action labels
- `messages` - System messages
- `validations` - Validation messages

## Implementation TODO

> ⚠️ **Important Workflow Note**: After completing each phase, update:
> - **i18n translation files** (`apps/demo/src/assets/i18n/{en-US,fa-IR}/order-management.json`) with all translation keys used in that phase
> - **Mock data services** (`libs/connectivity/mock/src/lib/order-management/`) with mock data for entities and services implemented in that phase
> 
> This ensures translations and mock data stay in sync with the implementation and allows for incremental testing.

### Phase 1: Configuration & Foundation
- [x] Update `const.ts` with entity configurations (BulkBuyOrder, BulkBuyOrderItem, MemberOrder, MemberOrderLine)
- [x] Create BulkBuyOrderStatusProvider with statuses: open, closed, cancelled
- [x] Create MemberOrderStatusProvider with statuses: pending, confirmed, paid, cancelled
- [x] Create BulkBuyOrderNumberIdentifierRuleProvider for order number generation (BBO-{YYYY}-{####})
- [x] Create SettingsProvider with TaxRate setting (NumberBox widget, 15% default, tenant scope)
- [ ] **Update i18n files** with translations for: module metadata, status definitions, settings
- [ ] **Update mock data** if needed for settings/default values

### Phase 2: Entity Definitions
- [ ] Create BulkBuyOrder entity definition with plugins (identifier, status, history, lock, compare, notes) and related entities
- [ ] Create BulkBuyOrderItem entity definition with computed properties plugin (total, perUnitInclGst, quantityAvailable)
- [ ] Create MemberOrder entity definition with plugins (status, history, lock, notes) and computed properties plugin (productTotal, freightShare, totalOwing)
- [ ] Create MemberOrderLine entity definition (simple line item linking MemberOrder to BulkBuyOrderItem)
- [ ] **Update i18n files** with translations for: entity definitions, field titles, descriptions, placeholders, groups
- [ ] **Update mock data** with mock entities and services for all four entities

### Phase 3: Integration & Providers
- [ ] Update PermissionDefinitionProvider with BulkBuyOrders.Management and BulkBuyOrders.Member permissions
- [ ] Update MenuProvider with three menu items: Bulk Buy Orders (admin), Available Orders (member - separate query), My Orders (member)
- [ ] Update EntityProvider to register all four entity factories
- [ ] **Update i18n files** with translations for: permissions, menus
- [ ] **Update mock data** if needed for permission/menu testing

### Phase 4: Business Logic
- [ ] Implement financial calculation logic via computed properties plugin (tax rate application, freight sharing, totals)
- [ ] Implement deadline enforcement validation rules (both entity-level and command-level - prevent changes after deadlineDate)
- [ ] **Update i18n files** with translations for: validation messages, computed property labels
- [ ] **Update mock data** with realistic test data that exercises calculations and validations

## Implementation Decisions

1. **Computed Properties**: Implemented via `computed-property` plugin with expression-based values
2. **Deadline Validation**: Both entity-level and command-level validation
3. **Available Orders Menu**: Separate query (not just filtered view)
4. **Tax Rate**: Tenant-level only (configurable via settings)
5. **Member Identification**: PersonManagement.Person (not CustomerManagement.Customer)

## Future Enhancements

1. **Other Items Support**: Add ability to track additional items not in main product list
2. **Product Creation**: Allow creating new products on-the-fly from order items
3. **Advanced Freight Calculation**: Support different freight sharing methods
4. **Payment Integration**: Integration with payment systems
5. **Notifications**: Notify members of order status changes
6. **Reporting**: Analytics and reporting for bulk buy orders

## Dependencies

- `@acorex/modules/supplier-management` - For supplier references
- `@acorex/modules/product-catalog` - For product references
- `@acorex/modules/person-management` - For member identification
- `@acorex/modules/identifier-management` - For order number generation
- `@acorex/platform/common` - Core platform services
- `@acorex/platform/layout` - Entity and UI components

