Task #38 » OrderCSVDocumentation_New.md
Order CSV Import/Export Documentation (New Format)
Tổng quan
Tài liệu này mô tả chi tiết về chức năng import/export CSV cho module Order với format mới sau khi thay đổi. Hệ thống hỗ trợ cả import và export với validation đầy đủ.
THAY ĐỔI QUAN TRỌNG
-
施設ID → 実施場所ID: Thay đổi từ
facilities.owner_facility_idsangplaces.owner_place_id - Thêm 受注企業: Field mới để phân biệt hệ thống tạo order
-
Thêm 独自実施場所ID: Field mới từ
places.owner_no -
実施場所 → 実施場所名: Thay đổi từ
facilities.placesangplaces.place -
Commodity: KHÔNG CÒN VALIDATE với
commodity_relations, lưu trực tiếp trongorders.commodity -
Database: Thêm bảng
placesvàplace_calendar_relationsđể quản lý địa điểm
Database Structure
Tables được sử dụng trong Order CSV Import/Export
Import Process
- orders - Bảng chính lưu thông tin Order
- order_statuses - Bảng lưu trạng thái Order
- order_date_prices - Bảng lưu giá theo ngày
- place_calendar_relations - Bảng quan hệ calendar với places
- places - Bảng mới lưu thông tin địa điểm
- temporary_order_dates - Bảng tạm thời kiểm tra trùng lặp
Export Process
- orders - Bảng chính lấy thông tin Order
- places - Bảng tham chiếu để lấy thông tin Place
- user_accounts - Bảng tham chiếu để lấy thông tin User
- owner_accounts - Bảng tham chiếu để lấy thông tin Owner
- place_calendar_relations - Bảng tham chiếu để lấy thông tin order_owner_id
1. orders (Bảng chính)
2. places (Bảng mới - thay thế facilities)
3. place_calendar_relations (Bảng mới - thay thế facility_calendar_relations)
4. order_statuses (Bảng trạng thái)
5. order_date_prices (Bảng giá theo ngày)
CSV Field Structure
Bảng chi tiết các field trong CSV (Format mới - 46 fields)
| STT | Field Name (Japanese) | Field Name (English) | Data Type | Required | Max Length | Validation Rules | Database Column | Description | Error Messages |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 予約ID | Order ID | Integer | No | - | 1-999999 | owner_order_id | ID của order (để trống nếu tạo mới) |
Điều kiện: Nếu có thì phải tồn tại trong database Error: 存在しない予約IDです。新規登録の場合は予約IDを空白にしてください。 |
| 2 | 受注企業 | Order Owner | Text | No | - | - | order_owner_id | 999: 自社登録、100: 楽市システム登録 (Field mới, chỉ hiển thị khi export) | - |
| 3 | 商材 | Commodity | Text | Yes | 50 | - | commodity | Tên hàng hóa (lưu trực tiếp trong orders.commodity) |
Điều kiện: Bắt buộc nhập, max 50 ký tự Error: 商材は入力必須です。商材は50文字以内で入力してください。 |
| 4 | 実施場所ID | Place ID | Integer | Yes | - | Must exist in Places | owner_place_id | ID của place (Thay đổi từ 施設ID) |
Điều kiện: Bắt buộc nhập, phải tồn tại trong places table Error: 存在しない実施場所IDです。 |
| 5 | 独自実施場所ID | Unique Place ID | Text | No | 100 | - | owner_no | - |
Điều kiện: Nếu có thì max 100 ký tự Error: 独自実施場所IDは100文字以内で入力してください。 |
| 6 | 実施場所名 | Place Name | Text | No | - | - | places.place | Tên place (lấy từ places table dựa trên 実施場所ID) | - |
| 7 | 施設名 | Facility Name | Text | No | - | - | facilities.name | Tên facility (lấy từ facilities table, chỉ hiển thị) | - |
| 8 | 都道府県 | Prefecture | Text | No | - | - | facilities.prefecture | - | - |
| 9 | 市区郡 | City | Text | No | - | - | facilities.city | - | - |
| 10 | 行政区 | Ward | Text | No | - | - | facilities.ward | - | - |
| 11 | 町名番地 | Address | Text | No | - | - | facilities.address | - | - |
| 12 | 建物 | Building | Text | No | - | - | facilities.building | - | - |
| 13 | 実施場所の広さ | Area Size | Text | No | - | - | places.breadth | - | - |
| 14 | 税抜合計金額 | Total Price (Ex Tax) | Integer | No | - | - | orders.total_price | Tổng tiền chưa thuế (tự động tính từ order_date_prices) | - |
| 15 | 税込合計金額 | Total Price (Inc Tax) | Integer | No | - | - | orders.total_tax_price | Tổng tiền có thuế (tự động tính từ order_date_prices) | - |
| 16 | 開始日付 | Start Date | Date | Yes | - | YYYY-MM-DD format | orders.start_date | Ngày bắt đầu |
Điều kiện: Bắt buộc nhập, format YYYY-MM-DD Error: 開始日付は入力必須です。YYYY-MM-DD形式で入力してください。 |
| 17 | 終了日付 | End Date | Date | Yes | - | YYYY-MM-DD format | orders.end_date | Ngày kết thúc |
Điều kiện: Bắt buộc nhập, format YYYY-MM-DD, >= 開始日付 Error: 終了日付は入力必須です。YYYY-MM-DD形式で入力してください。 |
| 18 | 商材の詳細 | Commodity Detail | Text | No | 60 | - | orders.commodity | Chi tiết hàng hóa |
Điều kiện: Nếu có thì max 60 ký tự Error: 商材の詳細は60文字以内で入力してください。 |
| 19 | 現場責任者 | Field Manager | Text | No | 30 | - | orders.field_manager_name | Người phụ trách hiện trường |
Điều kiện: Nếu có thì max 30 ký tự Error: 現場責任者は30文字以内で入力してください。 |
| 20 | 現場責任者の連絡先 | Field Manager Contact | Text | No | - | Phone format | orders.field_manager_tel | Liên hệ người phụ trách |
Điều kiện: Nếu có thì phải đúng format số điện thoại Nhật Error: 現場責任者の連絡先は正しい電話番号形式で入力してください。 |
| 21 | 入店者数 | Number of Visitors | Integer | No | - | 0-10000 | orders.number_of_visitors | Số lượng người vào |
Điều kiện: Nếu có thì phải từ 0-10000 Error: 入店者数は0から10000の間で入力してください。 |
| 22 | 入店者名 | Visitor Name | Text | No | 100 | - | orders.visitor | Tên người vào |
Điều kiện: Nếu có thì max 100 ký tự Error: 入店者名は100文字以内で入力してください。 |
| 23 | 催事開始時刻 | Event Start Time | Time | No | - | HH:MM format (15min unit) | orders.start_at | Thời gian bắt đầu sự kiện |
Điều kiện: Nếu có thì format HH:MM, 15 phút đơn vị Error: 催事開始時刻は15分単位で入力してください。 |
| 24 | 催事終了時刻 | Event End Time | Time | No | - | HH:MM format (15min unit) | orders.end_at | Thời gian kết thúc sự kiện |
Điều kiện: Nếu có thì format HH:MM, 15 phút đơn vị Error: 催事終了時刻は15分単位で入力してください。 |
| 25 | 搬入希望日時 | Carry-in Request DateTime | DateTime | No | - | YYYY-MM-DD HH:MM format | orders.carry_in_time | Thời gian mong muốn mang vào |
Điều kiện: Nếu có thì format YYYY-MM-DD HH:MM, 15 phút đơn vị Error: 搬入希望日時はYYYY-MM-DD HH:MM形式で入力してください。 |
| 26 | 搬出希望日時 | Carry-out Request DateTime | DateTime | No | - | YYYY-MM-DD HH:MM format | orders.carry_out_time | Thời gian mong muốn mang ra |
Điều kiện: Nếu có thì format YYYY-MM-DD HH:MM, 15 phút đơn vị Error: 搬出希望日時はYYYY-MM-DD HH:MM形式で入力してください。 |
| 27 | 搬入車両有無 | Carry Vehicle | Integer | Yes | - | 1-2 | orders.carry_car | 1: Có, 2: Không |
Điều kiện: Bắt buộc nhập, phải là 1 hoặc 2 Error: 搬入車両有無は1または2で入力してください。 |
| 28 | 搬入車両有の場合 | Carry Vehicle Detail | Text | No | 60 | - | orders.carry_car_remark | Chi tiết xe mang vào |
Điều kiện: Nếu có thì max 60 ký tự Error: 搬入車両有の場合は60文字以内で入力してください。 |
| 29 | 電源詳細 | Power Detail | Text | No | 1000 | - | orders.power_detail | Chi tiết về điện |
Điều kiện: Nếu có thì max 1000 ký tự Error: 電源詳細は1000文字以内で入力してください。 |
| 30 | 貸出希望備品 | Equipment Request | Text | No | 1000 | - | orders.equipment_detail | Thiết bị muốn thuê |
Điều kiện: Nếu có thì max 1000 ký tự Error: 貸出希望備品は1000文字以内で入力してください。 |
| 31 | 配布物 | Handout | Text | No | 60 | - | orders.handout | Vật phẩm phân phát |
Điều kiện: Nếu có thì max 60 ký tự Error: 配布物は60文字以内で入力してください。 |
| 32 | 店舗名(会社名) | Shop Name (Company) | Text | No | 80 | - | orders.shop_guide | Tên cửa hàng (công ty) |
Điều kiện: Nếu có thì max 80 ký tự Error: 店舗名(会社名)は80文字以内で入力してください。 |
| 33 | 店舗電話番号 | Shop Phone | Text | No | - | Phone format | orders.shop_guide_tel | Số điện thoại cửa hàng |
Điều kiện: Nếu có thì phải đúng format số điện thoại Nhật Error: 店舗電話番号は正しい電話番号形式で入力してください。 |
| 34 | ユーザアカウント名 | User Account Name | Text | No | - | - | user_accounts.name | Tên tài khoản user (lấy từ user_accounts) | |
| 35 | ユーザ会社名 | User Company Name | Text | No | - | - | user_accounts.company_name | Tên công ty user (lấy từ user_accounts) | |
| 36 | ユーザ店舗名 | User Shop Name | Text | No | - | - | user_accounts.shop_name | Tên cửa hàng user (lấy từ user_accounts) | |
| 37 | ユーザのメールアドレス | User Email | Text | Yes | 100 | Email format | user_accounts.email | Email của user (dùng để tìm user_account_id) |
Điều kiện: Bắt buộc nhập, format email hợp lệ, phải tồn tại trong user_accounts Error: ユーザのメールアドレスは入力必須です。正しいメールアドレス形式で入力してください。 |
| 38 | ユーザの電話番号 | User Phone | Text | No | - | - | user_accounts.tel | Số điện thoại user (lấy từ user_accounts) | - |
| 39 | 担当者名 | Manager Name | Text | Yes | 60 | Must exist in Owner Account | owner_accounts.name | Tên người phụ trách (dùng để tìm owner_account_id) |
Điều kiện: Bắt buộc nhập, max 60 ký tự, phải tồn tại trong owner_accounts Error: 担当者名は入力必須です。存在しない担当者名です。 |
| 40 | ステータス | Status | Integer | Yes | - | 1-3 | order_statuses.order_status | 1: 予約受付、2: 実施確定、3: 実施不可 |
Điều kiện: Bắt buộc nhập, phải là 1, 2 hoặc 3 Error: ステータスは1、2、3のいずれかで入力してください。 |
| 41 | 回答状態 | Reply Status | Integer | Yes | - | 1-2 | order_statuses.reply_status | 1: 未回答、2: 回答済 |
Điều kiện: Bắt buộc nhập, phải là 1 hoặc 2 Error: 回答状態は1または2で入力してください。 |
| 42 | 備考 | Remark | Text | No | 3000 | - | order_statuses.remark | Ghi chú |
Điều kiện: Nếu có thì max 3000 ký tự Error: 備考は3000文字以内で入力してください。 |
CSV Format Examples
CSV Header Structure (Format mới - 42 fields)
予約ID,受注企業,商材,実施場所ID,独自実施場所ID,実施場所名,施設名,都道府県,市区郡,行政区,町名番地,建物,実施場所の広さ,税抜合計金額,税込合計金額,開始日付,終了日付,商材の詳細,現場責任者,現場責任者の連絡先,入店者数,入店者名,催事開始時刻,催事終了時刻,搬入希望日時,搬出希望日時,搬入車両有無(1:有、2:無),搬入車両有の場合,電源詳細,貸出希望備品,配布物,店舗名(会社名),店舗電話番号,ユーザアカウント名,ユーザ会社名,ユーザ店舗名,ユーザのメールアドレス,ユーザの電話番号,担当者名,ステータス(1:予約受付、2:実施確定、3:実施不可),回答状態(1:未回答、 2:回答済),備考
LƯU Ý:
- Import: Có thể bỏ qua các field tự động điền (実施場所名, 都道府県, v.v.)
- Export: Bao gồm tất cả fields để hiển thị đầy đủ thông tin
Import CSV Sample Data (Format mới - Minimal)
,展示会,1001,PLACE001,2024-03-01,2024-03-03,展示会詳細,田中太郎,03-1234-5678,100,展示会参加者,09:00,18:00,2024-02-29 08:00,2024-03-03 19:00,1,トラック1台,電源詳細,備品あり,パンフレット,ABC商事,03-1234-5678,hanako@abc.com,佐藤次郎,1,1,備考
Export CSV Sample Data (Format mới - Full)
,自社登録,展示会,1001,PLACE001,東京コンベンションセンター,東京コンベンションセンター,メインホールA,東京都,渋谷区,神南,1-1-1,ビルA,300㎡,150000,165000,2024-03-01,2024-03-03,展示会詳細,田中太郎,03-1234-5678,100,展示会参加者,09:00,18:00,2024-02-29 08:00,2024-03-03 19:00,1,トラック1台,電源詳細,備品あり,パンフレット,ABC商事,03-1234-5678,山田花子,ABC商事,渋谷店,hanako@abc.com,03-1234-5678,佐藤次郎,1,1,備考
Configuration
CSV Import/Export Config
Environment Variables
# CSV Import Limit
CSV_IMPORT_LIMIT=3000
# Database Chunk Size
DB_CHUNK_SIZE=10000
# Storage Path
SYSTEM_STORAGE_TEMPORARY_PATH=tmp/
# File Expiration (hours)
CSV_DOWNLOAD_FILE_EXPIRED_AT=72
CSV_ERROR_FILE_EXPIRED_AT=336
Config Structure (config/web.php)
'csv' => [
'importLimit' => env('CSV_IMPORT_LIMIT', '3000'), // Max records per import
'downloadFileExpiredAt' => env('CSV_DOWNLOAD_FILE_EXPIRED_AT', 72), // Download file expiration (hours)
'errorFileExpiredAt' => env('CSV_ERROR_FILE_EXPIRED_AT', 336) // Error file expiration (hours)
],
'db' => [
'chunkSize' => env('DB_CHUNK_SIZE', '10000') // Database chunk size for processing
],
Order Owner Mapping
// Order Owner ID mapping
$orderOwnerMap = [
999 => '自社登録', // Own system registration
100 => '楽市システム登録' // Rakuichi system registration
];
Validation Rules
Business Logic Validation
1. Order ID
- Order ID: Nếu có thì phải tồn tại trong database
- Error: "存在しない予約IDです。新規登録の場合は予約IDを空白にしてください。"
2. Place (Thay đổi từ Facility)
- Place ID: Phải tồn tại trong Places table
- Error: "存在しない実施場所IDです。"
3. Unique Place ID (Field mới)
- Unique Place ID: Tùy chọn, nếu có thì phải là format hợp lệ
- Suggested validation: Alphanumeric, max 100 characters
- Error: "独自実施場所IDは100文字以内で入力してください。"
4. Commodity
- Commodity: Lưu trực tiếp trong orders.commodity, KHÔNG CÒN VALIDATE với commodity_relations
- Validation: Chỉ kiểm tra format và độ dài (max 50 characters)
- Business Logic: Không cần kiểm tra xem commodity có tồn tại trong master data hay không
- Error: "商材は50文字以内で入力してください。"
5. Date
- Start Date: Phải là format YYYY-MM-DD
- End Date: Phải là format YYYY-MM-DD và >= Start Date
- Error: "終了日付は開始日付と同じかそれよりも後にしてください。"
6. Time
- Event Start/End Time: Phải là 15 phút đơn vị (00, 15, 30, 45)
- Carry-in/out Time: Phải là format "YYYY-MM-DD HH:MM" và 15 phút đơn vị
- Error: "催事開始時刻は15分単位で入力してください。"
7. User Account
- User Email: Phải tồn tại trong User Account
- Error: "存在しないユーザーアカウントです。メールアドレスが正しいか確認してください。"
8. Manager
- Manager Name: Phải tồn tại trong Owner Account
- Error: "存在しない担当者名です。"
9. Place Calendar (Thay đổi từ Facility Calendar)
- Date Range: Không được trùng với ngày không thể đặt trong Place Calendar
- Error: "日程に実施場所の予約不可日が含まれています。"
10. Duplicate Check (Thay đổi từ Facility)
- Same File: Không được trùng "Place + Date" trong cùng file
- Error: "既にファイル内で同じ「実施場所+日付」の組み合わせが選択されています。"
Import Behavior & Field Mapping
QUAN TRỌNG: Cách thức Import các field
Fields được Import trực tiếp vào Database:
-
予約ID →
orders.owner_order_id -
商材 →
orders.commodity -
実施場所ID →
orders.place_id -
独自実施場所ID →
places.owner_no -
開始日付 →
orders.start_date -
終了日付 →
orders.end_date -
商材の詳細 →
orders.commodity -
現場責任者 →
orders.field_manager_name -
現場責任者の連絡先 →
orders.field_manager_tel -
入店者数 →
orders.number_of_visitors -
入店者名 →
orders.visitor -
催事開始時刻 →
orders.start_at -
催事終了時刻 →
orders.end_at -
搬入希望日時 →
orders.carry_in_time -
搬出希望日時 →
orders.carry_out_time -
搬入車両有無 →
orders.carry_car -
搬入車両有の場合 →
orders.carry_car_remark -
電源詳細 →
orders.power_detail -
貸出希望備品 →
orders.equipment_detail -
配布物 →
orders.handout -
店舗名(会社名) →
orders.shop_guide -
店舗電話番号 →
orders.shop_guide_tel -
ユーザのメールアドレス → Dùng để tìm
user_accounts.id -
担当者名 → Dùng để tìm
owner_accounts.id -
ステータス →
order_statuses.order_status -
回答状態 →
order_statuses.reply_status -
備考 →
order_statuses.remark
Fields được tính toán và lưu vào order_date_prices:
-
開始日付 ~ 終了日付 → Tạo records trong
order_date_pricescho từng ngày -
Giá cơ bản → Lấy từ
place_calendar_relationsdựa trên ngày và place_id -
Giá đặc biệt → Áp dụng nếu có trong
place_calendar_relations.special_price_sell
Fields được lưu vào place_calendar_relations:
-
受注企業 →
order_owner_idmặc định là 999 vì đang ở owner system -
実施場所ID →
owner_place_id -
Ngày trong khoảng →
regist_date(từ start_date đến end_date)
Fields được lưu vào temporary_order_dates:
- 実施場所ID + 開始日付 + 終了日付 → Dùng để kiểm tra trùng lặp trong cùng file
- owner_place_id → Để group theo place
- start_date, end_date → Để kiểm tra overlap
Fields KHÔNG được Import (bị bỏ qua khi import):
- 受注企業 → Bị bỏ qua, giá trị từ 受注企業 không có hiệu lực vì mặc định sẽ là 999
- 実施場所名 → Bị bỏ qua, không ghi vào database
- 施設名 → Bị bỏ qua, không ghi vào database (lấy từ facilities.name)
- 都道府県 → Bị bỏ qua, không ghi vào database
- 市区郡 → Bị bỏ qua, không ghi vào database
- 行政区 → Bị bỏ qua, không ghi vào database
- 町名番地 → Bị bỏ qua, không ghi vào database
- 建物 → Bị bỏ qua, không ghi vào database
- 実施場所の広さ → Bị bỏ qua, không ghi vào database
- 税抜合計金額 → Bị bỏ qua, tự động tính từ order_date_prices
- 税込合計金額 → Bị bỏ qua, tự động tính từ order_date_prices
- ユーザアカウント名 → Bị bỏ qua, không ghi vào database
- ユーザ会社名 → Bị bỏ qua, không ghi vào database
- ユーザ店舗名 → Bị bỏ qua, không ghi vào database
- ユーザの電話番号 → Bị bỏ qua, không ghi vào database
Fields mới (chỉ hiển thị trong Export):
-
受注企業 → Hiển thị dựa trên
place_calendar_relations.order_owner_id- 999 → "自社登録"
- 100 → "楽市システム登録"
Format Import vs Export:
Import CSV Format:
- Chỉ cần các field được import trực tiếp vào database
- Không cần các field tự động điền (có thể để trống hoặc bỏ qua)
-
Ví dụ: Chỉ cần
予約ID,商材,実施場所ID,開始日付,終了日付,...
Export CSV Format:
- Bao gồm tất cả 42 fields để hiển thị đầy đủ thông tin
-
Ví dụ:
予約ID,受注企業,商材,実施場所ID,独自実施場所ID,実施場所名,都道府県,...
Import Process
// Kiểm tra số lượng records
if (!ImportCsvUtility::checkRecordSize($file)) {
throw new RuntimeException('データ数が3000件を超えています。');
}
// Kiểm tra header
ImportCsvUtility::checkCsvHeader($file, $this->createHeader(), '利用予約');
Step 2: Data Processing
// Chuyển đổi encoding
$csvRecord[] = self::convertStringCode($wk);
// Xử lý BOM
$wk = preg_replace("/^\xEF\xBB\xBF/", '', $wk);
Step 3: Record Validation
// Validate từng field
$validator->validateDigit('予約ID', $obj->ownerOrderId, false, 1, null);
$validator->validateText('商材', $obj->commodity, true, null, 50); // CHỈ validate format, KHÔNG validate với commodity_relations
$validator->validateDigit('実施場所ID', $obj->ownerPlaceId, true, 1, null);
$validator->validateText('独自実施場所ID', $obj->ownerNo, false, null, 100);
$validator->validateDate('開始日付', $obj->startDate, true);
$validator->validateDate('終了日付', $obj->endDate, true);
// Business logic validation
if (!$this->validatePlace($obj->ownerPlaceId)) {
$validator->addErrorMessage('存在しない実施場所IDです。');
}
// LƯU Ý: Không còn validate commodity với commodity_relations
Step 4: Database Operations
// Insert/Update order
if (empty($wk->ownerOrderId)) {
$order = $this->orderUpsertRepository->insert($wk);
} else {
$order = $this->orderUpsertRepository->update($wk);
}
// Update order status
$this->orderStatusUpsertRepository->insert($wk);
// Update date prices
$this->orderDatePriceUpsertRepository->bulkInsert($insertData);
Export Process
Step 1: Data Retrieval
// Lấy danh sách orders
$orders = $this->orderSelectRepository->select($filterDto);
// Chunk processing
$chunks = $orders->chunk(config('web.db.chunkSize'));
Step 2: Data Formatting
// Format data cho CSV
return [
$dbRecord->ownerOrderId,
$this->getOrderOwnerDisplay($dbRecord->orderOwnerId), // 受注企業
$dbRecord->commodity,
$dbRecord->ownerPlaceId, // 実施場所ID
$dbRecord->ownerNo, // 独自実施場所ID
$dbRecord->placeName, // 実施場所名
$dbRecord->place, // 実施場所名
// ... các field khác
];
Step 3: File Generation
// Tạo CSV file
$file = CsvUtility::createCsvFile($filePath);
fputcsv($file, $this->createHeader());
// Write data
foreach ($chunks as $chunk) {
foreach ($chunk as $order) {
fputcsv($file, $this->formatData($order));
}
}
Error Handling
Error File Structure
予約ID,受注企業,商材,実施場所ID,独自実施場所ID,実施場所名,実施場所名,...,Error
,自社登録,展示会,1001,PLACE001,東京コンベンションセンター,メインホールA,...,存在しない実施場所IDです。
Common Error Messages
File Validation
項目数が正しくありません。最新の利用予約CSVをダウンロードして項目数を確認してください。
項目名が正しくありません。最新の利用予約CSVをダウンロードして項目名を確認してください。
データ数が3000件を超えています。
Field Validation
商材は入力必須です。
商材は50文字以内で入力してください。
実施場所IDは入力必須です。
実施場所IDは1以上の数字で入力してください。
独自実施場所IDは100文字以内で入力してください。
開始日付はYYYY-MM-DDの形式で入力してください。
終了日付は開始日付と同じかそれよりも後にしてください。
催事開始時刻は15分単位で入力してください。
搬入車両有無は1または2で入力してください。
Business Logic
存在しない予約IDです。新規登録の場合は予約IDを空白にしてください。
存在しない実施場所IDです。
存在しないユーザーアカウントです。メールアドレスが正しいか確認してください。
存在しない担当者名です。
日程に実施場所の予約不可日が含まれています。
既にファイル内で同じ「実施場所+日付」の組み合わせが選択されています。
Performance Considerations
Chunk Processing
- Chunk size: 100 records per chunk
- Memory usage: Giảm memory usage bằng cách xử lý từng chunk
- Error handling: Mỗi chunk được xử lý độc lập
Database Operations
- Batch insert: Sử dụng chunk để insert/update
- Transaction: Mỗi chunk được wrap trong transaction
- Error rollback: Rollback toàn bộ chunk nếu có lỗi
Security Considerations
File Upload Security
- File type validation: Chỉ chấp nhận .csv
- File size limit: Giới hạn số lượng records
- Path traversal protection: Validate file path
Data Validation
- Input sanitization: Tự động chuyển đổi encoding
- SQL injection protection: Sử dụng prepared statements
- XSS protection: Validate và escape output
Access Control
- Authentication: Yêu cầu đăng nhập
- Authorization: Kiểm tra quyền truy cập
- Organization isolation: Chỉ xử lý dữ liệu của organization hiện tại
Sequence Diagrams
Import Process Sequence Diagram
sequenceDiagram
participant U as User
participant C as Controller
participant S as OrderCsvService
participant V as Validator
participant R as Repository
participant DB as Database
U->>C: Upload CSV File
C->>S: processImport(file)
S->>S: validateFile(file)
Note over S: Check file size, format, encoding
S->>S: parseCsv(file)
Note over S: Convert SJIS-win to UTF-8
loop For each chunk (100 records)
S->>V: validateChunk(chunk)
V->>V: validateFields()
Note over V: Validate required fields, format, business rules
alt Validation Error
V->>S: return errors
S->>S: addToErrorFile(chunk, errors)
else Validation Success
S->>R: insertOrders(chunk)
R->>DB: beginTransaction()
loop For each order
R->>DB: insert/update orders
R->>DB: insert order_statuses
R->>DB: insert order_date_prices
R->>DB: insert place_calendar_relations
R->>DB: insert temporary_order_dates
end
R->>DB: commitTransaction()
end
end
S->>C: return result
C->>U: Show success/error message
Export Process Sequence Diagram
sequenceDiagram
participant U as User
participant C as Controller
participant S as OrderCsvService
participant R as Repository
participant DB as Database
U->>C: Request CSV Download
C->>S: processExport(filters)
S->>R: selectOrders(filters)
R->>DB: query orders with joins
DB->>R: return order data
R->>S: return orders
S->>S: formatData(orders)
Note over S: Format all 42 fields including auto-filled data
S->>S: createCsvFile()
Note over S: Generate CSV with BOM
loop For each chunk
S->>S: writeChunkToFile(chunk)
end
S->>C: return file path
C->>U: Download CSV file
Error Handling Sequence Diagram
sequenceDiagram
participant U as User
participant C as Controller
participant S as OrderCsvService
participant V as Validator
participant F as FileSystem
U->>C: Upload CSV with errors
C->>S: processImport(file)
S->>V: validateChunk(chunk)
V->>V: validateFields()
V->>S: return validation errors
S->>S: createErrorFile()
S->>F: write error records
Note over F: Include original data + error messages
S->>C: return error file path
C->>U: Show error message with download link
Current System Implementation
File Processing
-
Chunk size: 100 records per chunk (configurable via
config('web.db.chunkSize')) - Memory management: Xử lý từng chunk để tránh memory overflow
-
File storage: Temporary files lưu trong
storage/app/tmp/ - File cleanup: Tự động xóa file tạm sau khi xử lý
Error Handling
- Error file generation: Tạo file CSV với BOM chứa records có lỗi
- Error file format: Bao gồm header + data + error message column
-
Error file storage: Lưu trong
storage/app/tmp/với prefixOrder_import_error_ - Error file expiration: Tự động xóa sau 336 giờ (14 ngày)
Validation
- File validation: Kiểm tra extension .csv, số lượng records (max 3000)
- Header validation: Kiểm tra số lượng và tên cột chính xác
- Encoding validation: Tự động chuyển đổi từ SJIS-win sang UTF-8
- Business validation: Kiểm tra duplicate, reference data, business rules
Special Processing & Business Logic
Pre-Processing (Before Import)
-
Date Validation: Kiểm tra
開始日付<=終了日付 -
User Account Lookup: Tìm
user_account_idtừユーザのメールアドレス -
Owner Account Lookup: Tìm
owner_account_idtừ担当者名 -
Place Validation: Kiểm tra
実施場所IDtồn tại trongplacestable -
Order ID Validation: Nếu
予約IDđược cung cấp, kiểm tra tồn tại và quyền sở hữu
Post-Processing (After Import)
-
Total Price Calculation: Tự động tính
税抜合計金額và税込合計金額từorder_date_prices -
Status Update: Cập nhật
order_statusestable với status mới -
Audit Log: Ghi log thay đổi vào
batch_taskstable - Notification: Gửi email thông báo cho user và owner account
Special Business Rules
-
Commodity Handling:
- Không validate với
commodity_relationstable - Chỉ validate format và độ dài (50 ký tự)
- Lưu trực tiếp vào
orders.commodity
- Không validate với
-
Order Owner Logic:
-
受注企業= 999: 自社登録 (tự đăng ký) -
受注企業= 100: 楽市システム登録 (đăng ký qua hệ thống Rakuichi)
-
-
Date Range Validation:
-
開始日付phải <=終了日付 - Không được trùng lặp với order khác cùng place trong cùng khoảng thời gian
-
-
Price Calculation:
-
税抜合計金額= sum của tất cảorder_date_prices.price -
税込合計金額= sum của tất cảorder_date_prices.tax_price
-
Special Field Processing
-
Time Format Processing:
-
催事開始時刻và催事終了時刻: Validate 15 phút đơn vị (00, 15, 30, 45) -
搬入希望日時và搬出希望日時: Format "YYYY-MM-DD HH:MM"
-
-
Phone Number Processing:
-
現場責任者の連絡先và店舗電話番号: Validate format số điện thoại Nhật - Tự động format nếu cần thiết
-
-
Email Processing:
-
現場責任者メールアドレスvàユーザのメールアドレス: Validate email format - Chuyển đổi sang lowercase
-
-
Address Processing:
- Các field địa chỉ từ
placestable: Tự động điền từplacesdựa trên実施場所ID - Không được import trực tiếp, chỉ hiển thị trong export
- Các field địa chỉ từ