2a09d31ccc
- 新增公用 Pagination 组件,Roster/Money/Dashboard 列表加分页 - Dashboard 待办按类型显示不同图标(合同/薪资/解聘/月度) - 待办分为「风险提醒」「月度任务」两个顶层 tab - 归档与工资条生成解耦:归档只锁定批次,工资条单独生成 - 工资条管理新增「从批次汇总生成」按钮 - Dashboard 总览优先从已归档批次 BatchEntry 汇总数据 - 新增工资条生成待办提醒,生成后自动标记完成 - 修复高风险统计只含 CONTRACT/TERMINATION 类型 - 修复月度任务去重逻辑覆盖 SALARY 类型
631 lines
20 KiB
Plaintext
631 lines
20 KiB
Plaintext
generator client {
|
||
provider = "prisma-client-js"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
// ========== 枚举 ==========
|
||
|
||
enum Plan {
|
||
FREE
|
||
PRO
|
||
ENTERPRISE
|
||
}
|
||
|
||
enum Role {
|
||
ADMIN
|
||
HR
|
||
VIEWER
|
||
}
|
||
|
||
enum EmployeeStatus {
|
||
ACTIVE
|
||
RESIGNED
|
||
}
|
||
|
||
enum ContractType {
|
||
FIXED
|
||
UNFIXED
|
||
UNSIGNED
|
||
}
|
||
|
||
enum SignMethod {
|
||
PAPER
|
||
ELECTRONIC
|
||
}
|
||
|
||
enum RiskType {
|
||
CONTRACT
|
||
SALARY
|
||
TERMINATION
|
||
MONTHLY
|
||
}
|
||
|
||
enum RiskLevel {
|
||
HIGH
|
||
MEDIUM
|
||
LOW
|
||
}
|
||
|
||
enum PayrollBatchType {
|
||
REGULAR // 常规发薪
|
||
TERMINATION // 离职结算
|
||
BONUS // 年终奖/奖金
|
||
}
|
||
|
||
enum PayrollBatchStatus {
|
||
DRAFT // 草稿(可编辑)
|
||
ARCHIVED // 归档(已发薪,锁定)
|
||
}
|
||
|
||
enum PayslipItemType {
|
||
INPUT // 手工输入项(计算依据)
|
||
CALCULATED // 计算项(公式自动计算)
|
||
}
|
||
|
||
enum PayslipStatus {
|
||
PENDING // 待发布
|
||
PUBLISHED // 已发布到员工端
|
||
}
|
||
|
||
enum RiskStatus {
|
||
PENDING
|
||
RESOLVED
|
||
IGNORED
|
||
}
|
||
|
||
enum TerminationReason {
|
||
NEGOTIATED
|
||
FAULT
|
||
NONFAULT
|
||
LAYOFF
|
||
EXPIRED
|
||
}
|
||
|
||
enum RiskAssessment {
|
||
SAFE
|
||
WARNING
|
||
DANGER
|
||
}
|
||
|
||
enum OnboardingStatus {
|
||
PENDING
|
||
APPROVED
|
||
REJECTED
|
||
}
|
||
|
||
enum ContractConfirmStatus {
|
||
UNCONFIRMED
|
||
CONFIRMED
|
||
EXPIRED
|
||
}
|
||
|
||
// ========== 核心表 ==========
|
||
|
||
model Organization {
|
||
id String @id @default(cuid())
|
||
name String
|
||
plan Plan @default(FREE)
|
||
maxEmployees Int @default(20)
|
||
city String?
|
||
payrollFrequency Int @default(1) // 每月发薪次数(1=一次一批)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
users User[]
|
||
employees Employee[]
|
||
contracts LaborContract[]
|
||
overtimeRecords OvertimeRecord[]
|
||
terminations TerminationRecord[]
|
||
riskItems RiskItem[]
|
||
auditLogs AuditLog[]
|
||
payslips Payslip[]
|
||
payrollBatches PayrollBatch[]
|
||
payslipItems PayslipItem[]
|
||
salaryChangeRecords SalaryChangeRecord[]
|
||
onboardingLinks OnboardingLink[]
|
||
confirmLinks ContractConfirmLink[]
|
||
socialInsuranceConfig SocialInsuranceConfig?
|
||
notificationSetting NotificationSetting?
|
||
notificationLogs NotificationLog[]
|
||
employeeAttachments EmployeeAttachment[]
|
||
disciplinaryRecords DisciplinaryRecord[]
|
||
attendanceRecords AttendanceRecord[]
|
||
trainingRecords TrainingRecord[]
|
||
performanceRecords PerformanceRecord[]
|
||
}
|
||
|
||
model User {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
phone String @unique
|
||
email String?
|
||
passwordHash String
|
||
name String
|
||
role Role @default(ADMIN)
|
||
createdAt DateTime @default(now())
|
||
lastLoginAt DateTime?
|
||
}
|
||
|
||
// ========== 业务表 ==========
|
||
|
||
model Employee {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
name String
|
||
department String
|
||
hireDate DateTime
|
||
monthlySalary String // AES-256 加密存储
|
||
status EmployeeStatus @default(ACTIVE)
|
||
gender String?
|
||
phone String?
|
||
idCardNumber String? // AES-256 加密存储
|
||
emergencyContact String?
|
||
emergencyPhone String?
|
||
address String?
|
||
bankAccount String? // AES-256 加密存储
|
||
bankName String?
|
||
passwordHash String? // 员工端登录密码
|
||
isPregnant Boolean @default(false)
|
||
isInMedicalPeriod Boolean @default(false)
|
||
isWorkInjured Boolean @default(false)
|
||
// 薪税扩展
|
||
socialInsBase Float? // 社保缴费基数(按人核定)
|
||
housingFundBase Float? // 公积金缴费基数(按人核定)
|
||
specialDeduction Float @default(0) // 专项附加扣除(子女教育、赡养老人等,员工portal端填报)
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
contracts LaborContract[]
|
||
overtimeRecords OvertimeRecord[]
|
||
terminations TerminationRecord[]
|
||
riskItems RiskItem[]
|
||
payslips Payslip[]
|
||
salaryChanges SalaryChangeRecord[]
|
||
batchEntries BatchEntry[]
|
||
attachments EmployeeAttachment[]
|
||
disciplinaryRecords DisciplinaryRecord[]
|
||
attendanceRecords AttendanceRecord[]
|
||
trainingRecords TrainingRecord[]
|
||
performanceRecords PerformanceRecord[]
|
||
}
|
||
|
||
model LaborContract {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
signDate DateTime?
|
||
startDate DateTime
|
||
endDate DateTime?
|
||
contractType ContractType
|
||
signMethod SignMethod @default(PAPER)
|
||
contractYears Int @default(3)
|
||
probationMonths Int @default(0)
|
||
probationSalary Int @default(0)
|
||
renewalCount Int @default(0)
|
||
attachmentName String?
|
||
attachmentUrl String?
|
||
electronicContractNo String?
|
||
electronicContractUrl String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
confirmLinks ContractConfirmLink[]
|
||
}
|
||
|
||
model OvertimeRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
month String // YYYY-MM
|
||
weekdayHours Float @default(0)
|
||
weekendHours Float @default(0)
|
||
holidayHours Float @default(0)
|
||
weekdayPay Float @default(0)
|
||
weekendPay Float @default(0)
|
||
holidayPay Float @default(0)
|
||
totalPay Float @default(0)
|
||
createdAt DateTime @default(now())
|
||
|
||
@@unique([employeeId, month])
|
||
}
|
||
|
||
model TerminationRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
reason TerminationReason
|
||
terminationDate DateTime
|
||
compensation Float @default(0)
|
||
riskLevel RiskAssessment @default(SAFE)
|
||
checklist Json
|
||
remark String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
}
|
||
|
||
model RiskItem {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String?
|
||
employee Employee? @relation(fields: [employeeId], references: [id], onDelete: SetNull)
|
||
type RiskType
|
||
level RiskLevel
|
||
status RiskStatus @default(PENDING)
|
||
title String
|
||
description String
|
||
actionUrl String?
|
||
resolvedAt DateTime?
|
||
resolvedBy String?
|
||
remark String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([orgId, status])
|
||
@@index([orgId, type])
|
||
}
|
||
|
||
model AuditLog {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
userId String
|
||
action String
|
||
entity String
|
||
entityId String?
|
||
detail Json?
|
||
ip String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([orgId, createdAt])
|
||
}
|
||
|
||
// ========== 社保 & 通知 & 附件 ==========
|
||
|
||
model SocialInsuranceConfig {
|
||
id String @id @default(cuid())
|
||
orgId String @unique
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
city String @default("北京")
|
||
pensionOrg Float @default(16) // 养老保险 企业比例 %
|
||
pensionEmp Float @default(8) // 养老保险 个人比例 %
|
||
medicalOrg Float @default(9.8) // 医疗保险 企业比例 %
|
||
medicalEmp Float @default(2) // 医疗保险 个人比例 %
|
||
unemploymentOrg Float @default(0.5) // 失业保险 企业比例 %
|
||
unemploymentEmp Float @default(0.5) // 失业保险 个人比例 %
|
||
injuryOrg Float @default(0.2) // 工伤保险 企业比例 %
|
||
maternityOrg Float @default(0.8) // 生育保险 企业比例 %
|
||
housingOrg Float @default(12) // 公积金 企业比例 %
|
||
housingEmp Float @default(12) // 公积金 个人比例 %
|
||
baseMin Float @default(6326) // 缴费基数下限
|
||
baseMax Float @default(33891) // 缴费基数上限
|
||
updatedAt DateTime @updatedAt
|
||
}
|
||
|
||
model NotificationSetting {
|
||
id String @id @default(cuid())
|
||
orgId String @unique
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
contractExpiry Boolean @default(true)
|
||
expiryDays Int @default(30)
|
||
contractUnsigned Boolean @default(true)
|
||
overtimeAlert Boolean @default(true)
|
||
payslipReady Boolean @default(true)
|
||
// 月度事务提醒日(每月几号)
|
||
payrollDay Int @default(10) // 发薪日
|
||
socialInsDay Int @default(15) // 社保缴纳日
|
||
housingFundDay Int @default(15) // 公积金缴纳日
|
||
taxDay Int @default(15) // 个税申报日
|
||
wechatWebhook String?
|
||
emailNotify Boolean @default(false)
|
||
email String?
|
||
updatedAt DateTime @updatedAt
|
||
}
|
||
|
||
model NotificationLog {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
type String // CONTRACT_EXPIRY / CONTRACT_UNSIGNED / OVERTIME / PAYSLIP
|
||
title String
|
||
content String
|
||
channel String // WECHAT / EMAIL / IN_APP
|
||
status String @default("SENT") // SENT / FAILED
|
||
employeeId String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([orgId, createdAt])
|
||
}
|
||
|
||
model EmployeeAttachment {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
fileName String
|
||
fileType String // ID_CARD / BANK_CARD / CONTRACT_SCAN / EDUCATION / OTHER
|
||
fileUrl String
|
||
fileSize Int @default(0)
|
||
uploadedBy String
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
// ========== 仲裁证据链 ==========
|
||
|
||
model DisciplinaryRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
violationDate DateTime
|
||
violationType String // LATE/ABSENT/INSUBORDINATION/MISCONDUCT/VIOLATE_POLICY/OTHER
|
||
description String
|
||
severity String @default("WARNING") // WARNING/SERIOUS/SEVERE
|
||
action String @default("ORAL_WARNING") // ORAL_WARNING/WRITTEN_WARNING/DEDUCTION/DEMOTION/TERMINATION
|
||
actionDetail String?
|
||
employeeAck Boolean @default(false) // 员工是否签字确认
|
||
ackDate DateTime?
|
||
ackMethod String? // SIGN/ELECTRONIC/REFUSED
|
||
witness String? // 见证人
|
||
attachmentUrl String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
model AttendanceRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
date DateTime
|
||
checkInTime String? // HH:mm
|
||
checkOutTime String? // HH:mm
|
||
status String @default("NORMAL") // NORMAL/LATE/EARLY_LEAVE/ABSENT/LEAVE/BUSINESS_TRIP
|
||
lateMinutes Int @default(0)
|
||
earlyMinutes Int @default(0)
|
||
workHours Float @default(0)
|
||
overtimeHours Float @default(0)
|
||
remark String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
|
||
@@unique([employeeId, date])
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
model TrainingRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
trainingDate DateTime
|
||
topic String // 培训主题/制度名称
|
||
content String? // 培训内容摘要
|
||
trainer String?
|
||
duration Float @default(0) // 培训时长(小时)
|
||
ackStatus String @default("PENDING") // PENDING/SIGNED/REFUSED
|
||
ackDate DateTime?
|
||
attachmentUrl String? // 签收单扫描件
|
||
remark String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
model PerformanceRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
period String // 考核周期 YYYY-MM 或 YYYY-Q1
|
||
score Float @default(0) // 考核得分
|
||
grade String @default("B") // A/B/C/D
|
||
result String @default("QUALIFIED") // EXCELLENT/QUALIFIED/NEED_IMPROVE/UNQUALIFIED
|
||
summary String? // 考核评语
|
||
improvementPlan String? // 改进计划(不胜任时)
|
||
employeeAck Boolean @default(false)
|
||
ackDate DateTime?
|
||
reviewer String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
|
||
@@unique([employeeId, period])
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
// ========== 员工端表 ==========
|
||
|
||
model Payslip {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
month String // YYYY-MM
|
||
// 薪酬构成
|
||
baseSalary Float @default(0)
|
||
overtimePay Float @default(0)
|
||
weekdayOvertimePay Float @default(0)
|
||
weekendOvertimePay Float @default(0)
|
||
holidayOvertimePay Float @default(0)
|
||
allowance Float @default(0)
|
||
deduction Float @default(0)
|
||
bonus Float @default(0) // 奖金/年终奖
|
||
totalPay Float @default(0) // 应发合计
|
||
// 扣除项
|
||
socialEmp Float @default(0) // 个人社保
|
||
housingEmp Float @default(0) // 个人公积金
|
||
tax Float @default(0) // 个人所得税
|
||
netPay Float @default(0) // 实发工资 = totalPay - socialEmp - housingEmp - tax
|
||
// 累计预扣法
|
||
ytdIncome Float @default(0) // 当年累计收入
|
||
ytdTaxDeducted Float @default(0) // 当年累计已扣税
|
||
ytdSocialEmp Float @default(0) // 当年累计个人社保
|
||
ytdHousingEmp Float @default(0) // 当年累计个人公积金
|
||
// 状态
|
||
status PayslipStatus @default(PENDING) // PENDING → PUBLISHED
|
||
confirmedAt DateTime?
|
||
confirmedIp String?
|
||
publishedAt DateTime? // 工资条发布到员工端的时间
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique([employeeId, month])
|
||
@@index([orgId, month])
|
||
@@index([orgId, status])
|
||
}
|
||
|
||
model PayrollBatch {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
month String // YYYY-MM
|
||
batchNo Int // 批次序号(1, 2, 3...)
|
||
name String // 批次名称
|
||
type PayrollBatchType @default(REGULAR)
|
||
status PayrollBatchStatus @default(DRAFT)
|
||
employeeCount Int @default(0)
|
||
totalPay Float @default(0)
|
||
totalNetPay Float @default(0)
|
||
totalSocialOrg Float @default(0)
|
||
totalSocialEmp Float @default(0)
|
||
totalHousingOrg Float @default(0)
|
||
totalHousingEmp Float @default(0)
|
||
totalTax Float @default(0)
|
||
remark String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
archivedAt DateTime?
|
||
updatedAt DateTime @updatedAt
|
||
|
||
entries BatchEntry[]
|
||
|
||
@@unique([orgId, month, batchNo])
|
||
@@index([orgId, month])
|
||
@@index([orgId, status])
|
||
}
|
||
|
||
model BatchEntry {
|
||
id String @id @default(cuid())
|
||
batchId String
|
||
batch PayrollBatch @relation(fields: [batchId], references: [id], onDelete: Cascade)
|
||
orgId String
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
// 薪酬项(可编辑的输入项)
|
||
baseSalary Float @default(0)
|
||
overtimePay Float @default(0)
|
||
allowance Float @default(0)
|
||
deduction Float @default(0)
|
||
bonus Float @default(0)
|
||
// 自动计算项
|
||
socialEmp Float @default(0)
|
||
socialOrg Float @default(0)
|
||
housingEmp Float @default(0)
|
||
housingOrg Float @default(0)
|
||
tax Float @default(0)
|
||
totalPay Float @default(0) // 应发合计
|
||
netPay Float @default(0) // 实发工资
|
||
// 风险提示
|
||
riskWarnings Json?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique([batchId, employeeId])
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
model PayslipItem {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
name String // 显示名称
|
||
code String // 字段代码
|
||
type PayslipItemType @default(INPUT)
|
||
formula String? // 计算公式(CALCULATED 类型),如 "baseSalary + overtimePay + allowance - deduction"
|
||
order Int @default(0)
|
||
isDefault Boolean @default(true) // 系统预置项不可删除
|
||
isEditable Boolean @default(true)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique([orgId, code])
|
||
}
|
||
|
||
model SalaryChangeRecord {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
employeeId String
|
||
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||
oldSalary Float
|
||
newSalary Float
|
||
effectiveDate DateTime // 生效日期
|
||
reason String?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([orgId, employeeId])
|
||
}
|
||
|
||
model OnboardingLink {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
token String @unique
|
||
employeeName String?
|
||
phone String?
|
||
status OnboardingStatus @default(PENDING)
|
||
formData Json?
|
||
expiresAt DateTime
|
||
usedAt DateTime?
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([orgId, status])
|
||
}
|
||
|
||
model ContractConfirmLink {
|
||
id String @id @default(cuid())
|
||
orgId String
|
||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||
contractId String
|
||
contract LaborContract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
||
token String @unique
|
||
status ContractConfirmStatus @default(UNCONFIRMED)
|
||
confirmedAt DateTime?
|
||
confirmedIp String?
|
||
expiresAt DateTime
|
||
createdBy String
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([orgId, status])
|
||
}
|