Claude Code Plugins

Community-maintained marketplace

Feedback

Enterprise ERP Consultant

@Krosebrook/source-of-truth-monorepo
1
0

Expert guidance for enterprise resource planning systems, business logic, domain modeling, and ERP integration patterns. Use when building ERP systems, implementing business workflows, or integrating with ERP platforms.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name Enterprise ERP Consultant
description Expert guidance for enterprise resource planning systems, business logic, domain modeling, and ERP integration patterns. Use when building ERP systems, implementing business workflows, or integrating with ERP platforms.
version 1.0.0
allowed-tools Read, Write, Edit

Enterprise ERP Consultant

Enterprise resource planning architecture and business domain patterns.

Core ERP Modules

1. Financial Management

// Chart of Accounts
interface Account {
  code: string;
  name: string;
  type: 'asset' | 'liability' | 'equity' | 'revenue' | 'expense';
  parentCode?: string;
  balance: number;
}

// General Ledger Entry
interface JournalEntry {
  id: string;
  date: Date;
  description: string;
  lines: JournalLine[];
  posted: boolean;
}

interface JournalLine {
  accountCode: string;
  debit: number;
  credit: number;
  description: string;
}

// Double-entry bookkeeping validation
function validateJournalEntry(entry: JournalEntry): boolean {
  const totalDebit = entry.lines.reduce((sum, line) => sum + line.debit, 0);
  const totalCredit = entry.lines.reduce((sum, line) => sum + line.credit, 0);
  return Math.abs(totalDebit - totalCredit) < 0.01; // Allow for rounding
}

2. Inventory Management

from enum import Enum
from datetime import datetime
from pydantic import BaseModel, Field

class InventoryMethod(str, Enum):
    FIFO = "fifo"  # First In, First Out
    LIFO = "lifo"  # Last In, First Out
    AVERAGE = "average"  # Weighted Average

class StockMovement(BaseModel):
    product_id: str
    quantity: int
    movement_type: str  # 'in', 'out', 'adjustment'
    reference: str
    timestamp: datetime
    cost_per_unit: float = 0

class InventoryService:
    def __init__(self, method: InventoryMethod = InventoryMethod.FIFO):
        self.method = method
        self.stock_layers: dict[str, list[StockMovement]] = {}

    def receive_stock(self, product_id: str, quantity: int, cost: float):
        """Record stock receipt."""
        if product_id not in self.stock_layers:
            self.stock_layers[product_id] = []

        movement = StockMovement(
            product_id=product_id,
            quantity=quantity,
            movement_type='in',
            reference=f"PO-{datetime.now().timestamp()}",
            timestamp=datetime.now(),
            cost_per_unit=cost
        )
        self.stock_layers[product_id].append(movement)

    def issue_stock(self, product_id: str, quantity: int) -> float:
        """Issue stock and return COGS."""
        if product_id not in self.stock_layers:
            raise ValueError(f"Product {product_id} not found")

        layers = self.stock_layers[product_id]
        remaining = quantity
        cogs = 0.0

        if self.method == InventoryMethod.FIFO:
            for layer in layers:
                if remaining <= 0:
                    break
                issued = min(layer.quantity, remaining)
                cogs += issued * layer.cost_per_unit
                layer.quantity -= issued
                remaining -= issued

        return cogs

    def get_inventory_value(self, product_id: str) -> float:
        """Calculate current inventory value."""
        layers = self.stock_layers.get(product_id, [])
        return sum(layer.quantity * layer.cost_per_unit for layer in layers)

3. Order Management

// Order-to-Cash Process
interface SalesOrder {
  orderId: string;
  customerId: string;
  orderDate: Date;
  status: OrderStatus;
  lines: OrderLine[];
  totalAmount: number;
  paymentTerms: string;
}

enum OrderStatus {
  Draft = 'draft',
  Confirmed = 'confirmed',
  Shipped = 'shipped',
  Invoiced = 'invoiced',
  Paid = 'paid',
  Cancelled = 'cancelled',
}

interface OrderLine {
  productId: string;
  quantity: number;
  unitPrice: number;
  discount: number;
  taxRate: number;
  lineTotal: number;
}

class OrderWorkflow {
  async confirmOrder(orderId: string): Promise<void> {
    const order = await this.getOrder(orderId);

    // Check inventory availability
    for (const line of order.lines) {
      const available = await this.checkInventory(line.productId);
      if (available < line.quantity) {
        throw new Error(`Insufficient inventory for ${line.productId}`);
      }
    }

    // Reserve inventory
    for (const line of order.lines) {
      await this.reserveInventory(line.productId, line.quantity);
    }

    // Update order status
    await this.updateOrderStatus(orderId, OrderStatus.Confirmed);

    // Create shipment
    await this.createShipment(orderId);
  }

  async invoiceOrder(orderId: string): Promise<string> {
    const order = await this.getOrder(orderId);

    if (order.status !== OrderStatus.Shipped) {
      throw new Error('Order must be shipped before invoicing');
    }

    // Create invoice
    const invoice = await this.createInvoice(order);

    // Create accounting entries
    await this.createJournalEntry({
      date: new Date(),
      description: `Invoice ${invoice.id}`,
      lines: [
        { accountCode: '1200', debit: order.totalAmount, credit: 0 }, // AR
        { accountCode: '4000', debit: 0, credit: order.totalAmount }, // Revenue
      ],
    });

    // Update order status
    await this.updateOrderStatus(orderId, OrderStatus.Invoiced);

    return invoice.id;
  }
}

4. Manufacturing (MRP)

from datetime import datetime, timedelta
from typing import List

class BillOfMaterials(BaseModel):
    """Product structure definition."""
    product_id: str
    components: List['BOMComponent']

class BOMComponent(BaseModel):
    component_id: str
    quantity: float
    unit: str
    scrap_factor: float = 0.05  # 5% default scrap

class ManufacturingOrder(BaseModel):
    mo_id: str
    product_id: str
    quantity: float
    scheduled_start: datetime
    scheduled_end: datetime
    status: str  # 'draft', 'confirmed', 'in_progress', 'done'

class MRPEngine:
    """Material Requirements Planning."""

    def calculate_requirements(
        self,
        product_id: str,
        quantity: float,
        required_date: datetime
    ) -> List[dict]:
        """Calculate material requirements."""
        bom = self.get_bom(product_id)
        requirements = []

        for component in bom.components:
            net_quantity = quantity * component.quantity * (1 + component.scrap_factor)
            on_hand = self.get_on_hand(component.component_id)
            on_order = self.get_on_order(component.component_id)

            net_requirement = max(0, net_quantity - on_hand - on_order)

            if net_requirement > 0:
                # Calculate lead time
                lead_time = self.get_lead_time(component.component_id)
                order_date = required_date - timedelta(days=lead_time)

                requirements.append({
                    'component_id': component.component_id,
                    'quantity': net_requirement,
                    'required_date': required_date,
                    'order_date': order_date,
                    'action': 'purchase' if self.is_purchased(component.component_id) else 'manufacture'
                })

                # Recursively calculate for sub-assemblies
                if self.has_bom(component.component_id):
                    sub_requirements = self.calculate_requirements(
                        component.component_id,
                        net_requirement,
                        order_date
                    )
                    requirements.extend(sub_requirements)

        return requirements

5. Multi-Tenancy & Data Isolation

// Row-Level Security Pattern
interface TenantContext {
  tenantId: string;
  userId: string;
  permissions: string[];
}

class TenantAwareRepository<T> {
  constructor(
    private tenantContext: TenantContext,
    private db: Database
  ) {}

  async find(filters: any): Promise<T[]> {
    // Automatically add tenant filter
    return this.db.query({
      ...filters,
      tenant_id: this.tenantContext.tenantId,
    });
  }

  async create(data: Partial<T>): Promise<T> {
    // Automatically add tenant ID
    return this.db.insert({
      ...data,
      tenant_id: this.tenantContext.tenantId,
      created_by: this.tenantContext.userId,
    });
  }
}

// PostgreSQL RLS policy
const RLS_POLICY = `
CREATE POLICY tenant_isolation ON invoices
  FOR ALL
  USING (tenant_id = current_setting('app.current_tenant')::uuid);

ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
`;

6. Approval Workflows

from enum import Enum

class ApprovalStatus(str, Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"

class ApprovalRule(BaseModel):
    document_type: str
    amount_threshold: float
    approver_role: str
    sequence: int

class ApprovalWorkflow:
    def __init__(self):
        self.rules: List[ApprovalRule] = []

    def add_rule(self, rule: ApprovalRule):
        self.rules.append(rule)
        self.rules.sort(key=lambda r: r.sequence)

    async def submit_for_approval(
        self,
        document_type: str,
        document_id: str,
        amount: float
    ) -> str:
        """Submit document for approval."""
        applicable_rules = [
            rule for rule in self.rules
            if rule.document_type == document_type and amount >= rule.amount_threshold
        ]

        if not applicable_rules:
            # Auto-approve if no rules apply
            return await self.auto_approve(document_id)

        # Create approval requests
        for rule in applicable_rules:
            await self.create_approval_request(
                document_id=document_id,
                approver_role=rule.approver_role,
                sequence=rule.sequence
            )

        return "pending_approval"

    async def approve(self, approval_id: str, approver_id: str):
        """Process approval."""
        approval = await self.get_approval(approval_id)
        approval.status = ApprovalStatus.APPROVED
        approval.approved_by = approver_id
        approval.approved_at = datetime.now()

        # Check if all approvals complete
        all_approvals = await self.get_document_approvals(approval.document_id)
        if all(a.status == ApprovalStatus.APPROVED for a in all_approvals):
            await self.finalize_document(approval.document_id)

7. Audit Trail

interface AuditLog {
  id: string;
  tenantId: string;
  userId: string;
  action: 'create' | 'update' | 'delete';
  entityType: string;
  entityId: string;
  changes: Record<string, { old: any; new: any }>;
  timestamp: Date;
  ipAddress: string;
}

class AuditService {
  async logChange(
    entity: any,
    oldValues: any,
    action: string
  ): Promise<void> {
    const changes: Record<string, any> = {};

    for (const key in entity) {
      if (entity[key] !== oldValues?.[key]) {
        changes[key] = {
          old: oldValues?.[key],
          new: entity[key],
        };
      }
    }

    await this.createAuditLog({
      action,
      entityType: entity.constructor.name,
      entityId: entity.id,
      changes,
      timestamp: new Date(),
    });
  }
}

Integration Patterns

SAP Integration

from pyrfc import Connection

class SAPConnector:
    def __init__(self, config: dict):
        self.conn = Connection(**config)

    def create_sales_order(self, order_data: dict) -> str:
        """Create sales order in SAP."""
        result = self.conn.call(
            'BAPI_SALESORDER_CREATEFROMDAT2',
            ORDER_HEADER_IN=order_data['header'],
            ORDER_ITEMS_IN=order_data['items']
        )
        return result['SALESDOCUMENT']

When to Use: ERP development, business logic implementation, financial systems, inventory management, order processing.