Files
QuantEngineByItz/oms-wms-erp/PHASE2-ROADMAP.md
T
kjh2064 b34b0dd7d6
Validators (Pushes and Pull Requests) / UI & Storage Validation (pull_request) Failing after 12s
Validators (Pushes and Pull Requests) / Database & Schema Validation (pull_request) Successful in 13s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (pull_request) Failing after 28s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / CI Workflow Lint (pull_request) Failing after 10s
Validators (Pushes and Pull Requests) / Security & Secrets (pull_request) Successful in 12s
Validators (Pushes and Pull Requests) / Notify PR Results (pull_request) Successful in 2s
Frontend CI Pipeline / ci-frontend-8-steps (pull_request) Failing after 2m50s
Add OMS WMS ERP platform
2026-07-27 00:45:39 +09:00

11 KiB
Raw Blame History

Phase 2 Roadmap: Typed Fields & Pinia Stores

Duration: Week 3-4 (2026-08-12 → 2026-08-26)
Goal: Build Layer 2 (Typed Fields) + State Management (Pinia)


Phase 2 Structure

Step 1: Typed Fields (Layer 2) — Week 3

  • 12 Typed Field components
  • Validation & Formatting utilities
  • 100+ Storybook stories
  • 70+ integration tests

Step 2: Pinia Stores — Week 4

  • 10 store modules (orders, inventory, products, etc.)
  • API client setup
  • Mock Service Worker (MSW)
  • State management patterns

Step 3: API Integration — Week 4

  • OpenAPI SDK auto-generation
  • API client wrapper
  • Error handling middleware
  • Request/response interceptors

Step 4: Integration Testing — Week 4

  • Form validation chains
  • API mock testing (MSW)
  • State mutation testing
  • E2E test scenarios (50+)

Phase 2 Step 1: Typed Fields (Week 3)

Completed (5/12)

  1. TextField — Text inputs with validation

    • Types: text, email, password, url, tel
    • File: src/components/fields/typed/TextField/
    • Stories: 8+
    • Tests: 5+
  2. DateField — Date picker

    • Format: YYYY-MM-DD (ISO)
    • Min/Max validation
    • File: src/components/fields/typed/DateField/
    • Stories: 8+
    • Tests: 5+
  3. CurrencyField — Amount input with formatting

    • Locale: Korean (₩)
    • Decimals: configurable
    • File: src/components/fields/typed/CurrencyField/
    • Stories: 10+
    • Tests: 5+
  4. SelectField — Dropdown with validation

    • Options: typed array
    • Searchable: ready
    • File: src/components/fields/typed/SelectField/
    • Stories: 8+
    • Tests: 5+
  5. StatusField — Predefined status selector

    • Statuses: DRAFT, PENDING, APPROVED, ACTIVE, COMPLETED, CANCELLED, FAILED
    • Colors: status-based badges
    • File: src/components/fields/typed/StatusField/
    • Stories: 8+
    • Tests: 5+

Templates (7/12) — Ready to Implement

  1. TimeField (time picker, HH:mm)
  2. PercentageField (0-100%, formatted)
  3. QuantityField (positive integers)
  4. MultiSelectField (array of values)
  5. CheckboxField (boolean)
  6. SearchField (autocomplete with API)
  7. PhoneField (formatted phone)

Shared Utilities

useValidation.ts — Validation composable

- required, email, minLength, maxLength
- min, max, pattern, numeric
- positiveInteger, percentage, url
- Chainable: validator.validate(value, [rule1, rule2])

useFormatting.ts — Formatting composable

- formatCurrency, parseCurrency
- formatDate, parseDate, formatTime, parseTime
- formatPhone, parsePhone
- formatNumber, truncate, capitalize

Testing (Phase 2 Step 1)

Unit Tests: 5-8 per field × 12 = 60-96 tests

  • Props validation
  • Event emissions
  • Error handling
  • Formatting/parsing

Storybook: 8-12 stories per field × 12 = 96-144 stories

  • Default state
  • Disabled state
  • With error
  • With help text
  • With validation
  • Edge cases

Target: All stories render, all tests PASS by 2026-08-19


Phase 2 Step 2: Pinia Stores (Week 4)

10 Store Modules

src/stores/modules/
├── orders.ts           (OMS: Order management)
├── inventory.ts        (WMS: Stock levels)
├── products.ts         (ERP: Product master)
├── customers.ts        (OMS: Customer master)
├── suppliers.ts        (ERP: Supplier master)
├── stockTransfers.ts   (WMS: Stock movements)
├── glAccounts.ts       (ERP: GL accounting)
├── vouchers.ts         (ERP: Journal entries)
├── users.ts            (Admin: User management)
└── warehouses.ts       (WMS: Warehouse master)

Store Structure (Composition API)

// Each store follows this pattern:
export const useOrderStore = defineStore('orders', () => {
  // State
  const orders = ref<Order[]>([])
  const selectedOrder = ref<Order | null>(null)
  const loading = ref(false)
  const error = ref<string | null>(null)
  const filters = ref({...})

  // Computed
  const orderCount = computed(() => orders.value.length)
  const filteredOrders = computed(() => {...})
  const totalAmount = computed(() => {...})

  // Actions (async)
  const fetchOrders = async () => {...}
  const createOrder = async (payload) => {...}
  const updateOrder = async (id, payload) => {...}
  const deleteOrder = async (id) => {...}

  // Mutations
  const setFilter = (key, value) => {...}
  const clearFilters = () => {...}

  return {
    // State
    orders, selectedOrder, loading, error, filters,
    // Computed
    orderCount, filteredOrders, totalAmount,
    // Actions
    fetchOrders, createOrder, updateOrder, deleteOrder,
    // Mutations
    setFilter, clearFilters
  }
})

Example: Orders Store

// State
- orders: Order[]
- selectedOrder: Order | null
- loading: boolean
- error: string | null
- filters: {status, dateRange, customerId}

// Computed
- orderCount: number
- filteredOrders: Order[]
- totalAmount: number

// Actions
- fetchOrders(limit, offset)
- fetchOrderById(orderId)
- createOrder(payload)
- updateOrder(orderId, payload)
- deleteOrder(orderId)

// Mutations
- setFilter(key, value)
- clearFilters()

Store Setup (src/stores/index.ts)

export { useOrderStore } from './modules/orders'
export { useInventoryStore } from './modules/inventory'
export { useProductStore } from './modules/products'
export { useCustomerStore } from './modules/customers'
// ... etc

Usage in Components

<script setup lang="ts">
import { useOrderStore } from '@/stores'

const orderStore = useOrderStore()

// Access state
const orders = orderStore.orders
const loading = orderStore.loading

// Access computed
const filteredOrders = orderStore.filteredOrders

// Call actions
await orderStore.fetchOrders(100, 0)
await orderStore.createOrder({...})
</script>

Phase 2 Step 3: API Client Integration

OpenAPI SDK Generation

# From spec/63_oms_wms_erp_api_openapi.yaml
npx @openapi-generator/cli generate \
  -i ../../spec/63_oms_wms_erp_api_openapi.yaml \
  -g typescript-axios \
  -o src/services/api/generated

Generated Files

src/services/api/generated/
├── models/
│   ├── Order.ts
│   ├── OrderLine.ts
│   ├── Inventory.ts
│   └── ... (all 15 models)
├── apis/
│   ├── OrdersApi.ts
│   ├── InventoryApi.ts
│   ├── ProductsApi.ts
│   └── ... (all 11 resources)
└── index.ts

API Client Wrapper (src/services/api/client.ts)

import axios from 'axios'
import { Configuration, OrdersApi, InventoryApi, ... } from './generated'

const apiConfig = new Configuration({
  basePath: process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'
})

export const ordersApi = new OrdersApi(apiConfig)
export const inventoryApi = new InventoryApi(apiConfig)
export const productsApi = new ProductsApi(apiConfig)
// ... etc

Pinia Integration

// In store: const response = await ordersApi.listOrders({ limit, offset })
export const useOrderStore = defineStore('orders', () => {
  const fetchOrders = async () => {
    try {
      const response = await ordersApi.listOrders({ limit: 100, offset: 0 })
      orders.value = response.data
    } catch (err) {
      error.value = (err as Error).message
    }
  }
  // ...
})

Phase 2 Step 4: Integration Testing

Mock Service Worker (MSW) Setup

// tests/mocks/handlers.ts
import { http, HttpResponse } from 'msw'

export const handlers = [
  http.get('/api/orders', () => {
    return HttpResponse.json([
      { orderId: '1', orderNo: 'ORD-001', status: 'DRAFT', ... }
    ])
  }),
  http.post('/api/orders', ({ request }) => {
    return HttpResponse.json(
      { orderId: '2', orderNo: 'ORD-002', ... },
      { status: 201 }
    )
  }),
  // ... more handlers
]

Integration Test Example

// tests/integration/orders.spec.ts
describe('Orders Store with API', () => {
  beforeEach(() => {
    server.listen()
  })

  afterEach(() => {
    server.close()
  })

  it('fetches orders from API', async () => {
    const store = useOrderStore()
    await store.fetchOrders()
    expect(store.orders).toHaveLength(1)
    expect(store.orders[0].orderNo).toBe('ORD-001')
  })

  it('creates new order', async () => {
    const store = useOrderStore()
    const newOrder = await store.createOrder({ customerId: 'CUST-001' })
    expect(newOrder.orderId).toBe('2')
  })
})

E2E Test Scenarios (50+)

// tests/e2e/order-workflow.spec.ts
test('Complete order workflow', async ({ page }) => {
  // 1. Navigate to orders
  await page.goto('/admin/orders')
  
  // 2. Create order
  await page.click('button:text("Create")')
  await page.fill('[name="customerId"]', 'CUST-001')
  await page.fill('[name="quantity"]', '100')
  await page.click('button:text("Submit")')
  
  // 3. Verify order created
  await expect(page).toContainText('Order created')
  
  // 4. Edit order
  await page.click('button:text("Edit")')
  await page.fill('[name="quantity"]', '150')
  await page.click('button:text("Save")')
  
  // 5. Verify audit trail
  await page.goto('/admin/audit-logs')
  await expect(page).toContainText('Order updated')
})

Phase 2 Completion Criteria

By End of Week 3 (2026-08-19)

  • All 12 Typed Fields implemented
  • All Storybook stories rendering (100+ stories)
  • All unit tests passing (70+ tests)
  • Validation composable complete
  • Formatting composable complete

By End of Week 4 (2026-08-26)

  • All 10 Pinia stores implemented
  • OpenAPI SDK generated
  • API client wrapper complete
  • MSW setup for testing
  • 50+ integration tests passing
  • 50+ E2E test scenarios passing

Success Metrics

Metric Target Status
Typed Fields 12/12 5/12
Storybook Stories 100+ Planned
Unit Tests 70+ Planned
Integration Tests 50+ Planned
E2E Tests 50+ Planned
Code Coverage 70%+ Target
Lighthouse Score 90+ Target
Bundle Size <500MB Target

Timeline

Week 3 (2026-08-12 → 2026-08-19)
├─ Step 1.1: Generate 7 remaining Typed Fields (Mon-Tue)
├─ Step 1.2: Add Storybook stories for all 12 (Wed-Thu)
├─ Step 1.3: Add unit tests for all 12 (Fri)
└─ Deliverable: 12 Typed Fields, 100+ stories, 70+ tests ✅

Week 4 (2026-08-20 → 2026-08-26)
├─ Step 2.1: Create 10 Pinia store modules (Mon-Tue)
├─ Step 2.2: Setup OpenAPI SDK + API client (Wed)
├─ Step 2.3: Implement MSW + integration tests (Thu)
├─ Step 2.4: Add E2E test scenarios (Fri)
└─ Deliverable: Pinia stores, API client, 100+ tests ✅

Next: Phase 3 (Domain Fields, Week 5-6)

Status: 🚀 Phase 2 Started (2026-08-12)
Step 1 Progress: 5/12 Typed Fields (42%)
Timeline: 2 weeks (2026-08-12 → 2026-08-26)