后台定价保存不再清空 3D 段
- payload 的 model3d 缺席或为 null 统一表示沿用当前 3D 定价,显式给出时才覆盖 - 保存路径先取当前快照合并,避免改图 / 视频价格让 3D 提交一直失败关闭 - 补用例覆盖「省略保持」与「显式覆盖」两种语义
This commit is contained in:
@@ -110,6 +110,17 @@ impl EditorGenerationPricingConfig {
|
||||
.price(query)
|
||||
}
|
||||
|
||||
/// 后台 payload 的「可省略」语义:`model3d` 缺席或为 null 表示沿用当前 3D 段。
|
||||
///
|
||||
/// 3D 段目前只由文件配置提供(后台记录形状还表达不了 endpoint × 模型版本 × 是否带贴图
|
||||
/// 的底价与 add-on 叠加),因此保存图 / 视频价格时绝不能把它清成 None。
|
||||
pub(crate) fn with_previous_model3d(mut self, previous: &Self) -> Self {
|
||||
if self.model3d.is_none() {
|
||||
self.model3d = previous.model3d.clone();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn image_model_mud_points(
|
||||
&self,
|
||||
model: Option<&str>,
|
||||
|
||||
@@ -510,7 +510,9 @@ fn editor_generation_pricing_from_record(
|
||||
}
|
||||
// TODO Tripo 3D 定价:后台记录形状还只有 `模型 → 档位 → 单价`,表达不了
|
||||
// endpoint × 模型版本 × 是否有贴图的底价与 add-on 叠加,因此 3D 段暂由文件配置提供,
|
||||
// 后台改价不会覆盖它;等记录形状补齐后再改为从 SpacetimeDB 读取。
|
||||
// 后台 payload 的 `model3d` 可空:省略 / null 一律沿用当前值(见保存路径的
|
||||
// `with_previous_model3d`),后台改价不会覆盖它;
|
||||
// 等记录形状补齐后再改为从 SpacetimeDB 读取。
|
||||
let config = EditorGenerationPricingConfig {
|
||||
models,
|
||||
model3d: legacy_fallback.model3d.clone(),
|
||||
@@ -797,6 +799,12 @@ impl AppState {
|
||||
admin_user_id: String,
|
||||
next: EditorGenerationPricingConfig,
|
||||
) -> Result<EditorGenerationPricingConfig, EditorGenerationPricingError> {
|
||||
// 后台 payload 的 `model3d` 允许缺席或为 null:两种情况都表示沿用当前 3D 定价。
|
||||
// 3D 段现在只由文件配置提供,若不合并,改一次图 / 视频价格就会把它清成 None,
|
||||
// 3D 提交会一直失败关闭到进程重启。
|
||||
let previous = self.editor_generation_pricing_store.snapshot()?;
|
||||
let next = next.with_previous_model3d(&previous);
|
||||
|
||||
#[cfg(test)]
|
||||
{
|
||||
let _ = admin_user_id;
|
||||
@@ -2778,6 +2786,47 @@ mod tests {
|
||||
use spacetime_client::SpacetimeClientStage;
|
||||
|
||||
use super::*;
|
||||
use crate::tripo3d::pricing::Model3dAddOn;
|
||||
|
||||
/// 后台 payload 省略 / 置空 3D 段时必须沿用当前 3D 定价:
|
||||
/// 改一次图 / 视频价格不能把文件提供的 3D 段清掉。
|
||||
#[tokio::test]
|
||||
async fn saving_pricing_without_model3d_keeps_existing_model3d() {
|
||||
let state = AppState::new(AppConfig::default()).expect("state should build");
|
||||
let before = state
|
||||
.editor_generation_pricing()
|
||||
.await
|
||||
.expect("默认定价必须可读");
|
||||
let default_model3d = before.model3d.clone().expect("默认配置必须带 3D 定价段");
|
||||
|
||||
let mut omitted = before.clone();
|
||||
omitted.model3d = None;
|
||||
let saved = state
|
||||
.save_editor_generation_pricing("admin:test".to_string(), omitted)
|
||||
.await
|
||||
.expect("省略 3D 段的保存必须成功");
|
||||
assert_eq!(saved.model3d.as_ref(), Some(&default_model3d));
|
||||
|
||||
// 显式给出 3D 段时按 payload 生效,而不是无脑沿用旧值。
|
||||
let mut custom = default_model3d.clone();
|
||||
custom.add_on_prices.insert(Model3dAddOn::QuadMesh, 7);
|
||||
let mut explicit = before.clone();
|
||||
explicit.model3d = Some(custom.clone());
|
||||
let saved = state
|
||||
.save_editor_generation_pricing("admin:test".to_string(), explicit)
|
||||
.await
|
||||
.expect("显式 3D 段的保存必须成功");
|
||||
assert_eq!(saved.model3d.as_ref(), Some(&custom));
|
||||
assert_eq!(
|
||||
state
|
||||
.editor_generation_pricing()
|
||||
.await
|
||||
.expect("定价必须可读")
|
||||
.model3d
|
||||
.as_ref(),
|
||||
Some(&custom)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn template_library_credentials_never_mix_dedicated_and_general_pairs() {
|
||||
|
||||
Reference in New Issue
Block a user