代码片段

接口

mongodb 中文文档

查询

1
2
3
4
await MAPP.db_queryAll({
model: '',
condition: {}
})

获取一条数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const commodity = await MAPP.db_getOne({
model: 'commodity',
condition: {
_id: '58805dd61d8bdc9c56cc3e2d',
distributed: {
$elemMatch: {
store_id: '5d64d9b75fc33f07bcfe1435'
}
}
},
filters: {
'distributed.$:': 1
}
})
  1. 不分页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const result = await MAPP.db_queryAll({
model: 'area',
condition: {},
pageTurn: false, //默认true
type: 'noPage', //默认''
isCount: false,
params: {
page: i + 1,
limit: 1
},
options: {
lean: true
},
filters: {
adcode: true
},
})
  1. 获取过滤数组第一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const {
result = [], count = 0
} = await MAPP.db_queryAll({
model: 'commodity',
condition: {
'distributed.store_id': '5d64d9b75fc33f07bcfe1435'
},
filters: {
'distributed.$': 1
}
})

//返回
[{
_id: 58805 dd61d8bdc9c56cc3e2d,
distributed: [
[Object]
]
}]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
$project: {
medical: 1, // 医保商品
epidemic_situation: 1, // 疫情商品
name: 1,
bar_code: 1,
prescription: 1,
original_price: 1,
current_price: 1,
unit_num: 1,
// distributed: 1,
three_categories: 1,
cold_chain: 1,
overseas: 1,
hide_goods: 1,
filteredArray: {
'$filter': {
input: '$distributed',
as: 'item',
cond: {
'$and': [
{ '$eq': ['$$item.store_id', ObjectId('6201e7893d257513aa054e5c')] },
{ '$eq': ['$$item.shelf', true] },
{ '$gt': ['$$item.stock', 0] }
]
}
}
}
}
},

// 获取数组第一个元素
{ $project: { firstArrayElement: { $arrayElemAt: ["$myArrayField", 0] } } }

jsuan.png

  1. 联表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const result = await MAPP.db_queryAll({
model: "",
params: {
page,
limit,
},
isCount: false, //不返回条数
type: "populate", //设置连表
populate: [
{
path: "user_id", //本表id字段
select: "nickname full_name phone_number", //外表字段过滤
model: "member", //外表
},
{
path: "cashier_id",
select: "staff_name",
model: "store_staff",
},
],
sort: {},
filters: {},
});
  1. 数组拆分在合并
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const obj = await MAPP.db_aggregateAll({
model: 'match_package',
params: parameter,
aggregate: [
{
$match: {
store_ids: {
$in: [new MAPP.MTypesId(store_id)]
},
enable: true,
start_time: { $lte: time },
end_time: { $gte: time }
}
},
{ $unwind: '$promotional_goods' },
{
$lookup: {
from: 'commodity',
localField: 'promotional_goods.goods_id',
foreignField: '_id',
as: 'commodity',
},
},
{ $unwind: '$commodity' },
{
$addFields: {
'distributed': {
$filter: {
input: '$commodity.distributed',
as: 'item',
cond: {
'$eq': ['$$item.store_id', new MAPP.MTypesId(store_id)]
}
}
}
}
},
{
$redact: {
$cond: {
if: {
$and: [
{ $ne: ['$distributed', []] }
]
},
then: '$$KEEP',
else: '$$PRUNE'
}
}
},
{
$unwind: '$distributed'
},
{
$project: {
title: 1,
limit_number: 1,
package_original_price: 1,
package_total_price: 1,
package_stock: 1,
image: 1,
promotional_goods: 1,
activity_label: 1,
priority: -1,
update_time: -1,
// commodity: 1,
distributed: 1
}
},
{
$group: {
_id: '$_id',
out: { $last: '$$ROOT' },
stocks: {
// $push: '$distributed.stock'
$push: { $cond: [{ $gt: ['$distributed.stock', 0] }, true, false] }
},
promotional_goods: {
$push: '$promotional_goods'
}
}
},
{
$addFields: {
noStocks: {
'$filter': {
input: '$stocks',
as: 'v',
cond: {
// $lte: ['$$v', 0]
$eq: ['$$v', false]
}
}
}
}
},
{
$addFields: {
stock: { $arrayElemAt: ['$noStocks', 0] }
}
},
// 添加字段
{
$addFields: {
hasStock: { $cond: [{ $eq: ['$stock', false] }, false, true] }
}
},
{
$sort: {
hasStock: -1,
'out.priority': -1,
'out.update_time': -1
}
}
// {
// $project: {
// _id: 1,
// out: 1,
// stocks: 1,
// hasStock: 1
// }
// }
]
})

取模 $mod

获取一条数据 MAPP.db_getOne()

更新

1
2
3
4
5
6
7
await MAPP.db_setOne({
model: '',
condition: {},
data: {
$set: {}
}
})

语法

1
2
3
4
5
6
7
8
9
10
data: {
//更新数据
$set: {},
//插入数据,重复的不插入
$addToSet: {}
//插入数据
$push: {}
//更新或插入数据
$setOnInsert: {}
}

搜索并更新

1
2
3
4
5
await MAPP.db_setOne({
model: 'commodity',
condition: { _id: product_id, 'distributed.store_id': store_id },
data: { $inc: { 'distributed.$.stock': stock } },
})

更新或插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
await MAPP.db_setOne({
model: '',
condition: {},
data: {
$set: {},
$setOnInsert: {}
},
options: {
lean: true,
new: true,
upsert: true,
setDefaultsOnInsert: true,
},
})
// options 必须配置

多次嵌套修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
await MAPP.db_setOne({
        model: 'deliver_accept_order',
        condition: { _id: _id, product_list: { $elemMatch: { batch_number: { $elemMatch: { _id: batch_number_id } } } } },
        data: {
          $set: {
            receipt_status: 2,
            'product_list.$[e].batch_number.$[val].in_quantity': in_quantity,
            'product_list.$[e].batch_number.$[val].diff_quantity': transit_quantity - in_quantity,
            'product_list.$[e].batch_number.$[val].low_quantity': low_quantity,
            'product_list.$[e].batch_number.$[val].low_reason': low_reason,
            'product_list.$[e].batch_number.$[val].take_status': in_quantity > 0 ? 1 : 0
          }
        },
        // 更新多层嵌套数组
        options: {
          arrayFilters: [{
            'e.product_id': goods_mongoId,
          }, {
            'val.batch_id': batch_number_id
          }],
          multi: true
        }
      })

数组操作

修改数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 修改部分
await MAPP.db_setMany({
model: "commodity",
condition: {
"distributed.store_id": { $in: store_ids },
// prescription: prescriptions
},
data: { $set: { [`distributed.$[elem].reduction_ids`]: _ids } },
options: {
arrayFilters: [{ "elem.store_id": { $in: store_ids } }],
},
});
// 全部修改
await MAPP.db_setMany({
model: "commodity",
condition: { status: { $ne: 1 } },
data: {
$set: { "distributed.$[].shelf": true },
},
});

聚合

基础

1
2
3
4
5
await MAPP.db_aggregateAll({
model: "",
condition: {},
aggregate: [],
});

$filter 过滤数组符合的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
{
$project: {
assigners: {
$filter: {
input: '$assigners',
as: 'item',
cond: {
$eq: ['$$item.id', MAPP.MTypesId(staff_id)]
}
}
}
}
}

$group统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
$group: {
_id: '$product_list.product_id', //需要统计的_id字段
// 总价统计
amount_stat: {
$sum: { $multiply: ['$product_list.cypher_price', '$product_list.quantity'] },
},
product_id: {
$first: '$$ROOT.product_list.product_id', //第一个统计字段
},
quantity_stat: {
$sum: '$product_list.quantity',
},
},
},

$lookup 连表 unwind 拆分

注:连表是数组,需要把数组拆分成对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
$lookup: {
from: 'commodity', //外表
localField: 'group.kind_id', //本表关联
foreignField: '_id', //外表关联
as: 'commodity', //显示字段
},
},
{
$unwind: {
path: '$commodity', //数组拆分
preserveNullAndEmptyArrays: true // 空数组也拆分.
}
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const result = await MAPP.db_aggregateAll({
model: 'order_goods_record',
isCount: false,
pageTurn: false,
aggregate: [
{
$match: {
order_id: MAPP.MTypesId('63e9f04109ae774560a44829')
}
},
{
$unwind: {
path: '$product_list',
preserveNullAndEmptyArrays: true // 空数组也拆分.
}
},
{
$group: {
_id: {
'product_id': '$product_list.product_id',
'batch_id': '$product_list.batch_id',
'type': '$product_list.type',
'activity_id': '$product_list.activity_id',
},
// 第一个商品
product_first: {
'$first': '$product_list'
},
// 统计金额
amount_stat: {
$sum: { $multiply: ['$product_list.final_price', '$product_list.spare_quantity'] },
},
}
}
]
})
console.log(result, 123)

商品查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
let aggregate = [
{
$match: match
},
// {
// $sort: {
// priority: -1,
// 'original_gift_goods.sort': 1,
// update_time: -1
// }
// },
{
$project: {
distributed: {
'$filter': {
input: '$commodity.distributed',
as: 'item',
cond: {
'$and': [
{ '$eq': ['$$item.store_id', new MAPP.MTypesId(store_id)] },
{ '$eq': ['$$item.shelf', true] }
]
}
}
}
}
},
{
$redact: {
$cond: {
if: {
$and: [
{ $ne: ['$distributed', []] }
]
},
then: '$$KEEP',
else: '$$PRUNE'
}
}
},
{
$unwind: '$distributed'
},
{ // 增加是否库存字段
$addFields: {
hasStock: { $cond: [{ $gt: ['$distributed.stock', 0] }, true, false] }
}
},
{
$sort: {
hasStock: -1,
_id: -1
}
}
]

字符串截取 $substr

https://www.jianshu.com/p/8aa8794101e3

1
2
3
4
5
6
7
8
9
db.getCollection('notice').aggregate(
[
{
$project: {
content: { $substrCP: ['$content', 0, 20] } //从0开始截取长度为20的字符串
}
}
]
)

$$ROOT 根元素过滤

1
2
3
4
5
{
$project: {
goods_ids: '$$ROOT.check.goods_ids',
}
}

删除

1
2
3
4
5
6
7
8
9
10
11
const res = await MAPP.db_deleteOne({
model: 'medicate_info',
condition: {
_id: $id
}
})
if (res.ok && res.value) {
ctx.info({ message: '删除成功' })
} else {
ctx.info({ message: '删除失败', status: 403 })
}

通用方法

MAPP

路径 \api-medicalCenter\libs\utils\

plusminusmultiplydivision

selectTime 获取时间范围

1
2
3
4
5
// 传入
// Month: 本月 LastMonth: 上月 Yesterday:昨天 Day: 今天
// LastWeek:上周  Week: 本周  Year:今年 LastYear:去年
const timeRange = MAPP.selectTime('Today')
console.log(timeRange) // [ 1658764800000, 1658851199999 ]

formatFloat 保留几位小数(四舍五入)

1
const a = MAPP.formatFloat('2.567', 2) // 2.57

formatMoney 保留金额两位

1
const a = MAPP.formatMoney(5.335) // 5.34

identityGetAge 身份证获取年龄

110101190001011009

220202202002020022

在线身份证号码验证

1
const age = MAPP.identityGetAge('220202202002020022') //2

方法代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 身份证获取年龄
function identityGetAge(u = '') {
u = u.toString()
let len = (u + '').length
let strBirthday = ''
if (len === 18) {
// 处理18位的身份证号码从号码中得到生日和性别代码
strBirthday =
u.substr(6, 4) +
'/' +
u.substr(10, 2) +
'/' +
u.substr(12, 2)
}
if (len === 15) {
let birthdayValue = ''
birthdayValue = u.charAt(6) + u.charAt(7)
if (parseInt(birthdayValue) < 10) {
strBirthday =
'20' +
u.substr(6, 2) +
'/' +
u.substr(8, 2) +
'/' +
u.substr(10, 2)
} else {
strBirthday =
'19' +
u.substr(6, 2) +
'/' +
u.substr(8, 2) +
'/' +
u.substr(10, 2)
}
}
// 时间字符串里,必须是“/”
let birthDate = new Date(strBirthday)
let nowDateTime = new Date()
let age = nowDateTime.getFullYear() - birthDate.getFullYear()
// 再考虑月、天的因素;.getMonth()获取的是从0开始的,这里进行比较,不需要加1
if (
nowDateTime.getMonth() < birthDate.getMonth() ||
(nowDateTime.getMonth() === birthDate.getMonth() &&
nowDateTime.getDate() < birthDate.getDate())
) {
age--
}
return age.toString() === 'NaN' ? 0 : Number(age)
}

identityGetAge 身份证获取生日

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const identityGetBirth = (u = '', s = '-') => {
u = u.toString()
let len = (u + '').length
let strBirthday = ''
if (len === 18) {
// 处理18位的身份证号码从号码中得到生日和性别代码
strBirthday = u.substr(6, 4) + s + u.substr(10, 2) + s + u.substr(12, 2)
}
//第一代身份证15位,现在基本没有了
if (len === 15) {
let birthdayValue = ''
birthdayValue = u.charAt(6) + u.charAt(7)
if (parseInt(birthdayValue) < 10) {
strBirthday =
'20' +
u.substr(6, 2) +
s +
u.substr(8, 2) +
s +
u.substr(10, 2)
} else {
strBirthday =
'19' +
u.substr(6, 2) +
s +
u.substr(8, 2) +
s +
u.substr(10, 2)
}
}
return strBirthday
}
const a= identityGetBirth('220202202002020022')
console.log(a) //"2020-02-02"

identityGetSex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 按身份证号码获取性别
* @idNumber 身份证号码
* @return 男:male;女:female;异常(身份证号码为空或长度、格式错误):undefined
*/
function identityGetSex(idNumber='') {
if (idNumber) {
let genderCode='' // 性别代码
if (idNumber.length === 18) { // 二代身份证号码长度为18位(第17位为性别代码)
genderCode = idNumber.charAt(16)
} else if (idNumber.length === 15) { // 一代身份证号码长度为15位(第15位为性别代码)
genderCode = idNumber.charAt(14)
}
if (genderCode && !isNaN(genderCode)) {
// 两代身份证号码的性别代码都为男奇女偶
if (parseInt(genderCode) % 2 === 0) {
return 'female'
}
return 'male'
}
}
return ''
}
1
2
const male=identityGetSex('220202202002020022')
console.log(male,'111')

校验

路径 \api-medicalCenter\middleware

validator 校验 userAuth 不用登录

1
2
3
4
5
6
7
8
9
10
11
12
13
{
userAuth: false,
validator: {
verification_code: 'required|min:6',
phone: 'required|cellphoneNumber',
password: 'required|min:6',
'order_group.*.order_number': 'required|string',
openid: 'string',
type: 'required|in:order_library,premium_voucher,dr_appointmen,order_deposit,order_retainage',
voucher_id: [{ required_if: ['type', 'premium_voucher'] }, 'mongodbId'], //数组写法
store_ids: 'required|split-mongodbId', //mongodbId逗号隔开
},
},

多个|隔开
required 必传
min:6 最小 6 位
split-mongodbId 数组 id

常用
mongodbId numeric object string array

fullName 姓名应该在 2-4 个中文字符
IDCard 身份证号码验证
phoneNumber

缓存

注:

  1. 本地测试要配置nginx中的server_name地址参数
  2. 获取去掉配置

数据缓存
路径 \api-medicalCenter\src\@common\cache

促商品缓存
路径 \api-medicalCenter\src\@common\promotion

缓存进程
路径 \api-medicalCenter\src\@common\process

/**

  • 类型 genre: cache promotion
  • 方式
  • cache
  • 0 allCache 1 cacheBrandCommodity 2 cacheBrandAssort 3 cacheCategoriesCommodity 4 cacheCategoriesAssort
  • 5 cacheCommodityIntegral 6 cacheCourierCompanyAssort 7 cacheIntegralGoods 8 cacheCouponGoods 9 cacheMemberGrade
  • 10 cacheStore 11 cacheMallGuideAssort 12 cacheDistributionGoods 13 cacheCommodityIntegralDeduction 14 cacheCommodity
  • promotion
  • 0 allStoreRule 1 cipherRule
    */
    调用方法
1
2
const process_child = fork(MAPP.resolvePath('src/@common/process.js'))
process_child.send({ genre: 'promotion', method: [1], conditions: { 1: { store_id: existence.store_ids, genre: 'reduction' } } }) //满减

索引

创建索引

1
2
3
4
5
6
7
const res = await MAPP.db_getDataModel('commodity').collection.createIndex({ name: 'text' })
// 多个
collection.createIndexes([{ key: { 'level': 1 }, name: '级别'}])

// 删除
collection.dropIndexes()
// name_text

事务

Windows 下开启副本集

事务 demo 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const session = await MAPP.Mongoose.startSession() // 启用事务
try {
await session.startTransaction() // 开始事务
const result = await MAPP.db_setOne({
model: 'commodity',
condition: {
_id: '58805dd61d8bdc9c56cc3e2d'
},
data: { $set: { common_name: '氢溴酸右美沙芬片[测试]' } },
options: {
session,
new: true
}
})
console.log(result.common_name) // 修改后的结果
// eslint-disable-next-line no-throw-literal
// throw 'Too big' // 抛出错误
// to do something..... 代码业务方法
await session.commitTransaction() // 提交事务
await session.endSession()
} catch (e) {
await session.abortTransaction() // 终止事务
await session.endSession()
}

微信模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 微信服务订阅
*/
const name = 'wx_service_subscription'

module.exports = MAPP.injectDBModel(
{
// 模板名称 1.售后状态通知 2.订单发货通知 3.缴费通知 4.续费成功通知 5.待尾款提示 6.用药提醒 7.复购提醒 8.订单审核通知
name: { type: String, default: '' },
// 模版id
template_id: { type: String, default: '' },
// 是否启用
enable: { type: Boolean, default: false },
},
name
)

用药提醒

字段说明 参数
药品名称 {{thing1.DATA}}
用法用量 {{thing6.DATA}}
注意事项 {{thing7.DATA}}

说明:在订单支付后绑定模板 id 触发

复购提醒

{thing1:{value:""}} 最多 20 个中文字符,超出无法发送

字段说明 参数
药品信息 {{thing1.DATA}}
温馨提示 {{thing3.DATA}}

说明:

  1. 定时器每日 8 点推送 (最近 1 个月内商品订单信息开始推送)
  2. 复购推送规则
  • 待收货,已完成交易,已授权未推送过的订单
  • 推送时间:发货时间 + 疗程时间 <=当前时间
  • 推送疗程为下一个最近时间的疗程
  • 购买的数量没有在疗程内,不推送消息
  • 推送内容[药品信息][温馨提示](文字内容不超过 20 个字符)

用药提醒例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let data = {
thing3: { value: v.name || '------' }, // 药品名称
thing6: { value: v.usage || '------' }, // 用法用量
thing7: { value: v.precautions || '------' } // 注意事项
// console.log()
}
// 推送消息
await wx.subscribeMessage({
touser: openid,
page: `pagesD/indent/details?_id=${order._id}`,
template_id: wx_service_subscription.template_id,
miniprogramState: CONFIG.miniprogramState,
data,
}).then((data) => {
console.log(data)
// 用户拒绝或者没有订阅消息
// {
// errcode: 43101,
// errmsg: 'user refuse to accept the msg rid: 62fc6378-7f857407-1a8a6b2c'
// }
if (Number(data.errcode) === 0) {
console.log('微信订阅通知发送成功!')
}
}).catch((err) => {
console.log(err)
})

后台

配置

npm run copyConfig

开发版配置设置

1
2
const url = 'xcx.fenxiangqu.cn'
const ossUrl = 'https://syhl-newretail-dev.oss-cn-shenzhen.aliyuncs.com'
1
2
3
4
5
6
7
8
9
10
11
12
13
{
api: {
BASE_API: `http://192.168.1.208:4556`,
// 上传 请求
UPLOAD_URL: `http://192.168.1.208:4556`,
// websocket 请求
WSS_URL: `ws://192.168.1.208:3378/websocket`,
// 资源访问
RESOURCES_URL: ossUrl,
// b2c 微商城
B2C_APP_URL: '',
},
}

消息中心

数据表 message_center order_type 4 商品订单 5 退款订单
推送消息到后台方法 pushBackstageMsg
推送全部 to_user_id: 'all'

  1. 支付订单推送 用户支付订单成功后自动推送

  2. 退款单推送 用户申请退款单自动推送

推送规则

  1. 超级管理员和有关联该订单门店管理员
  2. 一个订单推送一条消息
  3. 按门店推送

b2c

推荐商品

/commodity/recommend/random

类型:1 首页 2 详情推荐

说明: 推荐商品必须库存大于 0,上架状态

一, b2c 首页推荐

9 个可以自定义

  1. 最多设置 50 个推荐商品
  2. b2c 前台最多随机 9 个推荐商品
  3. 超过 9 个才会随机
  4. 小于 9 个推荐商品 + 普通商品

二, 详情推荐

  1. 最多随机 8 个商品(关联相同商品的品牌,分类)

限销

下单算该商品已购买的数量了(已取消订单不算)

限销拦截以下

  1. 加入购物车
  2. 设置商品数量
  3. 立即购买
  4. 提交订单
  5. 支付订单

前台商品搜索

  1. b2c 前台商品列表搜索条件(/commodity)

    • 主要搜索
      name 商品名称/条码/厂家
    • 其他搜索
      brand_id 品牌 id
      categories_id 分类 id
      prescription 处方药类型
      for_people 适合人群
      in_stock 是否有货 (distributed.stock)
      new_product 是否新品 (distributed.new_product)
      promotion 促销类型(满赠,满赠) (distributed.gift_ids distributed.reduction_ids)
    • 排序
      price_sort 价格降升序 (distributed.current_price)
      sales_sort 销量排序 (distributed.sales)
  2. b2c 前台跨境商品列表搜索(/commodity/overseas)

    • 主要搜索 name 商品名称/条码
    • 排序 sort 字段降序
  3. b2c 前台其他商品排序(/commodity/leaderboard /floor/:id)

    • 楼层 库存降序 (distributed.stock)
    • 商品排行榜 销量降序 (distributed.sales)

移动医疗

医师端

患者端

分销

特殊分销

页面测试

D:\fix-bug\uni-b2c\src\pagesA\crossBorder

pagesA/crossBorder/index

http://192.168.1.208:8082/pagesA/crossBorder/index

任选

多商品任选计算

例子 商品 A 商品 B
单价 x 数量(元 x 件) 10 20
规则 1: 2 件 20 元 6.66 x 1 13.33 x 1
规则 2: 3 件 30 元 6 x 1 12 x 2
规则 3: 4 件 40 元 6.66 x 2 13.33 x 2

计算:

规则 1:
商品 A 总价 10 x 1 = 10
商品 B 总价 20 x 1 = 20
商品 A 实际单价 = (10 ÷ 30 x 20) ÷ 1 ≈ 6.66
商品 B 实际单价 = (20 ÷ 30 x 20) ÷ 1 ≈ 13.33

规则 2:
商品 A 总价 10 x 1 = 10
商品 B 总价 20 x 2 = 40
商品 A 实际单价 = (10 ÷ 50 x 30) ÷ 1 = 6
商品 B 实际单价 = (40 ÷ 50 x 30) ÷ 2 = 12

规则 3:
商品 A 总价 10 x 2 = 20
商品 B 总价 20 x 2 = 40
商品 A 实际单价 = (20 ÷ 60 x 40) ÷ 2 = 6 ≈ 6.66
商品 B 实际单价 = (40 ÷ 60 x 40) ÷ 2 ≈ 13.33

珍药优选

1.前台结算只能选择珍药商品结算

分销佣金

分销佣金指南(雨雀)

个人分销商佣金字段(表distributor)

wait_commission: 待结算
commission 已结算
extractable_commission 可提取
already_commission 已提取

佣金结算

  1. 提交订单(含分销商品)生成分销单(表distribution_order)

方法: 普通分销 distributorOrder 特殊分销 codeDistributorOrder

  1. 支付订单生成分销收入明细(表distribution_income_details) 未到账
    方法: distributionIncome
    说明 1: 分销单中分销收益有两条数据生成两条明细
    说明 2: 明细结余(待结算+已结算+可提取)
    说明 3: 全部退款取消订单 删除分销收入明细数据

  2. 确认收货结算佣金(表distributor)
    方法: distributionIReceipt
    说明 1: 按结算规则判断分销商个人佣金对应字段结算
    说明 2: 更新收入分销明细结字段
    结算规则:

    1. settlement_data=0 release_date=0 extractable_commission 可提现
    2. settlement_data=0 release_date>0 commission 已结算
    3. settlement_data>0 wait_commission 待结算
  3. 结算定时器
    方法: settlementCommission
    说明:

    1. 结算日 已结算增加 待结算减少
    2. 发放日 可提取增加 已提取减少

后台账户佣金: 已结算+可提现

b2c 前台账户佣金
累计收益: 已结算+可提取+已提现
今日预估收入:今天分销收入明细amount字段累加(含未到账,创建时间)
本月预估收入:本月分销收入明细amount字段累加(含未到账,创建时间)
账户余额: 已结算+可提现

店员端

app_shop_assistant

webpos

退款

webpos 退款功能说明:

  1. 全部退款可以按原路退或按现金退
  2. 部分退款,按原路退或现金退(单支付)
  3. 部分退款,只能按现金退(多支付)
  4. 退款金额不能超出订单实收金额
  5. 自定义退款数量不能超出商品原数量
  6. 退款金额为商品最终价格金额(平摊后的金额)
  7. 退款金额不能超出商品平摊后的金额

收银台

order_total 应收金额 (订单金额)
pay_total 实付金额
coupon_amount 优惠券抵扣金额
discount_amount 促销优惠金额 (满减金额)
member_amount 会员优惠金额 (会员价/内购价)
whole_amount 整单改价金额 (整单/单品字段二选一)
single_amount 单品改价金额 (整单/单品字段二选一)

save_data.is_change_price = false 是否自动切换价格(切换会员默认选择最优会员价)
save_data.no_change = true 是否处理商品会员价/内购价

save_data.pay_total = 0 重新计算应收金额
save_data.coupon_amount = 0 重新计算优惠券金额

getPendingOne 获取默认挂单信息

getPendingOrder 获取挂单详细信息

productSum 计算商品金额支付

savePendingOrder 保存挂单信息

fullReductionOffer 满减处理方法

fullGiftOffer 满赠处理方法

optimalAmount 处理最优解

goodPromotionRuleList 获取所有商品促销类型

goodSortFn 商品排序

disposeProductList 处理商品字段

noBatchNumber 只按商品销售 (清除批号数组)

disposeBatchNumber 处理批号数据

收银台字段说明:

品种数量: 商品个数(对应商品最大的序号)
应收金额 = 商品总价相加
实收金额 = 应收金额 - 促销优惠 - 改价金额 - 优惠券金额

促销优惠 = 赠品金额 + 满减金额

单品改价

只有普通商品才能改价

会员价/内购价修改价格变成商城价

接口名 /commodity/modify/:id

促销

优先级:

目前 webpos 添加顺序

  1. 限时抢购 —> 满减 —> 满赠—> 普通

同个活动的优先级: 先按设置优先级,再按更新时间

1
2
3
4
sort: {
priority: -1,
update_time: -1
}

促销类型

general 普通商品
match_package 组合套餐
redemption 加钱换购
limited_time_buying 限时抢购
presale 预售
integral_exchange 积分兑换

1.普通商品 2.限时抢购(限时,限量) 3.满减 4.满赠 5.组合套餐 6.换购 7.预售 8.积分兑换

门店商品库存不足时,下架状态无法下单购买

库存注意:

  1. webpos 库存按商品批号库存,b2c 库存按商品总库存判断
  2. 赠品活动库存目前版本已去掉(赠品库存按门店库存)
  3. 限时抢购设置商品活动库存为 0 时,不限时库存,为商品门店库存
  4. 组合套餐设置活动库存为 0 时,不限时库存,库存为组合商品内最小套餐数量
  5. 活动库存小于门店库存,按门店库存销售
  6. webpos 批号排序:先按有效期日期近到远排序,如有效期一样,则按批号库存从大到小排序

组合商品库存 1.当活动库存大于 0 时,以门店库存为主,必须小于活动库存 2.当活动库存等于 0 时(没限制库存) 以活动库存为主

简单功能说明

促销类型 说明
普通商品 普通商品含商城价/会员价/内购价,只有普通商品才能切换价格类型
限时抢购 限时(按时),限量(按日) (含活动价格,活动库存,限购数量)
满减 满购x元/件减y元满购x元/件打y折
满赠 购买x元/件送y件赠品购买x元/件加送y件赠品 (已去掉赠品库存)
组合套餐 多个商品价格和数量捆绑合计 (含套餐价格,活动库存,限购数量)
换购 达到某个金额后,可以选择加钱换购多种商品 (含换购价格,活动库存,换购数量)
预售 商品先支付定金,在指定时间支付尾款 (含预售金额,定金,活动库存)
积分兑换 积分兑换商品 (含兑换库存,兑换价格)

预售说明:

  1. 预售定金/尾款支付必须是同种支付方式 (暂不支持多支付方式)
  2. 预售可设置定金为 0,可只支付尾款

收银台/购物车说明:

  1. 目前促销活动规则只能手动选择
  2. 同种商品只能用一个促销活动,不同种商品可以设置同种一个促销(满减,满赠)
  3. 订单可以有多个促销活动的商品
  4. 改价: 只能改普通商品的价格,不能修改促销商品价格
  5. 添加会员后,再添加商品默认带出商品最优价(会员价,内购价)
  6. 有满减促销时,先减满减金额,再减优惠券金额

公式–商品分摊(订单含满减,优惠券)

  1. 商品促销分摊 = (促销金额 ÷ 总金额) x 商品金额
  2. 商品优惠券分摊 = (优惠券金额 ÷ 总金额) x 商品金额
  3. 商品支付金额 = 商品金额 - 满减分摊- 优惠券分摊

例子:

jsuan.png

webpos

const goodPromotionRuleList 处理,获取所有商品促销类型

const disposeProductList 处理商品字段

const disposeBatchNumber 处理所有商品批号库存

过滤条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let result = await MAPP.db_queryAll({
model: 'batch_number',
type: 'noPage',
pageTurn: false,
isCount: false,
condition: {
store_id,
status: '合格',
is_delete: 0,
goods_id: {
$in: good_ids_arr.reduce((p, n) => p.concat(MAPP.MTypesId(n.toString())), []),
},
},
})

b2c 立即购买

最优促销规则

商品列表

order_total 订单金额 (应收金额)
pay_total 实付金额 (实收金额)

配置打包

桌面应用包

  1. package.json 中的 dependencies 添加以下三个依赖包(用 npm 安装)
    "electron": "^12.0.0",
    "electron-devtools-installer": "^3.1.0",
    "vue-cli-plugin-electron-builder": "~2.0.0",

    执行 electron:build 报错

    在项目根目录新增.npmrc 文件

    添加
    ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/

    全局安装 npm install electron -g

    安装失败处理: npm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/ //配置安装镜像源地址
    打包失败处理: npm config set ELECTRON_BUILDER_BINARIES_MIRROR https://mirrors.huaweicloud.com/electron-builder-binaries/ // 配置打包镜像源地址

    安装源说明

  2. manifest.json 路由配置history改成hash

  3. 运行打包

npm run electron 打包 64 位应用程序
npm run electron:build32 打包 32 位应用程序

商品

获取所有商品促销类型 const goodPromotionRuleList

处理商品促销字段提示合并组合商品和赠品,换购商品(重新加载商品列表) const disposeProductList

高德地图

先创建Web服务应用(接口) Web端应用(页面)保存 key 和密钥

库存

新零售目前库存字段

  1. 商品总库存

    冻结数量blocked_stock 占用数量 occupy_stock 门店库存stock

    可销库存 = 门店库存 - 冻结数量 - 占用数量

  2. 批号库存 stock 冻结数量 blocked_stock

    可销库存 = 批号库存 - 冻结数量

webpos 库存说明:

  1. 目前销售先冻结或占用数量,同步日清后才去扣除掉门店账面库存数量,冻结和占用数量
  2. 页面显示的库存都是可销库存
  3. 按批号销售:直接冻结商品所在批号数量和冻结商品总数量
  4. 按商品销售:商品销售自动分配批号,出现负库存,数量加在商品占用数量字段
  5. 日清结果:
    ① 更新商品账面和批号库存
    ② 更新订单商品批号数据和日清状态
    ③ 插入/更新新的库存流水记录

webpos 销售

总库存字段

按商品销售:

可销库存 = 门店账面库存 - 冻结数量 - 占用数量

例子 商品 A 批号 1 批号 2 数据(行)
库存(件) 15 10 5
1. 销售 10 冻结:10,可销:5 冻结:10,可销:0 冻结:0,可销:5 A1 x 10
2. 销售 12 冻结:12,可销:3 冻结:10,可销:0 冻结:2,可销:3 A1 x 10
A2 x 2
3. 销售 20(负) 冻结 15,可销:0,占用:5 冻结:10,可销:0 冻结:5,可销:0 A1 x 10
A2 x 5
A (空) x 5

带下划线的文本

门店商品批号库存查询
circulation_record

封装方法

1
2
3
4
5
6
7
8
9
10
11
// 添加批号库存记录
await addCirculationRecord({
good_id: commodity._id,
batch_id: batch_one ? batch_one._id : null,
quantity: TRANSIT_QUANTITY,
receipt_number: PUT_NUMBER,
receipt_type: 'c', // 单据类型 a入库 b销售 c门店调拨 d退库 e初装 f盘点 g退款 h取消订单
operator = '',
operator_id = null,
store_id
})
1
2
3
4
5
6
// 扣商品库存
await MAPP.db_setOne({
model: 'commodity',
condition: { _id: commodity._id, 'distributed.store_id': pick_store._id },
data: { $inc: { 'distributed.$.stock': inc_stock } },
})

库存批号库存

1
2
3
4
5
6
7
8
9
10
11
await MAPP.db_setOne({
model: 'batch_number',
condition: {
_id: batch_one._id
},
data: {
$inc: {
stock: inc_stock
}
}
})

库存单据

单据保护:审核前是否修改原单数据

只要有任一总部账号进入审核页面,均触发单据保护

data_protection 请货单 盘点单 配送单 退库单

是否审核: 总店是否可审核其他门店单据

1
2
3
4
5
6
7
8
9
    // 盘点单是否需审核
    check_need_audit: { type: Boolean, default: true },
    // 请货单是否需审核
    apply_lading_need_audit: { type: Boolean, default: true },
    // 手录入库单是否需审核
    warehousing_need_audit: { type: Boolean, default: true },
    // 门店退库单是否需审核
    refund_lading_need_audit: { type: Boolean, default: true },

盘点单

说明:

  1. 完成盘点单后,需要判断是否需要审核
  2. 如需要审核,由中台总店审核和平账库存
  3. 如无需审核,则店员端自动审核通过并自动平账库存
  4. 审核通过后才会推送(每 2 分钟)

请货单

说明:

  1. 子门店向子门店请货,不推送 erp,由子门店处理
  2. 子门店向总部请货,推送 erp,由 erp 同步接口出库单 (每 2 分钟同步一次)
  3. 请货单可以配置是否需要审核

店员端:

A 门店—>B 门店

A 门店 向 B 门店请货

一 、请货流程:

  1. 选择发货门店
  2. 添加请货商品
  3. 设置商品请货数量
  4. 提交请货单
  5. 审核请货单(如审核驳回可以修改后重新提交)

二 、出库流程 (子门店之间)

  1. B 门店生成拣货任务 (总部没有生成拣货任务)
  2. 获取根据请货单商品
  3. 选择商品批号和设置数量(子门店需要冻结库存)
  4. 确认出库 (减少账面库存)
  5. A 门店生成收货任务

三 、收货流程

  1. 子门店之间,出库数量等于收货数量
  2. 总库出库,子门店收货可以不等于出库数量

出库单

说明:

  1. 新零售出库单有关联请货单
  2. erp 出库单可以不关联请货单

价格

新零售目前商品价格: 普通价(零售价/现价) 会员价 付费会员价 内购价 (四种)

注意:

  1. 若线下零售价为 0 时,用线上零售价
  2. 会员价包括商城会员价(免费),付费会员价
  3. 内购价针对职工内部(职工账号与会员手机号一致则享受内购价)

设置等级会员价

  1. 权益中心必须开启
  2. 设置商品折扣字段 (折扣大于 0)

current_price 零售价(线上)
current_price_offline 零售价(线下)
staff_price 内购价
member_price 会员价
paid_price plus 会员价

会员价

说明:

  1. 普通会员优先级: 商品指定价 > 其它等级商品折扣
  2. 折扣值范围: 0 < 折扣 < 10
  3. 会员价计算: 会员价 = 零售价 x 折扣 x 0.1
  4. 会员价有可能会大于零售价
  5. 优惠金额: 零售价 - 会员价 (可正可负)

例子:
A 商品 10 元,享折扣八折
会员价: 10x8x0.1=8(元)

member_price 普通会员价商品表(指定)

mall_member 普通会员等级表

字段结构

1
2
3
4
5
6
7
8
9
"member_benefits" : [
{
"type" : "discount",
"name" : "",
"number" : 8,
"key_ids" : [],
"_id" : ObjectId("63f85eca8cd8ed367bb1aa97")
},
]
1
2
3
4
5
6
7
8
9
10
11
 // 获取方法
// 普通会员价
const { member_price = 0, is_member } = await getMemberPrice({ current_price: commodity.current_price, user_id })
commodity.member_price = member_price
commodity.is_member = is_member


//批量修改

await memberGoods({ pageTurn: false, good_list: result, store_id, user_id })

plus 会员价

说明:

  1. plus 会员优先级: 商品指定价> 专属商品折扣 > 其它商品折扣
  2. 折扣值范围: 0 < 折扣 < 10
  3. 会员价计算: 会员价 = 零售价 x 折扣 x 0.1

paid_price 付费会员价商品表(指定)

paid_member 付费 plus 会员表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"member_benefits" : [
//专属商品折扣
{
"type" : "exclusive_merchandise",
"name" : "",
"number" : 7,
//专属商品折扣
"key_ids" : [
ObjectId("58805dd61d8bdc9c56cc3e31"),
ObjectId("58805dd61d8bdc9c56cc3e32"),
],
//指定商品价
"goods_ids" : [
ObjectId("58805dd61d8bdc9c56cc3e3c"),
],
"_id" : ObjectId("63f7139568a92829840ec51a")
},
{
//其它商品折扣
"type" : "discount",
"name" : "",
"number" : 8,
"key_ids" : [],
"goods_ids" : [],
"_id" : ObjectId("63f7139568a92829840ec518")
},
]
1
2
3
4
//获取方法
const obj = await getPaidPrice({ current_price: commodity.current_price, user_id }, ctx)
commodity.paid_price = obj.paid_price
commodity.is_paid = obj.is_paid

内购价

说明:

  1. 内购价: 商品指定价 > 专属商品折扣
  2. 折扣值范围: 0 < 折扣 < 10
  3. 内购价计算: 内购价 = 零售价 x 折扣 x 0.1

staff_price 内购价商品表(指定)

staff_member 内购规则表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"member_benefits" : [
{
// 专属商品
"type" : "exclusive_merchandise",
"name" : "",
"number" : 8,
// 商品折扣
"key_ids" : [
ObjectId("58805dd61d8bdc9c56cc3e2d"),
],
// 商品指定价
"goods_ids" : [
ObjectId("58805dd61d8bdc9c56cc3e31"),
],
"_id" : ObjectId("64ebf7a08656fa4768ad1e7a")
}
],

订单

权益

新版 2867 改版

  1. 积分倍率: 按用户类型拿最大的一条规则赠送倍率规则

  2. 优惠券 先全部领取, 有可能改了领取数量,要拆分未领取的数量

客服

说明:

  1. 按门店匹配

调度

自动调度说明(定时器)

  1. 开启自动调度配置,设置无响应时间
  2. 所有未接入的对话 (有对话过的)
  3. 对话更新时间小于(当前时间 - 无响应时间)

商品

product_list

单个商品价格:
price:零售价
cypher_price : 普通价(零售价/会员价/plus 价/内购价)
reduction_number: 满减抵扣金额
coupon_number: 优惠券抵扣金额
member_number: 会员抵扣金额
integral_price: 积分抵扣金额
final_price 最终价格(实际支付价格)

达到满减条件为:

  1. 满减活动商品实际支付总价 >= 满减门槛规则金额
  2. 满减活动商品总件数 >= 满减门槛件数

满减满足金额为普通商品cypher_price计算判断

优惠券可用条件为: 总商品实际支付总价 - 满减金额 >= 优惠券门槛金额

价格计算

普通价 = 零售价 - 折扣金额 - 改价金额

cypher_price = price - member_number - change_number

支付价 = 普通价 - 满减金额 - 优惠券金额 - 积分抵扣金额

final_price = cypher_price - reduction_number - coupon_number - integral_price

:

  1. 如抵扣金额(优惠金额小于 0.01 元)按 0 元计算
  2. webpos 达到满减条件为: 满减活动商品零售价总价 >= 满减门槛规则金额

打印

型号 :Xprinter 58

指令

易语言安装与破解说明:
一、解压后,先安装易语言 5.9 官方正式版
二、将易语言 5.92 版升级包里面的文件复制到安装目录
三、将易语言 5.92 破解补丁里面的“e.exe”复制到安装目录
四、可以选择安装易语言助手
五、如果出现静态连接失败,请使用“易语言静态连接失败智能修复器 v1.2.exe”进行修复

开钱箱源码

.版本 2
.支持库 eAPI

.程序集 程序集 1

.子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行
.局部变量 hPrinter, 整数型
.局部变量 pd, PRINTER_DEFAULTS
.局部变量 字符串, 字节型, , “5”

字符串 = { 27, 112, 0, 128, 128 } ‘ 打印机指令
OpenPrinter (取默认打印机 (), hPrinter, pd)
StartDocPrinterA (hPrinter, 1, pd)
StartPagePrinter (hPrinter)
WritePrinter (hPrinter, 字符串, 5, 0)
ClosePrinter (hPrinter)
‘ 调试输出 (OpenPrinter (取默认打印机 (), hPrinter, pd))
‘ 调试输出 (hPrinter)
‘ 调试输出 (StartDocPrinterA (hPrinter, 1, pd))
‘ 调试输出 (StartPagePrinter (hPrinter))
‘ 调试输出 (WritePrinter (hPrinter, 字符串, 5, 0))
‘ 调试输出 (ClosePrinter (hPrinter))
返回 (0) ‘ 可以根据您的需要返回任意数值

其他打印机开钱箱指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Axionhm A715 27,112,0,48,251
Axionhm A756 27,112,0,48,251
Axionhm A794 27,112,0,48,251
Bixolon SRP-275 27,112,48,55,121
Epson All 27,121,48,55,121
Epson M51PD 27,112,48,55,121
Epson TM-T60 27,112,32,25
Epson TM-L60II 27,70,0,50,50
Epson TM-T70 27,112,48,55,121
Epson T88iii 27,112,0,25,250
Epson TM-U200D 27,112,0,25,250
Epson T88iiiP 27,112,0,64,240
Epson TM-U200D 27,112,0,64,240
Epson TM-88IV 27,112,48,55,121
Epson TM-88V 27,112,48,55,121
Epson M188D 27,112,48,55,121
Epson M192C 27,112,48,55,121
Epson TM-U200 27,112,0,25,250
Epson TM-U200B 27,112,48,25,250
Epson TM-U200D 27,112,0,64,240
Epson TM-U210PD 27,112,0,25,250
Epson TM-U210-D 27,112,0,25,250
Epson TM-U220A 27,112,0,25,250
Epson TM-U220PD 27,112,0,25,250
Epson TM-U295 27,112,48,55,121
Epson ADP-300 27,112,0,25,250
Epson TM-300D 27,112,0,25,250
Epson TM-U950P 27,112,0,25,250
Epson TM-U300PD 27,112,0,25,250
Epson TM-U325D 27,112,0,25,250
Epson TM-U375 27,112,0,25,250
Epson M665A 27,112,0,50,250
Epson TM-T883P 27,112,0,50,250
Epson TM-U950P 27,112,0,50,250
Epson TM-H500II 27,113,0,25,250
Epson TM-H6000 27,112,48,55,121
IBM 4610 7
IBM 4611 27,112,0,50,250
Ithaca PcOS-51 27,112,0,25,250
Ithaca PcOS-52 27,112,0,25,250
Ithaca PcOSjet 27,112,0,25,250
Ithaca 80-PLUS 27,120,1
Ithaca SERIES-90 27,120,1
Ithaca 150 27,120,1
Ithaca POSjet-1000 27,120,1
NCR 7167 27,120,1
Oliveti PRT-100 27,112,0,25,250
Pos-X XR-200 27,112,0,25,250
Pos-X XR-500 27,112,0,25,250
Posiflex CR-4200 27,112,80,25,250
Posiflex AURA-5600 27,112,0,25,250
Posiflex PP6000 27,112,0,25,250
Posiflex PP7000 27,112,0,25,250
Samsung SRP-131 27,112,0,48,50
Samsung SRP-270 27,112,0,25,250
Samsung SRP-270A 27,112,0,64,240
Samsung SRP-270 27,112,48,55,121
Samsung SRP-350 27,110,0,25,250
Star All 27,7,11,55,7
Star TSP 100 7
Star SP212 27,7,11,55,7
Star TSP200 27,7,11,55,7
Star SP500 27,122,49,7
Star TSP-600 27,7,10,50,7
Star TSP-700 27,07,11,55,07
Star SP2000 27,122,49,7
Tec RKP300 27,112,0,100,250
Tec TRST-53 27,112,0,100,250
Toshiba SX2100 27,112,32,55,255
Toshiba Tec-DRJST-51 27,112,0,100,250
Unisys EF4272 27,112,0,100,250
Wasp WTP-100 27,112,49,48,48

项目需求

裕创

字段

  1. 会员表member增加门店 store_ids 关联
  2. 平台配置platform_deploy
    总部派送,不限制门店库存
    1
    2
    3
    4
    5
    6
    7
    //JavaScript
    {
    // 门店缺货由总部派送(裕创280增加)
    head_office_delivery: { type: Boolean, default: false },
    // 门店会员访问权限(裕创280增加) 0 所有门店 1 仅限访问关联加盟店
    allow_stores: { type: Number, default: 0 },
    }
  3. 门店表store
    1
    2
    3
    4
    {
    // 门店类型 0 自营店 1 加盟店
    store_type: { type: Number, default: 0 },
    }
  4. 订单表 order_library
1
2
3
4
5
6
7
8
9
{
// 商品列表
product_list: [
{
// 调货门店erp内码
erp_code: { type: String, default: '' },
}
]
}

获取品平台配置

1
2
3
const platform_deploy = await MAPP.db_getOne({
model: 'platform_deploy',
})

调用方法

1
2
3
4
5
6
7
8
9
10
//JavaScript
const { headStoreGood } = require('../commodity/_methods')

let { stock: _stock = 0, store_id: _store_id = '' } = await headStoreGood({ goods_id: product_id, store_id })
// 当前门店是总部
if (_store_id.toString() === store_id.toString()) {
_stock = 0
}
storeCommodity.stock = MAPP.plus(storeCommodity.stock, _stock)

说明:
1、消费者如果只关联加盟店,且平台配置开启了【仅限访问关联加盟】(原【仅访问关联门店】),那么该消费者只能访问关联的加盟店,不可访问直营店和总店。
2、消费者如果关联了任意直营店,则可访问总店、其他任何直营店和已经关联的加盟店。
3、平台配置同时开启【仅限访问关联加盟】和【登录时选择配送方式】时,【登录时选择配送方式】的弹窗以消费是否关联了直营店为判断依据。
1)如果消费者仅关联加盟店,登录时弹窗不需要显示,且不限制可视门店距离,并直接进入已关联的最近加盟店。
2)如果消费者关联了任意直营店,登录时显示配送方式选择弹窗。
4、调货门店 erp 内码,指的是门店缺货由总部派送商品时,缺货门店的 erp 内码。

同步

商品基础表

同步字段 数据表字段 同步值 数据值 是否非空 说明
B_SN 1 非空 同步序号
NAME name 商品名称 商品名称 非空 名称
BAR_CODE bar_code 100001 100001 非空 条码
CODING coding A00001 A00001 非空 编码
COMMON_NAME common_name 通用名 通用名 非空 通用名
MNEMONIC_CODE mnemonic_code zjm zjm 非空 首字母
PRESCRIPTION prescription 处方药 处方药 可空 处方药类型
ORIGINAL_PRICE original_price 3 3 非空 商品原价
CURRENT_PRICE current_price 3 3 非空 商品现价(线上)
CURRENT_PRICE_OFFLINE current_price_offline 0 0 可空 商品现价(线下)
KEYWORD keyword 西药,感冒药 西药,感冒药 可空 关键字
DRUG_TYPE drug_type 西药 2 非空 药品类型
DOSAGE usage 每日三次 每日三次 可空 用法用量
UNIT unit 非空 单位
UNIT_NUM unit_num 1 1 非空 单位数量
WEIGHT weight 0 0 可空 重量
VOLUME volume 0 0 可空 体积
SPECIFICATION specification 500g/盒 500g/盒 非空 规格
FORMULATION formulation 肠溶片 肠溶片 可空 剂型
INGREDIENT ingredient - - 非空 成分
SHAPE shape - - 可空 性状
INDICATIONS indications - - 可空 适应症
OVERDOSE overdose - - 非空 药物过量
DRUG_EFFECT drug_effect - - 可空 药物作用
CLINICAL_GUIDELINES clinical_guidelines - - 可空 临床应用指南
MANUFACTURER manufacturer 生产厂家 生产厂家 非空 生产厂家
PRODUCTION_ORIGIN production_origin - - 可空 生产产地
FOR_PEOPLE for_people - - 可空 适用人群
TABOO taboo - - 可空 禁忌
STORAGE_METHOD storage_method - - 可空 贮藏方式
INTRODUCTION introduction - - 可空 商品简介
INDICATION indication - - 可空 功能主治
PRECAUTIONS precautions - - 可空 注意事项
ADVERSE_REACTIONS adverse_reactions - - 可空 不良反应
MEDICINE_INTERACTIONS medicine_interactions - - 可空 药物相互作用
GMP_CERTIFICATION gmp_certification - - 可空 GMP 认证
APPROVAL_NUMBER approval_number - - 可空 批准文号
VALIDITY_PERIOD validity_period - - 可空 有效期
MEDICAL medical Y true 非空 是否医保
THREE_CATEGORIES three_categories N false 非空 是否三类
COLD_CHAIN cold_chain N false 非空 是否冷链
OVERSEAS overseas N false 非空 是否境外
TARIFF tariff 0 0 非空 进口税率
EPIDEMIC_SITUATION epidemic_situation N false 非空 是否疫情
HIDE_GOODS hide_goods N false 可空 是否隐藏
SORT sort 0 0 可空 跨境排序
NEAR_TERM_WARNING near_term_warning 180 180 可空 近效期预警天数
LOCAL_CODE local_code - - 可空 本位码
INSERT_TIME YYYY-MM-DD HH:mm:ss 非空 插入时间

即时通讯

接口

文件:

绑定标识处理 /bin/socket.js

socket 对象封装 (客户端和服务端) /src/@common/socket_client.js

服务端连接 /src/@common/ws.js

消息中心通用方法 /src/@common/message_center.js

对应message_center数据表

提醒发货 订单消息间隔一分钟提醒有效

msg_type 自定类型 (提醒发货 订单 退单)

from: store_staff 店员端任务类型 (收货 拣货 请货单)

from message_center 店员端消息中心 请货审核 退货审核