diff --git a/app/DoctrineMigrations/Version20220603074035.php b/app/DoctrineMigrations/Version20220603074035.php
new file mode 100644
index 00000000000..60c3159c821
--- /dev/null
+++ b/app/DoctrineMigrations/Version20220603074035.php
@@ -0,0 +1,78 @@
+connection->fetchColumn(
+ 'SELECT COUNT(*) FROM mtb_csv_type WHERE id = 6'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO mtb_csv_type ('id', 'name', 'sort_no', 'discriminator_type') VALUES (6, 'Class NameCSV', 6, 'csvtype');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM mtb_csv_type WHERE id = 7'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO mtb_csv_type ('id', 'name', 'sort_no', 'discriminator_type') VALUES (7, 'Class Category CSV', 7, 'csvtype');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 206'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('206','6',,'Eccube\\Entity\\ClassName','id',,'規格ID','1','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 207'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('207','6',,'Eccube\\Entity\\ClassName','name',,'規格名','2','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 208'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('208','6',,'Eccube\\Entity\\ClassName','backend_name',,'管理名','3','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 209'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('209','7',,'Eccube\\Entity\\ClassCategory','id',,'規格分類ID','1','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 210'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('210','7',,'Eccube\\Entity\\ClassCategory','ClassName','id','規格ID','2','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 211'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('211','7',,'Eccube\\Entity\\ClassCategory','name',,'規格分類名','3','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ $statusExists = $this->connection->fetchColumn(
+ 'SELECT COUNT(*) FROM dtb_csv WHERE id = 212'
+ );
+ if ($statusExists == 0) {
+ $this->addSql("INSERT INTO dtb_csv ('id','csv_type_id','creator_id','entity_name','field_name','reference_field_name','disp_name','sort_no','enabled','create_date','update_date','discriminator_type') VALUES ('212','7',,'Eccube\\Entity\\ClassCategory','backend_name',,'分類管理名','4','1','2021-05-18 01:26:41','2021-05-18 01:26:41','csv');");
+ }
+ }
+
+ public function down(Schema $schema) : void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+
+ }
+}
diff --git a/app/config/eccube/packages/eccube_nav.yaml b/app/config/eccube/packages/eccube_nav.yaml
index c99677e05d3..e83df1b6ee3 100644
--- a/app/config/eccube/packages/eccube_nav.yaml
+++ b/app/config/eccube/packages/eccube_nav.yaml
@@ -22,6 +22,12 @@ parameters:
product_csv_import:
name: admin.product.product_csv_upload
url: admin_product_csv_import
+ class_name_csv_import:
+ name: admin.product.class_name_csv_upload
+ url: admin_product_class_name_csv_import
+ class_category_csv_import:
+ name: admin.product.class_category_csv_upload
+ url: admin_product_class_category_csv_import
category_csv_import:
name: admin.product.category_csv_upload
url: admin_product_category_csv_import
diff --git a/codeception/_data/class_category.csv b/codeception/_data/class_category.csv
new file mode 100644
index 00000000000..5d0c79d99b0
--- /dev/null
+++ b/codeception/_data/class_category.csv
@@ -0,0 +1,4 @@
+規格ID,規格分類ID,規格分類名,規格分類管理名,規格分類削除フラグ
+1,,アップロード規格分類1,,
+1,,アップロード規格分類2,,
+1,,アップロード規格分類3,,
\ No newline at end of file
diff --git a/codeception/_data/class_name.csv b/codeception/_data/class_name.csv
new file mode 100644
index 00000000000..e8c57218c34
--- /dev/null
+++ b/codeception/_data/class_name.csv
@@ -0,0 +1,4 @@
+規格ID,規格名,管理名,規格削除フラグ
+,アップロード規格1,,
+,アップロード規格2,,
+,アップロード規格3,,
diff --git a/codeception/_support/Page/Admin/ClassCategoryCsvUploadPage.php b/codeception/_support/Page/Admin/ClassCategoryCsvUploadPage.php
new file mode 100644
index 00000000000..f56a4f31d35
--- /dev/null
+++ b/codeception/_support/Page/Admin/ClassCategoryCsvUploadPage.php
@@ -0,0 +1,55 @@
+ div.alert-success';
+
+ /**
+ * ClassCategoryCsvUploadPage constructor.
+ */
+ public function __construct(\AcceptanceTester $I)
+ {
+ parent::__construct($I);
+ }
+
+ public static function go($I)
+ {
+ $page = new self($I);
+
+ return $page->goPage('/product/class_category_csv_upload', '規格分類CSV登録商品管理');
+ }
+
+ public function 入力_CSVファイル($fileName)
+ {
+ $this->tester->attachFile(['id' => 'admin_csv_import_import_file'], $fileName);
+
+ return $this;
+ }
+
+ public function CSVアップロード()
+ {
+ $this->tester->click(['id' => 'upload-button']);
+
+ return $this;
+ }
+
+ public function 雛形ダウンロード()
+ {
+ $this->tester->click('#download-button');
+
+ return $this;
+ }
+}
diff --git a/codeception/_support/Page/Admin/ClassCategoryManagePage.php b/codeception/_support/Page/Admin/ClassCategoryManagePage.php
index 2505ce1e395..bf80f1c63a3 100644
--- a/codeception/_support/Page/Admin/ClassCategoryManagePage.php
+++ b/codeception/_support/Page/Admin/ClassCategoryManagePage.php
@@ -85,6 +85,18 @@ public function acceptModal()
return $this;
}
+ public function CSVダウンロード実行()
+ {
+ $this->tester->click('body > div > div.c-contentsArea > div.c-outsideBlock > div > div > div.col-6.text-end > div > a:nth-child(1)');
+
+ return $this;
+ }
+
+ public function CSV出力項目設定()
+ {
+ $this->tester->click('body > div > div.c-contentsArea > div.c-outsideBlock > div > div > div.col-6.text-end > div > a:nth-child(2)');
+ }
+
public function 一覧_上に($rowNum)
{
$this->tester->dragAndDropBy("ul.list-group > li:nth-child(${rowNum})", 0, -60);
@@ -103,4 +115,9 @@ public function 一覧_名称($rowNum)
{
return "ul.list-group > li:nth-child(${rowNum}) > div > div.col.d-flex.align-items-center";
}
+
+ public static function XPathでタグを取得する($textEl)
+ {
+ return '//*[@id="page_admin_product_class_category"]/div[1]/div[3]/div[2]/div[1]/div/div[3]/div[2]/div/ul/li/div/div[3][contains(text(), "'.$textEl.'")]';
+ }
}
diff --git a/codeception/_support/Page/Admin/ClassNameCsvUploadPage.php b/codeception/_support/Page/Admin/ClassNameCsvUploadPage.php
new file mode 100644
index 00000000000..266325c46fc
--- /dev/null
+++ b/codeception/_support/Page/Admin/ClassNameCsvUploadPage.php
@@ -0,0 +1,55 @@
+ div.alert-success';
+
+ /**
+ * ClassNameCsvUploadPage constructor.
+ */
+ public function __construct(\AcceptanceTester $I)
+ {
+ parent::__construct($I);
+ }
+
+ public static function go($I)
+ {
+ $page = new self($I);
+
+ return $page->goPage('/product/class_name_csv_upload', '規格CSV登録商品管理');
+ }
+
+ public function 入力_CSVファイル($fileName)
+ {
+ $this->tester->attachFile(['id' => 'admin_csv_import_import_file'], $fileName);
+
+ return $this;
+ }
+
+ public function CSVアップロード()
+ {
+ $this->tester->click(['id' => 'upload-button']);
+
+ return $this;
+ }
+
+ public function 雛形ダウンロード()
+ {
+ $this->tester->click('#download-button');
+
+ return $this;
+ }
+}
diff --git a/codeception/_support/Page/Admin/ClassNameManagePage.php b/codeception/_support/Page/Admin/ClassNameManagePage.php
index 1edf45ada66..29660603cc3 100644
--- a/codeception/_support/Page/Admin/ClassNameManagePage.php
+++ b/codeception/_support/Page/Admin/ClassNameManagePage.php
@@ -79,6 +79,13 @@ public function 一覧_分類登録($rowNum)
return $this;
}
+ public function 一覧_分類登録2()
+ {
+ $this->tester->click("ul.list-group > li:last-child > div > div.col.d-flex.align-items-center > a");
+
+ return $this;
+ }
+
public function 一覧_編集($rowNum)
{
$this->tester->click("ul.list-group > li:nth-child(${rowNum}) > div > div.col-auto.text-end > a.action-edit");
@@ -103,6 +110,18 @@ public function acceptModal()
return $this;
}
+ public function CSVダウンロード実行()
+ {
+ $this->tester->click('body > div > div.c-contentsArea > div.c-outsideBlock > div > div > div.col-6.text-end > div > a:nth-child(1)');
+
+ return $this;
+ }
+
+ public function CSV出力項目設定()
+ {
+ $this->tester->click('body > div > div.c-contentsArea > div.c-outsideBlock > div > div > div.col-6.text-end > div > a:nth-child(2)');
+ }
+
public function 一覧_上に($rowNum)
{
$this->tester->dragAndDropBy("ul.list-group > li:nth-child(${rowNum})", 0, -60);
@@ -116,4 +135,9 @@ public function 一覧_下に($rowNum)
return $this;
}
+
+ public static function XPathでタグを取得する($textEl)
+ {
+ return '//*[@id="page_admin_product_class_name"]/div[1]/div[3]/div[3]/div[1]/div/div/div/div/ul/li/div/div[3]/a[contains(text(), "'.$textEl.'")]';
+ }
}
diff --git a/codeception/acceptance/EA03ProductCest.php b/codeception/acceptance/EA03ProductCest.php
index 8d0b846c057..5db3e4562a9 100644
--- a/codeception/acceptance/EA03ProductCest.php
+++ b/codeception/acceptance/EA03ProductCest.php
@@ -15,6 +15,8 @@
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManager;
use Page\Admin\CategoryCsvUploadPage;
+use Page\Admin\ClassNameCsvUploadPage;
+use Page\Admin\ClassCategoryCsvUploadPage;
use Page\Admin\CategoryManagePage;
use Page\Admin\ClassCategoryManagePage;
use Page\Admin\ClassNameManagePage;
@@ -872,6 +874,92 @@ public function product_カテゴリCSV登録雛形ファイルダウンロー
$I->assertEquals(1, count(file($CategoryTemplateCSV)), 'ヘッダ行だけのファイル');
}
+ public function product_規格CSV登録(AcceptanceTester $I)
+ {
+ $I->wantTo('EA0307-UC02-T01 規格CSV登録');
+
+ ClassNameManagePage::go($I);
+ $I->dontSeeElement(['xpath' => '//div[@id="sortable_list_box"]//a[contains(text(), "アップロード規格")]']);
+
+ ClassNameCsvUploadPage::go($I)
+ ->入力_CSVファイル('class_name.csv')
+ ->CSVアップロード();
+
+ $I->see('CSVファイルをアップロードしました', ClassNameCsvUploadPage::$完了メッセージ);
+
+ ClassNameManagePage::go($I);
+
+ $I->seeElement(['xpath' => ClassNameManagePage::XPathでタグを取得する('アップロード規格1')]);
+ $I->seeElement(['xpath' => ClassNameManagePage::XPathでタグを取得する('アップロード規格2')]);
+ $I->seeElement(['xpath' => ClassNameManagePage::XPathでタグを取得する('アップロード規格3')]);
+
+ // アップロード失敗 (フォーマットの異なるcsvをアップロードする)
+ ClassNameCsvUploadPage::go($I)
+ ->入力_CSVファイル('product.csv')
+ ->CSVアップロード();
+ $I->see('CSVのフォーマットが一致しません', '#upload-form');
+ }
+
+ /**
+ * @env firefox
+ * @env chrome
+ */
+ public function product_規格CSV登録雛形ファイルダウンロード(AcceptanceTester $I)
+ {
+ $I->wantTo('EA0307-UC02-T02 規格CSV登録雛形ファイルダウンロード');
+
+ // 雛形のダウンロード
+ ClassNameCsvUploadPage::go($I)->雛形ダウンロード();
+ $ClassNameTemplateCSV = $I->getLastDownloadFile('/^class_name\.csv$/');
+ $I->assertEquals(1, count(file($ClassNameTemplateCSV)), 'ヘッダ行だけのファイル');
+ }
+
+ public function product_規格分類CSV登録(AcceptanceTester $I)
+ {
+ $I->wantTo('EA0307-UC03-T01 規格分類CSV登録');
+
+ ClassNameManagePage::go($I)
+ ->一覧_分類登録(3);
+
+ ClassCategoryManagePage::at($I);
+ $I->dontSeeElement(['xpath' => '//div[@id="sortable_list_box"]//a[contains(text(), "アップロード規格分類")]']);
+
+ ClassCategoryCsvUploadPage::go($I)
+ ->入力_CSVファイル('class_category.csv')
+ ->CSVアップロード();
+
+ $I->see('CSVファイルをアップロードしました', ClassCategoryCsvUploadPage::$完了メッセージ);
+
+ ClassNameManagePage::go($I)
+ ->一覧_分類登録2();
+
+ ClassCategoryManagePage::at($I);
+
+ $I->seeElement(['xpath' => ClassCategoryManagePage::XPathでタグを取得する('アップロード規格分類1')]);
+ $I->seeElement(['xpath' => ClassCategoryManagePage::XPathでタグを取得する('アップロード規格分類2')]);
+ $I->seeElement(['xpath' => ClassCategoryManagePage::XPathでタグを取得する('アップロード規格分類3')]);
+
+ // アップロード失敗 (フォーマットの異なるcsvをアップロードする)
+ ClassCategoryCsvUploadPage::go($I)
+ ->入力_CSVファイル('product.csv')
+ ->CSVアップロード();
+ $I->see('CSVのフォーマットが一致しません', '#upload-form');
+ }
+
+ /**
+ * @env firefox
+ * @env chrome
+ */
+ public function product_規格分類CSV登録雛形ファイルダウンロード(AcceptanceTester $I)
+ {
+ $I->wantTo('EA0307-UC03-T02 規格分類CSV登録雛形ファイルダウンロード');
+
+ // 雛形のダウンロード
+ ClassCategoryCsvUploadPage::go($I)->雛形ダウンロード();
+ $ClassCategoryTemplateCSV = $I->getLastDownloadFile('/^class_category\.csv$/');
+ $I->assertEquals(1, count(file($ClassCategoryTemplateCSV)), 'ヘッダ行だけのファイル');
+ }
+
public function product_タグ登録(AcceptanceTester $I)
{
$I->wantTo('EA0308-UC01-T01 / UC01-T02 タグ登録');
diff --git a/src/Eccube/Controller/Admin/Product/ClassCategoryController.php b/src/Eccube/Controller/Admin/Product/ClassCategoryController.php
index 9f6e189d423..a25ac281566 100644
--- a/src/Eccube/Controller/Admin/Product/ClassCategoryController.php
+++ b/src/Eccube/Controller/Admin/Product/ClassCategoryController.php
@@ -14,15 +14,18 @@
namespace Eccube\Controller\Admin\Product;
use Eccube\Controller\AbstractController;
+use Eccube\Entity\Master\CsvType;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Form\Type\Admin\ClassCategoryType;
use Eccube\Repository\ClassCategoryRepository;
use Eccube\Repository\ClassNameRepository;
use Eccube\Repository\ProductClassRepository;
+use Eccube\Service\CsvExportService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
@@ -44,21 +47,29 @@ class ClassCategoryController extends AbstractController
*/
protected $classNameRepository;
+ /**
+ * @var CsvExportService
+ */
+ protected $csvExportService;
+
/**
* ClassCategoryController constructor.
*
* @param ProductClassRepository $productClassRepository
* @param ClassCategoryRepository $classCategoryRepository
* @param ClassNameRepository $classNameRepository
+ * @param CsvExportService $csvExportService
*/
public function __construct(
ProductClassRepository $productClassRepository,
ClassCategoryRepository $classCategoryRepository,
- ClassNameRepository $classNameRepository
+ ClassNameRepository $classNameRepository,
+ CsvExportService $csvExportService
) {
$this->productClassRepository = $productClassRepository;
$this->classCategoryRepository = $classCategoryRepository;
$this->classNameRepository = $classNameRepository;
+ $this->csvExportService = $csvExportService;
}
/**
@@ -265,4 +276,77 @@ public function moveSortNo(Request $request)
return new Response('Successful');
}
}
+
+ /**
+ * 規格分類CSVの出力.
+ *
+ * @Route("/%eccube_admin_route%/product/class_category/export/{class_name_id}", name="admin_product_class_category_export")
+ *
+ * @param Request $request
+ *
+ * @return StreamedResponse
+ */
+ public function export(Request $request, $class_name_id)
+ {
+ // タイムアウトを無効にする.
+ set_time_limit(0);
+
+ // sql loggerを無効にする.
+ $em = $this->entityManager;
+ $em->getConfiguration()->setSQLLogger(null);
+
+ $response = new StreamedResponse();
+ $response->setCallback(function () use ($request, $class_name_id) {
+ // CSV種別を元に初期化.
+ $this->csvExportService->initCsvType(CsvType::CSV_TYPE_CLASS_CATEGORY);
+ // ヘッダ行の出力.
+ $this->csvExportService->exportHeader();
+
+ $qb = $this->classCategoryRepository
+ ->createQueryBuilder('cc')
+ ->where('cc.ClassName = :ClassName')
+ ->setParameter('ClassName', $class_name_id)
+ ->orderBy('cc.sort_no', 'DESC');
+
+ // データ行の出力.
+ $this->csvExportService->setExportQueryBuilder($qb);
+ $this->csvExportService->exportData(function ($entity, $csvService) use ($request) {
+ $Csvs = $csvService->getCsvs();
+
+ /** @var $ClassCategory \Eccube\Entity\ClassCategory */
+ $ClassCategory = $entity;
+
+ // CSV出力項目と合致するデータを取得.
+ $ExportCsvRow = new \Eccube\Entity\ExportCsvRow();
+ foreach ($Csvs as $Csv) {
+ $ExportCsvRow->setData($csvService->getData($Csv, $ClassCategory));
+
+ $event = new EventArgs(
+ [
+ 'csvService' => $csvService,
+ 'Csv' => $Csv,
+ 'ClassCategory' => $ClassCategory,
+ 'ExportCsvRow' => $ExportCsvRow,
+ ],
+ $request
+ );
+ $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_CLASS_CATEGORY_CSV_EXPORT, $event);
+
+ $ExportCsvRow->pushData();
+ }
+ //$row[] = number_format(memory_get_usage(true));
+ // 出力.
+ $csvService->fputcsv($ExportCsvRow->getRow());
+ });
+ });
+ $now = new \DateTime();
+ $filename = 'class_category_'.$now->format('YmdHis').'.csv';
+ $response->headers->set('Content-Type', 'application/octet-stream');
+ $response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
+ $response->send();
+
+ log_info('規格分類CSV出力ファイル名', [$filename]);
+
+ return $response;
+ }
}
diff --git a/src/Eccube/Controller/Admin/Product/ClassNameController.php b/src/Eccube/Controller/Admin/Product/ClassNameController.php
index be9f39b3cfd..bf6fc2aeddd 100644
--- a/src/Eccube/Controller/Admin/Product/ClassNameController.php
+++ b/src/Eccube/Controller/Admin/Product/ClassNameController.php
@@ -15,13 +15,16 @@
use Eccube\Controller\AbstractController;
use Eccube\Entity\ClassName;
+use Eccube\Entity\Master\CsvType;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Form\Type\Admin\ClassNameType;
use Eccube\Repository\ClassNameRepository;
+use Eccube\Service\CsvExportService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
@@ -33,14 +36,23 @@ class ClassNameController extends AbstractController
*/
protected $classNameRepository;
+ /**
+ * @var CsvExportService
+ */
+ protected $csvExportService;
+
/**
* ClassNameController constructor.
*
* @param ClassNameRepository $classNameRepository
+ * @param CsvExportService $csvExportService
*/
- public function __construct(ClassNameRepository $classNameRepository)
- {
+ public function __construct(
+ ClassNameRepository $classNameRepository,
+ CsvExportService $csvExportService
+ ) {
$this->classNameRepository = $classNameRepository;
+ $this->csvExportService = $csvExportService;
}
/**
@@ -184,4 +196,77 @@ public function moveSortNo(Request $request)
return new Response();
}
}
+
+ /**
+ * 規格CSVの出力.
+ *
+ * @Route("/%eccube_admin_route%/product/class_name/export", name="admin_product_class_name_export")
+ *
+ * @param Request $request
+ *
+ * @return StreamedResponse
+ */
+ public function export(Request $request)
+ {
+ // タイムアウトを無効にする.
+ set_time_limit(0);
+
+ // sql loggerを無効にする.
+ $em = $this->entityManager;
+ $em->getConfiguration()->setSQLLogger(null);
+
+ $response = new StreamedResponse();
+ $response->setCallback(function () use ($request) {
+ // CSV種別を元に初期化.
+ $this->csvExportService->initCsvType(CsvType::CSV_TYPE_CLASS_NAME);
+
+ // ヘッダ行の出力.
+ $this->csvExportService->exportHeader();
+
+ $qb = $this->classNameRepository
+ ->createQueryBuilder('cn')
+ ->orderBy('cn.sort_no', 'DESC');
+
+ // データ行の出力.
+ $this->csvExportService->setExportQueryBuilder($qb);
+ $this->csvExportService->exportData(function ($entity, $csvService) use ($request) {
+ $Csvs = $csvService->getCsvs();
+
+ /** @var $ClassName \Eccube\Entity\ClassName */
+ $ClassName = $entity;
+
+ // CSV出力項目と合致するデータを取得.
+ $ExportCsvRow = new \Eccube\Entity\ExportCsvRow();
+ foreach ($Csvs as $Csv) {
+ $ExportCsvRow->setData($csvService->getData($Csv, $ClassName));
+
+ $event = new EventArgs(
+ [
+ 'csvService' => $csvService,
+ 'Csv' => $Csv,
+ 'ClassName' => $ClassName,
+ 'ExportCsvRow' => $ExportCsvRow,
+ ],
+ $request
+ );
+ $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_CLASS_NAME_CSV_EXPORT, $event);
+
+ $ExportCsvRow->pushData();
+ }
+ //$row[] = number_format(memory_get_usage(true));
+ // 出力.
+ $csvService->fputcsv($ExportCsvRow->getRow());
+ });
+ });
+
+ $now = new \DateTime();
+ $filename = 'class_name_'.$now->format('YmdHis').'.csv';
+ $response->headers->set('Content-Type', 'application/octet-stream');
+ $response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
+ $response->send();
+
+ log_info('規格CSV出力ファイル名', [$filename]);
+
+ return $response;
+ }
}
diff --git a/src/Eccube/Controller/Admin/Product/CsvImportController.php b/src/Eccube/Controller/Admin/Product/CsvImportController.php
index 31e9c282444..c5bbd06caf6 100644
--- a/src/Eccube/Controller/Admin/Product/CsvImportController.php
+++ b/src/Eccube/Controller/Admin/Product/CsvImportController.php
@@ -18,6 +18,8 @@
use Eccube\Controller\Admin\AbstractCsvImportController;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Category;
+use Eccube\Entity\ClassName;
+use Eccube\Entity\ClassCategory;
use Eccube\Entity\Product;
use Eccube\Entity\ProductCategory;
use Eccube\Entity\ProductClass;
@@ -27,6 +29,7 @@
use Eccube\Form\Type\Admin\CsvImportType;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\CategoryRepository;
+use Eccube\Repository\ClassNameRepository;
use Eccube\Repository\ClassCategoryRepository;
use Eccube\Repository\DeliveryDurationRepository;
use Eccube\Repository\Master\ProductStatusRepository;
@@ -81,6 +84,11 @@ class CsvImportController extends AbstractCsvImportController
*/
protected $classCategoryRepository;
+ /**
+ * @var ClassNameRepository
+ */
+ protected $classNameRepository;
+
/**
* @var ProductImageRepository
*/
@@ -126,6 +134,7 @@ class CsvImportController extends AbstractCsvImportController
* @param SaleTypeRepository $saleTypeRepository
* @param TagRepository $tagRepository
* @param CategoryRepository $categoryRepository
+ * @param ClassNameRepository $classNameRepository
* @param ClassCategoryRepository $classCategoryRepository
* @param ProductImageRepository $productImageRepository
* @param ProductStatusRepository $productStatusRepository
@@ -141,6 +150,7 @@ public function __construct(
SaleTypeRepository $saleTypeRepository,
TagRepository $tagRepository,
CategoryRepository $categoryRepository,
+ ClassNameRepository $classNameRepository,
ClassCategoryRepository $classCategoryRepository,
ProductImageRepository $productImageRepository,
ProductStatusRepository $productStatusRepository,
@@ -153,6 +163,7 @@ public function __construct(
$this->saleTypeRepository = $saleTypeRepository;
$this->tagRepository = $tagRepository;
$this->categoryRepository = $categoryRepository;
+ $this->classNameRepository = $classNameRepository;
$this->classCategoryRepository = $classCategoryRepository;
$this->productImageRepository = $productImageRepository;
$this->productStatusRepository = $productStatusRepository;
@@ -843,6 +854,262 @@ public function csvCategory(Request $request, CacheUtil $cacheUtil)
return $this->renderWithError($form, $headers);
}
+ /**
+ * 規格登録CSVアップロード
+ *
+ * @Route("/%eccube_admin_route%/product/class_name_csv_upload", name="admin_product_class_name_csv_import")
+ * @Template("@admin/Product/csv_class_name.twig")
+ */
+ public function csvClassName(Request $request, CacheUtil $cacheUtil)
+ {
+ $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
+
+ $headers = $this->getClassNameCsvHeader();
+ if ('POST' === $request->getMethod()) {
+ $form->handleRequest($request);
+ if ($form->isValid()) {
+ $formFile = $form['import_file']->getData();
+ if (!empty($formFile)) {
+ log_info('規格CSV登録開始');
+ $data = $this->getImportData($formFile);
+ if ($data === false) {
+ $this->addErrors(trans('admin.common.csv_invalid_format'));
+
+ return $this->renderWithError($form, $headers, false);
+ }
+
+ $getId = function ($item) {
+ return $item['id'];
+ };
+ $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
+ return $value['required'];
+ })));
+
+ $headerByKey = array_flip(array_map($getId, $headers));
+
+ $columnHeaders = $data->getColumnHeaders();
+ if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
+ $this->addErrors(trans('admin.common.csv_invalid_format'));
+
+ return $this->renderWithError($form, $headers, false);
+ }
+
+ $size = count($data);
+ if ($size < 1) {
+ $this->addErrors(trans('admin.common.csv_invalid_no_data'));
+
+ return $this->renderWithError($form, $headers, false);
+ }
+ $this->entityManager->getConfiguration()->setSQLLogger(null);
+ $this->entityManager->getConnection()->beginTransaction();
+ // CSVファイルの登録処理
+ foreach ($data as $row) {
+ // dump($row,$headerByKey);exit;
+ /** @var $ClassName ClassName */
+ $ClassName = new ClassName();
+ if (isset($row[$headerByKey['id']]) && strlen($row[$headerByKey['id']]) > 0) {
+ if (!preg_match('/^\d+$/', $row[$headerByKey['id']])) {
+ $this->addErrors(($data->key() + 1).'行目の規格IDが存在しません。');
+
+ return $this->renderWithError($form, $headers);
+ }
+ $ClassName = $this->classNameRepository->find($row[$headerByKey['id']]);
+ if (!$ClassName) {
+ $this->addErrors(($data->key() + 1).'行目の更新対象の規格IDが存在しません。新規登録の場合は、規格IDの値を空で登録してください。');
+
+ return $this->renderWithError($form, $headers);
+ }
+ }
+
+ if (isset($row[$headerByKey['class_name_del_flg']]) && StringUtil::isNotBlank($row[$headerByKey['class_name_del_flg']])) {
+ if (StringUtil::trimAll($row[$headerByKey['class_name_del_flg']]) == 1) {
+ if ($ClassName->getId()) {
+ log_info('規格削除開始', [$ClassName->getId()]);
+ try {
+ $this->classNameRepository->delete($ClassName);
+ log_info('規格削除完了', [$ClassName->getId()]);
+ } catch (ForeignKeyConstraintViolationException $e) {
+ log_info('規格削除エラー', [$ClassName->getId(), $e]);
+ $message = trans('admin.common.delete_error_foreign_key', ['%name%' => $ClassName->getName()]);
+ $this->addError($message, 'admin');
+
+ return $this->renderWithError($form, $headers);
+ }
+ }
+
+ continue;
+ }
+ }
+
+ if (!isset($row[$headerByKey['name']]) || StringUtil::isBlank($row[$headerByKey['name']])) {
+ $this->addErrors(($data->key() + 1).'行目規格名が設定されていません。');
+
+ return $this->renderWithError($form, $headers);
+ } else {
+ $ClassName->setName(StringUtil::trimAll($row[$headerByKey['name']]));
+ }
+
+ if (isset($row[$headerByKey['backend_name']]) && StringUtil::isNotBlank($row[$headerByKey['backend_name']])) {
+ $ClassName->setBackendName(StringUtil::trimAll($row[$headerByKey['backend_name']]));
+ }
+
+ if ($this->hasErrors()) {
+ return $this->renderWithError($form, $headers);
+ }
+ $this->entityManager->persist($ClassName);
+ $this->classNameRepository->save($ClassName);
+ }
+
+ $this->entityManager->getConnection()->commit();
+ log_info('規格CSV登録完了');
+ $message = 'admin.common.csv_upload_complete';
+ $this->session->getFlashBag()->add('eccube.admin.success', $message);
+
+ $cacheUtil->clearDoctrineCache();
+ }
+ }
+ }
+
+ return $this->renderWithError($form, $headers);
+ }
+
+
+ /**
+ * 規格分類CSV登録CSVアップロード
+ *
+ * @Route("/%eccube_admin_route%/product/class_category_csv_upload", name="admin_product_class_category_csv_import")
+ * @Template("@admin/Product/csv_class_category.twig")
+ */
+ public function csvClassCategory(Request $request, CacheUtil $cacheUtil)
+ {
+ $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
+
+ $headers = $this->getClassCategoryCsvHeader();
+ if ('POST' === $request->getMethod()) {
+ $form->handleRequest($request);
+ if ($form->isValid()) {
+ $formFile = $form['import_file']->getData();
+ if (!empty($formFile)) {
+ log_info('規格分類CSV登録開始');
+ $data = $this->getImportData($formFile);
+ if ($data === false) {
+ $this->addErrors(trans('admin.common.csv_invalid_format'));
+
+ return $this->renderWithError($form, $headers, false);
+ }
+
+ $getId = function ($item) {
+ return $item['id'];
+ };
+ $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
+ return $value['required'];
+ })));
+
+ $headerByKey = array_flip(array_map($getId, $headers));
+
+ $columnHeaders = $data->getColumnHeaders();
+ if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
+ $this->addErrors(trans('admin.common.csv_invalid_format'));
+
+ return $this->renderWithError($form, $headers, false);
+ }
+
+ $size = count($data);
+ if ($size < 1) {
+ $this->addErrors(trans('admin.common.csv_invalid_no_data'));
+
+ return $this->renderWithError($form, $headers, false);
+ }
+ $this->entityManager->getConfiguration()->setSQLLogger(null);
+ $this->entityManager->getConnection()->beginTransaction();
+ // CSVファイルの登録処理
+ foreach ($data as $row) {
+ // dump($row,$headerByKey);exit;
+ /** @var $ClassCategory ClassCategory */
+ $ClassCategory = new ClassCategory();
+
+ if (isset($row[$headerByKey['id']]) && strlen($row[$headerByKey['id']]) > 0) {
+ if (!preg_match('/^\d+$/', $row[$headerByKey['id']])) {
+ $this->addErrors(($data->key() + 1).'行目の規格分類IDが存在しません。');
+
+ return $this->renderWithError($form, $headers);
+ }
+ $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['id']]);
+ if (!$ClassCategory) {
+ $this->addErrors(($data->key() + 1).'行目の更新対象の規格分類IDが存在しません。新規登録の場合は、規格分類IDの値を空で登録してください。');
+
+ return $this->renderWithError($form, $headers);
+ }
+ }
+
+ if (isset($row[$headerByKey['class_name_id']]) && strlen($row[$headerByKey['class_name_id']]) > 0) {
+ if (!preg_match('/^\d+$/', $row[$headerByKey['class_name_id']])) {
+ $this->addErrors(($data->key() + 1).'行目の規格IDが存在しません。');
+
+ return $this->renderWithError($form, $headers);
+ }
+ $ClassName = $this->classNameRepository->find($row[$headerByKey['class_name_id']]);
+ if (!$ClassName) {
+ $this->addErrors(($data->key() + 1).'行目の更新対象の規格IDが存在しません。');
+
+ return $this->renderWithError($form, $headers);
+ }
+ $ClassCategory->setClassName($ClassName);
+ }
+
+ if (isset($row[$headerByKey['class_category_del_flg']]) && StringUtil::isNotBlank($row[$headerByKey['class_category_del_flg']])) {
+ if (StringUtil::trimAll($row[$headerByKey['class_category_del_flg']]) == 1) {
+ if ($ClassCategory->getId()) {
+ log_info('規格分類削除開始', [$ClassCategory->getId()]);
+ try {
+ $this->classCategoryRepository->delete($ClassCategory);
+ log_info('規格分類削除完了', [$ClassCategory->getId()]);
+ } catch (ForeignKeyConstraintViolationException $e) {
+ log_info('規格分類削除エラー', [$ClassCategory->getId(), $e]);
+ $message = trans('admin.common.delete_error_foreign_key', ['%name%' => $ClassCategory->getName()]);
+ $this->addError($message, 'admin');
+
+ return $this->renderWithError($form, $headers);
+ }
+ }
+
+ continue;
+ }
+ }
+
+ if (!isset($row[$headerByKey['name']]) || StringUtil::isBlank($row[$headerByKey['name']])) {
+ $this->addErrors(($data->key() + 1).'行目規格分類名が設定されていません。');
+
+ return $this->renderWithError($form, $headers);
+ } else {
+ $ClassCategory->setName(StringUtil::trimAll($row[$headerByKey['name']]));
+ }
+
+ if (isset($row[$headerByKey['backend_name']]) && StringUtil::isNotBlank($row[$headerByKey['backend_name']])) {
+ $ClassCategory->setBackendName(StringUtil::trimAll($row[$headerByKey['backend_name']]));
+ }
+
+ if ($this->hasErrors()) {
+ return $this->renderWithError($form, $headers);
+ }
+ $this->entityManager->persist($ClassCategory);
+ $this->classCategoryRepository->save($ClassCategory);
+ }
+
+ $this->entityManager->getConnection()->commit();
+ log_info('規格分類CSV登録完了');
+ $message = 'admin.common.csv_upload_complete';
+ $this->session->getFlashBag()->add('eccube.admin.success', $message);
+
+ $cacheUtil->clearDoctrineCache();
+ }
+ }
+ }
+
+ return $this->renderWithError($form, $headers);
+ }
+
+
/**
* アップロード用CSV雛形ファイルダウンロード
*
@@ -860,6 +1127,12 @@ public function csvTemplate(Request $request, $type)
} elseif ($type == 'category') {
$headers = $this->getCategoryCsvHeader();
$filename = 'category.csv';
+ } elseif ($type == 'class_name') {
+ $headers = $this->getClassNameCsvHeader();
+ $filename = 'class_name.csv';
+ } elseif ($type == 'class_category') {
+ $headers = $this->getClassCategoryCsvHeader();
+ $filename = 'class_category.csv';
} else {
throw new NotFoundHttpException();
}
@@ -1602,6 +1875,69 @@ protected function getCategoryCsvHeader()
];
}
+ /**
+ * 規格CSVヘッダー定義
+ */
+ protected function getClassNameCsvHeader()
+ {
+ return [
+ trans('admin.product.class_name_csv.class_name_id_col') => [
+ 'id' => 'id',
+ 'description' => 'admin.product.class_name_csv.class_name_id_description',
+ 'required' => false,
+ ],
+ trans('admin.product.class_name_csv.class_name_col') => [
+ 'id' => 'name',
+ 'description' => 'admin.product.class_name_csv.class_name_description',
+ 'required' => true,
+ ],
+ trans('admin.product.class_name_csv.class_backend_name_col') => [
+ 'id' => 'backend_name',
+ 'description' => 'admin.product.class_name_csv.class_backend_name_description',
+ 'required' => false,
+ ],
+ trans('admin.product.class_name_csv.delete_flag_col') => [
+ 'id' => 'class_name_del_flg',
+ 'description' => 'admin.product.class_name_csv.delete_flag_description',
+ 'required' => false,
+ ],
+ ];
+ }
+
+ /**
+ * 規格分類CSVヘッダー定義
+ */
+ protected function getClassCategoryCsvHeader()
+ {
+ return [
+ trans('admin.product.class_category_csv.class_name_id_col') => [
+ 'id' => 'class_name_id',
+ 'description' => 'admin.product.class_category_csv.class_name_id_description',
+ 'required' => true,
+ ],
+ trans('admin.product.class_category_csv.class_category_id_col') => [
+ 'id' => 'id',
+ 'description' => 'admin.product.class_category_csv.class_category_id_description',
+ 'required' => false,
+ ],
+ trans('admin.product.class_category_csv.class_category_name_col') => [
+ 'id' => 'name',
+ 'description' => 'admin.product.class_category_csv.class_category_name_description',
+ 'required' => true,
+ ],
+ trans('admin.product.class_category_csv.class_category_backend_name_col') => [
+ 'id' => 'backend_name',
+ 'description' => 'admin.product.class_category_csv.class_category_backend_name_description',
+ 'required' => false,
+ ],
+ trans('admin.product.class_category_csv.delete_flag_col') => [
+ 'id' => 'class_category_del_flg',
+ 'description' => 'admin.product.class_category_csv.delete_flag_description',
+ 'required' => false,
+ ],
+ ];
+ }
+
/**
* ProductCategory作成
*
diff --git a/src/Eccube/Entity/Master/CsvType.php b/src/Eccube/Entity/Master/CsvType.php
index 908c7f471c1..829470f6e25 100644
--- a/src/Eccube/Entity/Master/CsvType.php
+++ b/src/Eccube/Entity/Master/CsvType.php
@@ -52,5 +52,15 @@ class CsvType extends \Eccube\Entity\Master\AbstractMasterEntity
* @var integer
*/
public const CSV_TYPE_CATEGORY = 5;
+
+ /**
+ * @var integer
+ */
+ public const CSV_TYPE_CLASS_NAME = 6;
+
+ /**
+ * @var integer
+ */
+ public const CSV_TYPE_CLASS_CATEGORY = 7;
}
}
diff --git a/src/Eccube/Event/EccubeEvents.php b/src/Eccube/Event/EccubeEvents.php
index 1cff1fab64e..3d02d9a86b6 100644
--- a/src/Eccube/Event/EccubeEvents.php
+++ b/src/Eccube/Event/EccubeEvents.php
@@ -214,6 +214,9 @@ final class EccubeEvents
// delete
public const ADMIN_PRODUCT_CLASS_CATEGORY_DELETE_COMPLETE = 'admin.product.class.category.delete.complete';
+ // export
+ const ADMIN_PRODUCT_CLASS_CATEGORY_CSV_EXPORT = 'admin.product.class.category.csv.export';
+
/**
* Admin/Product/ClassNameController
*/
@@ -224,6 +227,9 @@ final class EccubeEvents
// delete
public const ADMIN_PRODUCT_CLASS_NAME_DELETE_COMPLETE = 'admin.product.class.name.delete.complete';
+ // export
+ const ADMIN_PRODUCT_CLASS_NAME_CSV_EXPORT = 'admin.product.class.name.csv.export';
+
/**
* Admin/Product/CsvImportController
*/
diff --git a/src/Eccube/Resource/doctrine/import_csv/en/dtb_csv.csv b/src/Eccube/Resource/doctrine/import_csv/en/dtb_csv.csv
index 92ae9e99aad..08c4a5cbf69 100644
--- a/src/Eccube/Resource/doctrine/import_csv/en/dtb_csv.csv
+++ b/src/Eccube/Resource/doctrine/import_csv/en/dtb_csv.csv
@@ -203,3 +203,10 @@ 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
+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
+210,7,,Eccube\\Entity\\ClassCategory,id,,Class Category ID,1,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
+211,7,,Eccube\\Entity\\ClassCategory,ClassName,id,Class NameID,2,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
+212,7,,Eccube\\Entity\\ClassCategory,name,,Class Category Name,3,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
+213,7,,Eccube\\Entity\\ClassCategory,backend_name,,Class Category Backend Name,4,1,2021-05-18 01:26:41,2021-05-18 01:26:41,csv
\ No newline at end of file
diff --git a/src/Eccube/Resource/doctrine/import_csv/en/mtb_csv_type.csv b/src/Eccube/Resource/doctrine/import_csv/en/mtb_csv_type.csv
index 0c0117df7b9..5c38627e153 100644
--- a/src/Eccube/Resource/doctrine/import_csv/en/mtb_csv_type.csv
+++ b/src/Eccube/Resource/doctrine/import_csv/en/mtb_csv_type.csv
@@ -4,3 +4,5 @@ id,name,sort_no,discriminator_type
3,Order CSV,1,csvtype
4,Delivery CSV,1,csvtype
5,Category CSV,5,csvtype
+6,Class NameCSV,6,csvtype
+7,Class Category CSV,7,csvtype
\ No newline at end of file
diff --git a/src/Eccube/Resource/doctrine/import_csv/ja/dtb_csv.csv b/src/Eccube/Resource/doctrine/import_csv/ja/dtb_csv.csv
index 70e71ecb45a..e6e878bcf95 100644
--- a/src/Eccube/Resource/doctrine/import_csv/ja/dtb_csv.csv
+++ b/src/Eccube/Resource/doctrine/import_csv/ja/dtb_csv.csv
@@ -203,3 +203,10 @@
"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"
+"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"
+"210","7",,"Eccube\\Entity\\ClassCategory","id",,"規格分類ID","1","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
+"211","7",,"Eccube\\Entity\\ClassCategory","ClassName","id","規格ID","2","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
+"212","7",,"Eccube\\Entity\\ClassCategory","name",,"規格分類名","3","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
+"213","7",,"Eccube\\Entity\\ClassCategory","backend_name",,"分類管理名","4","1","2021-05-18 01:26:41","2021-05-18 01:26:41","csv"
\ No newline at end of file
diff --git a/src/Eccube/Resource/doctrine/import_csv/ja/mtb_csv_type.csv b/src/Eccube/Resource/doctrine/import_csv/ja/mtb_csv_type.csv
index 4015fb15f06..a01c284ebd0 100644
--- a/src/Eccube/Resource/doctrine/import_csv/ja/mtb_csv_type.csv
+++ b/src/Eccube/Resource/doctrine/import_csv/ja/mtb_csv_type.csv
@@ -4,3 +4,5 @@ id,name,sort_no,discriminator_type
"3","受注CSV","1","csvtype"
"4","配送CSV","1","csvtype"
"5","カテゴリCSV","5","csvtype"
+"6","規格CSV","6","csvtype"
+"7","規格分類CSV","7","csvtype"
\ No newline at end of file
diff --git a/src/Eccube/Resource/locale/messages.en.yaml b/src/Eccube/Resource/locale/messages.en.yaml
index ecd21c78965..3814214df3c 100644
--- a/src/Eccube/Resource/locale/messages.en.yaml
+++ b/src/Eccube/Resource/locale/messages.en.yaml
@@ -606,6 +606,8 @@ admin.product.class_category_management: Option Groups
admin.product.category_management: Categories
admin.product.tag_management: Tags
admin.product.product_csv_upload: Product CSV
+admin.product.class_name_csv_upload: Class Name CSV
+admin.product.class_category_csv_upload: Class Category CSV
admin.product.category_csv_upload: Category CSV
# flash messages
@@ -776,6 +778,28 @@ admin.product.category_csv.parent_category_id_description: ""
admin.product.category_csv.delete_flag_col: Category Deletion Flag
admin.product.category_csv.delete_flag_description: "Specify 0: Upload or 1: Delete. If unspecified, it is set to 0."
+# Class Name CSV Templates
+admin.product.class_name_csv.class_name_id_col: Class Name ID
+admin.product.class_name_csv.class_name_id_description: For a new class name registration, please leave it empty. To update the registered class name, please specify the class name ID.
+admin.product.class_name_csv.class_name_col: Class Name
+admin.product.class_name_csv.class_name_description: ''
+admin.product.class_name_csv.class_backend_name_col: Backend Name
+admin.product.class_name_csv.class_backend_name_description: ''
+admin.product.class_name_csv.delete_flag_col: Class Name Deletion Flag
+admin.product.class_name_csv.delete_flag_description: 'Specify 0: Upload or 1: Delete. If unspecified, it is set to 0.'
+
+# Class Category CSV Templates
+admin.product.class_category_csv.class_name_id_col: Class Name ID
+admin.product.class_category_csv.class_name_id_description: Specify an existing Class Name ID.
+admin.product.class_category_csv.class_category_id_col: Class Category ID
+admin.product.class_category_csv.class_category_id_description: For a new class category registration, please leave it empty. To update the registered class category, please specify the class category ID.
+admin.product.class_category_csv.class_category_name_col: Class Category Name
+admin.product.class_category_csv.class_category_name_description: ''
+admin.product.class_category_csv.class_category_backend_name_col: Class Category Backend Name
+admin.product.class_category_csv.class_category_backend_name_description: ''
+admin.product.class_category_csv.delete_flag_col: Class Category Deletion Flag
+admin.product.class_category_csv.delete_flag_description: 'Specify 0: Upload or 1: Delete. If unspecified, it is set to 0.'
+
# Product CSV
admin.product.product_csv_upload__title: "Upload product CSV"
admin.product.product_csv_upload__message: "Upload the product CSV file. Is it OK?"
@@ -1743,6 +1767,8 @@ tooltip.setting.system.system.php_info: PHP details relevant to EC-CUBE.
tooltip.store.template.template_code: This code will be used as the directory name where the template is saved.
tooltip.store.template.template_name: Set the name of the template to be displayed in the Admin Console.
tooltip.store.template.template_file: Upload an archive file that contains a set of templates.
+tooltip.class_name.csv_upload: Standards can be registered in a batch using the specified type of CSV data.
+tooltip.class_name.csv_format: You can easily create CSV data of the specified type by downloading and editing the template file.
#====================================================================================
# Installation
diff --git a/src/Eccube/Resource/locale/messages.ja.yaml b/src/Eccube/Resource/locale/messages.ja.yaml
index f504a9c1365..dc25f2d14a5 100644
--- a/src/Eccube/Resource/locale/messages.ja.yaml
+++ b/src/Eccube/Resource/locale/messages.ja.yaml
@@ -606,6 +606,8 @@ admin.product.class_category_management: 規格分類管理
admin.product.category_management: カテゴリ管理
admin.product.tag_management: タグ管理
admin.product.product_csv_upload: 商品CSV登録
+admin.product.class_name_csv_upload: 規格CSV登録
+admin.product.class_category_csv_upload: 規格分類CSV登録
admin.product.category_csv_upload: カテゴリCSV登録
# flashメッセージ
@@ -776,6 +778,28 @@ admin.product.category_csv.parent_category_id_description: ""
admin.product.category_csv.delete_flag_col: カテゴリ削除フラグ
admin.product.category_csv.delete_flag_description: 0:登録 1:削除を指定します。未指定の場合、0として扱います。
+# 規格CSV雛形
+admin.product.class_name_csv.class_name_id_col: 規格ID
+admin.product.class_name_csv.class_name_id_description: 新規登録の場合は空にしてください。既存の規格を更新する場合は、規格IDを指定してください。
+admin.product.class_name_csv.class_name_col: 規格名
+admin.product.class_name_csv.class_name_description: ''
+admin.product.class_name_csv.class_backend_name_col: 管理名
+admin.product.class_name_csv.class_backend_name_description: ''
+admin.product.class_name_csv.delete_flag_col: 規格削除フラグ
+admin.product.class_name_csv.delete_flag_description: 0:登録 1:削除を指定します。未指定の場合、0として扱います。
+
+# 規格分類CSV雛形
+admin.product.class_category_csv.class_name_id_col: 規格ID
+admin.product.class_category_csv.class_name_id_description: 既存の規格IDを指定してください。
+admin.product.class_category_csv.class_category_id_col: 規格分類ID
+admin.product.class_category_csv.class_category_id_description: 新規登録の場合は空にしてください。既存の規格分類を更新する場合は、規格分類IDを指定してください。
+admin.product.class_category_csv.class_category_name_col: 規格分類名
+admin.product.class_category_csv.class_category_name_description: ''
+admin.product.class_category_csv.class_category_backend_name_col: 規格分類管理名
+admin.product.class_category_csv.class_category_backend_name_description: ''
+admin.product.class_category_csv.delete_flag_col: 規格分類削除フラグ
+admin.product.class_category_csv.delete_flag_description: 0:登録 1:削除を指定します。未指定の場合、0として扱います。
+
# 商品CSV
admin.product.product_csv_upload__title: "商品CSVをアップロードします"
admin.product.product_csv_upload__message: "商品CSVファイルをアップロードします。よろしいですか?"
@@ -1744,6 +1768,8 @@ tooltip.setting.system.system.php_info: このEC-CUBEに関係しているPHPの
tooltip.store.template.template_code: テンプレートの格納先のディレクトリ名になります。
tooltip.store.template.template_name: 管理画面で表示するテンプレートの名前を設定します。
tooltip.store.template.template_file: テンプレート一式となるアーカイブをアップロードします。
+tooltip.class_name.csv_upload: 所定の型のCSVデータを用いて規格を一括で登録することができます。
+tooltip.class_name.csv_format: 雛形ファイルをダウンロードして編集すれば、簡単に所定の型のCSVデータを作成できます。
#====================================================================================
# インストール画面
diff --git a/src/Eccube/Resource/template/admin/Product/class_category.twig b/src/Eccube/Resource/template/admin/Product/class_category.twig
index 34ef394ad4a..a10e431562a 100644
--- a/src/Eccube/Resource/template/admin/Product/class_category.twig
+++ b/src/Eccube/Resource/template/admin/Product/class_category.twig
@@ -142,6 +142,24 @@ file that was distributed with this source code.
+
diff --git a/src/Eccube/Resource/template/admin/Product/class_name.twig b/src/Eccube/Resource/template/admin/Product/class_name.twig
index 1069892eaa4..9fc4dcedaf4 100644
--- a/src/Eccube/Resource/template/admin/Product/class_name.twig
+++ b/src/Eccube/Resource/template/admin/Product/class_name.twig
@@ -130,6 +130,24 @@ file that was distributed with this source code.
{% endblock %}
{% block main %}
+
diff --git a/src/Eccube/Resource/template/admin/Product/csv_class_category.twig b/src/Eccube/Resource/template/admin/Product/csv_class_category.twig
new file mode 100644
index 00000000000..02c9283486b
--- /dev/null
+++ b/src/Eccube/Resource/template/admin/Product/csv_class_category.twig
@@ -0,0 +1,129 @@
+{#
+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.
+#}
+{% extends '@admin/default_frame.twig' %}
+
+{% set menus = ['product', 'class_category_csv_import'] %}
+
+{% block title %}{{ 'admin.product.class_category_csv_upload'|trans }}{% endblock %}
+{% block sub_title %}{{ 'admin.product.product_management'|trans }}{% endblock %}
+
+{% form_theme form '@admin/Form/bootstrap_4_horizontal_layout.html.twig' %}
+
+{% block javascript %}
+
+
+{% endblock javascript %}
+{% block main %}
+
+
+
+
+
+
+
+
{{ 'admin.common.csv_select'|trans }}
+
+
+
+
+
+
+
+
+
+
+ {% for header, key in headers %}
+
+
+
+ {% if key.description %}
+ {{ key.description|trans|raw }}
+ {% endif %}
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/src/Eccube/Resource/template/admin/Product/csv_class_name.twig b/src/Eccube/Resource/template/admin/Product/csv_class_name.twig
new file mode 100644
index 00000000000..3b72d0b43b9
--- /dev/null
+++ b/src/Eccube/Resource/template/admin/Product/csv_class_name.twig
@@ -0,0 +1,129 @@
+{#
+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.
+#}
+{% extends '@admin/default_frame.twig' %}
+
+{% set menus = ['product', 'class_name_csv_import'] %}
+
+{% block title %}{{ 'admin.product.class_name_csv_upload'|trans }}{% endblock %}
+{% block sub_title %}{{ 'admin.product.product_management'|trans }}{% endblock %}
+
+{% form_theme form '@admin/Form/bootstrap_4_horizontal_layout.html.twig' %}
+
+{% block javascript %}
+
+
+{% endblock javascript %}
+{% block main %}
+
+
+
+
+
+
+
+
{{ 'admin.common.csv_select'|trans }}
+
+
+
+
+
+
+
+
+
+
+ {% for header, key in headers %}
+
+
+
+ {% if key.description %}
+ {{ key.description|trans|raw }}
+ {% endif %}
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+
+{% endblock %}