import { apiRequest } from './api.js' export const EXPENSE_MEMORY_TRANSPORT_OPTIONS = ['飞机', '火车', '轮船'] export const EXPENSE_MEMORY_MIN_DAYS = 30 export const EXPENSE_MEMORY_MAX_DAYS = 365 function normalizeText(value) { return String(value || '').trim() } function normalizeInteger(value, fallback = 0) { const normalized = Number.parseInt(String(value ?? ''), 10) return Number.isFinite(normalized) ? normalized : fallback } function requireReason(value) { const reason = normalizeText(value) if (!reason) throw new Error('请填写操作理由。') return reason } function requireTransportValue(value) { const normalized = normalizeText(value) if (!EXPENSE_MEMORY_TRANSPORT_OPTIONS.includes(normalized)) { throw new Error('出行方式仅支持飞机、火车或轮船。') } return normalized } function requireExpiresInDays(value) { const normalized = normalizeInteger(value) if (normalized < EXPENSE_MEMORY_MIN_DAYS || normalized > EXPENSE_MEMORY_MAX_DAYS) { throw new Error('有效期必须在 30 到 365 天之间。') } return normalized } function requireExpectedGeneration(value) { const normalized = normalizeInteger(value) if (normalized < 1) throw new Error('缺少有效的记忆版本。') return normalized } function requireRequestId(value) { const normalized = normalizeText(value) if (normalized.length < 8) throw new Error('缺少有效的幂等请求标识。') return normalized } export function normalizeOrganizationExpenseMemory(item = {}) { if (!item || typeof item !== 'object') return null const id = normalizeText(item.id) const scopeType = normalizeText(item.scopeType || item.scope_type).toLowerCase() if (!id || !['enterprise', 'department'].includes(scopeType)) return null const originType = normalizeText(item.originType || item.origin_type) return { id, fieldKey: normalizeText(item.fieldKey || item.field_key) || 'transport_mode', value: normalizeText(item.value), status: normalizeText(item.status).toLowerCase(), scopeType, scopeId: normalizeText(item.scopeId || item.scope_id), scopeLabel: normalizeText(item.scopeLabel || item.scope_label) || (scopeType === 'enterprise' ? '企业统一规则' : '部门规则'), source: normalizeText(item.source), originType, sourceLabel: originType === 'admin_managed' ? '管理员显式维护' : '组织规则', generation: Math.max(1, normalizeInteger(item.generation, 1)), policyVersion: normalizeText(item.policyVersion || item.policy_version), validFrom: normalizeText(item.validFrom || item.valid_from), expiresAt: normalizeText(item.expiresAt || item.expires_at), managedAt: normalizeText(item.managedAt || item.managed_at), canRevoke: Boolean(item.canRevoke ?? item.can_revoke), createdAt: normalizeText(item.createdAt || item.created_at), updatedAt: normalizeText(item.updatedAt || item.updated_at) } } export function normalizeOrganizationExpenseMemories(payload = {}) { const items = Array.isArray(payload) ? payload : payload?.items return (Array.isArray(items) ? items : []) .map((item) => normalizeOrganizationExpenseMemory(item)) .filter(Boolean) } export function buildOrganizationExpenseMemoryCreatePayload(input = {}) { const scopeType = normalizeText(input.scopeType || input.scope_type).toLowerCase() if (!['enterprise', 'department'].includes(scopeType)) { throw new Error('请选择企业或部门作用域。') } const payload = { scope_type: scopeType, value: requireTransportValue(input.value), expires_in_days: requireExpiresInDays(input.expiresInDays ?? input.expires_in_days), reason: requireReason(input.reason), request_id: requireRequestId(input.requestId || input.request_id) } if (scopeType === 'department') { const scopeId = normalizeText(input.scopeId || input.scope_id) if (!scopeId) throw new Error('请选择要适用的部门。') payload.scope_id = scopeId } return payload } export function buildOrganizationExpenseMemoryUpdatePayload(input = {}) { return { value: requireTransportValue(input.value), expires_in_days: requireExpiresInDays(input.expiresInDays ?? input.expires_in_days), expected_generation: requireExpectedGeneration( input.expectedGeneration ?? input.expected_generation ), reason: requireReason(input.reason), request_id: requireRequestId(input.requestId || input.request_id) } } export function buildOrganizationExpenseMemoryRevokePayload(input = {}) { return { expected_generation: requireExpectedGeneration( input.expectedGeneration ?? input.expected_generation ), reason: requireReason(input.reason), request_id: requireRequestId(input.requestId || input.request_id) } } export async function fetchOrganizationExpenseMemories(options = {}) { const payload = await apiRequest('/expense-application-memories/organization', options) return normalizeOrganizationExpenseMemories(payload) } export async function createOrganizationExpenseMemory(input = {}, options = {}) { const payload = await apiRequest('/expense-application-memories/organization', { method: 'POST', body: JSON.stringify(buildOrganizationExpenseMemoryCreatePayload(input)), ...options }) return normalizeOrganizationExpenseMemory(payload) } export async function updateOrganizationExpenseMemory(memoryId, input = {}, options = {}) { const id = normalizeText(memoryId) if (!id) throw new Error('缺少要更新的记忆标识。') const payload = await apiRequest( `/expense-application-memories/organization/${encodeURIComponent(id)}`, { method: 'PUT', body: JSON.stringify(buildOrganizationExpenseMemoryUpdatePayload(input)), ...options } ) return normalizeOrganizationExpenseMemory(payload) } export function revokeOrganizationExpenseMemory(memoryId, input = {}, options = {}) { const id = normalizeText(memoryId) if (!id) return Promise.reject(new Error('缺少要撤销的记忆标识。')) return apiRequest( `/expense-application-memories/organization/${encodeURIComponent(id)}/revoke`, { method: 'POST', body: JSON.stringify(buildOrganizationExpenseMemoryRevokePayload(input)), ...options } ) }