Phát hiện xung đột thời gian cho hoạt động thương mại điện tử - Kiểm tra xung đột khối thời gian

Trong nhiều trường hợp, các hoạt động thương mại điện tử cần có thời gian duy nhất, ví dụ như các chương trình flash sale, phải có khoảng thời gian riêng biệt.

Thông thường, sau khi hoạt động bắt đầu, không nên sửa đổi thời gian hoạt động, có thể sửa đổi nội dung hoặc sản phẩm, nhưng nếu sửa đổi thời gian sẽ gây ra vấn đề xung đột lớn, việc kiểm tra thời gian hoạt động sẽ trở nên rất phức tạp.

Dưới đây là một giải pháp sử dụng quy tắc liệt kê, framework được sử dụng là Laravel.

Dưới đây là demo

Bảng dữ liệu

CREATE TABLE `mao_free_delivery` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `title` varchar(50) NOT NULL COMMENT 'Tiêu đề hoạt động',
 `sum_money` decimal(10,2) unsigned NOT NULL COMMENT 'Số tiền miễn phí vận chuyển',
 `shop_id` int(10) unsigned NOT NULL COMMENT 'ID cửa hàng người tạo',
 `user_id` int(10) unsigned NOT NULL COMMENT 'ID người dùng tạo',
 `start_time` timestamp NULL DEFAULT NULL COMMENT 'Thời gian bắt đầu hoạt động',
 `end_time` timestamp NULL DEFAULT NULL COMMENT 'Thời gian kết thúc hoạt động',
 `division_method` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '1 là toàn bộ, 2 là một số sản phẩm, 3 là theo danh mục',
 `ids` varchar(5000) DEFAULT NULL COMMENT 'Bộ sưu tập ID',
 `created_at` timestamp NULL DEFAULT NULL COMMENT 'Thời gian tạo hoạt động',
 `updated_at` timestamp NULL DEFAULT NULL COMMENT 'Thời gian cập nhật hoạt động',
 `is_enabled` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT 'Trạng thái, 1 là mặc định, 2 là tắt',
 `is_del` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT 'Trạng thái xóa, 1 là mặc định, 2 là xóa',
 `sort` int(10) unsigned NOT NULL DEFAULT '255' COMMENT 'Sắp xếp',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Bảng hoạt động miễn phí vận chuyển';
// Kiểm tra xung đột thời gian hoạt động khi chỉnh sửa, có thể xung đột với các hoạt động khác
    public static function kiemTraXungDotThoiGian($shop_id = null, $thoiGianBatDau = null, $thoiGianKetThuc = null, $id = null, &$loi = null)
    {
          if(empty($thoiGianBatDau)){
            $loi = 'Thời gian bắt đầu không được để trống';
            return FALSE;
        }
        if(empty($thoiGianKetThuc)){
            $loi = 'Thời gian kết thúc không được để trống';
            return FALSE;
        }
        if(strtotime($thoiGianBatDau) > strtotime($thoiGianKetThuc)){
            $loi = 'Thời gian bắt đầu không được lớn hơn thời gian kết thúc';
            return FALSE;
        }
        if(strtotime($thoiGianBatDau) == strtotime($thoiGianKetThuc)){
            $loi = 'Thời gian bắt đầu không được bằng thời gian kết thúc';
            return FALSE;
        }
        $dieuKien[]=['is_del', '=', self::IS_DEL];
    $dieuKien[]=['is_enabled', '=', self::IS_ENABLED];
        $dieuKien[]=['shop_id', '=', $shop_id];
        $ketQua = self::layThongTinHoatDong($dieuKien);
        if(empty($ketQua)){//Không có dữ liệu thì thêm mới
            return true;
        }
        if($id){//Khi chỉnh sửa, loại bỏ dữ liệu đang được chỉnh sửa
            foreach ($ketQua as $k1 => $v1) {
                if(in_array($id,$v1)){
                    unset($ketQua[$k1]);
                }
            }
        }
//        pp($ketQua);
         //Đầu tiên sắp xếp khối thời gian, sau đó so sánh khối
        $canCan = [];
        foreach ($ketQua as $key => &$value) {//Chuyển thành thời gian, tránh lỗi ở các phiên bản PHP khác
            $canCan[] = $value['start_time'] = strtotime($value['start_time']);
            $canCan[] = $value['end_time'] = strtotime($value['end_time']);
        }
        //Sắp xếp nổi bọt trước, sau đó kiểm tra mảng và mảng gốc, tránh lỗi dữ liệu
        $ketQuaSapXepNoiBong =  self::sapXepNoiBong($canCan);
        foreach ($ketQua as $k=> $v) {//Kiểm tra dữ liệu, tìm start_time và end_time trong mảng gốc, nếu 2 khóa bằng nhau hoặc chênh lệch lớn hơn 1 thì dữ liệu lỗi
          if(!in_array($v['start_time'],$ketQuaSapXepNoiBong)){
              $loi = 'Kiểm tra dữ liệu lỗi, không tìm thấy thời gian bắt đầu';
              return FALSE;
          }
          if(!in_array($v['end_time'],$ketQuaSapXepNoiBong)){
              $loi = 'Kiểm tra dữ liệu lỗi, không tìm thấy thời gian kết thúc';
              return FALSE;
          }
          
          $batDau = array_search($v['start_time'],$ketQuaSapXepNoiBong);
          $ketThuc   = array_search($v['end_time'],$ketQuaSapXepNoiBong);
          
          if($batDau == $ketThuc){
              $loi = 'Kiểm tra dữ liệu lỗi, thời gian bắt đầu và kết thúc giống nhau';
              return FALSE;
          }
          
          if($ketThuc - $batDau >1){
              $loi = 'Kiểm tra dữ liệu lỗi, sắp xếp thời gian lỗi';
              return FALSE;
          }
        }

        //Đầu tiên kiểm tra biên, sau đó lặp lại để kiểm tra
        if(strtotime($thoiGianBatDau) < $ketQuaSapXepNoiBong['0'] && strtotime($thoiGianKetThuc) < $ketQuaSapXepNoiBong['0']){//Thời gian kết thúc phải nhỏ hơn phần tử đầu tiên của mảng so sánh, nếu không sẽ xung đột
                  return true;
        }
        if(strtotime($thoiGianBatDau) > $ketQuaSapXepNoiBong[(count($ketQuaSapXepNoiBong)-1)] && strtotime($thoiGianKetThuc) > $ketQuaSapXepNoiBong[(count($ketQuaSapXepNoiBong)-1)] ){
                  return true;
        }
        foreach ($ketQuaSapXepNoiBong as $kk => $vv) {
            //Các phần tử ở giữa phải nằm trong 01   23  45  67  89
              if($kk % 2 == 1){
                  if(strtotime($thoiGianBatDau) > $ketQuaSapXepNoiBong[$kk] && strtotime($thoiGianKetThuc) < $ketQuaSapXepNoiBong[$kk+1]){
                         return true;
                   }
              }
        }
        $loi = 'Lỗi sắp xếp thời gian, xin vui lòng không nhập thời gian bắt đầu hoặc kết thúc giống với hoạt động khác';
        return FALSE;
    }
    public static function sapXepNoiBong(array $mang = []){
            $doDai=count($mang);
          //Thiết lập một mảng rỗng để nhận bong nổi
          //Vòng lặp này kiểm soát số vòng lặp nổi bọt cần thiết
          for($i=1;$i<$doDai;$i++)
          { //Vòng lặp này kiểm soát số lần so sánh cần thiết mỗi vòng lặp để nổi lên một số
            for($k=0;$k<$doDai-$i;$k++)
            {
               if($mang[$k]>$mang[$k+1])
                {
                    $tam=$mang[$k+1];
                    $mang[$k+1]=$mang[$k];
                    $mang[$k]=$tam;
                }
            }
          }
          return $mang;
    }
    
    public static function layThongTinHoatDong(array $dieuKien = []){
        if(empty($dieuKien)){
            return FALSE;
        }
        $hoatDongM = new HoatDongM();
        $res = $hoatDongM->where($dieuKien)->get();
        if ($res) {
            return $res->toArray();
        }
        return FALSE;
    }
foreach ($ketQuaSapXepNoiBong as $kk => $vv) {
            //Các phần tử ở giữa phải nằm trong 01   23  45  67  89
              if($kk % 2 == 1){
                  if(strtotime($thoiGianBatDau) > $ketQuaSapXepNoiBong[$kk] && strtotime($thoiGianKetThuc) < $ketQuaSapXepNoiBong[$kk+1]){
                         return true;
                   }
              }
        }

Phần khó hiểu nhất là ở đây, thực chất là kiểm tra xem có thể chèn thời gian bắt đầu và kết thúc mới vào giữa 01 23 45 67 89 hay không, nếu phù hợp thì trả về true

Tôi sử dụng phương pháp liệt kê, nếu thỏa mãn một điều kiện thì có thể chèn, nếu không thì trả về false, và lưu ý rằng thời gian mới không được trùng với thời gian bắt đầu hoặc kết thúc của bất kỳ hoạt động nào khác, vì cần sắp xếp nổi bọt,

nếu trùng sẽ bị phát hiện lỗi dữ liệu, trên giao diện sử dụng plugin chèn thời gian, gợi ý người dùng thêm một giây

2021年7月5日17:01:51

Vì sử dụng chức năng phát hiện xung đột thời gian này trong nhiều năm, tôi đã tối ưu hóa một phiên bản

<?php

namespace App\Service\V1;

use App\Service\V1\BaseService;
use Exception;

class PhatHienXungDotThoiGianService extends BaseService
{
    /**
     * Kiểm tra xung đột khối thời gian hoạt động
     * @param string|null $thoiGianBatDau Thời gian bắt đầu hoạt động
     * @param string|null $thoiGianKetThuc Thời gian kết thúc hoạt động
     * @param array $mangDuLieu Mảng dữ liệu cần kiểm tra, chú ý giảm bớt các trường để kiểm tra hiệu suất tốt hơn, các trường cần thiết là [[id,start_time,end_time],[id,start_time,end_time]]
     * @param null $id Khi chỉnh sửa, ID cần kiểm tra
     * @return bool
     * @throws Exception
     */
    public static function kiemTra(string $thoiGianBatDau = null, string $thoiGianKetThuc = null, array $mangDuLieu = [], $id = null)
    {
        if (empty($thoiGianBatDau)) {
            throw new Exception('Thời gian bắt đầu không được để trống');
        }
        if (empty($thoiGianKetThuc)) {
            throw new Exception('Thời gian kết thúc không được để trống');
        }
        if (strtotime($thoiGianBatDau) > strtotime($thoiGianKetThuc)) {
            throw new Exception('Thời gian bắt đầu không được lớn hơn thời gian kết thúc');
        }
        if (strtotime($thoiGianBatDau) == strtotime($thoiGianKetThuc)) {
            throw new Exception('Thời gian bắt đầu không được bằng thời gian kết thúc');
        }
        //Nếu không có dữ liệu khác thì trả về true
        if (empty($mangDuLieu)) {
            return true;
        } else {
            if ($id) {//Khi chỉnh sửa, loại bỏ dữ liệu đang được chỉnh sửa
                foreach ($mangDuLieu as $k1 => $v1) {
                    if (in_array($id, $v1)) {
                        unset($mangDuLieu[$k1]);
                    }
                }
            }
        }

//        pp($mangDuLieu);
        //Đầu tiên sắp xếp khối thời gian, sau đó so sánh khối
        $canCan = [];
        foreach ($mangDuLieu as $key => &$value) {//Chuyển thành thời gian, tránh lỗi ở các phiên bản PHP khác
            $canCan[] = $value['start_time'] = strtotime($value['start_time']);
            $canCan[] = $value['end_time'] = strtotime($value['end_time']);
        }
        //Sắp xếp nổi bọt trước, sau đó kiểm tra mảng và mảng gốc, tránh lỗi dữ liệu
        $ketQuaSapXepNoiBong = self::sapXepNoiBong($canCan);
        foreach ($mangDuLieu as $k => $v) {//Kiểm tra dữ liệu, tìm start_time và end_time trong mảng gốc, nếu 2 khóa bằng nhau hoặc chênh lệch lớn hơn 1 thì dữ liệu lỗi
            if (!in_array($v['start_time'], $ketQuaSapXepNoiBong)) {
                throw new Exception('Kiểm tra dữ liệu lỗi, không tìm thấy thời gian bắt đầu');
            }
            if (!in_array($v['end_time'], $ketQuaSapXepNoiBong)) {
                throw new Exception('Kiểm tra dữ liệu lỗi, không tìm thấy thời gian kết thúc');
            }
            $batDau = array_search($v['start_time'], $ketQuaSapXepNoiBong);
            $ketThuc = array_search($v['end_time'], $ketQuaSapXepNoiBong);

            if ($batDau == $ketThuc) {
                throw new Exception('Kiểm tra dữ liệu lỗi, thời gian bắt đầu và kết thúc giống nhau');
            }
            if ($ketThuc - $batDau > 1) {
                throw new Exception('Kiểm tra dữ liệu lỗi, sắp xếp thời gian lỗi');
            }
        }
        //Đầu tiên kiểm tra biên, sau đó lặp lại để kiểm tra
        if (strtotime($thoiGianBatDau) < $ketQuaSapXepNoiBong['0'] && strtotime($thoiGianKetThuc) < $ketQuaSapXepNoiBong['0']) {//Thời gian kết thúc phải nhỏ hơn phần tử đầu tiên của mảng so sánh, nếu không sẽ xung đột
            return true;
        }
        if (strtotime($thoiGianBatDau) > $ketQuaSapXepNoiBong[(count($ketQuaSapXepNoiBong) - 1)] && strtotime($thoiGianKetThuc) > $ketQuaSapXepNoiBong[(count($ketQuaSapXepNoiBong) - 1)]) {
            return true;
        }
        foreach ($ketQuaSapXepNoiBong as $kk => $vv) {
            //Các phần tử ở giữa phải nằm trong 01   23  45  67  89
            if ($kk % 2 == 1) {
                if (strtotime($thoiGianBatDau) > $ketQuaSapXepNoiBong[$kk] && strtotime($thoiGianKetThuc) < $ketQuaSapXepNoiBong[$kk + 1]) {
                    return true;
                }
            }
        }
        throw new Exception('Lỗi sắp xếp thời gian, xin vui lòng không nhập thời gian bắt đầu hoặc kết thúc giống với hoạt động khác');
    }


    public static function sapXepNoiBong(array $mang = [])
    {
        $doDai = count($mang);
        //Thiết lập một mảng rỗng để nhận bong nổi
        //Vòng lặp này kiểm soát số vòng lặp nổi bọt cần thiết
        for ($i = 1; $i < $doDai; $i++) { //Vòng lặp này kiểm soát số lần so sánh cần thiết mỗi vòng lặp để nổi lên một số
            for ($k = 0; $k < $doDai - $i; $k++) {
                if ($mang[$k] > $mang[$k + 1]) {
                    $tam = $mang[$k + 1];
                    $mang[$k + 1] = $mang[$k];
                    $mang[$k] = $tam;
                }
            }
        }
        return $mang;
    }

}

Mã kiểm tra

  public function test(Request $request)
    {
        $duLieu = [];
//        $duLieu = [
//            ['id' => 0, 'start_time' => '2021-07-01 00:00:00', 'end_time' => '2021-07-03 00:00:00'],
//            ['id' => 1, 'start_time' => '2021-07-05 00:00:00', 'end_time' => '2021-07-06 00:00:00'],
//            ['id' => 2, 'start_time' => '2021-07-10 00:00:00', 'end_time' => '2021-07-12 00:00:00'],
//            ['id' => 3, 'start_time' => '2021-07-15 00:00:00', 'end_time' => '2021-07-20 00:00:00']
//        ];

        $thoiGianBatDau = '2021-07-03 00:00:01';
        $thoiGianKetThuc = '2021-07-04 00:00:00';
        $id = '';
        try {
            $dd = PhatHienXungDotThoiGianService::kiemTra($thoiGianBatDau, $thoiGianKetThuc, $duLieu, $id);
            p($dd);
        } catch (Exception $e) {
            p($e->getMessage() . $e->getFile() . $e->getLine() . $e->getCode());
        }

    }

Thẻ: laravel php time-conflict-detection E-commerce algorithm

Đăng vào ngày 9 tháng 6 lúc 19:29