浏览代码

feat: enhance product entity and mapper to calculate total calories based on nutritional values

IlhamTahir 1 月之前
父节点
当前提交
2dfc1dafec
共有 3 个文件被更改,包括 91 次插入10 次删除
  1. 20 10
      src/pet-feeder/entity/product.entity.ts
  2. 66 0
      src/pet-feeder/mapper/product.mapper.ts
  3. 5 0
      src/pet-feeder/vo/product.vo.ts

+ 20 - 10
src/pet-feeder/entity/product.entity.ts

@@ -26,24 +26,34 @@ export class Product extends BaseEntity {
   @Column()
   totalWeight: number;
 
-  //蛋白质
-  @Column()
+  //蛋白质(百分比,如0.6表示60%)
+  @Column({
+    type: 'double',
+  })
   protein: number;
 
-  // 脂肪
-  @Column()
+  // 脂肪(百分比)
+  @Column({
+    type: 'double',
+  })
   fat: number;
 
-  // 粗纤维
-  @Column()
+  // 粗纤维(百分比)
+  @Column({
+    type: 'double',
+  })
   fiber: number;
 
-  // 粗灰分
-  @Column()
+  // 粗灰分(百分比)
+  @Column({
+    type: 'double',
+  })
   ash: number;
 
-  // 水分
-  @Column()
+  // 水分(百分比)
+  @Column({
+    type: 'double',
+  })
   moisture: number;
 
   @OneToMany(

+ 66 - 0
src/pet-feeder/mapper/product.mapper.ts

@@ -6,7 +6,72 @@ import { productCategoryLabels } from '@/pet-feeder/enum/product-category';
 
 @Injectable()
 export class ProductMapper extends BaseMapper<Product, ProductVo> {
+  /**
+   * 计算产品的代谢能(ME - Metabolizable Energy)
+   * 基于营养成分计算每克产品的能量值
+   *
+   * @param protein 蛋白质含量(百分比,如0.4表示40%)
+   * @param fat 脂肪含量(百分比)
+   * @param fiber 粗纤维含量(百分比)
+   * @param ash 粗灰分含量(百分比)
+   * @param moisture 水分含量(百分比)
+   * @returns ME值 (kcal/g)
+   */
+  private calculateME(
+    protein: number,
+    fat: number,
+    fiber: number,
+    ash: number,
+    moisture: number,
+  ): number {
+    // 步骤1: 计算干物质
+    const dryMatter = 1 - moisture;
+
+    // 步骤2: 计算NEF(无氮浸出物)
+    const nef =
+      1 -
+      protein * (1 - moisture) -
+      fat * (1 - moisture) -
+      fiber * (1 - moisture) -
+      ash * (1 - moisture) -
+      moisture;
+
+    // 步骤3: 计算各营养成分质量
+    const proteinMass = protein * dryMatter;
+    const fatMass = fat * dryMatter;
+    const fiberMass = fiber * dryMatter;
+
+    // 步骤4: 计算干物质中粗纤维含量占比
+    const fiberPercentageInDryMatter = (fiberMass / dryMatter) * 100;
+
+    // 步骤5: 计算GE(总能)
+    const ge = 5.7 * proteinMass + 9.4 * fatMass + 4.1 * (nef + fiberMass);
+
+    // 步骤6: 计算能量消化率
+    const digestibility = 87.9 - 0.88 * fiberPercentageInDryMatter;
+
+    // 步骤7: 计算DE(消化能)
+    const de = (ge * digestibility) / 100;
+
+    // 步骤8: 计算ME(代谢能)
+    const me = de - 0.77 * proteinMass;
+
+    return me;
+  }
+
   toVo(entity: Product): ProductVo {
+    // 计算ME值(每克产品的能量)
+    const mePerGram = this.calculateME(
+      entity.protein,
+      entity.fat,
+      entity.fiber,
+      entity.ash,
+      entity.moisture,
+    );
+
+    // 计算整包产品的总能量
+    const totalCalories = mePerGram * entity.totalWeight;
+
     return {
       ...super.toVo(entity),
       name: entity.name,
@@ -19,6 +84,7 @@ export class ProductMapper extends BaseMapper<Product, ProductVo> {
       ash: entity.ash,
       moisture: entity.moisture,
       totalWeight: entity.totalWeight,
+      totalCalories: Number(totalCalories.toFixed(2)), // 保留2位小数
     };
   }
 }

+ 5 - 0
src/pet-feeder/vo/product.vo.ts

@@ -36,4 +36,9 @@ export class ProductVo extends BaseVo {
 
   @ApiProperty()
   moisture: number;
+
+  @ApiProperty({
+    description: '产品总能量(kcal),基于ME算法计算',
+  })
+  totalCalories: number;
 }