Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions app/DoctrineMigrations/Version20260617000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* 受注管理用メモ(order_memo)の CSV 出力項目を dtb_csv へ追加する.
*
* 新規インストールは import_csv/{ja,en}/dtb_csv.csv で反映されるため、
* 本マイグレーションは既存環境向け(冪等)。
*/
final class Version20260617000000 extends AbstractMigration
{
public function up(Schema $schema): void
{
// 商品 CSV(csv_type_id = 1)へ Product.order_memo を追加
$productExists = $this->connection->fetchOne("SELECT COUNT(*) FROM dtb_csv WHERE csv_type_id = 1 AND field_name = 'order_memo'");
if ($productExists == 0) {
$sortNo = $this->connection->fetchOne('SELECT MAX(sort_no) + 1 FROM dtb_csv WHERE csv_type_id = 1');
$this->addSql("INSERT INTO dtb_csv (
csv_type_id, creator_id, entity_name, field_name, disp_name, sort_no, enabled, create_date, update_date, discriminator_type
) VALUES (
1, null, ?, 'order_memo', '受注管理用メモ', $sortNo, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'csv'
)",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
['Eccube\\\\Entity\\\\Product']);
}

// 配送/出荷 CSV(csv_type_id = 4)へ OrderItem.order_memo を追加
$orderItemExists = $this->connection->fetchOne("SELECT COUNT(*) FROM dtb_csv WHERE csv_type_id = 4 AND field_name = 'order_memo'");
if ($orderItemExists == 0) {
$sortNo = $this->connection->fetchOne('SELECT MAX(sort_no) + 1 FROM dtb_csv WHERE csv_type_id = 4');
$this->addSql("INSERT INTO dtb_csv (
csv_type_id, creator_id, entity_name, field_name, disp_name, sort_no, enabled, create_date, update_date, discriminator_type
) VALUES (
4, null, ?, 'order_memo', '受注管理用メモ', $sortNo, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'csv'
)",
['Eccube\\\\Entity\\\\OrderItem']);
}
}

public function down(Schema $schema): void
{
$this->addSql("DELETE FROM dtb_csv WHERE csv_type_id = 1 AND entity_name = 'Eccube\\\\Entity\\\\Product' AND field_name = 'order_memo'");
$this->addSql("DELETE FROM dtb_csv WHERE csv_type_id = 4 AND entity_name = 'Eccube\\\\Entity\\\\OrderItem' AND field_name = 'order_memo'");
}
}
5 changes: 5 additions & 0 deletions app/config/eccube/packages/purchaseflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ services:
- { name: eccube.item.holder.preprocessor, flow_type: shopping, priority: 1000 }
- { name: eccube.item.holder.preprocessor, flow_type: order, priority: 1000 }

eccube.purchase.flow.item.holder.preprocessor.order.memo.preprocessor: # 商品の受注管理用メモを商品明細へコピー
class: Eccube\Service\PurchaseFlow\Processor\OrderMemoPreprocessor
tags:
- { name: eccube.item.holder.preprocessor, flow_type: shopping, priority: 100 }

eccube.purchase.flow.item.holder.preprocessor.order.no.processor:
class: Eccube\Service\PurchaseFlow\Processor\OrderNoProcessor
arguments:
Expand Down
27 changes: 27 additions & 0 deletions e2e/setup-fixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,5 +212,32 @@
echo " Multi-cart test product already exists\n";
}

// --- 受注管理用メモ確認用の受注 (#6821) ---
// 注文確定時に商品メモが受注明細へコピーされた状態を再現し、
// 受注編集画面のメモアイコン/モーダル表示を E2E で検証できるようにする。
$orderMemoName01 = '受注メモ確認用';
$orderMemoText = "梱包時は割れ物注意\n同梱物: 取扱説明書";
$existingMemoOrder = $entityManager->getRepository(\Eccube\Entity\Order::class)
->findOneBy(['name01' => $orderMemoName01]);
if (!$existingMemoOrder) {
$memoProduct = $generator->createProduct('受注管理用メモ商品', 0);
$memoProduct->setOrderMemo($orderMemoText);
$memoCustomer = $entityManager->getRepository(Customer::class)->findAll()[0];
$Delivery = $entityManager->getRepository(\Eccube\Entity\Delivery::class)->findAll()[0];
$Order = $generator->createOrder($memoCustomer, $memoProduct->getProductClasses()->toArray(), $Delivery);
$Order->setName01($orderMemoName01);
$Order->setName02('太郎');
$Order->setOrderStatus($entityManager->getRepository(OrderStatus::class)->find(OrderStatus::NEW));
$Order->setOrderDate(new \DateTime());
// 注文確定時のコピーを再現: 商品明細にのみメモを設定する
foreach ($Order->getProductOrderItems() as $item) {
$item->setOrderMemo($memoProduct->getOrderMemo());
}
$entityManager->flush();
echo " Created order-memo test order\n";
} else {
echo " Order-memo test order already exists\n";
}

echo "Fixtures setup complete.\n";
$kernel->shutdown();
29 changes: 29 additions & 0 deletions e2e/tests/admin-order.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,4 +567,33 @@ test.describe('Admin Order (EA04)', () => {

await popup.close();
});

test('order_受注管理用メモのアイコンとモーダル表示 - #6821', async ({ page }) => {
// 受注明細にメモを持つフィクスチャ受注(注文者: 受注メモ確認用)を開く
await goOrderList(page);
await searchOrder(page, '受注メモ確認用');
await expect(page.locator(searchResultMsg)).not.toContainText('検索結果:0件が該当しました');

await page.locator('#search_result tbody tr:first-child a.action-edit').click();
await page.waitForLoadState('load');
await expect(page.locator(pageTitle)).toContainText('受注登録');

// メモアイコンは商品明細のみに表示される(送料・手数料・値引きには出ない)
const memoLink = page.locator('a[data-bs-target^="#order_memo_"]');
await expect(memoLink).toHaveCount(1);

// ツールチップのオーバーレイによるクリック阻害を避ける
await page.evaluate(() => document.querySelectorAll('.tooltip').forEach((el) => el.remove()));

// アイコンクリックでモーダルにメモ全文が表示される
await memoLink.click();
const modal = page.locator('[id^="order_memo_"].modal.show');
await expect(modal).toBeVisible();
await expect(modal).toContainText('梱包時は割れ物注意');
await expect(modal).toContainText('同梱物: 取扱説明書');

// 閉じる (フェードアウトの完了まで自動リトライで待つ)
await modal.locator('[data-bs-dismiss="modal"]').first().click();
await expect(page.locator('[id^="order_memo_"].modal.show')).toHaveCount(0);
});
});
19 changes: 19 additions & 0 deletions e2e/tests/admin-product.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1360,4 +1360,23 @@ test.describe('Admin Product (EA03)', () => {
await page.waitForLoadState('load');
await expect(page.locator('.alert-success')).toContainText('保存しました');
});

test('product_受注管理用メモの保存と表示 - #6821', async ({ page }) => {
const memo = `梱包時は割れ物注意 ${Date.now()}\n同梱物: 取扱説明書`;

// 受注管理用メモを入力して商品を新規登録
await page.goto(`/${adminRoute}/product/product/new`);
await page.waitForLoadState('load');
await page.locator('#admin_product_name').fill('受注メモテスト商品');
await page.locator('#admin_product_class_price02').fill('1000');
// フリーエリア直後の受注管理用メモカードが存在することを確認
await expect(page.locator('#admin_product_order_memo')).toBeVisible();
await page.locator('#admin_product_order_memo').fill(memo);
await page.locator('button.ladda-button[type="submit"]').click();
await page.waitForLoadState('load');
await expect(page.locator('.alert-success')).toContainText('保存しました');

// 編集画面の再表示でメモが保持されていることを確認
await expect(page.locator('#admin_product_order_memo')).toHaveValue(memo);
});
});
13 changes: 13 additions & 0 deletions src/Eccube/Controller/Admin/Product/CsvImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,14 @@ public function csvProduct(Request $request): array|JsonResponse
}
}

if (isset($row[$headerByKey['order_memo']])) {
if (StringUtil::isNotBlank($row[$headerByKey['order_memo']])) {
$Product->setOrderMemo(StringUtil::trimAll($row[$headerByKey['order_memo']]));
} else {
$Product->setOrderMemo();
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// 商品画像登録
$this->createProductImage($row, $Product, $data, $headerByKey);

Expand Down Expand Up @@ -1672,6 +1680,11 @@ protected function getProductCsvHeader(): array
'description' => 'admin.product.product_csv.free_area_description',
'required' => false,
],
trans('admin.product.product_csv.order_memo_col') => [
'id' => 'order_memo',
'description' => 'admin.product.product_csv.order_memo_description',
'required' => false,
],
trans('admin.product.product_csv.delete_flag_col') => [
'id' => 'product_del_flg',
'description' => 'admin.product.product_csv.delete_flag_description',
Expand Down
23 changes: 23 additions & 0 deletions src/Eccube/Entity/OrderItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ public function isPoint(): bool
#[ORM\Column(name: 'processor_name', type: Types::STRING, nullable: true)]
private ?string $processor_name = null;

#[ORM\Column(name: 'order_memo', type: Types::TEXT, nullable: true)]
private ?string $order_memo = null;

#[ORM\ManyToOne(targetEntity: Order::class, inversedBy: 'OrderItems')]
#[ORM\JoinColumn(name: 'order_id', referencedColumnName: 'id')]
private ?Order $Order = null;
Expand Down Expand Up @@ -478,6 +481,26 @@ public function setProcessorName(?string $processorName = null): static
return $this;
}

/**
* Get orderMemo.
*/
public function getOrderMemo(): ?string
{
return $this->order_memo;
}

/**
* Set orderMemo.
*
* @return $this
*/
public function setOrderMemo(?string $orderMemo = null): static
{
$this->order_memo = $orderMemo;

return $this;
}

/**
* Set order.
*/
Expand Down
21 changes: 21 additions & 0 deletions src/Eccube/Entity/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,9 @@ public function hasProductClass(): bool
#[ORM\Column(name: 'free_area', type: Types::TEXT, nullable: true)]
private ?string $free_area = null;

#[ORM\Column(name: 'order_memo', type: Types::TEXT, nullable: true)]
private ?string $order_memo = null;

/**
* @var \DateTime
*/
Expand Down Expand Up @@ -703,6 +706,24 @@ public function getFreeArea(): ?string
return $this->free_area;
}

/**
* Set orderMemo.
*/
public function setOrderMemo(?string $orderMemo = null): Product
{
$this->order_memo = $orderMemo;

return $this;
}

/**
* Get orderMemo.
*/
public function getOrderMemo(): ?string
{
return $this->order_memo;
}

/**
* Set createDate.
*/
Expand Down
6 changes: 6 additions & 0 deletions src/Eccube/Form/Type/Admin/ProductType.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
new Assert\Length(['max' => $this->eccubeConfig['eccube_lltext_len']]),
],
])
->add('order_memo', TextareaType::class, [
'required' => false,
'constraints' => [
new Assert\Length(['max' => $this->eccubeConfig['eccube_lltext_len']]),
],
])

// 右ブロック
->add('Status', ProductStatusType::class, [
Expand Down
2 changes: 2 additions & 0 deletions src/Eccube/Resource/doctrine/import_csv/en/dtb_csv.csv
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ id,csv_type_id,creator_id,entity_name,field_name,reference_field_name,disp_name,
196,4,,Eccube\\Entity\\Shipping,tracking_number,,Tracking No. ,69,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
197,4,,Eccube\\Entity\\Shipping,note,,Delivery Notes,70,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
198,4,,Eccube\\Entity\\Shipping,mail_send_date,,Shipping notice sent on,71,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
216,4,,Eccube\\Entity\\OrderItem,order_memo,,Order Management Memo,72,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
199,5,,Eccube\\Entity\\Category,id,,Category ID,1,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
200,5,,Eccube\\Entity\\Category,sort_no,,Display Priority,2,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
201,5,,Eccube\\Entity\\Category,name,,Category Name,3,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
Expand All @@ -203,6 +204,7 @@ id,csv_type_id,creator_id,entity_name,field_name,reference_field_name,disp_name,
204,1,,Eccube\\Entity\\ProductClass,TaxRule,tax_rate,Tax Rate,"31","0","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
205,2,,Eccube\\Entity\\Customer,point,,Point,32,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
206,1,,Eccube\\Entity\\ProductClass,visible,,Product options visible flag,32,0,2022-11-24 00:00:00,2022-11-24 00:00:00,csv
215,1,,Eccube\\Entity\\Product,order_memo,,Order Management Memo,33,1,2017-03-07 10:14:00,2017-03-07 10:14:00,csv
207,6,,Eccube\\Entity\\ClassName,id,,Class Name ID,1,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
208,6,,Eccube\\Entity\\ClassName,name,,Class Name,2,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
209,6,,Eccube\\Entity\\ClassName,backend_name,,Backend Name,3,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
Expand Down
2 changes: 2 additions & 0 deletions src/Eccube/Resource/doctrine/import_csv/ja/dtb_csv.csv
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
"196","4",,"Eccube\\Entity\\Shipping","tracking_number",,"出荷伝票番号","69","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"197","4",,"Eccube\\Entity\\Shipping","note",,"配達用メモ","70","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"198","4",,"Eccube\\Entity\\Shipping","mail_send_date",,"出荷メール送信日","71","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"216","4",,"Eccube\\Entity\\OrderItem","order_memo",,"受注管理用メモ","72","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"199","5",,"Eccube\\Entity\\Category","id",,"カテゴリID","1","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"200","5",,"Eccube\\Entity\\Category","sort_no",,"表示ランク","2","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"201","5",,"Eccube\\Entity\\Category","name",,"カテゴリ名","3","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
Expand All @@ -203,6 +204,7 @@
"204","1",,"Eccube\\Entity\\ProductClass","TaxRule","tax_rate","税率","31","0","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"205","2",,"Eccube\\Entity\\Customer","point",,"ポイント","33","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"206","1",,"Eccube\\Entity\\ProductClass","visible",,"商品規格表示フラグ","32","0","2022-11-24 00:00:00","2022-11-24 00:00:00","csv"
"215","1",,"Eccube\\Entity\\Product","order_memo",,"受注管理用メモ","33","1","2017-03-07 10:14:00","2017-03-07 10:14:00","csv"
"207","6",,"Eccube\\Entity\\ClassName","id",,"規格ID","1","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
"208","6",,"Eccube\\Entity\\ClassName","name",,"規格名","2","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
"209","6",,"Eccube\\Entity\\ClassName","backend_name",,"管理名","3","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
Expand Down
5 changes: 5 additions & 0 deletions src/Eccube/Resource/locale/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,8 @@ admin.product.delivery_fee: Shipping Charge
admin.product.tax_rate: Tax
admin.product.free_area: Miscellaneous
admin.product.free_area__card_title: Miscellaneous
admin.product.order_memo: Order Management Memo
admin.product.order_memo__card_title: Order Management Memo
admin.product.delete_flag: Product Deletion Flag
admin.product.search_category: Category Search
admin.product.save_tag: Tags
Expand Down Expand Up @@ -737,6 +739,8 @@ admin.product.product_csv.keyword_col: Search Keywords
admin.product.product_csv.keyword_description: ""
admin.product.product_csv.free_area_col: Miscellaneous
admin.product.product_csv.free_area_description: ""
admin.product.product_csv.order_memo_col: Order Management Memo
admin.product.product_csv.order_memo_description: Management memo that will be copied to order items. Not visible to customers.
admin.product.product_csv.delete_flag_col: Product Deletion Flag
admin.product.product_csv.delete_flag_description: "Specify 0: Register 1: Delete. If unspecified, it will be set to 0."
admin.product.product_csv.product_image_col: Product Images
Expand Down Expand Up @@ -1696,6 +1700,7 @@ tooltip.product.sale_limit: This will limit the number of products shoppers can
tooltip.product.delivery_duration: You can register estimated shipping date per product.
tooltip.product.product_class: You can review and manage the option(s) set to this product.
tooltip.product.free_area: The entry will be displayed on the product page. The placement varies according to the design templates.
tooltip.product.order_memo: Management memo that will be copied to order items. Not visible to customers.
tooltip.product.shop_memo: Notes for store use. This will not be displayed on the Front Screen.
tooltip.product.backend_name: "You can register an alias for administrator (e.g. Option Name: Size - Alias: Size (Clothing) or Size (Shoes) etc. It will not be displayed on the Front Screen."
tooltip.product.csv_upload: Bulk product registration is available with a CSV template.
Expand Down
5 changes: 5 additions & 0 deletions src/Eccube/Resource/locale/messages.ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,8 @@ admin.product.delivery_fee: 商品送料
admin.product.tax_rate: 税率
admin.product.free_area: フリーエリア
admin.product.free_area__card_title: フリーエリア
admin.product.order_memo: 受注管理用メモ
admin.product.order_memo__card_title: 受注管理用メモ
admin.product.delete_flag: 商品削除フラグ
admin.product.search_category: カテゴリ検索
admin.product.save_tag: タグ登録
Expand Down Expand Up @@ -736,6 +738,8 @@ admin.product.product_csv.keyword_col: 検索ワード
admin.product.product_csv.keyword_description: ""
admin.product.product_csv.free_area_col: フリーエリア
admin.product.product_csv.free_area_description: ""
admin.product.product_csv.order_memo_col: 受注管理用メモ
admin.product.product_csv.order_memo_description: 受注時に注文明細へコピーされる管理用メモです。顧客には表示されません。
admin.product.product_csv.delete_flag_col: 商品削除フラグ
admin.product.product_csv.delete_flag_description: 0:登録 1:削除を指定します。未指定の場合、0として扱います。
admin.product.product_csv.product_image_col: 商品画像
Expand Down Expand Up @@ -1696,6 +1700,7 @@ tooltip.product.sale_limit: 購入者が一度に購入できる個数を制限
tooltip.product.delivery_duration: 発送日の目安期間を商品ごとに登録できます。
tooltip.product.product_class: この商品に設定された規格を確認・管理できます。
tooltip.product.free_area: 商品詳細ページに入力内容が表示されます。表示位置はデザインテンプレートによって異なります。
tooltip.product.order_memo: 受注時に注文明細へコピーされる管理用メモです。顧客には表示されません。
tooltip.product.shop_memo: 店舗用のメモ欄です。フロント画面には表示されません。
tooltip.product.backend_name: 管理者用に別名を登録しておくことができます(例:規格名:サイズ 管理名:サイズ(服)、サイズ(靴)等 )。フロント画面には表示されません。
tooltip.product.csv_upload: 所定の型のCSVデータを用いて商品を一括で登録することができます。
Expand Down
Loading
Loading