use chrono::NaiveDate;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum InstrumentType {
Options,
#[default]
RSUs,
PSUs,
}
impl std::fmt::Display for InstrumentType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Options => write!(f, "Options"),
Self::RSUs => write!(f, "RSUs"),
Self::PSUs => write!(f, "PSUs"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum VestingType {
Cliff,
#[default]
Graded,
Performance,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VestingEntry {
pub period: u32,
pub vesting_date: NaiveDate,
#[serde(with = "crate::serde_decimal")]
pub percentage: Decimal,
#[serde(with = "crate::serde_decimal")]
pub cumulative_percentage: Decimal,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VestingSchedule {
pub vesting_type: VestingType,
pub total_periods: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cliff_periods: Option<u32>,
pub vesting_entries: Vec<VestingEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StockGrant {
pub id: String,
pub entity_code: String,
pub employee_id: String,
pub grant_date: NaiveDate,
pub instrument_type: InstrumentType,
pub quantity: u32,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "crate::serde_decimal::option"
)]
pub exercise_price: Option<Decimal>,
#[serde(with = "crate::serde_decimal")]
pub fair_value_at_grant: Decimal,
#[serde(with = "crate::serde_decimal")]
pub total_grant_value: Decimal,
pub vesting_schedule: VestingSchedule,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub expiration_date: Option<NaiveDate>,
#[serde(with = "crate::serde_decimal")]
pub forfeiture_rate: Decimal,
pub currency: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StockCompExpense {
pub grant_id: String,
pub entity_code: String,
pub period: String,
#[serde(with = "crate::serde_decimal")]
pub expense_amount: Decimal,
#[serde(with = "crate::serde_decimal")]
pub cumulative_recognized: Decimal,
#[serde(with = "crate::serde_decimal")]
pub remaining_unrecognized: Decimal,
#[serde(with = "crate::serde_decimal")]
pub forfeiture_rate: Decimal,
}