Assist_Design/apps/bff/src/integrations/japanpost/services/japanpost-address.service.ts
barsa 78689da8fb feat(address): implement Japan address form with ZIP code lookup
- Add JapanAddressForm component for complete Japanese address input.
- Integrate ZipCodeInput for automatic address population via Japan Post API.
- Create hooks for ZIP code lookup and address service status.
- Define address-related types and constants in the domain package.
- Document the feature, including environment variables and API endpoints.
- Implement mapping functions for WHMCS and Salesforce address formats.
2026-01-13 18:41:17 +09:00

85 lines
2.7 KiB
TypeScript

/**
* Japan Post Address Service
*
* Address lookup service using Japan Post API.
* Transforms raw API responses to domain types using domain mappers.
*/
import {
Injectable,
Inject,
BadRequestException,
ServiceUnavailableException,
} from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
import { JapanPostConnectionService } from "./japanpost-connection.service.js";
import { JapanPost } from "@customer-portal/domain/address/providers";
import type { AddressLookupResult } from "@customer-portal/domain/address";
@Injectable()
export class JapanPostAddressService {
constructor(
private readonly connection: JapanPostConnectionService,
@Inject(Logger) private readonly logger: Logger
) {}
/**
* Lookup address by ZIP code
*
* @param zipCode - ZIP code (with or without hyphen, e.g., "100-0001" or "1000001")
* @returns Domain AddressLookupResult with Japanese and romanized address data
* @throws BadRequestException if ZIP code format is invalid
* @throws ServiceUnavailableException if Japan Post API is unavailable
*/
async lookupByZipCode(zipCode: string): Promise<AddressLookupResult> {
// Normalize ZIP code (remove hyphen)
const normalizedZip = zipCode.replace(/-/g, "");
// Validate format
if (!/^\d{7}$/.test(normalizedZip)) {
throw new BadRequestException("ZIP code must be 7 digits (e.g., 100-0001)");
}
// Check if service is configured
if (!this.connection.isConfigured()) {
this.logger.error("Japan Post API not configured");
throw new ServiceUnavailableException("Address lookup service is not available");
}
try {
const rawResponse = await this.connection.searchByZipCode(normalizedZip);
// Use domain mapper for transformation (single transformation point)
const result = JapanPost.transformJapanPostSearchResponse(rawResponse);
this.logger.log("Japan Post address lookup completed", {
zipCode: normalizedZip,
found: result.count > 0,
count: result.count,
});
return result;
} catch (error) {
// Re-throw known exceptions
if (error instanceof BadRequestException || error instanceof ServiceUnavailableException) {
throw error;
}
this.logger.error("Japan Post address lookup failed", {
zipCode: normalizedZip,
error: extractErrorMessage(error),
});
throw new ServiceUnavailableException("Failed to lookup address. Please try again.");
}
}
/**
* Check if the Japan Post service is available
*/
isAvailable(): boolean {
return this.connection.isConfigured();
}
}