Commit 54eee31e by 杨树贤

暂时版本

parent 8ed2a0f5
# 价格生成逻辑文档
## 概述
本文档详细描述 `LyService.LyGoodsDetail` 方法中的价格生成逻辑,该逻辑根据组织ID(`org_id`)对不同类型的供应商采用不同的价格处理策略。
## 组织类型
| OrgId | 组织名称 | 说明 |
|-------|----------|------|
| 0 | 兼容旧价格体系 | 为兼容价格体系之前的数据保留 |
| 1 | 猎芯 | 采用标准价格体系 |
| 3 | 爱智/华云 | 需要兼容老数据和新价格体系 |
---
## 价格生成主流程
```
switch sku.OrgId
├── case 0: 空处理(兼容旧数据)
├── case 1: 猎芯价格体系
│ ├── GetCoefficientAndPrice() → 获取系数和计算价格
│ ├── getCustomPriceList() → 获取自定义价格
│ └── GetActivityPrice() → 获取活动价格
└── case 3: 爱智/华云价格体系
├── 寄售商品判断 (source == 12) → 跳过价格体系
└── 老数据兼容判断
├── 老数据格式 → GetIEdgePrice() → 处理爱智特定价格格式
└── 新价格体系 → 标准价格体系流程 + transformIEdgeLadderPrice()
└── GetActivityPrice() → 获取活动价格
GetCostForZiying() → 处理自营成本价
```
---
## 猎芯组织 (OrgId = 1) 价格流程
### 1. GetCoefficientAndPrice()
核心价格计算方法,根据供应商类型分为两条路径:
#### 专卖供应商 (supplier_id = 17)
**流程:**
1. 处理特殊供应商价格 (`TransformSpecialSupplierPrice`)
2. 处理香港自营渠道 (`L0018562`) 汇率转换
3. 获取折扣系数 (`GetDiscountRatio`)
4. 应用折扣系数到价格
**关键逻辑:**
```go
// 香港自营特殊处理:WMS同步的美金未税成本价需要转换
if sku.Canal == "L0018562" {
// 1. 获取实时汇率
// 2. 计算人民币含税价格(汇率 × 关税1.13)
// 3. 生成阶梯价
}
```
#### 代购供应商
**流程:**
1. 获取折扣系数 (`GetDiscountRatio`)
2. 获取售价组系数 (`GetPriceRatio`)
3. 获取供应商系数 (Redis: `pool_supplier_ratio`)
4. 计算成本价和售价
**价格计算公式:**
```
成本价(美金) = 原始美金价 × 折扣系数(美金)
售价(美金) = 成本价(美金) × 售价组系数(美金)
成本价(人民币) = 原始美金价 × 汇率 × 关税(1.13) × 折扣系数(人民币)
售价(人民币) = 成本价(人民币) × 售价组系数(人民币)
```
**特殊供应商处理:**
- MRO (supplier_id=1688):只有人民币价格,直接作为成本价
- Digikey (supplier_id=7):可能同时有人民币和美金价格
### 2. getCustomPriceList()
根据组织ID获取自定义价格配置,生成多个自定义价格阶梯。
```go
// 例如:会员价利润10%,企业价利润5%
// 会在基础价格上应用不同的利润率系数
customPriceList = [
{PriceName: "会员价", LadderPrice: [...]},
{PriceName: "企业价", LadderPrice: [...]}
]
```
### 3. GetActivityPrice()
应用活动价格(折扣/特价活动)。
---
## 爱智组织 (OrgId = 3) 价格流程
### 特殊判断逻辑
爱智组织需要处理**历史遗留数据****新价格体系**的兼容问题。
#### 1. 寄售商品跳过
```go
if sku.Source == 12 {
break // 寄售商品不走价格体系
}
```
#### 2. 老数据兼容判断
**老数据特征:**
| 阶梯数量 | 第一个阶梯条件 | 数据类型 | 处理方式 |
|----------|----------------|----------|----------|
| 2 | `Purchases != 0` | 老数据 | GetIEdgePrice() |
| 3 | `Purchases == 0` | 新配置(成本+会员+企业) | GetIEdgePrice() |
| 4 | `Purchases == 0` | 新配置(成本+会员+企业+限价) | GetIEdgePrice() |
**老数据处理 (GetIEdgePrice):**
```go
// Purchases 值映射到价格名称
0 "成本价"
1 "标准价"
2 "企业价"
3 "销售限价"
// 过滤规则:
// - 3个阶梯:删除第一个(成本价),保留标准价+企业价
// - 4个阶梯:取中间两个(标准价+企业价)
```
#### 3. 走价格体系的最新配置
**条件:**
- 阶梯数量为2,第一个阶梯是0(成本价 + 销售限价)
**处理流程:**
1. 去掉销售限价(因为走价格体系的前提是有成本价)
```go
if len(sku.LadderPrice) == 2 {
sku.LadderPrice = sku.LadderPrice[:1] // 只保留成本价
}
```
2. 走标准价格体系(同猎芯流程)
- `GetCoefficientAndPrice()`
- `getCustomPriceList()`
3. 华云阶梯价特殊转换 (`transformIEdgeLadderPrice`)
```go
// 华云兼容格式:
// 自定义价格 → 转换为2个阶梯的格式
// purchases=1: 标准价
// purchases=2: 企业价
```
---
## 关键数据结构
### LadderPrice(阶梯价格)
```go
type LadderPrice struct {
Purchases int64 // 购买数量
PriceUs float64 // 美金售价
PriceCn float64 // 人民币售价
PriceCostUs float64 // 成本价美金
PriceCostCn float64 // 成本价人民币
PriceAc float64 // 活动价人民币
PriceAcUs float64 // 活动价美金
PriceName string // 价格名称(华云专用)
}
```
### 华云价格名称映射
```go
priceNameMap := map[int64]string{
0: "成本价",
1: "标准价",
2: "企业价",
3: "销售限价",
}
```
---
## 特殊供应商汇率处理 (TransformSpecialSupplierPrice)
针对存入"美金"字段但实际是其他币种的供应商进行转换:
| 供应商ID | 原始币种 | 处理方式 |
|----------|----------|----------|
| 6 (Element14) | 港币 | 港币 → 人民币 → 美金 |
| 21 (RS) | 人民币 | 人民币 → 美金 |
| 1676 (Buerklin) | 欧元 | 欧元 → 人民币 → 美金 |
**汇率转换流程:**
1. 获取币种转人民币汇率 (`erp_rate`)
2. 人民币转美金汇率 = 币种汇率 ÷ 美金汇率
3. 应用转换到阶梯价
---
## 后续处理
### GetCostForZiying()
处理自营供应商的成本价。
### 最小起订量校验
```go
// 最小起订量要大于等于阶梯价的最小阶梯数量
if purchases > sku.Moq {
sku.Moq = purchases
}
```
---
## 总结
1. **猎芯 (OrgId=1)**:标准价格体系,通过系数计算生成阶梯价
2. **爱智 (OrgId=3)**:复杂兼容逻辑,需要判断数据版本并选择不同的处理路径
3. **核心公式**:成本价 × 利润系数 = 售价
4. **关键系数**:折扣系数、售价组系数、供应商系数
---
*文档生成时间:2025年4月*
# 商品价格生成逻辑说明(产品版)
# 商品价格生成逻辑说明(产品版)
## 一、整体流程概述
当用户查看商品详情时,系统会根据商品所属的组织类型,采用不同的价格计算方式。目前主要有两种组织:
- **猎芯(OrgId = 1)**:标准价格体系
- **爱智/华云(OrgId = 3)**:兼容多种历史数据格式
---
## 二、猎芯的价格生成流程
### 第一步:基础价格计算(GetCoefficientAndPrice)
#### 情况A:专卖供应商(supplier_id = 17,自营渠道)
**说明:** supplier_id = 17 是"专营供应商"的统一标识,实际上包含多个自营渠道:
- **L0018319**:国内自营(WMS同步人民币未税成本价)
- **L0018562**:香港自营(WMS同步美金未税成本价)
- **L0003270**:其他自营渠道
- 以及其他以 L 开头的专营渠道编码
**核心概念:单一成本价 vs 自营商品成本价**
这是两个不同的概念,需要区分清楚:
| 类型 | 定义 | 适用场景 |
|-----|------|---------|
| **单一成本价** | 上传数据只有**1个阶梯**,且 `Purchases = 0` | 代购供应商(从第三方采购的商品) |
| **自营商品成本价** | WMS同步的库存成本价(含税) | 专营供应商 supplier_id = 17(自营商品) |
**单一成本价的判断逻辑:**
```
上传的数据:
- 只有1个阶梯,且 Purchases = 0 → 代表是【单一成本价】
- 有多个阶梯,且 Purchases > 0 → 代表是【已有阶梯价】
```
**单一成本价的特点:**
- 供应商上传时只提供了一个成本价(没有设置阶梯价)
- 系统需要根据这个成本价,自动生成完整的阶梯价格
- 适用于专营供应商(supplier_id = 17)
**自营商品成本价的特点:**
- 从WMS系统同步过来的库存成本价
- 国内自营(L0018319):同步人民币含税成本价
- 香港自营(L0018562):同步美金未税成本价
- 需要根据汇率和关税转换成含税成本价
---
**流程说明:**
1. **汇率转换(仅香港自营 L0018562)**
- WMS同步的是美金未税成本价
- 需要 × 汇率 × 关税(1.13) = 人民币含税成本价
2. **判断是否有成本价**
- 如果 `PriceCostUs``PriceCostCn` 都为0:调用 `GenerateLadderPrice()` 生成阶梯价
- 如果已有成本价:直接使用,应用折扣系数
3. **获取折扣系数** (`GetDiscountRatio`):从配置获取折扣比例
4. **应用折扣**:最终售价 = 成本价 × 折扣系数
---
**核心方法:GenerateLadderPrice(单一成本价生成阶梯价)**
**适用范围:代购供应商(supplier_id ≠ 17)**
当代购供应商上传商品时,如果只提供了一个成本价(Purchases = 0),没有设置阶梯价,系统会调用这个方法自动生成完整的阶梯价格。
**注意:自营商品(supplier_id = 17)不走这个逻辑**,因为自营商品有WMS同步的成本价,使用另外的价格计算方式。
**情况1:起订量 ≤ 50 的固定阶梯(MOQ小的商品)**
当最小起订量较小时,系统使用**固定的阶梯数量和固定的利润率**来生成价格,防止卖亏。
**固定阶梯配置表:**
| MOQ范围 | 阶梯1 | 阶梯2 | 阶梯3 | 阶梯4 | 阶梯5 |
|---------|-------|-------|-------|-------|-------|
| < 10 | MOQ | 30 | 100 | 300 | 1000 |
| 10-29 | MOQ | 50 | 200 | 500 | 1000 |
| 30-50 | MOQ | 200 | 500 | 1000 | 2000 |
**固定利润率(安全保底):**
- 阶梯1(MOQ):11% 利润
- 阶梯2:10% 利润
- 阶梯3:9% 利润
- 阶梯4:8% 利润
- 阶梯5:7% 利润
**示例(MOQ = 5):**
```
成本价:¥100
生成的阶梯价:
- 5个:¥100 × 1.11 = ¥111(11%利润)
- 30个:¥100 × 1.10 = ¥110(10%利润)
- 100个:¥100 × 1.09 = ¥109(9%利润)
- 300个:¥100 × 1.08 = ¥108(8%利润)
- 1000个:¥100 × 1.07 = ¥107(7%利润)
```
**情况2:起订量 > 50 的动态阶梯(MOQ大的商品)**
当最小起订量较大时,系统根据**库存量****配置的售价组系数**动态计算阶梯数量和利润率。
**计算逻辑:**
1. 根据库存量确定可以展示多少个阶梯(库存要满足该阶梯的数量需求)
2. 从售价组配置中读取利润系数
3. 成本价 × 利润系数 = 各阶梯售价
**关键配置参数:**
- `ladderPriceMiniProfitLevel`:最小利润点阶梯数(如设为5,表示最多展示5个阶梯,从第5个利润点开始倒推)
- `costLadderCount`:根据库存计算出的实际阶梯数
**利润阶梯计算示例:**
```
假设售价组配置了9个利润系数(利润从低到高):
[1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.11, 1.12, 1.13]
MOQ = 100,库存 = 5000
最小利润点 = 5
库存满足的阶梯数 = 3(100×1=100, 100×5=500, 100×10=1000 都在库存范围内)
因为 3 < 5,所以倒推取利润阶梯:
阶梯1 → 取第(5-3+0)=3个利润系数 = 1.07
阶梯2 → 取第(5-3+1)=3个利润系数 = 1.08
阶梯3 → 取第(5-3+2)=5个利润系数 = 1.09
最终价格:
- 100个:¥成本 × 1.07
- 500个:¥成本 × 1.08
- 1000个:¥成本 × 1.09
```
---
**举个栗子(香港自营 L0018562):**
```
WMS同步数据:
- 美金成本价:$100(未税)
- 汇率:7.2
- 关税:1.13
计算过程:
1. 人民币成本 = $100 × 7.2 × 1.13 = ¥813.6
2. 折扣系数:0.95(95折)
3. 最终成本价:¥813.6 × 0.95 = ¥772.92
生成阶梯价(假设MOQ=5):
- 5个:¥772.92 × 1.11 = ¥857.94
- 30个:¥772.92 × 1.10 = ¥850.21
- 100个:¥772.92 × 1.09 = ¥842.48
- 300个:¥772.92 × 1.08 = ¥834.75
- 1000个:¥772.92 × 1.07 = ¥827.02
```
#### 情况B:代购供应商(从第三方采购)
**流程说明:**
1. **获取三个系数:**
- **折扣系数**:商品的折扣比例
- **售价组系数**:不同采购数量的利润系数
- **供应商系数**:供应商级别的加成系数
2. **计算成本价:**
- 美金成本 = 原始采购价 × 折扣系数
- 人民币成本 = 原始采购价 × 汇率 × 关税 × 折扣系数
3. **计算售价:**
- 美金售价 = 美金成本 × 售价组系数
- 人民币售价 = 人民币成本 × 售价组系数
**特殊供应商说明:**
- **MRO(1688)**:只有人民币价格,直接作为成本价
- **Digikey(7)**:可能同时有人民币和美金价格
**价格计算示例:**
```
原始采购价:$100
折扣系数:0.95
售价组系数:1.15(15%利润)
汇率:7.2
关税:1.13
计算过程:
美金成本 = $100 × 0.95 = $95
美金售价 = $95 × 1.15 = $109.25
人民币成本 = $100 × 7.2 × 1.13 × 0.95 = ¥772.2
人民币售价 = ¥772.2 × 1.15 = ¥888.03
```
### 第二步:生成自定义价格(getCustomPriceList)
**业务场景:**
除了标准售价外,还需要展示会员价、企业价等多种价格。
**流程说明:**
1. 根据组织ID从Redis获取自定义价格规则
2. 每条规则包含:价格名称(如"会员价")+ 利润比例(如10%)
3. 在标准售价基础上,应用不同的利润率,生成多套阶梯价
**举个栗子:**
```
标准售价阶梯:
- 1个:¥100
- 10个:¥95
- 100个:¥90
自定义价格配置:
- 会员价:利润10%
- 企业价:利润5%
生成结果:
会员价阶梯:
- 1个:¥100 × 1.10 = ¥110
- 10个:¥95 × 1.10 = ¥104.5
- 100个:¥90 × 1.10 = ¥99
企业价阶梯:
- 1个:¥100 × 1.05 = ¥105
- 10个:¥95 × 1.05 = ¥99.75
- 100个:¥90 × 1.05 = ¥94.5
```
### 第三步:应用活动价格(GetActivityPrice)
**业务场景:**
商品参与促销活动时,需要计算活动价。
**流程说明:**
1. 检查商品是否参与活动
2. 如有活动,根据活动规则计算活动价
3. 活动价会覆盖标准售价展示给用户
---
## 三、爱智/华云的价格生成流程
爱智的价格逻辑比较复杂,因为需要兼容**历史遗留数据****新的价格体系**
### 第一步:判断是否为寄售商品
**判断条件:** `source == 12`
**处理逻辑:**
- **是寄售商品**:直接跳过价格体系,使用上传的价格
- **非寄售商品**:继续后续判断
### 第二步:判断数据类型(老数据 vs 新数据)
根据阶梯价的数量和格式,判断是老数据还是新数据:
#### 情况A:老数据格式(直接展示,不走价格体系)
**老数据的三种情况:**
| 阶梯数量 | 第一个阶梯 | 数据说明 | 处理方式 |
|---------|-----------|---------|---------|
| 2个 | 数量≠0 | 旧版格式(标准价+企业价)| GetIEdgePrice处理 |
| 3个 | 数量=0 | 新版格式(成本价+会员价+企业价)| GetIEdgePrice处理,删除成本价 |
| 4个 | 数量=0 | 新版格式(成本+会员+企业+限价)| GetIEdgePrice处理,取中间两个 |
**GetIEdgePrice处理逻辑:**
1. **给每个阶梯添加价格名称:**
- 数量0 → "成本价"
- 数量1 → "标准价"
- 数量2 → "企业价"
- 数量3 → "销售限价"
2. **过滤不需要展示的价格:**
- 3个阶梯时:删除第一个(成本价),只展示标准价+企业价
- 4个阶梯时:取中间两个(标准价+企业价)
**举个栗子(3个阶梯):**
```
上传的数据:
- 数量0:¥50(成本价)
- 数量1:¥100(标准价)
- 数量2:¥80(企业价)
处理后展示:
- 数量1:标准价 ¥100
- 数量2:企业价 ¥80
成本价内部保留,前端不展示
```
#### 情况B:新数据格式(走价格体系)
**判断条件:**
- 阶梯数量为2
- 第一个阶梯数量为0(即成本价)
**处理流程:**
1. **预处理阶梯价:**
如果同时有成本价和销售限价,去掉销售限价(因为走价格体系的前提是有成本价)
```
原始:[成本价, 销售限价]
处理后:[成本价]
```
2. **走标准价格体系:**
和猎芯的流程一样:
- GetCoefficientAndPrice(基础价格计算)
- getCustomPriceList(生成自定义价格)
3. **华云格式转换(transformIEdgeLadderPrice):**
为了让华云的老系统能正常显示,需要将自定义价格转换成特定的格式:
```
转换前(自定义价格):
- 会员价:数量100,价格¥90
- 企业价:数量100,价格¥85
转换后(华云格式):
- 数量1:标准价 ¥90
- 数量2:企业价 ¥85
```
### 第三步:应用活动价格
和猎芯一样,检查是否有活动,应用活动价。
---
## 四、特殊供应商的币种转换
有些供应商存入"美金"字段的实际上不是美金,需要进行币种转换:
| 供应商 | 原始币种 | 转换逻辑 |
|-------|---------|---------|
| Element14(6)| 港币 | 港币 → 人民币 → 美金 |
| RS(21)| 人民币 | 人民币 → 美金 |
| Buerklin(1676)| 欧元 | 欧元 → 人民币 → 美金 |
**转换示例(Element14):**
```
原始价格:100港币
港币汇率:0.92(1港币 = 0.92人民币)
美金汇率:7.2(1美金 = 7.2人民币)
计算:
人民币 = 100 × 0.92 = 92元
美金 = 92 ÷ 7.2 = $12.78
```
---
## 五、后续处理
### 1. 自营成本价处理(GetCostForZiying)
针对自营供应商的特殊成本价处理。
### 2. 最小起订量校验
```
规则:最小起订量 ≥ 阶梯价的最小数量
示例:
- 商品设置的最小起订量:5个
- 阶梯价最小数量:10个
- 最终结果:最小起订量改为10个
```
---
## 六、总结对比表
| 组织 | 价格体系 | 主要特点 |
|-----|---------|---------|
| 猎芯(1)| 标准体系 | 通过系数计算价格,支持多种自定义价格 |
| 爱智(3)| 兼容体系 | 需要判断数据版本,老数据直接展示,新数据走价格体系 |
| 寄售商品 | 跳过体系 | 直接使用上传的价格 |
---
## 七、关键术语解释
| 术语 | 说明 |
|-----|------|
| 阶梯价 | 不同采购数量对应的不同价格,数量越多单价越低 |
| 成本价 | 采购成本,内部使用 |
| 标准价 | 普通用户看到的售价 |
| 会员价 | 会员用户专享价格 |
| 企业价 | 企业客户专享价格 |
| 折扣系数 | 对成本价的折扣比例 |
| 售价组系数 | 不同利润档位 |
| 最小起订量(MOQ)| 单次采购的最低数量要求 |
---
*文档编写时间:2025年4月*
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment