public static function writeRealTimeDataByOrder(int $orderId)
{
$order = Order::find($orderId);
if (!$order) return;
$deltaData = self::buildOrderIncrement($order);
# 如果查出来的交班表开始时间和结束都存在--那么数据是异常--在这个手动处理异常
# 1. 交班表添加一条数据,有开始时间(订单创建时间-1)没结束时间
# 2. 交班数据表开始时间为订单创建时间-1
$createTime = $order->getOrigin('create_time');
$startTime = self::getLastSwitchEmployee($order['shop_id'], $order['employee_id'], $order['device_num'], $createTime);
self::writeOrIncrement(
[
'shop_id' => $order['shop_id'],
'employee_id' => $order['op_employee_id'],
'device_num' => $order['device_num'],
'type' => 6,
],
$deltaData,
$startTime,
'',
);
$now = time();
$periods = self::getPeriodsArray($now);
foreach ($periods as $period) {
[$startTime, $endTime, $uniqueSign] =
self::generateUniqueSign(strtotime($period['start']), $period['type']);
# 三级:员工 + 设备
self::writeOrIncrement([
'shop_id' => $order['shop_id'],
'employee_id' => $order['op_employee_id'],
'device_num' => $order['device_num'],
'type' => $period['type'],
'unique_sign' => $uniqueSign,
], $deltaData, $startTime, $endTime);
# 二级:店铺
self::writeOrIncrement([
'shop_id' => $order['shop_id'],
'employee_id' => -1,
'device_num' => -1,
'type' => $period['type'],
'unique_sign' => $uniqueSign,
], $deltaData, $startTime, $endTime);
# 一级:全店
self::writeOrIncrement([
'shop_id' => 0,
'employee_id' => 0,
'device_num' => 0,
'type' => $period['type'],
'unique_sign' => $uniqueSign,
], $deltaData, $startTime, $endTime);
}
}
public static function getLastSwitchEmployee($shopId, $employeeId, $deviceNum, $orderCreateTime)
{
$last = SwitchEmployee::where([
'shop_id' => $shopId,
'employee_id' => $employeeId,
'device_num' => $deviceNum,
])->order(['create_time' => 'desc', 'id' => 'desc'])->find();
if ($last && !$last['end_time']) {
return $last['start_time'];
} else {
# 交班表创建新数据
SwitchEmployee::create([
'shop_id' => $shopId,
'employee_id' => $employeeId,
'device_num' => $deviceNum,
'start_time' => $orderCreateTime - 1,
]);
return $orderCreateTime - 1;
}
}
protected static function initSnapshotData()
{
return [
'cash_money' => 0,
'remain_money' => 0,
'saving_money' => 0,
'credit_money' => 0,
'scan_money' => 0,
'cash_order_num' => 0,
'scan_order_num' => 0,
'remain_order_num' => 0,
'saving_order_num' => 0,
'credit_order_num' => 0,
'total_order_num' => 0,
'total_charge_money' => 0,
'total_charge_times_money' => 0,
'total_continue_money' => 0,
'total_combo_money' => 0,
'total_refund_money' => 0,
'vip_money' => 0,
'sale_income' => 0,
'com_income' => 0,
'quick_money' => 0,
];
}
protected static function buildOrderIncrement($order)
{
$delta = self::initSnapshotData();
$delta['cash_money'] += $order['cash'];
$delta['remain_money'] += $order['remain_money'];
$delta['scan_money'] += $order['scan'];
$delta['saving_money'] += $order['saving'];
$delta['credit_money'] += $order['credit'];
if ($order['round_down_money'] > 0) {
$delta['cash_money'] -= $order['round_down_money'];
}
$delta['total_order_num'] += 1;
if ($order['pay_type'] & 1) $delta['cash_order_num']++;
if ($order['pay_type'] & 2) $delta['scan_order_num']++;
if ($order['pay_type'] & 4) $delta['remain_order_num']++;
if ($order['pay_type'] & 8) $delta['saving_order_num']++;
if ($order['pay_type'] & 16) $delta['credit_order_num']++;
switch ($order['order_type']) {
case 3:
$delta['total_charge_money'] += $order['real_money'];
break;
case 4:
$delta['total_charge_times_money'] += $order['real_money'];
break;
case 6:
$delta['total_refund_money'] += $order['real_money'];
break;
case 7:
case 8:
$delta['total_continue_money'] += $order['real_money'];
break;
case 9:
$delta['total_combo_money'] += $order['real_money'];
break;
case 10:
$delta['vip_money'] += $order['real_money'];
break;
}
$orderDetails = OrderDetail::alias('od')
->join('goods g', 'g.id = od.goods_id')
->where('od.order_id', $order['id'])
->field(['od.goods_num', 'od.goods_sale_price', 'g.goods_type'])
->select();
foreach ($orderDetails as $d) {
$money = $d['goods_num'] * $d['goods_sale_price'];
if (in_array($d['goods_type'], [2, 3, 4, 6])) {
$delta['service_money'] += $money;
}
if (in_array($d['goods_type'], [1, 5])) {
$delta['normal_money'] += $money;
}
}
$delta['quick_money'] += OrderDetail::where([
['order_id', '=', $order['id']],
['goods_id', '=', -2],
['order_band_id', '=', 0],
])->sum(Db::raw('goods_num * goods_sale_price'));
$delta['com_income'] += $order['real_money'] - $order['remain_money'];
$delta['sale_income'] += $delta['com_income'] - $delta['total_charge_money'];
return $delta;
}
public static function getPeriodsArray($baseTime)
{
$periods = [];
$baseDate = date('Y-m-d', $baseTime);
# ---------------- 日 ----------------
$periods[] = [
'type' => 1,
'start' => date('Y-m-d', strtotime('-1 day', $baseTime)),
'name' => '日'
];
# ---------------- 周(基准时间是周一) ----------------
if (date('N', $baseTime) == 1) {
$lastMonday = date('Y-m-d', strtotime('last monday', $baseTime));
$periods[] = ['type' => 2, 'start' => $lastMonday, 'name' => '周'];
}
# ---------------- 月(基准时间是 1 号) ----------------
if (date('d', $baseTime) == '01') {
$lastMonth = date('Y-m-01', strtotime('last month', $baseTime));
$periods[] = ['type' => 3, 'start' => $lastMonth, 'name' => '月'];
}
# ---------------- 季度 ----------------
if (self::isQuarterStart($baseDate)) {
$lastQuarter = self::getLastQuarterStart($baseDate);
$periods[] = ['type' => 4, 'start' => $lastQuarter, 'name' => '季'];
}
# ---------------- 年 ----------------
if (date('m-d', $baseTime) === '01-01') {
$lastYear = (date('Y', $baseTime) - 1) . '-01-01';
$periods[] = ['type' => 5, 'start' => $lastYear, 'name' => '年'];
}
return $periods;
}
/**
* 判断是否为季度第一天
*/
protected static function isQuarterStart($date)
{
$month = date('m', strtotime($date));
$day = date('d', strtotime($date));
# 季度开始月份的第一天:1月1日、4月1日、7月1日、10月1日
return in_array($month, ['01', '04', '07', '10']) && $day == '01';
}
/**
* 获取上一季度的开始日期
*/
protected static function getLastQuarterStart()
{
$currentMonth = date('n');
$year = date('Y');
if ($currentMonth >= 1 && $currentMonth <= 3) {
return ($year - 1) . '-10-01';
} elseif ($currentMonth >= 4 && $currentMonth <= 6) {
return $year . '-01-01';
} elseif ($currentMonth >= 7 && $currentMonth <= 9) {
return $year . '-04-01';
} else {
return $year . '-07-01';
}
}
public static function generateUniqueSign($timestamp, $type)
{
$startTime = 0;
$endTime = 0;
$uniqueSign = '';
$year = date('Y', $timestamp);
if ($type == 1) {
$uniqueSign = date('Y-m-d', $timestamp);
$startTime = strtotime($uniqueSign . ' 00:00:00');
$endTime = strtotime($uniqueSign . ' 23:59:59');
}
if ($type == 2) {
$week = date('W', $timestamp);
$uniqueSign = "{$year}-W{$week}";
$startTime = self::getStartTimeByWeekYear($week, $year);
$endTime = self::getEndTimeByWeekYear($week, $year);
}
if ($type == 3) {
$uniqueSign = date('Y-m', $timestamp);
$startTime = self::getStartTimeByYearMonth($year, date('n', $timestamp));
$endTime = self::getEndTimeByYearMonth($year, date('n', $timestamp));
}
if ($type == 4) {
$quarter = self::getQuarterNum($timestamp);
$uniqueSign = "{$year}-Q{$quarter}";
$startTime = self::getStartTimeByQuarter($year, $quarter);
$endTime = self::getEndTimeByQuarter($year, $quarter);
}
if ($type == 5) {
$year = date('Y', $timestamp);
$uniqueSign = $year;
$startTime = self::getStartTimeByYear($year);
$endTime = self::getEndTimeByYear($year);
}
return [$startTime, $endTime, $uniqueSign];
}
// 开始时间戳,第几周
private static function getStartTimeByWeekYear($week, $year)
{
return strtotime("{$year}-W{$week}");
}
// 结束时间戳,第几周
private static function getEndTimeByWeekYear($week, $year)
{
return strtotime("{$year}-W{$week}-7 23:59:59");
}
private static function getStartTimeByYearMonth($year, $month)
{
return strtotime("first day of $year-$month 00:00:00");
}
private static function getEndTimeByYearMonth($year, $month)
{
return strtotime("last day of $year-$month 23:59:59");
}
private static function getStartTimeByQuarter($year, $num)
{
$month = ($num - 1) * 3 + 1;
return strtotime("first day of $year-$month 00:00:00");
}
private static function getQuarterNum($timestamp)
{
$month = date('n', $timestamp);
return (int)ceil($month / 3);
}
private static function getEndTimeByQuarter($year, $num)
{
$month = $num * 3;
return strtotime("last day of $year-$month 23:59:59");
}
private static function getStartTimeByYear($year)
{
return strtotime("first day of $year-01 00:00:00");
}
private static function getEndTimeByYear($year)
{
return strtotime("last day of $year-12 23:59:59");
}
protected static function writeOrIncrement(
$where,
$deltaData,
$startTime,
$endTime,
)
{
if (empty($deltaData)) return;
$model = self::where($where)->lock(true)->find();
if ($model) {
$update = [];
foreach ($deltaData as $field => $value) {
if ($value != 0) {
$update[$field] = Db::raw("{$field} + {$value}");
}
}
if ($update) {
self::where('id', $model->id)->update($update);
}
} else {
$insertData = array_merge(
self::initSnapshotData(),
$where,
$deltaData,
[
'start_time' => $startTime,
'end_time' => $endTime,
]
);
self::create($insertData);
}
}
逻辑:订单支付完成–在某个表进行对应的数据累加
# 实时记录信息 CheckEmployee::writeRealTimeDataByOrder($order_id);
