LLM TypeScript 문제 제출 Gpt Sol m


[문제 1]
# TypeScript Coding Task: Asynchronous Order Fulfillment Processor

Implement an asynchronous TypeScript function that validates customer orders, resolves duplicate order events, checks product inventory, processes payments, and returns final order and inventory summaries.

## Function to Implement

```typescript
async function processOrders(
  products: unknown[],
  events: unknown[],
  authorizePayment: (customerId: string, amount: number) => Promise<boolean>
): Promise<{
  orders: OrderSummary[];
  inventory: InventorySummary[];
}>
```

Do not change the required function signature.

---

# 1. Product Input

`products` may contain objects and invalid values.

A valid product must contain:

```typescript
{
  productId: string;
  price: number;
  stock: number;
}
```

Validation rules:

* `productId` must be a non-empty string.
* `price` must be a finite positive number.
* `stock` must be a non-negative integer.
* Boolean values are invalid numbers.
* Numeric strings must not be converted.
* `NaN`, `Infinity`, and `-Infinity` are invalid.
* Extra fields may be ignored.

Examples of invalid values:

```typescript
{ productId: "", price: 10, stock: 2 }
{ productId: "P1", price: "10", stock: 2 }
{ productId: "P1", price: Infinity, stock: 2 }
{ productId: "P1", price: 10, stock: 1.5 }
{ productId: "P1", price: 10, stock: true }
```

## Duplicate Product IDs

If the same valid `productId` appears more than once, keep only the last valid occurrence.

An invalid later occurrence must not replace an earlier valid product.

All later processing must use only the final surviving products.

A product appearing only in a discarded duplicate must leave no residual effect.

---

# 2. Order Events

`events` may contain objects and invalid values.

Each valid event must contain:

```typescript
{
  eventId: string;
  orderId: string;
  timestamp: string;
  type: "place" | "cancel";
  customerId: string;
  items: Array<{
    productId: string;
    quantity: number;
  }>;
}
```

## General Event Validation

* `eventId` must be a non-empty string.
* `orderId` must be a non-empty string.
* `customerId` must be a non-empty string.
* `type` must be exactly `"place"` or `"cancel"`.
* `timestamp` must be valid.
* `items` must be an array.
* Extra fields may be ignored.

---

# 3. Timestamp Rules

Accept only the exact format:

```text
YYYY-MM-DDTHH:mm:ssZ
```

Examples:

```text
2026-07-01T09:00:00Z
2026-12-31T23:59:59Z
```

Reject:

```text
2026-7-1T9:00:00Z
2026-07-01 09:00:00
2026-07-01T25:00:00Z
2026-02-30T10:00:00Z
2026-07-01T09:00:00+09:00
```

Do not rely only on `Date.parse()` because it may accept unsupported formats.

The input string must exactly match the required format and represent a real UTC date and time.

---

# 4. Item Validation

For a `"place"` event:

* `items` must contain at least one item.
* Every item must be an object.
* `productId` must be a non-empty string.
* `quantity` must be a positive integer.
* Boolean quantities are invalid.
* Numeric strings must not be converted.
* Every referenced product must exist after product duplicate handling.
* The same `productId` must not appear more than once in one event.

If any item is invalid, ignore the entire event.

For a `"cancel"` event:

* `items` must be an empty array.
* Any cancel event with non-empty items is invalid.

---

# 5. Duplicate Event IDs

If the same valid `eventId` appears more than once, keep only the last valid occurrence.

An invalid later occurrence must not replace an earlier valid event.

Only final surviving events may affect orders, customers, products, counters, or output.

A customer, order, or product referenced only by a discarded event must leave no residual effect.

---

# 6. Event Processing Order

After validation and duplicate resolution, process events in this order:

1. `timestamp` ascending
2. `eventId` ascending when timestamps are equal

---

# 7. Order Lifecycle

Each `orderId` may have one of these states:

```text
not created
confirmed
cancelled
rejected
```

Once an order becomes `confirmed`, `cancelled`, or `rejected`, later `"place"` events for the same `orderId` must be rejected as duplicate order attempts.

A cancelled or rejected order cannot be reopened.

---

# 8. Place Event Processing

For a valid `"place"` event:

## Duplicate Order Attempt

If the `orderId` has already been processed by an earlier accepted or rejected place event:

* Reject the event.
* Do not call `authorizePayment`.
* Do not change inventory.
* Increase that order’s `rejectedEventCount`.

## Inventory Check

Calculate required stock using the event items.

If any product has insufficient stock:

* Reject the entire order.
* Do not call `authorizePayment`.
* Do not reduce any inventory.
* Set order status to `"rejected"`.
* Set rejection reason to `"INSUFFICIENT_STOCK"`.

Partial fulfillment is not allowed.

## Total Amount

Calculate:

```text
totalAmount = sum(product.price × quantity)
```

Round the final total to two decimal places.

Do not round individual line items before summation.

## Payment Authorization

If inventory is sufficient, call:

```typescript
await authorizePayment(customerId, totalAmount)
```

The function may:

* Resolve to `true`
* Resolve to `false`
* Reject by throwing an error

### Payment Approved

If it resolves to `true`:

* Confirm the order.
* Reduce all required product stock atomically.
* Set status to `"confirmed"`.
* Set rejection reason to `null`.

### Payment Declined

If it resolves to `false`:

* Do not change inventory.
* Set status to `"rejected"`.
* Set rejection reason to `"PAYMENT_DECLINED"`.

### Payment Error

If it rejects or throws:

* Do not change inventory.
* Set status to `"rejected"`.
* Set rejection reason to `"PAYMENT_ERROR"`.

Process payment calls sequentially in event order.

Do not run payment authorizations in parallel.

---

# 9. Cancel Event Processing

For a valid `"cancel"` event:

## Confirmed Order

If the order is confirmed:

* Restore all reserved stock.
* Change status to `"cancelled"`.
* Set `cancelledAt` to the normalized event timestamp.
* Increase `acceptedCancellationCount`.
* Do not call `authorizePayment`.

## Order Already Cancelled

Reject the event.

* Do not change inventory.
* Increase `rejectedEventCount`.

## Rejected Order

Reject the event.

* Do not change inventory.
* Increase `rejectedEventCount`.

## Unknown Order

Ignore the event completely.

Do not create an order summary for a cancel event whose `orderId` was never created by a valid surviving place event.

---

# 10. Order Summary Output

Return one summary for every order created by a valid surviving `"place"` event.

```typescript
interface OrderSummary {
  orderId: string;
  customerId: string;
  status: "confirmed" | "cancelled" | "rejected";
  items: Array<{
    productId: string;
    quantity: number;
    unitPrice: number;
    lineTotal: number;
  }>;
  totalAmount: number;
  rejectionReason:
    | "INSUFFICIENT_STOCK"
    | "PAYMENT_DECLINED"
    | "PAYMENT_ERROR"
    | null;
  placedAt: string;
  cancelledAt: string | null;
  acceptedCancellationCount: number;
  rejectedEventCount: number;
}
```

Rules:

* `items` must be sorted by `productId` ascending.
* `lineTotal` must be rounded to two decimal places.
* `totalAmount` must be rounded to two decimal places.
* Rejected orders must still include their validated items and calculated total.
* Orders rejected before payment due to insufficient stock must not call the payment function.
* Sort order summaries by:

  1. `placedAt` ascending
  2. `orderId` ascending

---

# 11. Inventory Summary Output

Return one summary for every final surviving valid product, even if unused.

```typescript
interface InventorySummary {
  productId: string;
  price: number;
  initialStock: number;
  finalStock: number;
  confirmedQuantity: number;
  restoredQuantity: number;
}
```

Rules:

* `initialStock` comes from the final surviving product definition.
* `confirmedQuantity` is the total quantity removed by confirmed orders.
* `restoredQuantity` is the total quantity restored through accepted cancellations.
* `finalStock` must equal:

```text
initialStock - confirmedQuantity + restoredQuantity
```

Sort inventory summaries by `productId` ascending.

---

# 12. Immutability

Do not modify:

* The original `products` array
* The original `events` array
* Any nested item arrays or objects
* Objects passed to `authorizePayment`

Create new internal records where needed.

---

# 13. Error Handling

Invalid input records must be ignored without throwing.

Only expected payment errors should be converted into `"PAYMENT_ERROR"`.

Do not hide unrelated programming errors with broad catch blocks around the entire function.

---

# 14. Testing Requirements

Write complete executable TypeScript code.

Include:

* All interfaces and types
* The `processOrders` function
* An asynchronous test runner
* Assertion-based tests
* A deterministic mock `authorizePayment` function
* Valid and invalid products
* Valid and invalid events
* A duplicate product where the final valid product changes price or stock
* An invalid later product duplicate that does not replace the earlier valid product
* A duplicate event whose final valid occurrence references a different customer, order, or product
* An invalid later event duplicate that does not replace an earlier valid event
* A confirmed order
* An insufficient-stock rejection
* A payment-declined rejection
* A payment-error rejection
* A successful cancellation with stock restoration
* A duplicate cancellation rejection
* A cancellation for an unknown order
* A duplicate place attempt for an existing order
* Two events sharing the same timestamp to verify `eventId` ordering
* A discarded duplicate event that must leave no residual customer, order, or inventory effect
* An exact timestamp-format rejection
* Boolean, `NaN`, and `Infinity` numeric validation
* Input immutability verification
* Complete expected-result comparison for both orders and inventory
* Verification of the exact sequence and arguments of payment calls

If an assertion fails:

* Print a clear expected-versus-actual difference.
* Exit with a non-zero status.

Print the final result after all tests pass.

---

# 15. Restrictions

* Use TypeScript.
* Do not use external libraries.
* Node.js standard-library modules are allowed.
* Do not use `any` unless interacting with raw unvalidated input.
* Do not use type assertions to bypass validation.
* Do not use `JSON.parse(JSON.stringify(...))` for cloning.
* Do not perform payment authorization calls in parallel.
* Do not mutate the original inputs.

---

# Output Format

Return the full answer in one TypeScript code block.

Do not include explanations outside the code block.


