Add skill for gameplay entry type workflows
This commit is contained in:
@@ -15,6 +15,16 @@ pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_REFUND: &str = "asse
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_REDEEM_CODE_REWARD: &str = "redeem_code_reward";
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_PUZZLE_AUTHOR_INCENTIVE_CLAIM: &str =
|
||||
"puzzle_author_incentive_claim";
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_DAILY_TASK_REWARD: &str = "daily_task_reward";
|
||||
pub const PROFILE_TASK_CYCLE_DAILY: &str = "daily";
|
||||
pub const PROFILE_TASK_STATUS_INCOMPLETE: &str = "incomplete";
|
||||
pub const PROFILE_TASK_STATUS_CLAIMABLE: &str = "claimable";
|
||||
pub const PROFILE_TASK_STATUS_CLAIMED: &str = "claimed";
|
||||
pub const PROFILE_TASK_STATUS_DISABLED: &str = "disabled";
|
||||
pub const TRACKING_SCOPE_KIND_SITE: &str = "site";
|
||||
pub const TRACKING_SCOPE_KIND_WORK: &str = "work";
|
||||
pub const TRACKING_SCOPE_KIND_MODULE: &str = "module";
|
||||
pub const TRACKING_SCOPE_KIND_USER: &str = "user";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_MARTIAL: &str = "martial";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_ARCANE: &str = "arcane";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_MACHINA: &str = "machina";
|
||||
@@ -295,6 +305,92 @@ pub struct RedeemProfileRewardCodeResponse {
|
||||
pub ledger_entry: ProfileWalletLedgerEntryResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileTaskItemResponse {
|
||||
pub task_id: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub event_key: String,
|
||||
pub cycle: String,
|
||||
pub threshold: u32,
|
||||
pub progress_count: u32,
|
||||
pub reward_points: u64,
|
||||
pub status: String,
|
||||
pub day_key: i64,
|
||||
pub claimed_at: Option<String>,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileTaskCenterResponse {
|
||||
pub day_key: i64,
|
||||
pub wallet_balance: u64,
|
||||
pub tasks: Vec<ProfileTaskItemResponse>,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ClaimProfileTaskRewardResponse {
|
||||
pub task_id: String,
|
||||
pub day_key: i64,
|
||||
pub reward_points: u64,
|
||||
pub wallet_balance: u64,
|
||||
pub ledger_entry: ProfileWalletLedgerEntryResponse,
|
||||
pub center: ProfileTaskCenterResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileTaskConfigAdminResponse {
|
||||
pub task_id: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub event_key: String,
|
||||
pub cycle: String,
|
||||
pub scope_kind: String,
|
||||
pub threshold: u32,
|
||||
pub reward_points: u64,
|
||||
pub enabled: bool,
|
||||
pub sort_order: i32,
|
||||
pub created_by: String,
|
||||
pub created_at: String,
|
||||
pub updated_by: String,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileTaskConfigAdminListResponse {
|
||||
pub entries: Vec<ProfileTaskConfigAdminResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AdminUpsertProfileTaskConfigRequest {
|
||||
pub task_id: String,
|
||||
pub title: String,
|
||||
#[serde(default)]
|
||||
pub description: Option<String>,
|
||||
pub event_key: String,
|
||||
pub cycle: String,
|
||||
pub scope_kind: String,
|
||||
pub threshold: u32,
|
||||
pub reward_points: u64,
|
||||
#[serde(default = "default_true")]
|
||||
pub enabled: bool,
|
||||
#[serde(default)]
|
||||
pub sort_order: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AdminDisableProfileTaskConfigRequest {
|
||||
pub task_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AdminUpsertProfileRedeemCodeRequest {
|
||||
@@ -339,6 +435,12 @@ pub struct ProfileRedeemCodeAdminResponse {
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileRedeemCodeAdminListResponse {
|
||||
pub entries: Vec<ProfileRedeemCodeAdminResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileInviteCodeAdminResponse {
|
||||
@@ -349,6 +451,12 @@ pub struct ProfileInviteCodeAdminResponse {
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileInviteCodeAdminListResponse {
|
||||
pub entries: Vec<ProfileInviteCodeAdminResponse>,
|
||||
}
|
||||
|
||||
fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
@@ -958,6 +1066,13 @@ mod tests {
|
||||
.to_string(),
|
||||
created_at: "2026-04-22T10:06:00Z".to_string(),
|
||||
},
|
||||
ProfileWalletLedgerEntryResponse {
|
||||
id: "ledger-9".to_string(),
|
||||
amount_delta: 10,
|
||||
balance_after: 212,
|
||||
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_DAILY_TASK_REWARD.to_string(),
|
||||
created_at: "2026-04-22T10:07:00Z".to_string(),
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
@@ -996,12 +1111,66 @@ mod tests {
|
||||
payload["entries"][7]["sourceType"],
|
||||
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_PUZZLE_AUTHOR_INCENTIVE_CLAIM)
|
||||
);
|
||||
assert_eq!(
|
||||
payload["entries"][8]["sourceType"],
|
||||
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_DAILY_TASK_REWARD)
|
||||
);
|
||||
assert_eq!(
|
||||
payload["entries"][0]["createdAt"],
|
||||
json!("2026-04-22T09:59:00Z")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_task_center_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(ProfileTaskCenterResponse {
|
||||
day_key: 20576,
|
||||
wallet_balance: 18,
|
||||
tasks: vec![ProfileTaskItemResponse {
|
||||
task_id: "daily_login".to_string(),
|
||||
title: "每日登录".to_string(),
|
||||
description: "".to_string(),
|
||||
event_key: "daily_login".to_string(),
|
||||
cycle: PROFILE_TASK_CYCLE_DAILY.to_string(),
|
||||
threshold: 1,
|
||||
progress_count: 1,
|
||||
reward_points: 10,
|
||||
status: PROFILE_TASK_STATUS_CLAIMABLE.to_string(),
|
||||
day_key: 20576,
|
||||
claimed_at: None,
|
||||
updated_at: "2026-05-03T00:00:00Z".to_string(),
|
||||
}],
|
||||
updated_at: "2026-05-03T00:00:00Z".to_string(),
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["walletBalance"], json!(18));
|
||||
assert_eq!(payload["tasks"][0]["taskId"], json!("daily_login"));
|
||||
assert_eq!(payload["tasks"][0]["rewardPoints"], json!(10));
|
||||
assert_eq!(
|
||||
payload["tasks"][0]["status"],
|
||||
json!(PROFILE_TASK_STATUS_CLAIMABLE)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_task_config_request_accepts_defaults() {
|
||||
let payload: AdminUpsertProfileTaskConfigRequest = serde_json::from_value(json!({
|
||||
"taskId": "daily_login",
|
||||
"title": "每日登录",
|
||||
"eventKey": "daily_login",
|
||||
"cycle": "daily",
|
||||
"scopeKind": "user",
|
||||
"threshold": 1,
|
||||
"rewardPoints": 10
|
||||
}))
|
||||
.expect("request should deserialize");
|
||||
|
||||
assert_eq!(payload.description, None);
|
||||
assert_eq!(payload.enabled, true);
|
||||
assert_eq!(payload.sort_order, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_recharge_center_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(ProfileRechargeCenterResponse {
|
||||
|
||||
Reference in New Issue
Block a user